From 88a36ffad6c11279990c1c96df32b95c1f6f526c Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 3 Jul 2020 13:57:49 +0200 Subject: A fix proposal for boudaries of a simplex python version --- .../include/gudhi/Simplex_tree/Simplex_tree_iterators.h | 5 +++++ src/python/gudhi/simplex_tree.pxd | 8 ++++++++ src/python/gudhi/simplex_tree.pyx | 16 ++++++++++++++++ src/python/include/Simplex_tree_interface.h | 11 +++++++++++ src/python/test/test_simplex_tree.py | 9 +++++++++ 5 files changed, 49 insertions(+) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h index 9007b6bd..9c864454 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h @@ -85,6 +85,11 @@ class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade< typedef typename SimplexTree::Vertex_handle Vertex_handle; typedef typename SimplexTree::Siblings Siblings; + Simplex_tree_boundary_simplex_iterator() + : sib_(nullptr), + st_(nullptr) { + } + // any end() iterator explicit Simplex_tree_boundary_simplex_iterator(SimplexTree * st) : last_(st->null_vertex()), diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index e748ac40..a64599e7 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -36,6 +36,12 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": Simplex_tree_skeleton_iterator operator++() nogil bint operator!=(Simplex_tree_skeleton_iterator) nogil + cdef cppclass Simplex_tree_boundary_iterator "Gudhi::Simplex_tree_interface::Boundary_simplex_iterator": + Simplex_tree_boundary_iterator() nogil + Simplex_tree_simplex_handle& operator*() nogil + Simplex_tree_boundary_iterator operator++() nogil + bint operator!=(Simplex_tree_boundary_iterator) nogil + cdef cppclass Simplex_tree_interface_full_featured "Gudhi::Simplex_tree_interface": Simplex_tree() nogil @@ -65,6 +71,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_end() nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) nogil + Simplex_tree_boundary_iterator get_boundary_iterator_begin(vector[int] simplex) nogil + Simplex_tree_boundary_iterator get_boundary_iterator_end(vector[int] simplex) nogil cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 20e66d9f..da445a12 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -285,6 +285,22 @@ cdef class SimplexTree: ct.append((v, filtered_simplex.second)) return ct + def get_boundaries(self, simplex): + """This function returns a generator with the boundaries of a given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: The (simplices of the) boundaries of a simplex + :rtype: generator with tuples(simplex, filtration) + """ + cdef Simplex_tree_boundary_iterator it = self.get_ptr().get_boundary_iterator_begin(simplex) + cdef Simplex_tree_boundary_iterator end = self.get_ptr().get_boundary_iterator_end(simplex) + + while it != end: + yield self.get_ptr().get_simplex_and_filtration(dereference(it)) + preincrement(it) + + def remove_maximal_simplex(self, simplex): """This function removes a given maximal N-simplex from the simplicial complex. diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 56d7c41d..c4f18eeb 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -36,6 +36,7 @@ class Simplex_tree_interface : public Simplex_tree { using Skeleton_simplex_iterator = typename Base::Skeleton_simplex_iterator; using Complex_simplex_iterator = typename Base::Complex_simplex_iterator; using Extended_filtration_data = typename Base::Extended_filtration_data; + using Boundary_simplex_iterator = typename Base::Boundary_simplex_iterator; public: @@ -188,6 +189,16 @@ class Simplex_tree_interface : public Simplex_tree { // this specific case works because the range is just a pair of iterators - won't work if range was a vector return Base::skeleton_simplex_range(dimension).end(); } + + Boundary_simplex_iterator get_boundary_iterator_begin(const Simplex& simplex) { + // this specific case works because the range is just a pair of iterators - won't work if range was a vector + return Base::boundary_simplex_range(Base::find(simplex)).begin(); + } + + Boundary_simplex_iterator get_boundary_iterator_end(const Simplex& simplex) { + // this specific case works because the range is just a pair of iterators - won't work if range was a vector + return Base::boundary_simplex_range(Base::find(simplex)).end(); + } }; } // namespace Gudhi diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 2137d822..7c49cb1a 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -340,3 +340,12 @@ def test_simplices_iterator(): assert st.find(simplex[0]) == True print("filtration is: ", simplex[1]) assert st.filtration(simplex[0]) == simplex[1] + +def test_boundaries_iterator(): + st = SimplexTree() + + assert st.insert([0, 1, 2, 3], filtration=1.0) == True + assert st.insert([1, 2, 3, 4], filtration=2.0) == True + + assert list(st.get_boundaries([1, 2, 3])) == [([1, 2], 1.0), ([1, 3], 1.0), ([2, 3], 1.0)] + assert list(st.get_boundaries([2, 3, 4])) == [([2, 3], 1.0), ([2, 4], 2.0), ([3, 4], 2.0)] -- cgit v1.2.3 From 85eec1ba750d56b66e3739dc486c6205f49fb31e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 3 Jul 2020 16:04:45 +0200 Subject: A proposal for simplex_tree reset_filtration (python & C++) --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 30 +++++++++++++++ src/Simplex_tree/test/simplex_tree_unit_test.cpp | 47 ++++++++++++++++++++++++ src/python/gudhi/simplex_tree.pxd | 1 + src/python/gudhi/simplex_tree.pyx | 10 +++++ src/python/test/test_simplex_tree.py | 22 +++++++++++ 5 files changed, 110 insertions(+) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 889dbd00..adc8e801 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1667,6 +1667,36 @@ class Simplex_tree { return sh; // None of its faces has the same filtration. } + public: + /** \brief This function resets filtration value until a given dimension. + * @param[in] filt_value The new filtration value. + * @param[in] max_dim The maximal dimension. + */ + void reset_filtration(Filtration_value filt_value, int max_dim) { + for (auto& simplex : root_.members()) { + simplex.second.assign_filtration(filt_value); + if (has_children(&simplex) && max_dim > 0) { + rec_reset_filtration(simplex.second.children(), filt_value, (max_dim - 1)); + } + } + clear_filtration(); // Drop the cache. + } + + private: + /** \brief Recursively resets filtration value until a given dimension. + * @param[in] sib Siblings to be parsed. + * @param[in] filt_value The new filtration value. + * @param[in] max_dim The maximal dimension. + */ + void rec_reset_filtration(Siblings * sib, Filtration_value filt_value, int max_dim) { + for (auto& simplex : sib->members()) { + simplex.second.assign_filtration(filt_value); + if (has_children(&simplex) && max_dim > 0) { + rec_reset_filtration(simplex.second.children(), filt_value, (max_dim - 1)); + } + } + } + private: Vertex_handle null_vertex_; /** \brief Total number of simplices in the complex, without the empty simplex.*/ diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 9b5fa8fe..9780f5b0 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -940,3 +940,50 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(generators, typeST, list_of_tested_variants) { BOOST_CHECK(st.edge_with_same_filtration(st.find({1,5}))==st.find({1,5})); } } + +BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_reset_filtration, typeST, list_of_tested_variants) { + std::clog << "********************************************************************" << std::endl; + std::clog << "TEST RESET FILTRATION" << std::endl; + typeST st; + + st.insert_simplex_and_subfaces({2, 1, 0}, 3.); + st.insert_simplex_and_subfaces({3, 0}, 2.); + st.insert_simplex_and_subfaces({3, 4, 5}, 3.); + st.insert_simplex_and_subfaces({0, 1, 6, 7}, 4.); + + /* Inserted simplex: */ + /* 1 6 */ + /* o---o */ + /* /X\7/ */ + /* o---o---o---o */ + /* 2 0 3\X/4 */ + /* o */ + /* 5 */ + + for (auto f_simplex : st.skeleton_simplex_range(3)) { + std::clog << "vertex = ("; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::clog << vertex << ","; + } + std::clog << ") - filtration =" << st.filtration(f_simplex) << std::endl; + BOOST_CHECK(st.filtration(f_simplex) >= 2.); + } + + // dimension until 5 even if simplex tree is of dimension 3 to test the limits + for(int dimension = 0; dimension < 6; dimension ++) { + st.reset_filtration(0., dimension); + for (auto f_simplex : st.skeleton_simplex_range(3)) { + std::clog << "vertex = ("; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::clog << vertex << ","; + } + std::clog << ") - filtration =" << st.filtration(f_simplex) << std::endl; + if (st.dimension(f_simplex) > dimension) + BOOST_CHECK(st.filtration(f_simplex) >= 1.); + else + BOOST_CHECK(st.filtration(f_simplex) == 0.); + } + } + +} + diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index e748ac40..12c2065e 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -57,6 +57,7 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": bool make_filtration_non_decreasing() nogil void compute_extended_filtration() nogil vector[vector[pair[int, pair[double, double]]]] compute_extended_persistence_subdiagrams(vector[pair[int, pair[double, double]]] dgm, double min_persistence) nogil + void reset_filtration(double filtration, int dimension) nogil # Iterators over Simplex tree pair[vector[int], double] get_simplex_and_filtration(Simplex_tree_simplex_handle f_simplex) nogil Simplex_tree_simplices_iterator get_simplices_iterator_begin() nogil diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 20e66d9f..41b06116 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -358,6 +358,16 @@ cdef class SimplexTree: """ return self.get_ptr().make_filtration_non_decreasing() + def reset_filtration(self, filtration, max_dim): + """This function resets filtration value until a given dimension. + + :param filtration: New threshold value. + :type filtration: float. + :param max_dim: The maximal dimension. + :type max_dim: int. + """ + self.get_ptr().reset_filtration(filtration, max_dim) + def extend_filtration(self): """ Extend filtration for computing extended persistence. This function only uses the filtration values at the 0-dimensional simplices, and computes the extended persistence diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 2137d822..1ca84c10 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -340,3 +340,25 @@ def test_simplices_iterator(): assert st.find(simplex[0]) == True print("filtration is: ", simplex[1]) assert st.filtration(simplex[0]) == simplex[1] + +def test_reset_filtration(): + st = SimplexTree() + + assert st.insert([0, 1, 2], 3.) == True + assert st.insert([0, 3], 2.) == True + assert st.insert([3, 4, 5], 3.) == True + assert st.insert([0, 1, 6, 7], 4.) == True + + for simplex in st.get_simplices(): + assert st.filtration(simplex[0]) >= 0. + + # dimension until 5 even if simplex tree is of dimension 3 to test the limits + for dimension in range(0, 6): + st.reset_filtration(0., dimension) + for simplex in st.get_skeleton(3): + print(simplex) + if len(simplex[0]) > (dimension + 1): + assert st.filtration(simplex[0]) >= 1. + else: + assert st.filtration(simplex[0]) == 0. + -- cgit v1.2.3 From c2aa4a3416bbdc09840217a8dcd89da7d9647513 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 28 Jul 2020 09:37:06 +0200 Subject: Remove Eigen compilation error for Alpha complex 3d --- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index f56e12d0..2c1b97a4 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -56,10 +56,6 @@ # error Alpha_complex_3d is only available for CGAL >= 4.11 #endif -#if !EIGEN_VERSION_AT_LEAST(3,1,0) -# error Alpha_complex_3d is only available for Eigen3 >= 3.1.0 installed with CGAL -#endif - namespace Gudhi { namespace alpha_complex { -- cgit v1.2.3 From 59e819dd9485bd55b2b3ec6440cb3e3200d96fcb Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 11 Aug 2020 09:43:36 +0200 Subject: Add build pip CI --- .github/workflows/pip-build-linux.yml | 45 +++++++++++++++++++++++++++++++++ .github/workflows/pip-build-osx.yml | 34 +++++++++++++++++++++++++ .github/workflows/pip-build-windows.yml | 42 ++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 .github/workflows/pip-build-linux.yml create mode 100644 .github/workflows/pip-build-osx.yml create mode 100644 .github/workflows/pip-build-windows.yml diff --git a/.github/workflows/pip-build-linux.yml b/.github/workflows/pip-build-linux.yml new file mode 100644 index 00000000..cf41d224 --- /dev/null +++ b/.github/workflows/pip-build-linux.yml @@ -0,0 +1,45 @@ +name: pip build linux + +on: [push, pull_request] + +jobs: + build: + name: build pip wheels + runs-on: ubuntu-latest + container: gudhi/pip_for_gudhi + steps: + - uses: actions/checkout@v1 + with: + submodules: true + - name: Build wheels for Python 3.5 + run: | + mkdir build_35 + cd build_35 + cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON35/bin/python .. + cd src/python + $PYTHON35/bin/python setup.py bdist_wheel + auditwheel repair dist/*.whl + - name: Build wheels for Python 3.6 + run: | + mkdir build_36 + cd build_36 + cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON36/bin/python .. + cd src/python + $PYTHON36/bin/python setup.py bdist_wheel + auditwheel repair dist/*.whl + - name: Build wheels for Python 3.7 + run: | + mkdir build_37 + cd build_37 + cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON37/bin/python .. + cd src/python + $PYTHON37/bin/python setup.py bdist_wheel + auditwheel repair dist/*.whl + - name: Build wheels for Python 3.8 + run: | + mkdir build_38 + cd build_38 + cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON38/bin/python .. + cd src/python + $PYTHON38/bin/python setup.py bdist_wheel + auditwheel repair dist/*.whl \ No newline at end of file diff --git a/.github/workflows/pip-build-osx.yml b/.github/workflows/pip-build-osx.yml new file mode 100644 index 00000000..4af7cd84 --- /dev/null +++ b/.github/workflows/pip-build-osx.yml @@ -0,0 +1,34 @@ +name: pip build osx + +on: [push, pull_request] + +jobs: + build: + runs-on: macos-latest + strategy: + max-parallel: 4 + matrix: + python-version: ['3.5', '3.6', '3.7', '3.8'] + name: Build wheels for Python ${{ matrix.python-version }} + steps: + - uses: actions/checkout@v1 + with: + submodules: true + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + - name: Install dependencies + run: | + brew update || true + brew install boost eigen gmp mpfr cgal || true + python -m pip install --user -r .github/build-requirements.txt + python -m pip install --user twine delocate + - name: Build python wheel + run: | + python --version + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DPython_ADDITIONAL_VERSIONS=3 .. + cd src/python + python setup.py bdist_wheel diff --git a/.github/workflows/pip-build-windows.yml b/.github/workflows/pip-build-windows.yml new file mode 100644 index 00000000..5119ac0c --- /dev/null +++ b/.github/workflows/pip-build-windows.yml @@ -0,0 +1,42 @@ +name: pip build windows + +on: [push, pull_request] + +jobs: + build: + runs-on: windows-latest + strategy: + max-parallel: 4 + matrix: + python-version: ['3.5', '3.6', '3.7', '3.8'] + name: Build wheels for Python ${{ matrix.python-version }} + steps: + - uses: actions/checkout@v1 + with: + submodules: true + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + - name: Patch + run: | + (new-object System.Net.WebClient).DownloadFile('https://github.com/microsoft/vcpkg/files/4978792/vcpkg_fixup_pkgconfig.cmake.txt','c:\vcpkg\scripts\cmake\vcpkg_fixup_pkgconfig.cmake') + (new-object System.Net.WebClient).DownloadFile('https://github.com/microsoft/vcpkg/files/4978796/vcpkg_acquire_msys.cmake.txt','c:\vcpkg\scripts\cmake\vcpkg_acquire_msys.cmake') + shell: powershell + - name: Install dependencies + run: | + vcpkg update + vcpkg upgrade --no-dry-run + vcpkg install boost-graph boost-serialization boost-date-time boost-system boost-filesystem boost-units boost-thread boost-program-options eigen3 mpfr mpir cgal --triplet x64-windows + python -m pip install --user -r .github/build-requirements.txt + python -m pip install --user twine + python -m pip list + - name: Build python wheel + run: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DGMP_INCLUDE_DIR="c:/vcpkg/installed/x64-windows/include" -DGMP_LIBRARIES="c:/vcpkg/installed/x64-windows/lib/mpir.lib" -DGMP_LIBRARIES_DIR="c:/vcpkg/installed/x64-windows/lib" -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows -DPython_ADDITIONAL_VERSIONS=3 .. + cd src/python + cp c:/vcpkg/installed/x64-windows/bin/mpfr.dll gudhi/ + cp c:/vcpkg/installed/x64-windows/bin/mpir.dll gudhi/ + python setup.py bdist_wheel \ No newline at end of file -- cgit v1.2.3 From a08971af8be1405c91429cf52e4c3301ffd50945 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 11 Aug 2020 17:13:22 +0200 Subject: Next release + version creation improvement --- .../for_maintainers/new_gudhi_version_creation.md | 41 ++++++++++++++++++- .github/next_release.md | 47 +++++----------------- CMakeGUDHIVersion.txt | 4 +- Dockerfile_gudhi_installation | 6 +-- 4 files changed, 54 insertions(+), 44 deletions(-) diff --git a/.github/for_maintainers/new_gudhi_version_creation.md b/.github/for_maintainers/new_gudhi_version_creation.md index 0dcb25fe..4de81b8a 100644 --- a/.github/for_maintainers/new_gudhi_version_creation.md +++ b/.github/for_maintainers/new_gudhi_version_creation.md @@ -88,8 +88,47 @@ ln -s @GUDHI_VERSION@ latest * 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 +## Pip package + +The pip package construction shall be started on release creation, you just have to check [gudhi github actions](https://github.com/GUDHI/gudhi-devel/actions) results. +The version number must be conform to [pep440](https://www.python.org/dev/peps/pep-0440/#pre-releases) + +## Conda package + +You have to fork [conda-forge/gudhi-feedstock](https://github.com/conda-forge/gudhi-feedstock). +The main changes consist into changing in the `recipe/meta.yaml`: +* `{% set version = "@GUDHI_VERSION@" %}` +* The cgal-cpp version number with the last one (you can find it [here](https://anaconda.org/conda-forge/cgal-cpp)) in the `host:` and the `run:` sections + +Create a Pull Request (PR) from this fork. +If you need to update conda tools (conda-build, conda-smithy, ...), add a comment in your PR saying `@conda-forge-admin, please rerender`, it will done automatically (do not forget to `git pull` the changes). + +## Docker image + +You have to modify the `Dockerfile_gudhi_installation` at the root of this repository in order to use the last release, cf. lines: +``` +... +RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudhi-release-@GUDHI_VERSION@/gudhi.@GUDHI_VERSION@.tar.gz" \ +&& tar xf gudhi.@GUDHI_VERSION@.tar.gz \ +&& cd gudhi.@GUDHI_VERSION@ \ +... +``` + +Build and push images to docker hub: +``` +docker build -f Dockerfile_gudhi_installation -t gudhi/latest_gudhi_version:@GUDHI_VERSION@ . +docker run --rm -it gudhi/latest_gudhi_version:@GUDHI_VERSION@ +``` + +***[Check there are no error with utils and python version]*** + +``` +docker tag gudhi/latest_gudhi_version:@GUDHI_VERSION@ gudhi/latest_gudhi_version:latest +docker push gudhi/latest_gudhi_version:latest +docker push gudhi/latest_gudhi_version:@GUDHI_VERSION@ +``` + ## 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/.github/next_release.md b/.github/next_release.md index 14546066..cd2376eb 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -1,47 +1,19 @@ -We are pleased to announce the release 3.3.0 of the GUDHI library. +We are pleased to announce the release 3.4.0 of the GUDHI library. -As a major new feature, the GUDHI library now offers a persistence-based clustering algorithm, weighted Rips complex using DTM -and edge collapse. +As a major new feature, the GUDHI library now offers ... -The GUDHI library is hosted on GitHub, 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.3.0.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.4.0.tar.gz). -Below is a list of changes made since GUDHI 3.2.0: +Below is a list of changes made since GUDHI 3.3.0: -- [DTM density estimator](https://gudhi.inria.fr/python/latest/point_cloud.html#module-gudhi.point_cloud.dtm) - - Python implementation of a density estimator based on the distance to the empirical measure defined by a point set. +- [Module](link) + - ... -- [DTM Rips complex](https://gudhi.inria.fr/python/latest/rips_complex_user.html#dtm-rips-complex) - - This Python implementation constructs a weighted Rips complex giving larger weights to outliers, - which reduces their impact on the persistence diagram - -- [Alpha complex](https://gudhi.inria.fr/python/latest/alpha_complex_user.html) - Python interface improvements - - 'fast' and 'exact' computations - - Delaunay complex construction by not setting filtration values - - Use the specific 3d alpha complex automatically to make the computations faster - -- [Clustering](https://gudhi.inria.fr/python/latest/clustering.html) - - Python implementation of [ToMATo](https://doi.org/10.1145/2535927), a persistence-based clustering algorithm - -- [Edge Collapse](https://gudhi.inria.fr/doc/latest/group__edge__collapse.html) of a filtered flag complex - - This C++ implementation reduces a filtration of Vietoris-Rips complex from its graph to another smaller - flag filtration with the same persistence. - -- [Bottleneck distance](https://gudhi.inria.fr/python/latest/bottleneck_distance_user.html) - - Python interface to [hera](https://github.com/grey-narn/hera)'s bottleneck distance - -- Persistence representations - - [Atol](https://gudhi.inria.fr/python/latest/representations.html#gudhi.representations.vector_methods.Atol) - is integrated in finite vectorisation methods. This - [article](https://www.fujitsu.com/global/about/resources/news/press-releases/2020/0316-01.html) talks about - applications using Atol. This module was originally available at - [https://github.com/martinroyer/atol](https://github.com/martinroyer/atol) - - Python interface change: [Wasserstein metrics](https://gudhi.inria.fr/python/latest/representations.html#gudhi.representations.metrics.WassersteinDistance) - is now [hera](https://github.com/grey-narn/hera) by default +- [Module](link) + - ... - Miscellaneous - - The [list of bugs that were solved since GUDHI-3.2.0](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.3.0+is%3Aclosed) - is available on GitHub. + - The [list of bugs that were solved since GUDHI-3.3.0](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.4.0+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. @@ -53,4 +25,3 @@ 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/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/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index a08b7b4d..5f1eaacf 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -1,8 +1,8 @@ # Must be conform to pep440 - https://www.python.org/dev/peps/pep-0440/#pre-releases set (GUDHI_MAJOR_VERSION 3) -set (GUDHI_MINOR_VERSION 3) +set (GUDHI_MINOR_VERSION 4) # GUDHI_PATCH_VERSION can be 'ZaN' for Alpha release, 'ZbN' for Beta release, 'ZrcN' for release candidate or 'Z' for a final release. -set (GUDHI_PATCH_VERSION 0) +set (GUDHI_PATCH_VERSION 0a0) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) message(STATUS "GUDHI version : ${GUDHI_VERSION}") diff --git a/Dockerfile_gudhi_installation b/Dockerfile_gudhi_installation index 996dd06b..92430fce 100644 --- a/Dockerfile_gudhi_installation +++ b/Dockerfile_gudhi_installation @@ -58,9 +58,9 @@ 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.2.0/gudhi.3.2.0.tar.gz" \ -&& tar xf gudhi.3.2.0.tar.gz \ -&& cd gudhi.3.2.0 \ +RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudhi-release-3.3.0/gudhi.3.3.0.tar.gz" \ +&& tar xf gudhi.3.3.0.tar.gz \ +&& cd gudhi.3.3.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 77cda62efd84ca7090d8796ca0197b03dbc22350 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau <10407034+VincentRouvreau@users.noreply.github.com> Date: Wed, 12 Aug 2020 07:28:31 +0200 Subject: Update src/python/gudhi/simplex_tree.pyx Co-authored-by: Marc Glisse --- src/python/gudhi/simplex_tree.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index da445a12..3ebae923 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -290,7 +290,7 @@ cdef class SimplexTree: :param simplex: The N-simplex, represented by a list of vertex. :type simplex: list of int. - :returns: The (simplices of the) boundaries of a simplex + :returns: The (simplices of the) boundary of a simplex :rtype: generator with tuples(simplex, filtration) """ cdef Simplex_tree_boundary_iterator it = self.get_ptr().get_boundary_iterator_begin(simplex) -- cgit v1.2.3 From 1f31e5ce995b0e7683c4eab7077317e28ee5b1b3 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 12 Aug 2020 08:02:00 +0200 Subject: code review: add a comment about Simplex_tree_boundary_simplex_iterator default ctor --- src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h index 9c864454..ee64a277 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h @@ -85,6 +85,7 @@ class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade< typedef typename SimplexTree::Vertex_handle Vertex_handle; typedef typename SimplexTree::Siblings Siblings; + // For cython purpose only. The object it initializes should be overwritten ASAP and never used before it is overwritten. Simplex_tree_boundary_simplex_iterator() : sib_(nullptr), st_(nullptr) { -- cgit v1.2.3 From 8f9c065df7f4629555ef09292c14c293891f1bdc Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 12 Aug 2020 10:03:26 +0200 Subject: code review: Add test to get boundaries from a vertex --- src/python/test/test_simplex_tree.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 7c49cb1a..036e88df 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -349,3 +349,4 @@ def test_boundaries_iterator(): assert list(st.get_boundaries([1, 2, 3])) == [([1, 2], 1.0), ([1, 3], 1.0), ([2, 3], 1.0)] assert list(st.get_boundaries([2, 3, 4])) == [([2, 3], 1.0), ([2, 4], 2.0), ([3, 4], 2.0)] + assert list(st.get_boundaries([2])) == [] -- cgit v1.2.3 From 458bc2dcf5044e1d5fde5326b2be35e526abd457 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 12 Aug 2020 13:06:03 +0200 Subject: code review: boundaries uses only once find and return a pair of iterator. Exception is raised when not found. tested --- src/python/gudhi/simplex_tree.pxd | 3 +-- src/python/gudhi/simplex_tree.pyx | 14 ++++++++------ src/python/include/Simplex_tree_interface.h | 12 +++++------- src/python/test/test_simplex_tree.py | 9 +++++++++ 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index a64599e7..e1b03391 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -71,8 +71,7 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_end() nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) nogil - Simplex_tree_boundary_iterator get_boundary_iterator_begin(vector[int] simplex) nogil - Simplex_tree_boundary_iterator get_boundary_iterator_end(vector[int] simplex) nogil + pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] get_boundary_iterators(vector[int] simplex) nogil except + cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 3ebae923..bc5b43f4 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -293,12 +293,14 @@ cdef class SimplexTree: :returns: The (simplices of the) boundary of a simplex :rtype: generator with tuples(simplex, filtration) """ - cdef Simplex_tree_boundary_iterator it = self.get_ptr().get_boundary_iterator_begin(simplex) - cdef Simplex_tree_boundary_iterator end = self.get_ptr().get_boundary_iterator_end(simplex) - - while it != end: - yield self.get_ptr().get_simplex_and_filtration(dereference(it)) - preincrement(it) + cdef pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] it = self.get_ptr().get_boundary_iterators(simplex) + + try: + while it.first != it.second: + yield self.get_ptr().get_simplex_and_filtration(dereference(it.first)) + preincrement(it.first) + except RuntimeError: + print("simplex not found - cannot find boundaries") def remove_maximal_simplex(self, simplex): diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index c4f18eeb..2c695d1b 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -190,14 +190,12 @@ class Simplex_tree_interface : public Simplex_tree { return Base::skeleton_simplex_range(dimension).end(); } - Boundary_simplex_iterator get_boundary_iterator_begin(const Simplex& simplex) { + std::pair get_boundary_iterators(const Simplex& simplex) { + auto bd_sh = Base::find(simplex); + if (bd_sh == Base::null_simplex()) + throw std::runtime_error("simplex not found - cannot find boundaries"); // this specific case works because the range is just a pair of iterators - won't work if range was a vector - return Base::boundary_simplex_range(Base::find(simplex)).begin(); - } - - Boundary_simplex_iterator get_boundary_iterator_end(const Simplex& simplex) { - // this specific case works because the range is just a pair of iterators - won't work if range was a vector - return Base::boundary_simplex_range(Base::find(simplex)).end(); + return std::make_pair(Base::boundary_simplex_range(bd_sh).begin(), Base::boundary_simplex_range(bd_sh).end()); } }; diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 036e88df..828400fb 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -350,3 +350,12 @@ def test_boundaries_iterator(): assert list(st.get_boundaries([1, 2, 3])) == [([1, 2], 1.0), ([1, 3], 1.0), ([2, 3], 1.0)] assert list(st.get_boundaries([2, 3, 4])) == [([2, 3], 1.0), ([2, 4], 2.0), ([3, 4], 2.0)] assert list(st.get_boundaries([2])) == [] + + with pytest.raises(RuntimeError): + list(st.get_boundaries([])) + + with pytest.raises(RuntimeError): + list(st.get_boundaries([0, 4])) # (0, 4) does not exist + + with pytest.raises(RuntimeError): + list(st.get_boundaries([6])) # (6) does not exist -- cgit v1.2.3 From 3a0a4fc525c84dbb64e41e73e4d138c2b873edbe Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 18 Aug 2020 09:32:35 +0200 Subject: Only python 3.8 should be enough to detect issues --- .github/workflows/pip-build-linux.yml | 24 ------------------------ .github/workflows/pip-build-osx.yml | 2 +- .github/workflows/pip-build-windows.yml | 2 +- 3 files changed, 2 insertions(+), 26 deletions(-) diff --git a/.github/workflows/pip-build-linux.yml b/.github/workflows/pip-build-linux.yml index cf41d224..14fdc8d2 100644 --- a/.github/workflows/pip-build-linux.yml +++ b/.github/workflows/pip-build-linux.yml @@ -11,30 +11,6 @@ jobs: - uses: actions/checkout@v1 with: submodules: true - - name: Build wheels for Python 3.5 - run: | - mkdir build_35 - cd build_35 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON35/bin/python .. - cd src/python - $PYTHON35/bin/python setup.py bdist_wheel - auditwheel repair dist/*.whl - - name: Build wheels for Python 3.6 - run: | - mkdir build_36 - cd build_36 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON36/bin/python .. - cd src/python - $PYTHON36/bin/python setup.py bdist_wheel - auditwheel repair dist/*.whl - - name: Build wheels for Python 3.7 - run: | - mkdir build_37 - cd build_37 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON37/bin/python .. - cd src/python - $PYTHON37/bin/python setup.py bdist_wheel - auditwheel repair dist/*.whl - name: Build wheels for Python 3.8 run: | mkdir build_38 diff --git a/.github/workflows/pip-build-osx.yml b/.github/workflows/pip-build-osx.yml index 4af7cd84..15b8880a 100644 --- a/.github/workflows/pip-build-osx.yml +++ b/.github/workflows/pip-build-osx.yml @@ -8,7 +8,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.5', '3.6', '3.7', '3.8'] + python-version: ['3.8'] name: Build wheels for Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/pip-build-windows.yml b/.github/workflows/pip-build-windows.yml index 5119ac0c..11f1ace9 100644 --- a/.github/workflows/pip-build-windows.yml +++ b/.github/workflows/pip-build-windows.yml @@ -8,7 +8,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.5', '3.6', '3.7', '3.8'] + python-version: ['3.8'] name: Build wheels for Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v1 -- cgit v1.2.3 From ddb2118f0af865588d7c14b88171dc04bb27c529 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 18 Aug 2020 14:38:31 +0200 Subject: reset_filtration from a dimension (instead of 'until') --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 31 ++++++++++++++---------- src/Simplex_tree/test/simplex_tree_unit_test.cpp | 14 +++++++---- src/python/gudhi/simplex_tree.pyx | 17 +++++++------ src/python/test/test_simplex_tree.py | 9 ++++--- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index adc8e801..89b4a5df 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1668,31 +1668,36 @@ class Simplex_tree { } public: - /** \brief This function resets filtration value until a given dimension. + /** \brief This function resets filtration value from a given dimension. Resets all the Simplex_tree when + * `min_dim = 0`. * @param[in] filt_value The new filtration value. - * @param[in] max_dim The maximal dimension. + * @param[in] min_dim The minimal dimension. */ - void reset_filtration(Filtration_value filt_value, int max_dim) { + void reset_filtration(Filtration_value filt_value, int min_dim) { for (auto& simplex : root_.members()) { - simplex.second.assign_filtration(filt_value); - if (has_children(&simplex) && max_dim > 0) { - rec_reset_filtration(simplex.second.children(), filt_value, (max_dim - 1)); + if (min_dim <= 0) { + simplex.second.assign_filtration(filt_value); + } + if (has_children(&simplex)) { + rec_reset_filtration(simplex.second.children(), filt_value, min_dim); } } clear_filtration(); // Drop the cache. } private: - /** \brief Recursively resets filtration value until a given dimension. + /** \brief Recursively resets filtration value from a given dimension. * @param[in] sib Siblings to be parsed. * @param[in] filt_value The new filtration value. - * @param[in] max_dim The maximal dimension. + * @param[in] min_dim The maximal dimension. */ - void rec_reset_filtration(Siblings * sib, Filtration_value filt_value, int max_dim) { - for (auto& simplex : sib->members()) { - simplex.second.assign_filtration(filt_value); - if (has_children(&simplex) && max_dim > 0) { - rec_reset_filtration(simplex.second.children(), filt_value, (max_dim - 1)); + void rec_reset_filtration(Siblings * sib, Filtration_value filt_value, int min_dim) { + for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { + if (min_dim <= dimension(sh)) { + sh->second.assign_filtration(filt_value); + } + if (has_children(sh)) { + rec_reset_filtration(sh->second.children(), filt_value, min_dim); } } } diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp index 9780f5b0..bdd41d34 100644 --- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp +++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp @@ -965,21 +965,25 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_reset_filtration, typeST, list_of_tes for (auto vertex : st.simplex_vertex_range(f_simplex)) { std::clog << vertex << ","; } - std::clog << ") - filtration =" << st.filtration(f_simplex) << std::endl; + std::clog << ") - filtration = " << st.filtration(f_simplex); + std::clog << " - dimension = " << st.dimension(f_simplex) << std::endl; + // Guaranteed by construction BOOST_CHECK(st.filtration(f_simplex) >= 2.); } // dimension until 5 even if simplex tree is of dimension 3 to test the limits - for(int dimension = 0; dimension < 6; dimension ++) { + for(int dimension = 5; dimension >= 0; dimension --) { + std::clog << "### reset_filtration - dimension = " << dimension << "\n"; st.reset_filtration(0., dimension); for (auto f_simplex : st.skeleton_simplex_range(3)) { std::clog << "vertex = ("; for (auto vertex : st.simplex_vertex_range(f_simplex)) { std::clog << vertex << ","; } - std::clog << ") - filtration =" << st.filtration(f_simplex) << std::endl; - if (st.dimension(f_simplex) > dimension) - BOOST_CHECK(st.filtration(f_simplex) >= 1.); + std::clog << ") - filtration = " << st.filtration(f_simplex); + std::clog << " - dimension = " << st.dimension(f_simplex) << std::endl; + if (st.dimension(f_simplex) < dimension) + BOOST_CHECK(st.filtration(f_simplex) >= 2.); else BOOST_CHECK(st.filtration(f_simplex) == 0.); } diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index b7682693..657d55be 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -328,7 +328,7 @@ cdef class SimplexTree: return self.get_ptr().prune_above_filtration(filtration) def expansion(self, max_dim): - """Expands the Simplex_tree containing only its one skeleton + """Expands the simplex tree containing only its one skeleton until dimension max_dim. The expanded simplicial complex until dimension :math:`d` @@ -338,7 +338,7 @@ cdef class SimplexTree: The filtration value assigned to a simplex is the maximal filtration value of one of its edges. - The Simplex_tree must contain no simplex of dimension bigger than + The simplex tree must contain no simplex of dimension bigger than 1 when calling the method. :param max_dim: The maximal dimension. @@ -358,15 +358,16 @@ cdef class SimplexTree: """ return self.get_ptr().make_filtration_non_decreasing() - def reset_filtration(self, filtration, max_dim): - """This function resets filtration value until a given dimension. + def reset_filtration(self, filtration, min_dim): + """This function resets filtration value from a given dimension. + Resets all the simplex tree when `min_dim = 0`. :param filtration: New threshold value. :type filtration: float. - :param max_dim: The maximal dimension. + :param max_dim: The minimal dimension. :type max_dim: int. """ - self.get_ptr().reset_filtration(filtration, max_dim) + self.get_ptr().reset_filtration(filtration, min_dim) def extend_filtration(self): """ Extend filtration for computing extended persistence. This function only uses the @@ -376,14 +377,14 @@ cdef class SimplexTree: .. note:: Note that after calling this function, the filtration - values are actually modified within the Simplex_tree. + values are actually modified within the simplex tree. The function :func:`extended_persistence` retrieves the original values. .. note:: Note that this code creates an extra vertex internally, so you should make sure that - the Simplex_tree does not contain a vertex with the largest possible value (i.e., 4294967295). + the simplex tree does not contain a vertex with the largest possible value (i.e., 4294967295). """ self.get_ptr().compute_extended_filtration() diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 6f1d01cc..ac2b59c7 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -367,15 +367,16 @@ def test_reset_filtration(): assert st.insert([3, 4, 5], 3.) == True assert st.insert([0, 1, 6, 7], 4.) == True + # Guaranteed by construction for simplex in st.get_simplices(): - assert st.filtration(simplex[0]) >= 0. + assert st.filtration(simplex[0]) >= 2. # dimension until 5 even if simplex tree is of dimension 3 to test the limits - for dimension in range(0, 6): + for dimension in range(5, -1, -1): st.reset_filtration(0., dimension) for simplex in st.get_skeleton(3): print(simplex) - if len(simplex[0]) > (dimension + 1): - assert st.filtration(simplex[0]) >= 1. + if len(simplex[0]) < (dimension) + 1: + assert st.filtration(simplex[0]) >= 2. else: assert st.filtration(simplex[0]) == 0. -- cgit v1.2.3 From ad7e537f37c93cba6e2b391bf68783359362afa4 Mon Sep 17 00:00:00 2001 From: yuichi-ike Date: Wed, 19 Aug 2020 13:49:27 +0900 Subject: docs modified --- src/python/doc/rips_complex_sum.inc | 22 +++++++++++----------- src/python/doc/rips_complex_user.rst | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/python/doc/rips_complex_sum.inc b/src/python/doc/rips_complex_sum.inc index c123ea2a..2cb24990 100644 --- a/src/python/doc/rips_complex_sum.inc +++ b/src/python/doc/rips_complex_sum.inc @@ -1,14 +1,14 @@ .. table:: :widths: 30 40 30 - +----------------------------------------------------------------+------------------------------------------------------------------------+----------------------------------------------------------------------+ - | .. figure:: | The Vietoris-Rips complex is a simplicial complex built as the | :Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse | - | ../../doc/Rips_complex/rips_complex_representation.png | clique-complex of a proximity graph. | | - | :figclass: align-center | | :Since: GUDHI 2.0.0 | - | | We also provide sparse approximations, to speed-up the computation | | - | | of persistent homology, and weighted versions, which are more robust | :License: MIT | - | | to outliers. | | - | | | | - +----------------------------------------------------------------+------------------------------------------------------------------------+----------------------------------------------------------------------+ - | * :doc:`rips_complex_user` | * :doc:`rips_complex_ref` | - +----------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------+------------------------------------------------------------------------+----------------------------------------------------------------------------------+ + | .. figure:: | The Vietoris-Rips complex is a simplicial complex built as the | :Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse, Yuichi Ike | + | ../../doc/Rips_complex/rips_complex_representation.png | clique-complex of a proximity graph. | | + | :figclass: align-center | | :Since: GUDHI 2.0.0 | + | | We also provide sparse approximations, to speed-up the computation | | + | | of persistent homology, and weighted versions, which are more robust | :License: MIT | + | | to outliers. | | + | | | | + +----------------------------------------------------------------+------------------------------------------------------------------------+----------------------------------------------------------------------------------+ + | * :doc:`rips_complex_user` | * :doc:`rips_complex_ref` | + +----------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/src/python/doc/rips_complex_user.rst b/src/python/doc/rips_complex_user.rst index 6048cc4e..27d218d4 100644 --- a/src/python/doc/rips_complex_user.rst +++ b/src/python/doc/rips_complex_user.rst @@ -7,9 +7,9 @@ Rips complex user manual Definition ---------- -==================================================================== ================================ ====================== -:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse :Since: GUDHI 2.0.0 :License: GPL v3 -==================================================================== ================================ ====================== +================================================================================ ================================ ====================== +:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse, Yuichi Ike :Since: GUDHI 2.0.0 :License: GPL v3 +================================================================================ ================================ ====================== +-------------------------------------------+----------------------------------------------------------------------+ | :doc:`rips_complex_user` | :doc:`rips_complex_ref` | -- cgit v1.2.3 From 6128a88a6780af29825c73af0e32100e93c2f0b5 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 19 Aug 2020 11:34:06 +0200 Subject: python code coverage on python circleci target. Fix language_level cython warning --- .circleci/config.yml | 10 ++++++---- src/python/setup.py.in | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b04efd52..f8dae062 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -57,20 +57,22 @@ jobs: cmake -DUSER_VERSION_DIR=version ..; make user_version; cd version; - 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 ..; + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 .; cd python; python3 setup.py build_ext --inplace; make sphinx; cp -R sphinx /tmp/sphinx; python3 setup.py install; python3 setup.py clean --all; - ctest -j 2 --output-on-failure; + python3 -B -m pytest test/*.py --cov-report html --cov=gudhi; + cp -R htmlcov /tmp/htmlcov; - store_artifacts: path: /tmp/sphinx + - store_artifacts: + path: /tmp/htmlcov + doxygen: docker: - image: gudhi/ci_for_gudhi:latest diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 98d058fc..3602fa42 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -32,7 +32,7 @@ runtime_library_dirs=[@GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS@] # Create ext_modules list from module list ext_modules = [] for module in cython_modules: - ext_modules.append(Extension( + extension = Extension( 'gudhi.' + module, sources = [source_dir + module + '.pyx',], language = 'c++', @@ -41,8 +41,8 @@ for module in cython_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,) + extension.cython_directives = {'language_level': str(sys.version_info[0])} ext_modules = cythonize(ext_modules) -- cgit v1.2.3 From bcad92a18c40b9926b3b25688ab5435c301990df Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 19 Aug 2020 11:40:40 +0200 Subject: need to append --- src/python/setup.py.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 3602fa42..f211f5d2 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -43,6 +43,7 @@ for module in cython_modules: include_dirs=include_dirs, runtime_library_dirs=runtime_library_dirs,) extension.cython_directives = {'language_level': str(sys.version_info[0])} + ext_modules.append(extension) ext_modules = cythonize(ext_modules) -- cgit v1.2.3 From 52cb44a02ad8ce9884db63724ea0a5f1e35c6172 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 19 Aug 2020 12:00:27 +0200 Subject: Try to setup.py clean failure --- .circleci/config.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f8dae062..77fad2ee 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -57,14 +57,16 @@ jobs: cmake -DUSER_VERSION_DIR=version ..; make user_version; cd version; - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 .; + 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; python3 setup.py build_ext --inplace; make sphinx; cp -R sphinx /tmp/sphinx; python3 setup.py install; python3 setup.py clean --all; - python3 -B -m pytest test/*.py --cov-report html --cov=gudhi; + python3 -B -m pytest ../../python/test/*.py --cov-report html --cov=gudhi; cp -R htmlcov /tmp/htmlcov; - store_artifacts: -- cgit v1.2.3 From 4a572af654afc22e2f5c26766f611b1918313509 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 20 Aug 2020 08:15:19 +0200 Subject: Roll back - why cannot clean ? --- .circleci/config.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 77fad2ee..eca9f91e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -66,15 +66,11 @@ jobs: cp -R sphinx /tmp/sphinx; python3 setup.py install; python3 setup.py clean --all; - python3 -B -m pytest ../../python/test/*.py --cov-report html --cov=gudhi; - cp -R htmlcov /tmp/htmlcov; + ctest -j 2 --output-on-failure; - store_artifacts: path: /tmp/sphinx - - store_artifacts: - path: /tmp/htmlcov - doxygen: docker: - image: gudhi/ci_for_gudhi:latest -- cgit v1.2.3 From 37786db094d0251bf070215e89e4446384dbe871 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 20 Aug 2020 09:35:31 +0200 Subject: Let's clean fail --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index eca9f91e..129fdc23 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -57,19 +57,19 @@ jobs: cmake -DUSER_VERSION_DIR=version ..; make user_version; cd version; - 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 ..; + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 .; cd python; python3 setup.py build_ext --inplace; make sphinx; cp -R sphinx /tmp/sphinx; python3 setup.py install; - python3 setup.py clean --all; - ctest -j 2 --output-on-failure; - + python3 setup.py clean --all || true; + python3 -B -m pytest test/*.py --cov-report html --cov=gudhi; + cp -R htmlcov /tmp/htmlcov; - store_artifacts: path: /tmp/sphinx + - store_artifacts: + path: /tmp/htmlcov doxygen: docker: -- cgit v1.2.3 From 151350f85c2799bcb2fde04c6746db7ab7e1ac95 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 20 Aug 2020 10:28:48 +0200 Subject: Add some debug traces and install pytest-cov for code coverage --- .circleci/config.yml | 1 + .github/test-requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 129fdc23..167cb4db 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -64,6 +64,7 @@ jobs: cp -R sphinx /tmp/sphinx; python3 setup.py install; python3 setup.py clean --all || true; + python3 -m pip list python3 -B -m pytest test/*.py --cov-report html --cov=gudhi; cp -R htmlcov /tmp/htmlcov; - store_artifacts: diff --git a/.github/test-requirements.txt b/.github/test-requirements.txt index 98f1007e..7d69c0b9 100644 --- a/.github/test-requirements.txt +++ b/.github/test-requirements.txt @@ -1,4 +1,5 @@ pytest +pytest-cov sphinx sphinxcontrib-bibtex sphinx-paramlinks -- cgit v1.2.3 From 129e85610cfd5a1e3db7f7d656e99915b96a3be5 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 20 Aug 2020 14:17:31 +0200 Subject: Some cleanup. CircleCI docker image build requires update --- .circleci/config.yml | 76 ++++++++++++++++++++++--------------------- Dockerfile_for_circleci_image | 3 ++ 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 167cb4db..285a66a5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,11 +8,11 @@ jobs: - run: name: Build and test examples command: | - mkdir build; - cd build; - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF ..; - make all; - ctest --output-on-failure; + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure tests: docker: @@ -22,11 +22,11 @@ jobs: - run: name: Build and test unitary tests command: | - mkdir build; - cd build; - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF ..; - make all; - ctest --output-on-failure; + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure utils: docker: @@ -36,11 +36,11 @@ jobs: - run: name: Build and test utilities command: | - mkdir build; - cd build; - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=OFF ..; - make all; - ctest --output-on-failure; + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure python: docker: @@ -52,25 +52,26 @@ jobs: command: | git submodule init git submodule update - mkdir build; - cd build; - cmake -DUSER_VERSION_DIR=version ..; - make user_version; - cd version; - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 .; - cd python; - python3 setup.py build_ext --inplace; - make sphinx; - cp -R sphinx /tmp/sphinx; - python3 setup.py install; - python3 setup.py clean --all || true; - python3 -m pip list - python3 -B -m pytest test/*.py --cov-report html --cov=gudhi; - cp -R htmlcov /tmp/htmlcov; + mkdir build + cd build + cmake -DUSER_VERSION_DIR=version .. + make user_version + cd version + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 . + cd python + python3 setup.py build_ext --inplace + make sphinx + cp -R sphinx /tmp/sphinx + python3 setup.py install + python3 setup.py clean --all + python3 -B -m pytest test/*.py --cov-report html --cov=gudhi + cp -R htmlcov /tmp/htmlcov - store_artifacts: path: /tmp/sphinx + destination: sphinx - store_artifacts: path: /tmp/htmlcov + destination: htmlcov doxygen: docker: @@ -82,16 +83,17 @@ jobs: 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 ..; - make doxygen 2>&1 | tee dox.log; - grep warning dox.log; - cp dox.log version/doc/html/; - cp -R version/doc/html /tmp/doxygen; + 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 .. + make doxygen 2>&1 | tee dox.log + grep warning dox.log + cp dox.log version/doc/html/ + cp -R version/doc/html /tmp/doxygen - store_artifacts: path: /tmp/doxygen + destination: doxygen workflows: version: 2 diff --git a/Dockerfile_for_circleci_image b/Dockerfile_for_circleci_image index 464097e7..87f57071 100644 --- a/Dockerfile_for_circleci_image +++ b/Dockerfile_for_circleci_image @@ -23,6 +23,9 @@ ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 +# Update again +RUN apt-get update + # Required for Gudhi compilation RUN apt-get install -y make \ git \ -- cgit v1.2.3 From 3845d669233afda0cb50270e3204c87d2814626f Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 21 Aug 2020 08:11:45 +0200 Subject: Add -DCMAKE_BUILD_TYPE=Release on installation doc --- src/common/doc/installation.h | 10 +++++----- src/python/doc/installation.rst | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index ce2c5448..6af645e2 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -14,13 +14,13 @@ \verbatim cd /path-to-gudhi/ mkdir build cd build/ -cmake .. +cmake -DCMAKE_BUILD_TYPE=Release .. make \endverbatim * By default, examples are disabled. You can activate their compilation with * ccmake (on Linux and Mac OSX), * cmake-gui (on Windows) or by modifying the * cmake command as follows : -\verbatim cmake -DWITH_GUDHI_EXAMPLE=ON .. +\verbatim cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=ON .. make \endverbatim * A list of utilities and examples is available here. * @@ -66,9 +66,9 @@ make doxygen * Some GUDHI modules (cf. \ref main_page "modules list"), and few examples require CGAL, a C++ library that provides * easy access to efficient and reliable geometric algorithms. * - * \note There is no need to install CGAL, you can just cmake . && make CGAL (or even - * cmake -DCGAL_HEADER_ONLY=ON .), thereafter you will be able to compile - * GUDHI by calling cmake -DCGAL_DIR=/your/path/to/CGAL-X.Y .. && make + * \note There is no need to install CGAL, you can just cmake -DCMAKE_BUILD_TYPE=Release . && make CGAL + * (or even cmake -DCMAKE_BUILD_TYPE=Release -DCGAL_HEADER_ONLY=ON .), thereafter you will be able to + * compile GUDHI by calling cmake -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=/your/path/to/CGAL-X.Y .. && make * * The procedure to install this library according to * your operating system is detailed here http://doc.cgal.org/latest/Manual/installation.html diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 78e1af73..4cc31d5c 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -65,7 +65,7 @@ one can build the GUDHI Python module, by running the following commands in a te cd /path-to-gudhi/ mkdir build cd build/ - cmake .. + cmake -DCMAKE_BUILD_TYPE=Release .. cd python make -- cgit v1.2.3 From 34c3812e5c70799a184cec315e7ee9d71c7ad5b7 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 21 Aug 2020 09:56:44 +0200 Subject: Virtual functions need signatures that exactly match --- .../Bitmap_cubical_complex_periodic_boundary_conditions_base.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 18901469..6a18f0eb 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -83,7 +83,7 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c * The boundary elements are guaranteed to be returned so that the * incidence coefficients are alternating. */ - virtual std::vector get_boundary_of_a_cell(std::size_t cell) const; + virtual inline std::vector get_boundary_of_a_cell(std::size_t cell) const; /** * A version of a function that return coboundary of a given cell for an object of @@ -93,7 +93,7 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c * To compute incidence between cells use compute_incidence_between_cells * procedure */ - virtual std::vector get_coboundary_of_a_cell(std::size_t cell) const; + virtual inline std::vector get_coboundary_of_a_cell(std::size_t cell) const; /** * This procedure compute incidence numbers between cubes. For a cube \f$A\f$ of @@ -114,7 +114,7 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c * @exception std::logic_error In case when the cube \f$B\f$ is not n-1 * dimensional face of a cube \f$A\f$. **/ - virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) { + virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) const { // first get the counters for coface and face: std::vector coface_counter = this->compute_counter_for_given_cell(coface); std::vector face_counter = this->compute_counter_for_given_cell(face); -- cgit v1.2.3 From cecacd28febcb6ce3e0a31ee35087f9f65b1cfdf Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 21 Aug 2020 11:47:05 +0200 Subject: Move examples and link to notebook --- src/python/doc/representations.rst | 64 ++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/src/python/doc/representations.rst b/src/python/doc/representations.rst index 041e3247..b0477197 100644 --- a/src/python/doc/representations.rst +++ b/src/python/doc/representations.rst @@ -12,11 +12,45 @@ This module, originally available at https://github.com/MathieuCarriere/sklearn- A diagram is represented as a numpy array of shape (n,2), as can be obtained from :func:`~gudhi.SimplexTree.persistence_intervals_in_dimension` for instance. Points at infinity are represented as a numpy array of shape (n,1), storing only the birth time. The classes in this module can handle several persistence diagrams at once. In that case, the diagrams are provided as a list of numpy arrays. Note that it is not necessary for the diagrams to have the same number of points, i.e., for the corresponding arrays to have the same number of rows: all classes can handle arrays with different shapes. -A small example is provided +Examples +-------- -.. only:: builder_html +Landscapes +^^^^^^^^^^ - * :download:`diagram_vectorizations_distances_kernels.py <../example/diagram_vectorizations_distances_kernels.py>` +This example computes the first two Landscapes associated to a persistence diagram with four points. The landscapes are evaluated on ten samples, leading to two vectors with ten coordinates each, that are eventually concatenated in order to produce a single vector representation. + +.. testcode:: + + import numpy as np + from gudhi.representations import Landscape + # A single diagram with 4 points + D = np.array([[0.,4.],[1.,2.],[3.,8.],[6.,8.]]) + diags = [D] + l=Landscape(num_landscapes=2,resolution=10).fit_transform(diags) + print(l) + +The output is: + +.. testoutput:: + + [[1.02851895 2.05703791 2.57129739 1.54277843 0.89995409 1.92847304 + 2.95699199 3.08555686 2.05703791 1.02851895 0. 0.64282435 + 0. 0. 0.51425948 0. 0. 0. + 0.77138922 1.02851895]] + +Various kernels +^^^^^^^^^^^^^^^ + +This small example is also provided +:download:`diagram_vectorizations_distances_kernels.py <../example/diagram_vectorizations_distances_kernels.py>` + +Machine Learning and Topological Data Analysis +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This `notebook `_ explains how to +efficiently combine machine learning and topological data analysis with the +:doc:`representations module`. Preprocessing @@ -46,27 +80,3 @@ Metrics :members: :special-members: :show-inheritance: - -Basic example -------------- - -This example computes the first two Landscapes associated to a persistence diagram with four points. The landscapes are evaluated on ten samples, leading to two vectors with ten coordinates each, that are eventually concatenated in order to produce a single vector representation. - -.. testcode:: - - import numpy as np - from gudhi.representations import Landscape - # A single diagram with 4 points - D = np.array([[0.,4.],[1.,2.],[3.,8.],[6.,8.]]) - diags = [D] - l=Landscape(num_landscapes=2,resolution=10).fit_transform(diags) - print(l) - -The output is: - -.. testoutput:: - - [[1.02851895 2.05703791 2.57129739 1.54277843 0.89995409 1.92847304 - 2.95699199 3.08555686 2.05703791 1.02851895 0. 0.64282435 - 0. 0. 0.51425948 0. 0. 0. - 0.77138922 1.02851895]] -- cgit v1.2.3 From e17585849c34db7e11b0d1f7278c93a6971335b5 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 21 Aug 2020 12:04:04 +0200 Subject: Add link to extended persistence notebook --- src/python/gudhi/simplex_tree.pyx | 41 ++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index dfb1d985..92645ffc 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -359,37 +359,39 @@ cdef class SimplexTree: return self.get_ptr().make_filtration_non_decreasing() def extend_filtration(self): - """ Extend filtration for computing extended persistence. This function only uses the - filtration values at the 0-dimensional simplices, and computes the extended persistence - diagram induced by the lower-star filtration computed with these values. + """ Extend filtration for computing extended persistence. This function only uses the filtration values at the + 0-dimensional simplices, and computes the extended persistence diagram induced by the lower-star filtration + computed with these values. .. note:: - Note that after calling this function, the filtration - values are actually modified within the Simplex_tree. - The function :func:`extended_persistence` - retrieves the original values. + Note that after calling this function, the filtration values are actually modified within the Simplex_tree. + The function :func:`extended_persistence` retrieves the original values. .. note:: - Note that this code creates an extra vertex internally, so you should make sure that - the Simplex_tree does not contain a vertex with the largest possible value (i.e., 4294967295). + Note that this code creates an extra vertex internally, so you should make sure that the Simplex_tree does + not contain a vertex with the largest possible value (i.e., 4294967295). + + This `notebook `_ + explains how to compute an extension of persistence called extended persistence. """ self.get_ptr().compute_extended_filtration() def extended_persistence(self, homology_coeff_field=11, min_persistence=0): - """This function retrieves good values for extended persistence, and separate the diagrams - into the Ordinary, Relative, Extended+ and Extended- subdiagrams. + """This function retrieves good values for extended persistence, and separate the diagrams into the Ordinary, + Relative, Extended+ and Extended- subdiagrams. - :param homology_coeff_field: The homology coefficient field. Must be a - prime number. Default value is 11. + :param homology_coeff_field: The homology coefficient field. Must be a prime number. Default value is 11. :type homology_coeff_field: int - :param min_persistence: The minimum persistence value (i.e., the absolute value of the difference between the persistence diagram point coordinates) to take into - account (strictly greater than min_persistence). Default value is - 0.0. - Sets min_persistence to -1.0 to see all values. + :param min_persistence: The minimum persistence value (i.e., the absolute value of the difference between the + persistence diagram point coordinates) to take into account (strictly greater than min_persistence). + Default value is 0.0. Sets min_persistence to -1.0 to see all values. :type min_persistence: float - :returns: A list of four persistence diagrams in the format described in :func:`persistence`. The first one is Ordinary, the second one is Relative, the third one is Extended+ and the fourth one is Extended-. See https://link.springer.com/article/10.1007/s10208-008-9027-z and/or section 2.2 in https://link.springer.com/article/10.1007/s10208-017-9370-z for a description of these subtypes. + :returns: A list of four persistence diagrams in the format described in :func:`persistence`. The first one is + Ordinary, the second one is Relative, the third one is Extended+ and the fourth one is Extended-. + See https://link.springer.com/article/10.1007/s10208-008-9027-z and/or section 2.2 in + https://link.springer.com/article/10.1007/s10208-017-9370-z for a description of these subtypes. .. note:: @@ -400,6 +402,9 @@ cdef class SimplexTree: The coordinates of the persistence diagram points might be a little different than the original filtration values due to the internal transformation (scaling to [-2,-1]) that is performed on these values during the computation of extended persistence. + + This `notebook `_ + explains how to compute an extension of persistence called extended persistence. """ cdef vector[pair[int, pair[double, double]]] persistence_result if self.pcohptr != NULL: -- cgit v1.2.3 From e73f832c637bb728270455919133825ca516d929 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 21 Aug 2020 12:09:47 +0200 Subject: Add barycenter notebook link --- src/python/doc/wasserstein_distance_user.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst index 96ec7872..9ffc2759 100644 --- a/src/python/doc/wasserstein_distance_user.rst +++ b/src/python/doc/wasserstein_distance_user.rst @@ -175,3 +175,10 @@ The output is: [[0.27916667 0.55416667] [0.7375 0.7625 ] [0.2375 0.2625 ]] + +Tutorial +******** + +This +`notebook `_ +presents the concept of barycenter, or Fréchet mean, of a family of persistence diagrams. \ No newline at end of file -- cgit v1.2.3 From d33eaa80b7c337fde11bb5db60df79fbc81fb483 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 21 Aug 2020 12:14:24 +0200 Subject: Add link to cubical notebook --- src/python/doc/cubical_complex_user.rst | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/python/doc/cubical_complex_user.rst b/src/python/doc/cubical_complex_user.rst index 3fd4e27a..6a211347 100644 --- a/src/python/doc/cubical_complex_user.rst +++ b/src/python/doc/cubical_complex_user.rst @@ -47,8 +47,8 @@ be a set of two elements). For further details and theory of cubical complexes, please consult :cite:`kaczynski2004computational` as well as the following paper :cite:`peikert2012topological`. -Data structure. ---------------- +Data structure +-------------- The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in :math:`\mathbb{R}^n`. This extra assumption allows for a memory efficient way of storing cubical complexes in a form @@ -77,8 +77,8 @@ Knowing the sizes of the bitmap, by a series of modulo operation, we can determi present in the product that gives the cube :math:`C`. In a similar way, we can compute boundary and the coboundary of each cube. Further details can be found in the literature. -Input Format. -------------- +Input Format +------------ In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users @@ -108,8 +108,8 @@ the program output is: Cubical complex is of dimension 2 - 49 simplices. -Periodic boundary conditions. ------------------------------ +Periodic boundary conditions +---------------------------- Often one would like to impose periodic boundary conditions to the cubical complex (cf. :doc:`periodic_cubical_complex_ref`). @@ -154,7 +154,13 @@ the program output is: Periodic cubical complex is of dimension 2 - 42 simplices. -Examples. ---------- +Examples +-------- End user programs are available in python/example/ folder. + +Tutorial +-------- + +This `notebook `_ +explains how to represent sublevels sets of functions using cubical complexes. \ No newline at end of file -- cgit v1.2.3 From e8cfcc7017f9002a229996232fdb2d03a41d7ea7 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 21 Aug 2020 15:40:17 +0200 Subject: Fix compilation issues when cgal but no eigen --- src/Alpha_complex/example/CMakeLists.txt | 8 ++- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 2 - src/Alpha_complex/test/CMakeLists.txt | 6 +- src/Alpha_complex/utilities/CMakeLists.txt | 4 +- src/Collapse/example/CMakeLists.txt | 41 ++++++++------ .../include/gudhi/Flag_complex_edge_collapser.h | 6 ++ src/Collapse/test/CMakeLists.txt | 16 ++++-- src/Collapse/utilities/CMakeLists.txt | 66 ++++++++++++---------- 8 files changed, 87 insertions(+), 62 deletions(-) diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 2eecd50c..6e231773 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -25,7 +25,7 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_test(NAME Alpha_complex_example_fast_from_off_32 COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" "32.0" "${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_32.txt") -if (DIFF_PATH) + if (DIFF_PATH) # Do not forget to copy test results files in current binary dir file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) file(COPY "alphaoffreader_for_doc_60.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) @@ -43,8 +43,10 @@ if (DIFF_PATH) add_test(Alpha_complex_example_fast_from_off_32_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt) set_tests_properties(Alpha_complex_example_fast_from_off_32_diff_files PROPERTIES DEPENDS Alpha_complex_example_fast_from_off_32) -endif() + endif() + endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) +if (NOT CGAL_VERSION VERSION_LESS 4.11.0) add_executable ( Alpha_complex_example_weighted_3d_from_points Weighted_alpha_complex_3d_from_points.cpp ) target_link_libraries(Alpha_complex_example_weighted_3d_from_points ${CGAL_LIBRARY}) if (TBB_FOUND) @@ -61,4 +63,4 @@ endif() add_test(NAME Alpha_complex_example_3d_from_points COMMAND $) -endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) +endif(NOT CGAL_VERSION VERSION_LESS 4.11.0) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index 2c1b97a4..622b10ee 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -38,8 +38,6 @@ #include #include // for CGAL_VERSION_NR -#include // for EIGEN_VERSION_AT_LEAST - #include #include diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index fe4b23e4..f38bd096 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -18,6 +18,10 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) gudhi_add_boost_test(Alpha_complex_test_unit) gudhi_add_boost_test(Delaunay_complex_test_unit) +endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + +if (NOT CGAL_VERSION VERSION_LESS 4.11.0) + add_executable ( Alpha_complex_3d_test_unit Alpha_complex_3d_unit_test.cpp ) target_link_libraries(Alpha_complex_3d_test_unit ${CGAL_LIBRARY}) add_executable ( Weighted_alpha_complex_3d_test_unit Weighted_alpha_complex_3d_unit_test.cpp ) @@ -38,4 +42,4 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) gudhi_add_boost_test(Periodic_alpha_complex_3d_test_unit) gudhi_add_boost_test(Weighted_periodic_alpha_complex_3d_test_unit) -endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) +endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) diff --git a/src/Alpha_complex/utilities/CMakeLists.txt b/src/Alpha_complex/utilities/CMakeLists.txt index 2ffbdde0..f0ddfc2c 100644 --- a/src/Alpha_complex/utilities/CMakeLists.txt +++ b/src/Alpha_complex/utilities/CMakeLists.txt @@ -27,7 +27,9 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) endif() install(TARGETS alpha_complex_persistence DESTINATION bin) +endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) +if (NOT CGAL_VERSION VERSION_LESS 4.11.0) add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp) target_link_libraries(alpha_complex_3d_persistence ${CGAL_LIBRARY} Boost::program_options) if (TBB_FOUND) @@ -75,4 +77,4 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) install(TARGETS alpha_complex_3d_persistence DESTINATION bin) -endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) +endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) diff --git a/src/Collapse/example/CMakeLists.txt b/src/Collapse/example/CMakeLists.txt index ba0e75e3..4456a844 100644 --- a/src/Collapse/example/CMakeLists.txt +++ b/src/Collapse/example/CMakeLists.txt @@ -1,23 +1,28 @@ project(Edge_collapse_examples) -# Point cloud -add_executable ( Edge_collapse_example_basic edge_collapse_basic_example.cpp ) -if (TBB_FOUND) - target_link_libraries(Edge_collapse_example_basic ${TBB_LIBRARIES}) -endif() +if (NOT EIGEN3_VERSION VERSION_LESS 3.1.0) -add_test(NAME Edge_collapse_example_basic COMMAND $) + # Point cloud + add_executable ( Edge_collapse_example_basic edge_collapse_basic_example.cpp ) + + if (TBB_FOUND) + target_link_libraries(Edge_collapse_example_basic ${TBB_LIBRARIES}) + endif() + + add_test(NAME Edge_collapse_example_basic COMMAND $) + + # Point cloud + add_executable ( Edge_collapse_conserve_persistence edge_collapse_conserve_persistence.cpp ) + + if (TBB_FOUND) + target_link_libraries(Edge_collapse_conserve_persistence ${TBB_LIBRARIES}) + endif() + + add_test(NAME Edge_collapse_conserve_persistence_1 COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "0.2") + + add_test(NAME Edge_collapse_conserve_persistence_2 COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "1.8") -# Point cloud -add_executable ( Edge_collapse_conserve_persistence edge_collapse_conserve_persistence.cpp ) - -if (TBB_FOUND) - target_link_libraries(Edge_collapse_conserve_persistence ${TBB_LIBRARIES}) -endif() - -add_test(NAME Edge_collapse_conserve_persistence_1 COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "0.2") - -add_test(NAME Edge_collapse_conserve_persistence_2 COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "1.8") +endif() \ No newline at end of file diff --git a/src/Collapse/include/gudhi/Flag_complex_edge_collapser.h b/src/Collapse/include/gudhi/Flag_complex_edge_collapser.h index b6b7f7c1..d3aead70 100644 --- a/src/Collapse/include/gudhi/Flag_complex_edge_collapser.h +++ b/src/Collapse/include/gudhi/Flag_complex_edge_collapser.h @@ -18,6 +18,7 @@ #include #include +#include // for EIGEN_VERSION_AT_LEAST #ifdef GUDHI_USE_TBB #include @@ -34,6 +35,11 @@ #include // for std::inserter #include // for std::decay +// Make compilation fail - required for external projects - https://github.com/GUDHI/gudhi-devel/issues/10 +#if !EIGEN_VERSION_AT_LEAST(3,1,0) +# error Alpha_complex is only available for Eigen3 >= 3.1.0 installed with CGAL +#endif + namespace Gudhi { namespace collapse { diff --git a/src/Collapse/test/CMakeLists.txt b/src/Collapse/test/CMakeLists.txt index c7eafb46..c04199e2 100644 --- a/src/Collapse/test/CMakeLists.txt +++ b/src/Collapse/test/CMakeLists.txt @@ -1,9 +1,13 @@ project(Collapse_tests) -include(GUDHI_boost_test) +if (NOT EIGEN3_VERSION VERSION_LESS 3.1.0) -add_executable ( Collapse_test_unit collapse_unit_test.cpp ) -if (TBB_FOUND) - target_link_libraries(Collapse_test_unit ${TBB_LIBRARIES}) -endif() -gudhi_add_boost_test(Collapse_test_unit) + include(GUDHI_boost_test) + + add_executable ( Collapse_test_unit collapse_unit_test.cpp ) + if (TBB_FOUND) + target_link_libraries(Collapse_test_unit ${TBB_LIBRARIES}) + endif() + gudhi_add_boost_test(Collapse_test_unit) + +endif() \ No newline at end of file diff --git a/src/Collapse/utilities/CMakeLists.txt b/src/Collapse/utilities/CMakeLists.txt index c742144b..97fef649 100644 --- a/src/Collapse/utilities/CMakeLists.txt +++ b/src/Collapse/utilities/CMakeLists.txt @@ -1,33 +1,37 @@ project(Collapse_utilities) -# From a point cloud -add_executable ( point_cloud_edge_collapse_rips_persistence point_cloud_edge_collapse_rips_persistence.cpp ) -target_link_libraries(point_cloud_edge_collapse_rips_persistence Boost::program_options) - -if (TBB_FOUND) - target_link_libraries(point_cloud_edge_collapse_rips_persistence ${TBB_LIBRARIES}) -endif() -add_test(NAME Edge_collapse_utilities_point_cloud_rips_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3" "-o" "off_results.pers") - -install(TARGETS point_cloud_edge_collapse_rips_persistence DESTINATION bin) - -# From a distance matrix -add_executable ( distance_matrix_edge_collapse_rips_persistence distance_matrix_edge_collapse_rips_persistence.cpp ) -target_link_libraries(distance_matrix_edge_collapse_rips_persistence Boost::program_options) - -if (TBB_FOUND) - target_link_libraries(distance_matrix_edge_collapse_rips_persistence ${TBB_LIBRARIES}) -endif() -add_test(NAME Edge_collapse_utilities_distance_matrix_rips_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/distance_matrix/tore3D_1307_distance_matrix.csv" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3" "-o" "csv_results.pers") - -install(TARGETS distance_matrix_edge_collapse_rips_persistence DESTINATION bin) - -if (DIFF_PATH) - add_test(Edge_collapse_utilities_diff_persistence ${DIFF_PATH} - "off_results.pers" "csv_results.pers") - set_tests_properties(Edge_collapse_utilities_diff_persistence PROPERTIES DEPENDS - "Edge_collapse_utilities_point_cloud_rips_persistence;Edge_collapse_utilities_distance_matrix_rips_persistence") - -endif() +if (NOT EIGEN3_VERSION VERSION_LESS 3.1.0) + + # From a point cloud + add_executable ( point_cloud_edge_collapse_rips_persistence point_cloud_edge_collapse_rips_persistence.cpp ) + target_link_libraries(point_cloud_edge_collapse_rips_persistence Boost::program_options) + + if (TBB_FOUND) + target_link_libraries(point_cloud_edge_collapse_rips_persistence ${TBB_LIBRARIES}) + endif() + add_test(NAME Edge_collapse_utilities_point_cloud_rips_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3" "-o" "off_results.pers") + + install(TARGETS point_cloud_edge_collapse_rips_persistence DESTINATION bin) + + # From a distance matrix + add_executable ( distance_matrix_edge_collapse_rips_persistence distance_matrix_edge_collapse_rips_persistence.cpp ) + target_link_libraries(distance_matrix_edge_collapse_rips_persistence Boost::program_options) + + if (TBB_FOUND) + target_link_libraries(distance_matrix_edge_collapse_rips_persistence ${TBB_LIBRARIES}) + endif() + add_test(NAME Edge_collapse_utilities_distance_matrix_rips_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/distance_matrix/tore3D_1307_distance_matrix.csv" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3" "-o" "csv_results.pers") + + install(TARGETS distance_matrix_edge_collapse_rips_persistence DESTINATION bin) + + if (DIFF_PATH) + add_test(Edge_collapse_utilities_diff_persistence ${DIFF_PATH} + "off_results.pers" "csv_results.pers") + set_tests_properties(Edge_collapse_utilities_diff_persistence PROPERTIES DEPENDS + "Edge_collapse_utilities_point_cloud_rips_persistence;Edge_collapse_utilities_distance_matrix_rips_persistence") + + endif() + +endif() \ No newline at end of file -- cgit v1.2.3 From d9ae2cb822631d68e4ef1cec7eed0124080c0020 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 24 Aug 2020 09:17:23 +0200 Subject: code review: call boundary_simplex_range only once --- src/python/include/Simplex_tree_interface.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index ab3f13f1..baff3850 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -226,7 +226,8 @@ class Simplex_tree_interface : public Simplex_tree { if (bd_sh == Base::null_simplex()) throw std::runtime_error("simplex not found - cannot find boundaries"); // this specific case works because the range is just a pair of iterators - won't work if range was a vector - return std::make_pair(Base::boundary_simplex_range(bd_sh).begin(), Base::boundary_simplex_range(bd_sh).end()); + auto boundary_srange = Base::boundary_simplex_range(bd_sh); + return std::make_pair(boundary_srange.begin(), boundary_srange.end()); } }; -- cgit v1.2.3 From f424715caab7609085cf155abd98c88674ec329d Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 24 Aug 2020 09:20:02 +0200 Subject: code review: really bad copy/paste... --- src/Collapse/include/gudhi/Flag_complex_edge_collapser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Collapse/include/gudhi/Flag_complex_edge_collapser.h b/src/Collapse/include/gudhi/Flag_complex_edge_collapser.h index d3aead70..713c6608 100644 --- a/src/Collapse/include/gudhi/Flag_complex_edge_collapser.h +++ b/src/Collapse/include/gudhi/Flag_complex_edge_collapser.h @@ -37,7 +37,7 @@ // Make compilation fail - required for external projects - https://github.com/GUDHI/gudhi-devel/issues/10 #if !EIGEN_VERSION_AT_LEAST(3,1,0) -# error Alpha_complex is only available for Eigen3 >= 3.1.0 installed with CGAL +# error Edge Collapse is only available for Eigen3 >= 3.1.0 #endif namespace Gudhi { -- cgit v1.2.3 From 023c4cc8a4fc167a03f9c87f066c80f722c0e520 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 24 Aug 2020 10:12:01 +0200 Subject: code review: override and remove inline --- .../Bitmap_cubical_complex_periodic_boundary_conditions_base.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h index 6a18f0eb..8ac7ae23 100644 --- a/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +++ b/src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h @@ -83,7 +83,7 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c * The boundary elements are guaranteed to be returned so that the * incidence coefficients are alternating. */ - virtual inline std::vector get_boundary_of_a_cell(std::size_t cell) const; + virtual std::vector get_boundary_of_a_cell(std::size_t cell) const override; /** * A version of a function that return coboundary of a given cell for an object of @@ -93,7 +93,7 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c * To compute incidence between cells use compute_incidence_between_cells * procedure */ - virtual inline std::vector get_coboundary_of_a_cell(std::size_t cell) const; + virtual std::vector get_coboundary_of_a_cell(std::size_t cell) const override; /** * This procedure compute incidence numbers between cubes. For a cube \f$A\f$ of @@ -114,7 +114,7 @@ class Bitmap_cubical_complex_periodic_boundary_conditions_base : public Bitmap_c * @exception std::logic_error In case when the cube \f$B\f$ is not n-1 * dimensional face of a cube \f$A\f$. **/ - virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) const { + virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) const override { // first get the counters for coface and face: std::vector coface_counter = this->compute_counter_for_given_cell(coface); std::vector face_counter = this->compute_counter_for_given_cell(face); -- cgit v1.2.3 From 12371aa8ec7693f97200c5b3df3aa20add4ad621 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 25 Aug 2020 08:43:19 +0200 Subject: Code review: min_dim = 0 as default and some doc review --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 9 ++++++--- src/python/gudhi/simplex_tree.pyx | 13 ++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 89b4a5df..9cd51081 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1670,10 +1670,13 @@ class Simplex_tree { public: /** \brief This function resets filtration value from a given dimension. Resets all the Simplex_tree when * `min_dim = 0`. + * `reset_filtration` may break the filtration property with `min_dim > 0`, and it is the user's responsibility to + * make it a valid filtration (using a large enough `filt_value`, or calling `make_filtration_non_decreasing` + * afterwards for instance). * @param[in] filt_value The new filtration value. - * @param[in] min_dim The minimal dimension. + * @param[in] min_dim The minimal dimension. Default value is 0. */ - void reset_filtration(Filtration_value filt_value, int min_dim) { + void reset_filtration(Filtration_value filt_value, int min_dim = 0) { for (auto& simplex : root_.members()) { if (min_dim <= 0) { simplex.second.assign_filtration(filt_value); @@ -1689,7 +1692,7 @@ class Simplex_tree { /** \brief Recursively resets filtration value from a given dimension. * @param[in] sib Siblings to be parsed. * @param[in] filt_value The new filtration value. - * @param[in] min_dim The maximal dimension. + * @param[in] min_dim The minimal dimension. */ void rec_reset_filtration(Siblings * sib, Filtration_value filt_value, int min_dim) { for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 657d55be..f28990cc 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -358,14 +358,17 @@ cdef class SimplexTree: """ return self.get_ptr().make_filtration_non_decreasing() - def reset_filtration(self, filtration, min_dim): - """This function resets filtration value from a given dimension. - Resets all the simplex tree when `min_dim = 0`. + def reset_filtration(self, filtration, min_dim = 0): + """This function resets filtration value from a given dimension. Resets all the simplex tree when + `min_dim = 0`. + `reset_filtration` may break the filtration property with `min_dim > 0`, and it is the user's responsibility to + make it a valid filtration (using a large enough `filt_value`, or calling `make_filtration_non_decreasing` + afterwards for instance). :param filtration: New threshold value. :type filtration: float. - :param max_dim: The minimal dimension. - :type max_dim: int. + :param min_dim: The minimal dimension. Default value is 0. + :type min_dim: int. """ self.get_ptr().reset_filtration(filtration, min_dim) -- cgit v1.2.3 From 723252b311a7989ef1d4271b3a812ec7d0be05f2 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 25 Aug 2020 12:50:22 +0200 Subject: Code review: use minimal depth recursively instead of computing dimension on each loop --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 9cd51081..70ef4c66 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1682,25 +1682,25 @@ class Simplex_tree { simplex.second.assign_filtration(filt_value); } if (has_children(&simplex)) { - rec_reset_filtration(simplex.second.children(), filt_value, min_dim); + rec_reset_filtration(simplex.second.children(), filt_value, min_dim - 1); } } clear_filtration(); // Drop the cache. } private: - /** \brief Recursively resets filtration value from a given dimension. + /** \brief Recursively resets filtration value when minimal depth <= 0. * @param[in] sib Siblings to be parsed. * @param[in] filt_value The new filtration value. - * @param[in] min_dim The minimal dimension. + * @param[in] min_depth The minimal depth. */ - void rec_reset_filtration(Siblings * sib, Filtration_value filt_value, int min_dim) { + void rec_reset_filtration(Siblings * sib, Filtration_value filt_value, int min_depth) { for (auto sh = sib->members().begin(); sh != sib->members().end(); ++sh) { - if (min_dim <= dimension(sh)) { + if (min_depth <= 0) { sh->second.assign_filtration(filt_value); } if (has_children(sh)) { - rec_reset_filtration(sh->second.children(), filt_value, min_dim); + rec_reset_filtration(sh->second.children(), filt_value, min_depth - 1); } } } -- cgit v1.2.3 From 625ff957479c8a37b4ae02bba29dfffc0d3f1a84 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 28 Aug 2020 14:38:28 +0200 Subject: code review: Rollback as these changes does not help --- src/python/setup.py.in | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/python/setup.py.in b/src/python/setup.py.in index f211f5d2..d2708177 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -32,7 +32,7 @@ runtime_library_dirs=[@GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS@] # Create ext_modules list from module list ext_modules = [] for module in cython_modules: - extension = Extension( + ext_modules.append(Extension( 'gudhi.' + module, sources = [source_dir + module + '.pyx',], language = 'c++', @@ -41,9 +41,8 @@ for module in cython_modules: libraries=libraries, library_dirs=library_dirs, include_dirs=include_dirs, - runtime_library_dirs=runtime_library_dirs,) - extension.cython_directives = {'language_level': str(sys.version_info[0])} - ext_modules.append(extension) + runtime_library_dirs=runtime_library_dirs, + cython_directives = {'language_level': str(sys.version_info[0])},)) ext_modules = cythonize(ext_modules) -- cgit v1.2.3 From 4e794277bfa2158ecaeb7e9db303b92ec84a2f3c Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 28 Aug 2020 14:40:22 +0200 Subject: bad identation --- 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 d2708177..98d058fc 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -42,7 +42,7 @@ for module in cython_modules: library_dirs=library_dirs, include_dirs=include_dirs, runtime_library_dirs=runtime_library_dirs, - cython_directives = {'language_level': str(sys.version_info[0])},)) + cython_directives = {'language_level': str(sys.version_info[0])},)) ext_modules = cythonize(ext_modules) -- cgit v1.2.3 From db938dbd74460e7a0fd705be8628984052f71dc0 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 4 Sep 2020 17:23:16 +0200 Subject: Alpha_kernel_d, its tests and Alpha complex to use it --- src/Alpha_complex/example/CMakeLists.txt | 3 + .../example/Weighted_alpha_complex_from_points.cpp | 54 ++++++++ src/Alpha_complex/include/gudhi/Alpha_complex.h | 106 ++++++++-------- .../include/gudhi/Alpha_complex/Alpha_kernel_d.h | 137 +++++++++++++++++++++ .../test/Alpha_kernel_d_unit_test.cpp | 132 ++++++++++++++++++++ src/Alpha_complex/test/CMakeLists.txt | 4 + 6 files changed, 387 insertions(+), 49 deletions(-) create mode 100644 src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp create mode 100644 src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h create mode 100644 src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 2eecd50c..c9b937ed 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -7,10 +7,13 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) target_link_libraries(Alpha_complex_example_from_off ${CGAL_LIBRARY}) add_executable ( Alpha_complex_example_fast_from_off Fast_alpha_complex_from_off.cpp ) target_link_libraries(Alpha_complex_example_fast_from_off ${CGAL_LIBRARY}) + add_executable ( Weighted_alpha_complex_example_from_points Weighted_alpha_complex_from_points.cpp ) + target_link_libraries(Weighted_alpha_complex_example_from_points ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(Alpha_complex_example_from_points ${TBB_LIBRARIES}) target_link_libraries(Alpha_complex_example_from_off ${TBB_LIBRARIES}) target_link_libraries(Alpha_complex_example_fast_from_off ${TBB_LIBRARIES}) + target_link_libraries(Weighted_alpha_complex_example_from_points ${TBB_LIBRARIES}) endif() add_test(NAME Alpha_complex_example_from_points COMMAND $) diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp new file mode 100644 index 00000000..19a04282 --- /dev/null +++ b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp @@ -0,0 +1,54 @@ +#include +// to construct a simplex_tree from alpha complex +#include + +#include + +#include +#include + +// Explicit dimension 2 Epeck_d kernel +using Kernel = CGAL::Epeck_d< CGAL::Dimension_tag<2> >; +using Bare_point = Kernel::Point_d; +using Weighted_point = Kernel::Weighted_point_d; +using Vector_of_points = std::vector; + +int main() { + // ---------------------------------------------------------------------------- + // Init of a list of points + // ---------------------------------------------------------------------------- + Vector_of_points points; + points.push_back(Weighted_point(Bare_point(1.0, 1.0) , 1.)); + points.push_back(Weighted_point(Bare_point(7.0, 0.0) , 1.)); + points.push_back(Weighted_point(Bare_point(4.0, 6.0) , 1.)); + points.push_back(Weighted_point(Bare_point(9.0, 6.0) , 1.)); + points.push_back(Weighted_point(Bare_point(0.0, 14.0), 1.)); + points.push_back(Weighted_point(Bare_point(2.0, 19.0), 1.)); + points.push_back(Weighted_point(Bare_point(9.0, 17.0), 1.)); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from the list of points + // ---------------------------------------------------------------------------- + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_weighted_points(points); + + Gudhi::Simplex_tree<> simplex; + if (alpha_complex_from_weighted_points.create_complex(simplex)) { + // ---------------------------------------------------------------------------- + // Display information about the alpha complex + // ---------------------------------------------------------------------------- + std::clog << "Weighted alpha complex is of dimension " << simplex.dimension() << + " - " << simplex.num_simplices() << " simplices - " << + simplex.num_vertices() << " vertices." << std::endl; + + std::clog << "Iterator on weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : simplex.filtration_simplex_range()) { + std::clog << " ( "; + for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { + std::clog << vertex << " "; + } + std::clog << ") -> " << "[" << simplex.filtration(f_simplex) << "] "; + std::clog << std::endl; + } + } + return 0; +} diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index ba91998d..8e9fe773 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -12,6 +12,7 @@ #ifndef ALPHA_COMPLEX_H_ #define ALPHA_COMPLEX_H_ +#include #include // to construct Alpha_complex from a OFF file of points #include @@ -20,6 +21,7 @@ #include // isnan, fmax #include +#include // aka. Weighted Delaunay triangulation #include // For EXACT or SAFE version #include // For FAST version #include @@ -91,49 +93,55 @@ template struct Is_Epeck_D> { static const bool val * guarantee that the output is a valid filtration (faces have a filtration value no larger than their cofaces). * - For performances reasons, it is advised to use `Alpha_complex` with \ref cgal ≥ 5.0.0. */ -template> +template, bool Weighted = false> class Alpha_complex { public: + /** \brief Geometric traits class that provides the geometric types and predicates needed by the triangulations.*/ + using Geom_traits = typename std::conditional, + Kernel>::type; // Add an int in TDS to save point index in the structure - typedef CGAL::Triangulation_data_structure, - CGAL::Triangulation_full_cell > TDS; - /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ - typedef CGAL::Delaunay_triangulation Delaunay_triangulation; + using TDS = CGAL::Triangulation_data_structure, + CGAL::Triangulation_full_cell >; + /** \brief A (Weighted or not) Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ + using Triangulation = typename std::conditional, + CGAL::Delaunay_triangulation>::type; + + using A_kernel_d = Alpha_kernel_d; + + // Numeric type of coordinates in the kernel + using FT = typename A_kernel_d::FT; + + /** \brief If Weighted, the weighted point is cached (point + weight [= squared radius]), + * else a pair of point and squared radius is cached. + */ + using Sphere = typename A_kernel_d::Sphere; /** \brief A point in Euclidean space.*/ - typedef typename Kernel::Point_d Point_d; - /** \brief Geometric traits class that provides the geometric types and predicates needed by Delaunay - * triangulations.*/ - typedef Kernel Geom_traits; + using Point_d = typename std::conditional::type; private: - typedef typename Kernel::Compute_squared_radius_d Squared_Radius; - typedef typename Kernel::Side_of_bounded_sphere_d Is_Gabriel; - typedef typename Kernel::Point_dimension_d Point_Dimension; - // Vertex_iterator type from CGAL. - typedef typename Delaunay_triangulation::Vertex_iterator CGAL_vertex_iterator; + using CGAL_vertex_iterator = typename Triangulation::Vertex_iterator; // size_type type from CGAL. - typedef typename Delaunay_triangulation::size_type size_type; + using size_type = typename Triangulation::size_type; // Structure to switch from simplex tree vertex handle to CGAL vertex iterator. - typedef typename std::vector< CGAL_vertex_iterator > Vector_vertex_iterator; - - // Numeric type of coordinates in the kernel - typedef typename Kernel::FT FT; + using Vector_vertex_iterator = typename std::vector< CGAL_vertex_iterator >; private: /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator. * Vertex handles are inserted sequentially, starting at 0.*/ Vector_vertex_iterator vertex_handle_to_iterator_; /** \brief Pointer on the CGAL Delaunay triangulation.*/ - Delaunay_triangulation* triangulation_; + Triangulation* triangulation_; /** \brief Kernel for triangulation_ functions access.*/ - Kernel kernel_; + A_kernel_d kernel_; + /** \brief Cache for geometric constructions: circumcenter and squared radius of a simplex.*/ - std::vector> cache_, old_cache_; + std::vector cache_, old_cache_; public: /** \brief Alpha_complex constructor from an OFF file name. @@ -160,10 +168,10 @@ class Alpha_complex { * * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. * - * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d + * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d or Kernel::Weighted_point_d. * * The type InputPointRange must be a range for which std::begin and - * std::end return input iterators on a Kernel::Point_d. + * std::end return input iterators on a Kernel::Point_d or Kernel::Weighted_point_d. */ template Alpha_complex(const InputPointRange& points) @@ -206,11 +214,8 @@ class Alpha_complex { auto last = std::end(points); if (first != last) { - // point_dimension function initialization - Point_Dimension point_dimension = kernel_.point_dimension_d_object(); - - // Delaunay triangulation is point dimension. - triangulation_ = new Delaunay_triangulation(point_dimension(*first)); + // Delaunay triangulation init with point dimension. + triangulation_ = new Triangulation(kernel_.get_dimension(*first)); std::vector point_cloud(first, last); @@ -218,18 +223,22 @@ class Alpha_complex { std::vector indices(boost::counting_iterator(0), boost::counting_iterator(point_cloud.size())); - typedef boost::iterator_property_map::iterator, - CGAL::Identity_property_map> Point_property_map; - typedef CGAL::Spatial_sort_traits_adapter_d Search_traits_d; + using Point_property_map = boost::iterator_property_map::iterator, + CGAL::Identity_property_map>; + using Search_traits_d = CGAL::Spatial_sort_traits_adapter_d; CGAL::spatial_sort(indices.begin(), indices.end(), Search_traits_d(std::begin(point_cloud))); - typename Delaunay_triangulation::Full_cell_handle hint; + typename Triangulation::Full_cell_handle hint; for (auto index : indices) { - typename Delaunay_triangulation::Vertex_handle pos = triangulation_->insert(point_cloud[index], hint); - // Save index value as data to retrieve it after insertion - pos->data() = index; - hint = pos->full_cell(); + typename Triangulation::Vertex_handle pos = triangulation_->insert(point_cloud[index], hint); + if (pos != nullptr) { + // Save index value as data to retrieve it after insertion + pos->data() = index; + hint = pos->full_cell(); + } else { + std::cout << "NULLPTR" << std::endl; + } } // -------------------------------------------------------------------------------------------- // structure to retrieve CGAL points from vertex handle - one vertex handle per point. @@ -270,9 +279,7 @@ class Alpha_complex { v.clear(); for (auto vertex : cplx.simplex_vertex_range(s)) v.push_back(get_point_(vertex)); - Point_d c = kernel_.construct_circumcenter_d_object()(v.cbegin(), v.cend()); - FT r = kernel_.squared_distance_d_object()(c, v[0]); - cache_.emplace_back(std::move(c), std::move(r)); + cache_.emplace_back(kernel_.get_sphere(v.cbegin(), v.cend())); } return cache_[k]; } @@ -282,13 +289,13 @@ class Alpha_complex { auto radius(SimplicialComplexForAlpha& cplx, typename SimplicialComplexForAlpha::Simplex_handle s) { auto k = cplx.key(s); if(k!=cplx.null_key()) - return old_cache_[k].second; + return kernel_.get_squared_radius(old_cache_[k]); // Using a transform_range is slower, currently. thread_local std::vector v; v.clear(); for (auto vertex : cplx.simplex_vertex_range(s)) v.push_back(get_point_(vertex)); - return kernel_.compute_squared_radius_d_object()(v.cbegin(), v.cend()); + return kernel_.get_squared_radius(v.cbegin(), v.cend()); } public: @@ -322,9 +329,9 @@ class Alpha_complex { bool exact = false, bool default_filtration_value = false) { // From SimplicialComplexForAlpha type required to insert into a simplicial complex (with or without subfaces). - typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle; - typedef typename SimplicialComplexForAlpha::Simplex_handle Simplex_handle; - typedef std::vector Vector_vertex; + using Vertex_handle = typename SimplicialComplexForAlpha::Vertex_handle; + using Simplex_handle = typename SimplicialComplexForAlpha::Simplex_handle; + using Vector_vertex = std::vector; if (triangulation_ == nullptr) { std::cerr << "Alpha_complex cannot create_complex from a NULL triangulation\n"; @@ -416,8 +423,8 @@ class Alpha_complex { template void propagate_alpha_filtration(SimplicialComplexForAlpha& complex, Simplex_handle f_simplex) { // From SimplicialComplexForAlpha type required to assign filtration values. - typedef typename SimplicialComplexForAlpha::Filtration_value Filtration_value; - typedef typename SimplicialComplexForAlpha::Vertex_handle Vertex_handle; + using Filtration_value = typename SimplicialComplexForAlpha::Filtration_value; + using Vertex_handle = typename SimplicialComplexForAlpha::Vertex_handle; // ### Foreach Tau face of Sigma for (auto f_boundary : complex.boundary_simplex_range(f_simplex)) { @@ -450,7 +457,8 @@ class Alpha_complex { while(shortiter != enditer && *longiter == *shortiter) { ++longiter; ++shortiter; } Vertex_handle extra = *longiter; auto const& cache=get_cache(complex, f_boundary); - bool is_gab = kernel_.squared_distance_d_object()(cache.first, get_point_(extra)) >= cache.second; + bool is_gab = kernel_.get_squared_distance(kernel_.get_circumcenter(cache), get_point_(extra)) >= + kernel_.get_squared_radius(cache); #ifdef DEBUG_TRACES std::clog << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << extra << std::endl; #endif // DEBUG_TRACES diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h new file mode 100644 index 00000000..87604ec4 --- /dev/null +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -0,0 +1,137 @@ +/* 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) 2020 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#ifndef ALPHA_COMPLEX_ALPHA_KERNEL_D_H_ +#define ALPHA_COMPLEX_ALPHA_KERNEL_D_H_ + +#include // For EXACT or SAFE version +#include // For FAST version +#include // for CGAL_VERSION_NR + +#include // for EIGEN_VERSION_AT_LEAST + +#include // for std::make_pair + +// Make compilation fail - required for external projects - https://github.com/GUDHI/gudhi-devel/issues/10 +#if CGAL_VERSION_NR < 1041101000 +# error Alpha_complex is only available for CGAL >= 4.11 +#endif + +#if !EIGEN_VERSION_AT_LEAST(3,1,0) +# error Alpha_complex is only available for Eigen3 >= 3.1.0 installed with CGAL +#endif + +namespace Gudhi { + +namespace alpha_complex { + +template < typename Kernel, bool Weighted = false > +class Alpha_kernel_d { +}; + +// Unweighted Kernel_d version +template < typename Kernel > +class Alpha_kernel_d { + private: + // Kernel for functions access. + Kernel kernel_; + public: + // Fake type for compilation to succeed (cf. std::conditional in Alpha_complex.h) + using Weighted_point_d = void; + using Point_d = typename Kernel::Point_d; + // Numeric type of coordinates in the kernel + using FT = typename Kernel::FT; + // Sphere is a pair of point and squared radius. + using Sphere = typename std::pair; + + int get_dimension(const Point_d& p0) const { + return kernel_.point_dimension_d_object()(p0); + } + + template + Sphere get_sphere(PointIterator begin, PointIterator end) const { + Point_d c = kernel_.construct_circumcenter_d_object()(begin, end); + FT r = kernel_.squared_distance_d_object()(c, *begin); + return std::make_pair(std::move(c), std::move(r)); + } + + template + FT get_squared_radius(PointIterator begin, PointIterator end) const { + return kernel_.compute_squared_radius_d_object()(begin, end); + } + + FT get_squared_radius(const Sphere& sph) const { + return sph.second; + } + + template + Point get_circumcenter(const Sphere& sph) const { + return sph.first; + } + + template + FT get_squared_distance(const Point& first, const Point& second) const { + return kernel_.squared_distance_d_object()(first, second); + } +}; + +// Weighted Kernel_d version +template < typename Kernel > +class Alpha_kernel_d { + private: + // Kernel for functions access. + Kernel kernel_; + public: + // Fake type for compilation to succeed (cf. std::conditional in Alpha_complex.h) + using Point_d = void; + using Weighted_point_d = typename Kernel::Weighted_point_d; + using Bare_point_d = typename Kernel::Point_d; + // Numeric type of coordinates in the kernel + using FT = typename Kernel::FT; + // Sphere is a weighted point (point + weight [= squared radius]). + using Sphere = Weighted_point_d; + + int get_dimension(const Weighted_point_d& p0) const { + return kernel_.point_dimension_d_object()(p0.point()); + } + + template + Sphere get_sphere(PointIterator begin, PointIterator end) const { + return kernel_.power_center_d_object()(begin, end); + } + + template + FT get_squared_radius(PointIterator begin, PointIterator end) const { + Sphere sph = get_sphere(begin, end); + return sph.weight(); + } + + FT get_squared_radius(const Sphere& sph) const { + return sph.weight(); + } + + template + Point get_circumcenter(const Sphere& sph) const { + return sph.point(); + } + + template + FT get_squared_distance(const Point& first, const Point& second) const { + return kernel_.power_distance_d_object()(first, second); + } +}; + +} // namespace alpha_complex + +namespace alphacomplex = alpha_complex; + +} // namespace Gudhi + +#endif // ALPHA_COMPLEX_ALPHA_KERNEL_D_H_ \ No newline at end of file diff --git a/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp new file mode 100644 index 00000000..70b65aad --- /dev/null +++ b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp @@ -0,0 +1,132 @@ +/* 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) 2020 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "alpha_kernel_d" +#include +#include + +#include +#include +#include + +#include +#include +#include // for std::pair + +#include +#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epeck_d< CGAL::Dynamic_dimension_tag > Exact_kernel_d; +// Use static dimension_tag for the user not to be able to set dimension +typedef CGAL::Epeck_d< CGAL::Dimension_tag<4> > Exact_kernel_s; +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Inexact_kernel_d; +// Use static dimension_tag for the user not to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Inexact_kernel_s; +// The triangulation uses the default instantiation of the TriangulationDataStructure template parameter + +typedef boost::mpl::list list_of_kernel_variants; + +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_dimension, TestedKernel, list_of_kernel_variants) { + Gudhi::alpha_complex::Alpha_kernel_d kernel; + std::vector p0 {0., 1., 2., 3.}; + typename TestedKernel::Point_d p0_d(p0.begin(), p0.end()); + + std::clog << "Dimension is " << kernel.get_dimension(p0_d) << std::endl; + BOOST_CHECK(kernel.get_dimension(p0_d) == 4); + + Gudhi::alpha_complex::Alpha_kernel_d w_kernel; + typename TestedKernel::Weighted_point_d w_p0_d(p0_d, 10.); + + std::clog << "Dimension is " << w_kernel.get_dimension(w_p0_d) << std::endl; + BOOST_CHECK(w_kernel.get_dimension(w_p0_d) == 4); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_sphere, TestedKernel, list_of_kernel_variants) { + using Unweighted_kernel = Gudhi::alpha_complex::Alpha_kernel_d; + // Sphere: (x-1)² + (y-1)² + z² + t² = 1 + // At least 5 points for a 3-sphere + std::vector p0 {1., 0., 0., 0.}; + std::vector p1 {0., 1., 0., 0.}; + std::vector p2 {1., 1., 1., 0.}; + std::vector p3 {1., 1., 0., 1.}; + std::vector p4 {1., 1., -1., 0.}; + + using Point_d = typename Unweighted_kernel::Point_d; + std::vector unw_pts; + unw_pts.push_back(Point_d(p0.begin(), p0.end())); + unw_pts.push_back(Point_d(p1.begin(), p1.end())); + unw_pts.push_back(Point_d(p2.begin(), p2.end())); + unw_pts.push_back(Point_d(p3.begin(), p3.end())); + unw_pts.push_back(Point_d(p4.begin(), p4.end())); + + Unweighted_kernel kernel; + auto unw_sphere = kernel.get_sphere(unw_pts.cbegin(), unw_pts.cend()); + + std::clog << "Center is " << unw_sphere.first << " - squared radius is " << unw_sphere.second << std::endl; + + using Weighted_kernel = Gudhi::alpha_complex::Alpha_kernel_d; + + using Weighted_point_d = typename Weighted_kernel::Weighted_point_d; + using Bare_point_d = typename Weighted_kernel::Bare_point_d; + std::vector w_pts; + w_pts.push_back(Weighted_point_d(Bare_point_d(p0.begin(), p0.end()), 0.)); + w_pts.push_back(Weighted_point_d(Bare_point_d(p1.begin(), p1.end()), 0.)); + w_pts.push_back(Weighted_point_d(Bare_point_d(p2.begin(), p2.end()), 0.)); + w_pts.push_back(Weighted_point_d(Bare_point_d(p3.begin(), p3.end()), 0.)); + w_pts.push_back(Weighted_point_d(Bare_point_d(p4.begin(), p4.end()), 0.)); + + Weighted_kernel w_kernel; + auto w_sphere = w_kernel.get_sphere(w_pts.cbegin(), w_pts.cend()); + + std::clog << "Center is " << w_sphere.point() << " - squared radius is " << w_sphere.weight() << std::endl; + + CGAL::NT_converter cast_to_double; + // The results shall be the same with weights = 0. + GUDHI_TEST_FLOAT_EQUALITY_CHECK(cast_to_double(unw_sphere.second), cast_to_double(w_sphere.weight())); + BOOST_CHECK(unw_sphere.first == w_sphere.point()); + + auto unw_sq_rd = kernel.get_squared_radius(unw_pts.cbegin(), unw_pts.cend()); + std::clog << "Squared radius is " << unw_sq_rd << std::endl; + GUDHI_TEST_FLOAT_EQUALITY_CHECK(cast_to_double(unw_sphere.second), cast_to_double(unw_sq_rd)); + auto w_sq_rd = w_kernel.get_squared_radius(w_pts.cbegin(), w_pts.cend()); + std::clog << "Squared radius is " << w_sq_rd << std::endl; + GUDHI_TEST_FLOAT_EQUALITY_CHECK(cast_to_double(w_sphere.weight()), cast_to_double(w_sq_rd)); +} + + +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_distance, TestedKernel, list_of_kernel_variants) { + using Unweighted_kernel = Gudhi::alpha_complex::Alpha_kernel_d; + + std::vector p0 {1., 0., 0., 0.}; + std::vector p1 {0., 1., 0., 0.}; + + using Point_d = typename Unweighted_kernel::Point_d; + Unweighted_kernel kernel; + auto dist_01 = kernel.get_squared_distance(Point_d(p0.begin(), p0.end()), Point_d(p1.begin(), p1.end())); + std::clog << "Distance is " << dist_01 << std::endl; + + using Weighted_kernel = Gudhi::alpha_complex::Alpha_kernel_d; + + using Weighted_point_d = typename Weighted_kernel::Weighted_point_d; + using Bare_point_d = typename Weighted_kernel::Bare_point_d; + std::vector w_pts; + + Weighted_kernel w_kernel; + auto w_dist_01 = w_kernel.get_squared_distance(Weighted_point_d(Bare_point_d(p0.begin(), p0.end()), 0.), + Weighted_point_d(Bare_point_d(p1.begin(), p1.end()), 0.)); + std::clog << "Distance is " << w_dist_01 << std::endl; + + CGAL::NT_converter cast_to_double; + // The results shall be the same with weights = 0. + GUDHI_TEST_FLOAT_EQUALITY_CHECK(cast_to_double(dist_01), cast_to_double(w_dist_01)); +} diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index fe4b23e4..bd61c0d8 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -10,13 +10,17 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) target_link_libraries(Alpha_complex_test_unit ${CGAL_LIBRARY}) add_executable ( Delaunay_complex_test_unit Delaunay_complex_unit_test.cpp ) target_link_libraries(Delaunay_complex_test_unit ${CGAL_LIBRARY}) + add_executable ( Alpha_kernel_d_test_unit Alpha_kernel_d_unit_test.cpp ) + target_link_libraries(Alpha_kernel_d_test_unit ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(Alpha_complex_test_unit ${TBB_LIBRARIES}) target_link_libraries(Delaunay_complex_test_unit ${TBB_LIBRARIES}) + target_link_libraries(Alpha_kernel_d_test_unit ${TBB_LIBRARIES}) endif() gudhi_add_boost_test(Alpha_complex_test_unit) gudhi_add_boost_test(Delaunay_complex_test_unit) + gudhi_add_boost_test(Alpha_kernel_d_test_unit) add_executable ( Alpha_complex_3d_test_unit Alpha_complex_3d_unit_test.cpp ) target_link_libraries(Alpha_complex_3d_test_unit ${CGAL_LIBRARY}) -- cgit v1.2.3 From 9922407fe6f5d8872522157555c3573e95930ac3 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 7 Sep 2020 10:31:11 +0200 Subject: Fix compilation error and test with 0. weights --- src/Alpha_complex/example/CMakeLists.txt | 4 +++- .../example/Weighted_alpha_complex_from_points.cpp | 14 +++++++------- .../include/gudhi/Alpha_complex/Alpha_kernel_d.h | 11 ++++------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 08eb979e..17dc896c 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -28,6 +28,8 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_test(NAME Alpha_complex_example_fast_from_off_32 COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" "32.0" "${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_32.txt") + add_test(NAME Weighted_alpha_complex_example_from_points COMMAND $) + if (DIFF_PATH) # Do not forget to copy test results files in current binary dir file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) @@ -47,7 +49,7 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) ${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt) set_tests_properties(Alpha_complex_example_fast_from_off_32_diff_files PROPERTIES DEPENDS Alpha_complex_example_fast_from_off_32) endif() - endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) +endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) if (NOT CGAL_VERSION VERSION_LESS 4.11.0) add_executable ( Alpha_complex_example_weighted_3d_from_points Weighted_alpha_complex_3d_from_points.cpp ) diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp index 19a04282..05858084 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp @@ -18,13 +18,13 @@ int main() { // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - points.push_back(Weighted_point(Bare_point(1.0, 1.0) , 1.)); - points.push_back(Weighted_point(Bare_point(7.0, 0.0) , 1.)); - points.push_back(Weighted_point(Bare_point(4.0, 6.0) , 1.)); - points.push_back(Weighted_point(Bare_point(9.0, 6.0) , 1.)); - points.push_back(Weighted_point(Bare_point(0.0, 14.0), 1.)); - points.push_back(Weighted_point(Bare_point(2.0, 19.0), 1.)); - points.push_back(Weighted_point(Bare_point(9.0, 17.0), 1.)); + points.push_back(Weighted_point(Bare_point(1.0, 1.0) , 0.)); + points.push_back(Weighted_point(Bare_point(7.0, 0.0) , 0.)); + points.push_back(Weighted_point(Bare_point(4.0, 6.0) , 0.)); + points.push_back(Weighted_point(Bare_point(9.0, 6.0) , 0.)); + points.push_back(Weighted_point(Bare_point(0.0, 14.0), 0.)); + points.push_back(Weighted_point(Bare_point(2.0, 19.0), 0.)); + points.push_back(Weighted_point(Bare_point(9.0, 17.0), 0.)); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index 87604ec4..a3e3845a 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -71,8 +71,7 @@ class Alpha_kernel_d { return sph.second; } - template - Point get_circumcenter(const Sphere& sph) const { + auto get_circumcenter(const Sphere& sph) const { return sph.first; } @@ -117,13 +116,11 @@ class Alpha_kernel_d { return sph.weight(); } - template - Point get_circumcenter(const Sphere& sph) const { - return sph.point(); + auto get_circumcenter(const Sphere& sph) const { + return sph; } - template - FT get_squared_distance(const Point& first, const Point& second) const { + FT get_squared_distance(const Weighted_point_d& first, const Weighted_point_d& second) const { return kernel_.power_distance_d_object()(first, second); } }; -- cgit v1.2.3 From 05c9c0060ec8ff4cbf8619ff74724c2eea426d84 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Sep 2020 16:43:36 +0200 Subject: CMake > 3.5 to use Boost targets. Compile only what is available from boost targets --- CMakeLists.txt | 2 +- src/Alpha_complex/utilities/CMakeLists.txt | 128 +++++++++++---------- src/Bottleneck_distance/example/CMakeLists.txt | 20 ++-- src/CMakeLists.txt | 2 +- src/Cech_complex/benchmark/CMakeLists.txt | 15 +-- src/Cech_complex/example/CMakeLists.txt | 15 +-- src/Cech_complex/test/CMakeLists.txt | 3 - src/Cech_complex/utilities/CMakeLists.txt | 19 +-- src/Collapse/utilities/CMakeLists.txt | 62 +++++----- src/Persistent_cohomology/benchmark/CMakeLists.txt | 14 ++- src/Persistent_cohomology/example/CMakeLists.txt | 79 +++++++------ src/Rips_complex/utilities/CMakeLists.txt | 67 ++++++----- src/Simplex_tree/example/CMakeLists.txt | 14 ++- src/Witness_complex/utilities/CMakeLists.txt | 36 +++--- src/cmake/modules/GUDHI_modules.cmake | 7 +- .../modules/GUDHI_third_party_libraries.cmake | 39 +------ src/common/doc/installation.h | 8 +- src/python/doc/installation.rst | 2 +- 18 files changed, 267 insertions(+), 265 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b82036b..4257a025 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.5) project(GUDHIdev) diff --git a/src/Alpha_complex/utilities/CMakeLists.txt b/src/Alpha_complex/utilities/CMakeLists.txt index f0ddfc2c..1e7dc1dd 100644 --- a/src/Alpha_complex/utilities/CMakeLists.txt +++ b/src/Alpha_complex/utilities/CMakeLists.txt @@ -1,80 +1,82 @@ project(Alpha_complex_utilities) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - add_executable (alpha_complex_persistence alpha_complex_persistence.cpp) - target_link_libraries(alpha_complex_persistence ${CGAL_LIBRARY} Boost::program_options) + if (TARGET Boost::program_options) + add_executable (alpha_complex_persistence alpha_complex_persistence.cpp) + target_link_libraries(alpha_complex_persistence ${CGAL_LIBRARY} Boost::program_options) - if (TBB_FOUND) - target_link_libraries(alpha_complex_persistence ${TBB_LIBRARIES}) - endif(TBB_FOUND) - add_test(NAME Alpha_complex_utilities_safe_alpha_complex_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "safe.pers") - add_test(NAME Alpha_complex_utilities_fast_alpha_complex_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "fast.pers" "-f") - add_test(NAME Alpha_complex_utilities_exact_alpha_complex_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "exact.pers" "-e") - if (DIFF_PATH) - add_test(Alpha_complex_utilities_diff_exact_alpha_complex ${DIFF_PATH} - "exact.pers" "safe.pers") - set_tests_properties(Alpha_complex_utilities_diff_exact_alpha_complex PROPERTIES DEPENDS - "Alpha_complex_utilities_exact_alpha_complex_persistence;Alpha_complex_utilities_safe_alpha_complex_persistence") - - add_test(Alpha_complex_utilities_diff_fast_alpha_complex ${DIFF_PATH} - "fast.pers" "safe.pers") - set_tests_properties(Alpha_complex_utilities_diff_fast_alpha_complex PROPERTIES DEPENDS - "Alpha_complex_utilities_fast_alpha_complex_persistence;Alpha_complex_utilities_safe_alpha_complex_persistence") + if (TBB_FOUND) + target_link_libraries(alpha_complex_persistence ${TBB_LIBRARIES}) + endif(TBB_FOUND) + add_test(NAME Alpha_complex_utilities_safe_alpha_complex_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "safe.pers") + add_test(NAME Alpha_complex_utilities_fast_alpha_complex_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "fast.pers" "-f") + add_test(NAME Alpha_complex_utilities_exact_alpha_complex_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-p" "2" "-m" "0.45" "-o" "exact.pers" "-e") + if (DIFF_PATH) + add_test(Alpha_complex_utilities_diff_exact_alpha_complex ${DIFF_PATH} + "exact.pers" "safe.pers") + set_tests_properties(Alpha_complex_utilities_diff_exact_alpha_complex PROPERTIES DEPENDS + "Alpha_complex_utilities_exact_alpha_complex_persistence;Alpha_complex_utilities_safe_alpha_complex_persistence") + add_test(Alpha_complex_utilities_diff_fast_alpha_complex ${DIFF_PATH} + "fast.pers" "safe.pers") + set_tests_properties(Alpha_complex_utilities_diff_fast_alpha_complex PROPERTIES DEPENDS + "Alpha_complex_utilities_fast_alpha_complex_persistence;Alpha_complex_utilities_safe_alpha_complex_persistence") + endif() + + install(TARGETS alpha_complex_persistence DESTINATION bin) endif() - - install(TARGETS alpha_complex_persistence DESTINATION bin) endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) if (NOT CGAL_VERSION VERSION_LESS 4.11.0) - add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp) - target_link_libraries(alpha_complex_3d_persistence ${CGAL_LIBRARY} Boost::program_options) - if (TBB_FOUND) - target_link_libraries(alpha_complex_3d_persistence ${TBB_LIBRARIES}) - endif(TBB_FOUND) + if (TARGET Boost::program_options) + add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp) + target_link_libraries(alpha_complex_3d_persistence ${CGAL_LIBRARY} Boost::program_options) + if (TBB_FOUND) + target_link_libraries(alpha_complex_3d_persistence ${TBB_LIBRARIES}) + endif(TBB_FOUND) - add_test(NAME Alpha_complex_utilities_alpha_complex_3d COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" - "-p" "2" "-m" "0.45" "-o" "safe_3d.pers") + add_test(NAME Alpha_complex_utilities_alpha_complex_3d COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" + "-p" "2" "-m" "0.45" "-o" "safe_3d.pers") - add_test(NAME Alpha_complex_utilities_exact_alpha_complex_3d COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" - "-p" "2" "-m" "0.45" "-o" "exact_3d.pers" "-e") + add_test(NAME Alpha_complex_utilities_exact_alpha_complex_3d COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" + "-p" "2" "-m" "0.45" "-o" "exact_3d.pers" "-e") - add_test(NAME Alpha_complex_utilities_fast_alpha_complex_3d COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" - "-p" "2" "-m" "0.45" "-o" "fast_3d.pers" "-f") - - if (DIFF_PATH) - add_test(Alpha_complex_utilities_diff_exact_alpha_complex_3d ${DIFF_PATH} - "exact_3d.pers" "safe_3d.pers") - set_tests_properties(Alpha_complex_utilities_diff_exact_alpha_complex_3d PROPERTIES DEPENDS - "Alpha_complex_utilities_exact_alpha_complex_3d;Alpha_complex_utilities_alpha_complex_3d") - add_test(Alpha_complex_utilities_diff_fast_alpha_complex_3d ${DIFF_PATH} - "fast_3d.pers" "safe_3d.pers") - set_tests_properties(Alpha_complex_utilities_diff_fast_alpha_complex_3d PROPERTIES DEPENDS - "Alpha_complex_utilities_fast_alpha_complex_3d;Alpha_complex_utilities_alpha_complex_3d") - endif() + add_test(NAME Alpha_complex_utilities_fast_alpha_complex_3d COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" + "-p" "2" "-m" "0.45" "-o" "fast_3d.pers" "-f") - add_test(NAME Alpha_complex_utilities_periodic_alpha_complex_3d_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off" - "-c" "${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt" - "-p" "2" "-m" "0") + if (DIFF_PATH) + add_test(Alpha_complex_utilities_diff_exact_alpha_complex_3d ${DIFF_PATH} + "exact_3d.pers" "safe_3d.pers") + set_tests_properties(Alpha_complex_utilities_diff_exact_alpha_complex_3d PROPERTIES DEPENDS + "Alpha_complex_utilities_exact_alpha_complex_3d;Alpha_complex_utilities_alpha_complex_3d") + add_test(Alpha_complex_utilities_diff_fast_alpha_complex_3d ${DIFF_PATH} + "fast_3d.pers" "safe_3d.pers") + set_tests_properties(Alpha_complex_utilities_diff_fast_alpha_complex_3d PROPERTIES DEPENDS + "Alpha_complex_utilities_fast_alpha_complex_3d;Alpha_complex_utilities_alpha_complex_3d") + endif() - add_test(NAME Alpha_complex_utilities_weighted_alpha_complex_3d COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off" - "-w" "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.weights" - "-p" "2" "-m" "0") + add_test(NAME Alpha_complex_utilities_periodic_alpha_complex_3d_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off" + "-c" "${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt" + "-p" "2" "-m" "0") - add_test(NAME Alpha_complex_utilities_weighted_periodic_alpha_complex_3d COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off" - "-w" "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.weights" - "-c" "${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt" - "-p" "2" "-m" "0" "-e") - - install(TARGETS alpha_complex_3d_persistence DESTINATION bin) + add_test(NAME Alpha_complex_utilities_weighted_alpha_complex_3d COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off" + "-w" "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.weights" + "-p" "2" "-m" "0") + add_test(NAME Alpha_complex_utilities_weighted_periodic_alpha_complex_3d COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off" + "-w" "${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.weights" + "-c" "${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt" + "-p" "2" "-m" "0" "-e") + + install(TARGETS alpha_complex_3d_persistence DESTINATION bin) + endif() endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) diff --git a/src/Bottleneck_distance/example/CMakeLists.txt b/src/Bottleneck_distance/example/CMakeLists.txt index 9839c59d..d16ea6e5 100644 --- a/src/Bottleneck_distance/example/CMakeLists.txt +++ b/src/Bottleneck_distance/example/CMakeLists.txt @@ -12,14 +12,16 @@ if (NOT CGAL_VERSION VERSION_LESS 4.11.0) endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - add_executable (alpha_rips_persistence_bottleneck_distance alpha_rips_persistence_bottleneck_distance.cpp) - target_link_libraries(alpha_rips_persistence_bottleneck_distance Boost::program_options) + if (TARGET Boost::program_options) + add_executable (alpha_rips_persistence_bottleneck_distance alpha_rips_persistence_bottleneck_distance.cpp) + target_link_libraries(alpha_rips_persistence_bottleneck_distance Boost::program_options) - if (TBB_FOUND) - target_link_libraries(alpha_rips_persistence_bottleneck_distance ${TBB_LIBRARIES}) - endif(TBB_FOUND) - - add_test(NAME Bottleneck_distance_example_alpha_rips_persistence_bottleneck - COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.15" "-m" "0.12" "-d" "3" "-p" "3") + if (TBB_FOUND) + target_link_libraries(alpha_rips_persistence_bottleneck_distance ${TBB_LIBRARIES}) + endif(TBB_FOUND) + + add_test(NAME Bottleneck_distance_example_alpha_rips_persistence_bottleneck + COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.15" "-m" "0.12" "-d" "3" "-p" "3") + endif() endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e4d78ac..cc230531 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.5) project(GUDHI) diff --git a/src/Cech_complex/benchmark/CMakeLists.txt b/src/Cech_complex/benchmark/CMakeLists.txt index c04bca53..bc54c0f3 100644 --- a/src/Cech_complex/benchmark/CMakeLists.txt +++ b/src/Cech_complex/benchmark/CMakeLists.txt @@ -1,12 +1,13 @@ -cmake_minimum_required(VERSION 2.6) project(Cech_complex_benchmark) # Do not forget to copy test files in current binary dir file(COPY "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) -add_executable(cech_complex_benchmark cech_complex_benchmark.cpp) -target_link_libraries(cech_complex_benchmark Boost::filesystem) - -if (TBB_FOUND) - target_link_libraries(cech_complex_benchmark ${TBB_LIBRARIES}) -endif() +if(TARGET Boost::filesystem) + add_executable(cech_complex_benchmark cech_complex_benchmark.cpp) + target_link_libraries(cech_complex_benchmark Boost::filesystem) + + if (TBB_FOUND) + target_link_libraries(cech_complex_benchmark ${TBB_LIBRARIES}) + endif() +endif() \ No newline at end of file diff --git a/src/Cech_complex/example/CMakeLists.txt b/src/Cech_complex/example/CMakeLists.txt index 98757988..1b08c7cb 100644 --- a/src/Cech_complex/example/CMakeLists.txt +++ b/src/Cech_complex/example/CMakeLists.txt @@ -1,13 +1,14 @@ -cmake_minimum_required(VERSION 2.6) project(Cech_complex_examples) -add_executable ( Cech_complex_example_step_by_step cech_complex_step_by_step.cpp ) -target_link_libraries(Cech_complex_example_step_by_step Boost::program_options) -if (TBB_FOUND) - target_link_libraries(Cech_complex_example_step_by_step ${TBB_LIBRARIES}) +if (TARGET Boost::program_options) + add_executable ( Cech_complex_example_step_by_step cech_complex_step_by_step.cpp ) + target_link_libraries(Cech_complex_example_step_by_step Boost::program_options) + if (TBB_FOUND) + target_link_libraries(Cech_complex_example_step_by_step ${TBB_LIBRARIES}) + endif() + add_test(NAME Cech_complex_utility_from_rips_on_tore_3D COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-r" "0.25" "-d" "3") endif() -add_test(NAME Cech_complex_utility_from_rips_on_tore_3D COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-r" "0.25" "-d" "3") add_executable ( Cech_complex_example_from_points cech_complex_example_from_points.cpp) if (TBB_FOUND) diff --git a/src/Cech_complex/test/CMakeLists.txt b/src/Cech_complex/test/CMakeLists.txt index db510af3..e6a2a18f 100644 --- a/src/Cech_complex/test/CMakeLists.txt +++ b/src/Cech_complex/test/CMakeLists.txt @@ -1,6 +1,3 @@ -cmake_minimum_required(VERSION 2.6) -project(Cech_complex_tests) - include(GUDHI_boost_test) add_executable ( Cech_complex_test_unit test_cech_complex.cpp ) diff --git a/src/Cech_complex/utilities/CMakeLists.txt b/src/Cech_complex/utilities/CMakeLists.txt index 253d7304..b183c8d8 100644 --- a/src/Cech_complex/utilities/CMakeLists.txt +++ b/src/Cech_complex/utilities/CMakeLists.txt @@ -1,14 +1,15 @@ -cmake_minimum_required(VERSION 2.6) project(Cech_complex_utilities) -add_executable(cech_persistence cech_persistence.cpp) -target_link_libraries(cech_persistence Boost::program_options) +if (TARGET Boost::program_options) + add_executable(cech_persistence cech_persistence.cpp) + target_link_libraries(cech_persistence Boost::program_options) -if (TBB_FOUND) - target_link_libraries(cech_persistence ${TBB_LIBRARIES}) -endif() + if (TBB_FOUND) + target_link_libraries(cech_persistence ${TBB_LIBRARIES}) + endif() -add_test(NAME Cech_complex_utility_from_rips_on_tore_3D COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3") + add_test(NAME Cech_complex_utility_from_rips_on_tore_3D COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3") -install(TARGETS cech_persistence DESTINATION bin) + install(TARGETS cech_persistence DESTINATION bin) +endif() \ No newline at end of file diff --git a/src/Collapse/utilities/CMakeLists.txt b/src/Collapse/utilities/CMakeLists.txt index 97fef649..bce99e90 100644 --- a/src/Collapse/utilities/CMakeLists.txt +++ b/src/Collapse/utilities/CMakeLists.txt @@ -1,37 +1,37 @@ project(Collapse_utilities) if (NOT EIGEN3_VERSION VERSION_LESS 3.1.0) - - # From a point cloud - add_executable ( point_cloud_edge_collapse_rips_persistence point_cloud_edge_collapse_rips_persistence.cpp ) - target_link_libraries(point_cloud_edge_collapse_rips_persistence Boost::program_options) - - if (TBB_FOUND) - target_link_libraries(point_cloud_edge_collapse_rips_persistence ${TBB_LIBRARIES}) - endif() - add_test(NAME Edge_collapse_utilities_point_cloud_rips_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3" "-o" "off_results.pers") - - install(TARGETS point_cloud_edge_collapse_rips_persistence DESTINATION bin) - - # From a distance matrix - add_executable ( distance_matrix_edge_collapse_rips_persistence distance_matrix_edge_collapse_rips_persistence.cpp ) - target_link_libraries(distance_matrix_edge_collapse_rips_persistence Boost::program_options) - - if (TBB_FOUND) - target_link_libraries(distance_matrix_edge_collapse_rips_persistence ${TBB_LIBRARIES}) - endif() - add_test(NAME Edge_collapse_utilities_distance_matrix_rips_persistence COMMAND $ - "${CMAKE_SOURCE_DIR}/data/distance_matrix/tore3D_1307_distance_matrix.csv" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3" "-o" "csv_results.pers") - - install(TARGETS distance_matrix_edge_collapse_rips_persistence DESTINATION bin) - - if (DIFF_PATH) - add_test(Edge_collapse_utilities_diff_persistence ${DIFF_PATH} - "off_results.pers" "csv_results.pers") - set_tests_properties(Edge_collapse_utilities_diff_persistence PROPERTIES DEPENDS - "Edge_collapse_utilities_point_cloud_rips_persistence;Edge_collapse_utilities_distance_matrix_rips_persistence") - + if (TARGET Boost::program_options) + # From a point cloud + add_executable ( point_cloud_edge_collapse_rips_persistence point_cloud_edge_collapse_rips_persistence.cpp ) + target_link_libraries(point_cloud_edge_collapse_rips_persistence Boost::program_options) + + if (TBB_FOUND) + target_link_libraries(point_cloud_edge_collapse_rips_persistence ${TBB_LIBRARIES}) + endif() + add_test(NAME Edge_collapse_utilities_point_cloud_rips_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3" "-o" "off_results.pers") + + install(TARGETS point_cloud_edge_collapse_rips_persistence DESTINATION bin) + + # From a distance matrix + add_executable ( distance_matrix_edge_collapse_rips_persistence distance_matrix_edge_collapse_rips_persistence.cpp ) + target_link_libraries(distance_matrix_edge_collapse_rips_persistence Boost::program_options) + + if (TBB_FOUND) + target_link_libraries(distance_matrix_edge_collapse_rips_persistence ${TBB_LIBRARIES}) + endif() + add_test(NAME Edge_collapse_utilities_distance_matrix_rips_persistence COMMAND $ + "${CMAKE_SOURCE_DIR}/data/distance_matrix/tore3D_1307_distance_matrix.csv" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3" "-o" "csv_results.pers") + + install(TARGETS distance_matrix_edge_collapse_rips_persistence DESTINATION bin) + + if (DIFF_PATH) + add_test(Edge_collapse_utilities_diff_persistence ${DIFF_PATH} + "off_results.pers" "csv_results.pers") + set_tests_properties(Edge_collapse_utilities_diff_persistence PROPERTIES DEPENDS + "Edge_collapse_utilities_point_cloud_rips_persistence;Edge_collapse_utilities_distance_matrix_rips_persistence") + endif() endif() endif() \ No newline at end of file diff --git a/src/Persistent_cohomology/benchmark/CMakeLists.txt b/src/Persistent_cohomology/benchmark/CMakeLists.txt index f38cc543..ad8dc84b 100644 --- a/src/Persistent_cohomology/benchmark/CMakeLists.txt +++ b/src/Persistent_cohomology/benchmark/CMakeLists.txt @@ -2,11 +2,13 @@ project(Persistent_cohomology_benchmark) if(GMP_FOUND) if(GMPXX_FOUND) - add_executable ( performance_rips_persistence EXCLUDE_FROM_ALL performance_rips_persistence.cpp ) - target_link_libraries(performance_rips_persistence Boost::program_options ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) - if (TBB_FOUND) - target_link_libraries(performance_rips_persistence ${TBB_LIBRARIES}) - endif(TBB_FOUND) - file(COPY "${CMAKE_SOURCE_DIR}/data/points/Kl.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + if (TARGET Boost::program_options) + add_executable ( performance_rips_persistence EXCLUDE_FROM_ALL performance_rips_persistence.cpp ) + target_link_libraries(performance_rips_persistence Boost::program_options ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) + if (TBB_FOUND) + target_link_libraries(performance_rips_persistence ${TBB_LIBRARIES}) + endif(TBB_FOUND) + file(COPY "${CMAKE_SOURCE_DIR}/data/points/Kl.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) + endif() endif(GMPXX_FOUND) endif(GMP_FOUND) diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 4c08cd68..d6a92ed6 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -1,46 +1,58 @@ project(Persistent_cohomology_examples) add_executable(plain_homology plain_homology.cpp) +if (TBB_FOUND) + target_link_libraries(plain_homology ${TBB_LIBRARIES}) +endif() +add_test(NAME Persistent_cohomology_example_plain_homology COMMAND $) +install(TARGETS plain_homology DESTINATION bin) add_executable(persistence_from_simple_simplex_tree persistence_from_simple_simplex_tree.cpp) - -add_executable(rips_persistence_step_by_step rips_persistence_step_by_step.cpp) -target_link_libraries(rips_persistence_step_by_step Boost::program_options) - -add_executable(rips_persistence_via_boundary_matrix rips_persistence_via_boundary_matrix.cpp) -target_link_libraries(rips_persistence_via_boundary_matrix Boost::program_options) - -add_executable(persistence_from_file persistence_from_file.cpp) -target_link_libraries(persistence_from_file Boost::program_options) - if (TBB_FOUND) - target_link_libraries(plain_homology ${TBB_LIBRARIES}) target_link_libraries(persistence_from_simple_simplex_tree ${TBB_LIBRARIES}) - target_link_libraries(rips_persistence_step_by_step ${TBB_LIBRARIES}) - target_link_libraries(rips_persistence_via_boundary_matrix ${TBB_LIBRARIES}) - target_link_libraries(persistence_from_file ${TBB_LIBRARIES}) endif() - -add_test(NAME Persistent_cohomology_example_plain_homology COMMAND $) add_test(NAME Persistent_cohomology_example_from_simple_simplex_tree COMMAND $ "1" "0") -add_test(NAME Persistent_cohomology_example_from_rips_step_by_step_on_tore_3D COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3") -add_test(NAME Persistent_cohomology_example_via_boundary_matrix COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/Kl.off" "-r" "0.16" "-d" "3" "-p" "3" "-m" "100") -add_test(NAME Persistent_cohomology_example_from_file_3_2_0 COMMAND $ - "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc" "-p" "2" "-m" "0") -add_test(NAME Persistent_cohomology_example_from_file_3_3_100 COMMAND $ - "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc" "-p" "3" "-m" "100") - -install(TARGETS plain_homology DESTINATION bin) install(TARGETS persistence_from_simple_simplex_tree DESTINATION bin) -install(TARGETS rips_persistence_step_by_step DESTINATION bin) -install(TARGETS rips_persistence_via_boundary_matrix DESTINATION bin) -install(TARGETS persistence_from_file DESTINATION bin) + +if(TARGET Boost::program_options) + add_executable(rips_persistence_step_by_step rips_persistence_step_by_step.cpp) + target_link_libraries(rips_persistence_step_by_step Boost::program_options) + if (TBB_FOUND) + target_link_libraries(rips_persistence_step_by_step ${TBB_LIBRARIES}) + endif() + add_test(NAME Persistent_cohomology_example_from_rips_step_by_step_on_tore_3D COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3") + install(TARGETS rips_persistence_step_by_step DESTINATION bin) +endif() + +if(TARGET Boost::program_options) + add_executable(rips_persistence_via_boundary_matrix rips_persistence_via_boundary_matrix.cpp) + target_link_libraries(rips_persistence_via_boundary_matrix Boost::program_options) + if (TBB_FOUND) + target_link_libraries(rips_persistence_via_boundary_matrix ${TBB_LIBRARIES}) + endif() + add_test(NAME Persistent_cohomology_example_via_boundary_matrix COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/Kl.off" "-r" "0.16" "-d" "3" "-p" "3" "-m" "100") + install(TARGETS rips_persistence_via_boundary_matrix DESTINATION bin) +endif() + +if(TARGET Boost::program_options) + add_executable(persistence_from_file persistence_from_file.cpp) + target_link_libraries(persistence_from_file Boost::program_options) + if (TBB_FOUND) + target_link_libraries(persistence_from_file ${TBB_LIBRARIES}) + endif() + add_test(NAME Persistent_cohomology_example_from_file_3_2_0 COMMAND $ + "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc" "-p" "2" "-m" "0") + add_test(NAME Persistent_cohomology_example_from_file_3_3_100 COMMAND $ + "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc" "-p" "3" "-m" "100") + install(TARGETS persistence_from_file DESTINATION bin) +endif() if(GMP_FOUND) - if(GMPXX_FOUND) + if(GMPXX_FOUND) + if(TARGET Boost::program_options) add_executable(rips_multifield_persistence rips_multifield_persistence.cpp ) target_link_libraries(rips_multifield_persistence Boost::program_options ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) @@ -50,19 +62,16 @@ if(GMP_FOUND) add_test(NAME Persistent_cohomology_example_multifield_2_71 COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "2" "-q" "71") install(TARGETS rips_multifield_persistence DESTINATION bin) - endif(GMPXX_FOUND) + endif() + endif(GMPXX_FOUND) endif(GMP_FOUND) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - add_executable(custom_persistence_sort custom_persistence_sort.cpp) target_link_libraries(custom_persistence_sort ${CGAL_LIBRARY}) - if (TBB_FOUND) target_link_libraries(custom_persistence_sort ${TBB_LIBRARIES}) endif(TBB_FOUND) add_test(NAME Persistent_cohomology_example_custom_persistence_sort COMMAND $) - install(TARGETS custom_persistence_sort DESTINATION bin) - endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/Rips_complex/utilities/CMakeLists.txt b/src/Rips_complex/utilities/CMakeLists.txt index d2448d7b..2081f142 100644 --- a/src/Rips_complex/utilities/CMakeLists.txt +++ b/src/Rips_complex/utilities/CMakeLists.txt @@ -1,34 +1,45 @@ project(Rips_complex_utilities) -add_executable(rips_distance_matrix_persistence rips_distance_matrix_persistence.cpp) -target_link_libraries(rips_distance_matrix_persistence Boost::program_options) - -add_executable(rips_persistence rips_persistence.cpp) -target_link_libraries(rips_persistence Boost::program_options) - -add_executable(rips_correlation_matrix_persistence rips_correlation_matrix_persistence.cpp) -target_link_libraries(rips_correlation_matrix_persistence Boost::system Boost::program_options) - -add_executable(sparse_rips_persistence sparse_rips_persistence.cpp) -target_link_libraries(sparse_rips_persistence Boost::program_options) +if(TARGET Boost::program_options) + add_executable(rips_distance_matrix_persistence rips_distance_matrix_persistence.cpp) + target_link_libraries(rips_distance_matrix_persistence Boost::program_options) + if (TBB_FOUND) + target_link_libraries(rips_distance_matrix_persistence ${TBB_LIBRARIES}) + endif() + add_test(NAME Rips_complex_utility_from_rips_distance_matrix COMMAND $ + "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" "-r" "1.0" "-d" "3" "-p" "3" "-m" "0") + install(TARGETS rips_distance_matrix_persistence DESTINATION bin) +endif() -if (TBB_FOUND) - target_link_libraries(rips_distance_matrix_persistence ${TBB_LIBRARIES}) - target_link_libraries(rips_persistence ${TBB_LIBRARIES}) - target_link_libraries(rips_correlation_matrix_persistence ${TBB_LIBRARIES}) - target_link_libraries(sparse_rips_persistence ${TBB_LIBRARIES}) +if(TARGET Boost::program_options) + add_executable(rips_persistence rips_persistence.cpp) + target_link_libraries(rips_persistence Boost::program_options) + if (TBB_FOUND) + target_link_libraries(rips_persistence ${TBB_LIBRARIES}) + endif() + add_test(NAME Rips_complex_utility_from_rips_on_tore_3D COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3") + install(TARGETS rips_persistence DESTINATION bin) endif() -add_test(NAME Rips_complex_utility_from_rips_distance_matrix COMMAND $ - "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" "-r" "1.0" "-d" "3" "-p" "3" "-m" "0") -add_test(NAME Rips_complex_utility_from_rips_on_tore_3D COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3") -add_test(NAME Rips_complex_utility_from_rips_correlation_matrix COMMAND $ - "${CMAKE_SOURCE_DIR}/data/correlation_matrix/lower_triangular_correlation_matrix.csv" "-c" "0.3" "-d" "3" "-p" "3" "-m" "0") -add_test(NAME Sparse_rips_complex_utility_on_tore_3D COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-e" "0.5" "-m" "0.2" "-d" "3" "-p" "2") +if(TARGET Boost::program_options) + add_executable(rips_correlation_matrix_persistence rips_correlation_matrix_persistence.cpp) + target_link_libraries(rips_correlation_matrix_persistence Boost::system Boost::program_options) + if (TBB_FOUND) + target_link_libraries(rips_correlation_matrix_persistence ${TBB_LIBRARIES}) + endif() + add_test(NAME Rips_complex_utility_from_rips_correlation_matrix COMMAND $ + "${CMAKE_SOURCE_DIR}/data/correlation_matrix/lower_triangular_correlation_matrix.csv" "-c" "0.3" "-d" "3" "-p" "3" "-m" "0") + install(TARGETS rips_correlation_matrix_persistence DESTINATION bin) +endif() -install(TARGETS rips_distance_matrix_persistence DESTINATION bin) -install(TARGETS rips_persistence DESTINATION bin) -install(TARGETS rips_correlation_matrix_persistence DESTINATION bin) -install(TARGETS sparse_rips_persistence DESTINATION bin) +if(TARGET Boost::program_options) + add_executable(sparse_rips_persistence sparse_rips_persistence.cpp) + target_link_libraries(sparse_rips_persistence Boost::program_options) + if (TBB_FOUND) + target_link_libraries(sparse_rips_persistence ${TBB_LIBRARIES}) + endif() + add_test(NAME Sparse_rips_complex_utility_on_tore_3D COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "-e" "0.5" "-m" "0.2" "-d" "3" "-p" "2") + install(TARGETS sparse_rips_persistence DESTINATION bin) +endif() diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt index a0aabee2..73b2c6f9 100644 --- a/src/Simplex_tree/example/CMakeLists.txt +++ b/src/Simplex_tree/example/CMakeLists.txt @@ -34,13 +34,15 @@ if(GMP_FOUND AND NOT CGAL_VERSION VERSION_LESS 4.11.0) endif() if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - add_executable ( Simplex_tree_example_cech_complex_cgal_mini_sphere_3d cech_complex_cgal_mini_sphere_3d.cpp ) - target_link_libraries(Simplex_tree_example_cech_complex_cgal_mini_sphere_3d Boost::program_options ${CGAL_LIBRARY}) - if (TBB_FOUND) - target_link_libraries(Simplex_tree_example_cech_complex_cgal_mini_sphere_3d ${TBB_LIBRARIES}) + if(TARGET Boost::program_options) + add_executable ( Simplex_tree_example_cech_complex_cgal_mini_sphere_3d cech_complex_cgal_mini_sphere_3d.cpp ) + target_link_libraries(Simplex_tree_example_cech_complex_cgal_mini_sphere_3d Boost::program_options ${CGAL_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(Simplex_tree_example_cech_complex_cgal_mini_sphere_3d ${TBB_LIBRARIES}) + endif() + add_test(NAME Simplex_tree_example_cech_complex_cgal_mini_sphere_3d COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" -r 0.3 -d 3) endif() - add_test(NAME Simplex_tree_example_cech_complex_cgal_mini_sphere_3d COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" -r 0.3 -d 3) endif () add_executable ( Simplex_tree_example_graph_expansion_with_blocker graph_expansion_with_blocker.cpp ) diff --git a/src/Witness_complex/utilities/CMakeLists.txt b/src/Witness_complex/utilities/CMakeLists.txt index d986d2d1..60fea0b4 100644 --- a/src/Witness_complex/utilities/CMakeLists.txt +++ b/src/Witness_complex/utilities/CMakeLists.txt @@ -2,26 +2,26 @@ project(Witness_complex_utilities) # 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_strong_witness_persistence strong_witness_persistence.cpp ) - target_link_libraries(Witness_complex_strong_witness_persistence Boost::program_options) + if(TARGET Boost::program_options) + add_executable ( Witness_complex_strong_witness_persistence strong_witness_persistence.cpp ) + target_link_libraries(Witness_complex_strong_witness_persistence Boost::program_options) - add_executable ( Witness_complex_weak_witness_persistence weak_witness_persistence.cpp ) - target_link_libraries(Witness_complex_weak_witness_persistence Boost::program_options) + add_executable ( Witness_complex_weak_witness_persistence weak_witness_persistence.cpp ) + target_link_libraries(Witness_complex_weak_witness_persistence Boost::program_options) - if (TBB_FOUND) - target_link_libraries(Witness_complex_strong_witness_persistence ${TBB_LIBRARIES}) - target_link_libraries(Witness_complex_weak_witness_persistence ${TBB_LIBRARIES}) - endif() - - add_test(NAME Witness_complex_strong_test_torus_persistence - COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-l" "20" "-a" "0.5") - add_test(NAME Witness_complex_weak_test_torus_persistence - COMMAND $ - "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-l" "20" "-a" "0.5") + if (TBB_FOUND) + target_link_libraries(Witness_complex_strong_witness_persistence ${TBB_LIBRARIES}) + target_link_libraries(Witness_complex_weak_witness_persistence ${TBB_LIBRARIES}) + endif() - install(TARGETS Witness_complex_strong_witness_persistence DESTINATION bin) - install(TARGETS Witness_complex_weak_witness_persistence DESTINATION bin) + add_test(NAME Witness_complex_strong_test_torus_persistence + COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-l" "20" "-a" "0.5") + add_test(NAME Witness_complex_weak_test_torus_persistence + COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-l" "20" "-a" "0.5") + install(TARGETS Witness_complex_strong_witness_persistence DESTINATION bin) + install(TARGETS Witness_complex_weak_witness_persistence DESTINATION bin) + endif() endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/cmake/modules/GUDHI_modules.cmake b/src/cmake/modules/GUDHI_modules.cmake index aab1dd08..ccaf1ac5 100644 --- a/src/cmake/modules/GUDHI_modules.cmake +++ b/src/cmake/modules/GUDHI_modules.cmake @@ -30,7 +30,12 @@ if (WITH_GUDHI_EXAMPLE) set(GUDHI_SUB_DIRECTORIES "${GUDHI_SUB_DIRECTORIES};example") endif() if (WITH_GUDHI_TEST) - set(GUDHI_SUB_DIRECTORIES "${GUDHI_SUB_DIRECTORIES};test") + # All tests are using boost tests + if(TARGET Boost::unit_test_framework) + set(GUDHI_SUB_DIRECTORIES "${GUDHI_SUB_DIRECTORIES};test") + else() + message("++ WITH_GUDHI_TEST but no TARGET Boost::unit_test_framework") + endif() endif() if (WITH_GUDHI_UTILITIES) set(GUDHI_SUB_DIRECTORIES "${GUDHI_SUB_DIRECTORIES};utilities") diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index a56a2756..489f3de5 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -1,42 +1,11 @@ # This files manage third party libraries required by GUDHI -find_package(Boost 1.56.0 REQUIRED COMPONENTS system filesystem unit_test_framework program_options thread) +find_package(Boost 1.56.0 QUIET OPTIONAL_COMPONENTS system thread filesystem unit_test_framework program_options) -if(NOT Boost_FOUND) +# Boost_FOUND is not reliable +if(NOT Boost_VERSION) message(FATAL_ERROR "NOTICE: This program requires Boost and will not be compiled.") -endif(NOT Boost_FOUND) - -# cf. https://cliutils.gitlab.io/modern-cmake/chapters/packages/Boost.html -# This is needed if your Boost version is newer than your CMake version -# or if you have an old version of CMake (<3.5) -if(NOT TARGET Boost::program_options) - add_library(Boost::program_options IMPORTED INTERFACE) - set_property(TARGET Boost::program_options PROPERTY - INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR}) - set_property(TARGET Boost::program_options PROPERTY - INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES}) -endif() -if(NOT TARGET Boost::filesystem) - add_library(Boost::filesystem IMPORTED INTERFACE) - set_property(TARGET Boost::filesystem PROPERTY - INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR}) - set_property(TARGET Boost::filesystem PROPERTY - INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES}) -endif() -if(NOT TARGET Boost::unit_test_framework) - add_library(Boost::unit_test_framework IMPORTED INTERFACE) - set_property(TARGET Boost::unit_test_framework PROPERTY - INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR}) - set_property(TARGET Boost::unit_test_framework PROPERTY - INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES}) -endif() -if(NOT TARGET Boost::system) - add_library(Boost::system IMPORTED INTERFACE) - set_property(TARGET Boost::system PROPERTY - INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR}) - set_property(TARGET Boost::system PROPERTY - INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES}) -endif() +endif(NOT Boost_VERSION) find_package(GMP) if(GMP_FOUND) diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index 6af645e2..9df1c2f0 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -6,7 +6,7 @@ * * \section compiling Compiling * The library uses c++14 and requires Boost ≥ 1.56.0 - * and CMake ≥ 3.1. + * and CMake ≥ 3.5. * It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015. * * \subsection utilities Utilities and examples @@ -17,8 +17,8 @@ cd build/ cmake -DCMAKE_BUILD_TYPE=Release .. make \endverbatim * By default, examples are disabled. You can activate their compilation with - * ccmake (on Linux and Mac OSX), - * cmake-gui (on Windows) or by modifying the + * ccmake (on Linux and Mac OSX), + * cmake-gui (on Windows) or by modifying the * cmake command as follows : \verbatim cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=ON .. make \endverbatim @@ -28,7 +28,7 @@ make \endverbatim * To install the library (headers and activated utilities), run the following command in a terminal: * \verbatim make install \endverbatim * This action may require to be in the sudoer or administrator of the machine in function of the operating system and - * of CMAKE_INSTALL_PREFIX. + * of CMAKE_INSTALL_PREFIX. * * \subsection testsuites Test suites * To test your build, run the following command in a terminal: diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 4cc31d5c..2f161d66 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -40,7 +40,7 @@ different, and in particular the `python/` subdirectory is actually `src/python/ there. The library uses c++14 and requires `Boost `_ :math:`\geq` 1.56.0, -`CMake `_ :math:`\geq` 3.1 to generate makefiles, +`CMake `_ :math:`\geq` 3.5 to generate makefiles, `NumPy `_, `Cython `_ and `pybind11 `_ to compile the GUDHI Python module. -- cgit v1.2.3 From e213f44cdf0b2e2cfa854789c5f14cbb5cb4ec96 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Sep 2020 17:51:26 +0200 Subject: Remove boost::system --- src/Rips_complex/utilities/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rips_complex/utilities/CMakeLists.txt b/src/Rips_complex/utilities/CMakeLists.txt index 2081f142..d8c8e0b8 100644 --- a/src/Rips_complex/utilities/CMakeLists.txt +++ b/src/Rips_complex/utilities/CMakeLists.txt @@ -24,7 +24,7 @@ endif() if(TARGET Boost::program_options) add_executable(rips_correlation_matrix_persistence rips_correlation_matrix_persistence.cpp) - target_link_libraries(rips_correlation_matrix_persistence Boost::system Boost::program_options) + target_link_libraries(rips_correlation_matrix_persistence Boost::program_options) if (TBB_FOUND) target_link_libraries(rips_correlation_matrix_persistence ${TBB_LIBRARIES}) endif() -- cgit v1.2.3 From c09f54487cc88eeb3afe1629ff8a3edc223df1eb Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 9 Sep 2020 11:17:02 +0200 Subject: Even if CGAL was requiring boost::thread no need to find it for gudhi. boost::thread removed from cgal on https://github.com/CGAL/cgal/commit/8a7d3fa --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 489f3de5..1fbc4244 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -1,6 +1,6 @@ # This files manage third party libraries required by GUDHI -find_package(Boost 1.56.0 QUIET OPTIONAL_COMPONENTS system thread filesystem unit_test_framework program_options) +find_package(Boost 1.56.0 QUIET OPTIONAL_COMPONENTS filesystem unit_test_framework program_options) # Boost_FOUND is not reliable if(NOT Boost_VERSION) -- cgit v1.2.3 From 58d79c972198938c6f3655a40540903e08242b36 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 9 Sep 2020 17:37:01 +0200 Subject: Use cgal 5.1 as only boost header only --- Dockerfile_for_pip | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Dockerfile_for_pip b/Dockerfile_for_pip index 8f60e37c..98668a04 100644 --- a/Dockerfile_for_pip +++ b/Dockerfile_for_pip @@ -14,23 +14,24 @@ RUN mkdir -p /opt/cmake \ && sh cmake-3.16.2-Linux-x86_64.sh --skip-license --prefix=/opt/cmake \ && rm -f cmake-3.16.2-Linux-x86_64.sh -RUN git clone -b boost-1.73.0 --depth 1 https://github.com/boostorg/boost.git \ - && cd boost \ - && git submodule update --init \ - && ./bootstrap.sh --with-libraries=filesystem,program_options,system,thread,test \ - && ./b2 headers \ - && ./b2 install \ +# yum install boost-devel installs boost 1.53 and copy is the only way to install headers only boost +RUN wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz \ + && tar xf boost_1_73_0.tar.gz \ + && cd boost_1_73_0 \ + && ./bootstrap.sh \ + && ls \ + && cp -r boost /usr/local/include/ \ && cd .. \ && rm -rf boost -RUN wget https://github.com/CGAL/cgal/releases/download/releases%2FCGAL-5.0.2/CGAL-5.0.2.tar.xz \ - && tar xf CGAL-5.0.2.tar.xz \ +RUN wget https://github.com/CGAL/cgal/releases/download/v5.1/CGAL-5.1.tar.xz \ + && tar xf CGAL-5.1.tar.xz \ && mkdir build \ && cd build \ - && /opt/cmake/bin/cmake -DCMAKE_BUILD_TYPE=Release ../CGAL-5.0.2/ \ + && /opt/cmake/bin/cmake -DCMAKE_BUILD_TYPE=Release ../CGAL-5.1/ \ && make install \ && cd .. \ - && rm -rf build CGAL-5.0.2 + && rm -rf build CGAL-5.1 ADD .github/build-requirements.txt / -- cgit v1.2.3 From 171ddab9b7a50f0303d7201fa547dbfb445f9698 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 11 Sep 2020 11:55:55 +0200 Subject: Requires CGAL >= 5.1. Fix is_gabriel computation --- src/Alpha_complex/example/CMakeLists.txt | 14 +++++++++----- .../example/Weighted_alpha_complex_from_points.cpp | 14 +++++++------- src/Alpha_complex/include/gudhi/Alpha_complex.h | 8 ++++++-- .../include/gudhi/Alpha_complex/Alpha_kernel_d.h | 17 ++++------------- src/Alpha_complex/test/CMakeLists.txt | 13 +++++++++---- 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt index 17dc896c..1fc2330a 100644 --- a/src/Alpha_complex/example/CMakeLists.txt +++ b/src/Alpha_complex/example/CMakeLists.txt @@ -7,13 +7,10 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) target_link_libraries(Alpha_complex_example_from_off ${CGAL_LIBRARY}) add_executable ( Alpha_complex_example_fast_from_off Fast_alpha_complex_from_off.cpp ) target_link_libraries(Alpha_complex_example_fast_from_off ${CGAL_LIBRARY}) - add_executable ( Weighted_alpha_complex_example_from_points Weighted_alpha_complex_from_points.cpp ) - target_link_libraries(Weighted_alpha_complex_example_from_points ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(Alpha_complex_example_from_points ${TBB_LIBRARIES}) target_link_libraries(Alpha_complex_example_from_off ${TBB_LIBRARIES}) target_link_libraries(Alpha_complex_example_fast_from_off ${TBB_LIBRARIES}) - target_link_libraries(Weighted_alpha_complex_example_from_points ${TBB_LIBRARIES}) endif() add_test(NAME Alpha_complex_example_from_points COMMAND $) @@ -28,8 +25,6 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_test(NAME Alpha_complex_example_fast_from_off_32 COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" "32.0" "${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_32.txt") - add_test(NAME Weighted_alpha_complex_example_from_points COMMAND $) - if (DIFF_PATH) # Do not forget to copy test results files in current binary dir file(COPY "alphaoffreader_for_doc_32.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) @@ -69,3 +64,12 @@ if (NOT CGAL_VERSION VERSION_LESS 4.11.0) COMMAND $) endif(NOT CGAL_VERSION VERSION_LESS 4.11.0) + +if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) + add_executable ( Weighted_alpha_complex_example_from_points Weighted_alpha_complex_from_points.cpp ) + target_link_libraries(Weighted_alpha_complex_example_from_points ${CGAL_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(Weighted_alpha_complex_example_from_points ${TBB_LIBRARIES}) + endif() + add_test(NAME Weighted_alpha_complex_example_from_points COMMAND $) +endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp index 05858084..19a04282 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp @@ -18,13 +18,13 @@ int main() { // Init of a list of points // ---------------------------------------------------------------------------- Vector_of_points points; - points.push_back(Weighted_point(Bare_point(1.0, 1.0) , 0.)); - points.push_back(Weighted_point(Bare_point(7.0, 0.0) , 0.)); - points.push_back(Weighted_point(Bare_point(4.0, 6.0) , 0.)); - points.push_back(Weighted_point(Bare_point(9.0, 6.0) , 0.)); - points.push_back(Weighted_point(Bare_point(0.0, 14.0), 0.)); - points.push_back(Weighted_point(Bare_point(2.0, 19.0), 0.)); - points.push_back(Weighted_point(Bare_point(9.0, 17.0), 0.)); + points.push_back(Weighted_point(Bare_point(1.0, 1.0) , 1.)); + points.push_back(Weighted_point(Bare_point(7.0, 0.0) , 1.)); + points.push_back(Weighted_point(Bare_point(4.0, 6.0) , 1.)); + points.push_back(Weighted_point(Bare_point(9.0, 6.0) , 1.)); + points.push_back(Weighted_point(Bare_point(0.0, 14.0), 1.)); + points.push_back(Weighted_point(Bare_point(2.0, 19.0), 1.)); + points.push_back(Weighted_point(Bare_point(9.0, 17.0), 1.)); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 8e9fe773..4316d9bc 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -210,6 +210,11 @@ class Alpha_complex { << std::endl; #endif +#if CGAL_VERSION_NR < 1050101000 + // Make compilation fail if weighted and CGAL < 5.1 + static_assert(!Weighted, "Weighted Alpha_complex is only available for CGAL >= 5.1"); +#endif + auto first = std::begin(points); auto last = std::end(points); @@ -457,8 +462,7 @@ class Alpha_complex { while(shortiter != enditer && *longiter == *shortiter) { ++longiter; ++shortiter; } Vertex_handle extra = *longiter; auto const& cache=get_cache(complex, f_boundary); - bool is_gab = kernel_.get_squared_distance(kernel_.get_circumcenter(cache), get_point_(extra)) >= - kernel_.get_squared_radius(cache); + bool is_gab = kernel_.is_gabriel(cache, get_point_(extra)); #ifdef DEBUG_TRACES std::clog << " | Tau is_gabriel(Sigma)=" << is_gab << " - vertexForGabriel=" << extra << std::endl; #endif // DEBUG_TRACES diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index a3e3845a..b64e4f59 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -71,13 +71,8 @@ class Alpha_kernel_d { return sph.second; } - auto get_circumcenter(const Sphere& sph) const { - return sph.first; - } - - template - FT get_squared_distance(const Point& first, const Point& second) const { - return kernel_.squared_distance_d_object()(first, second); + bool is_gabriel(const Sphere& circumcenter, const Point_d& point) { + return kernel_.squared_distance_d_object()(circumcenter.first, point) >= circumcenter.second; } }; @@ -116,12 +111,8 @@ class Alpha_kernel_d { return sph.weight(); } - auto get_circumcenter(const Sphere& sph) const { - return sph; - } - - FT get_squared_distance(const Weighted_point_d& first, const Weighted_point_d& second) const { - return kernel_.power_distance_d_object()(first, second); + bool is_gabriel(const Sphere& circumcenter, const Weighted_point_d& point) { + return kernel_.power_distance_d_object()(circumcenter, point) >= 0; } }; diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 71e4ea7c..837d2948 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -10,17 +10,13 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) target_link_libraries(Alpha_complex_test_unit ${CGAL_LIBRARY}) add_executable ( Delaunay_complex_test_unit Delaunay_complex_unit_test.cpp ) target_link_libraries(Delaunay_complex_test_unit ${CGAL_LIBRARY}) - add_executable ( Alpha_kernel_d_test_unit Alpha_kernel_d_unit_test.cpp ) - target_link_libraries(Alpha_kernel_d_test_unit ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(Alpha_complex_test_unit ${TBB_LIBRARIES}) target_link_libraries(Delaunay_complex_test_unit ${TBB_LIBRARIES}) - target_link_libraries(Alpha_kernel_d_test_unit ${TBB_LIBRARIES}) endif() gudhi_add_boost_test(Alpha_complex_test_unit) gudhi_add_boost_test(Delaunay_complex_test_unit) - gudhi_add_boost_test(Alpha_kernel_d_test_unit) endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) @@ -47,3 +43,12 @@ if (NOT CGAL_VERSION VERSION_LESS 4.11.0) gudhi_add_boost_test(Weighted_periodic_alpha_complex_3d_test_unit) endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) + +if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) + add_executable ( Alpha_kernel_d_test_unit Alpha_kernel_d_unit_test.cpp ) + target_link_libraries(Alpha_kernel_d_test_unit ${CGAL_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(Alpha_kernel_d_test_unit ${TBB_LIBRARIES}) + endif() + gudhi_add_boost_test(Alpha_kernel_d_test_unit) +endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) \ No newline at end of file -- cgit v1.2.3 From d299e943d6fd07a58a270fe685dac7b5d5d23964 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 11 Sep 2020 14:35:39 +0200 Subject: fonction was renamed between 5.1 and 5.2 --- .../include/gudhi/Alpha_complex/Alpha_kernel_d.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index b64e4f59..a4824207 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -82,6 +82,7 @@ class Alpha_kernel_d { private: // Kernel for functions access. Kernel kernel_; + public: // Fake type for compilation to succeed (cf. std::conditional in Alpha_complex.h) using Point_d = void; @@ -98,7 +99,13 @@ class Alpha_kernel_d { template Sphere get_sphere(PointIterator begin, PointIterator end) const { + // power_center_d_object has been renamed between CGAL 5.1 and 5.2 +#if defined CGAL_VERSION_NR >= 1050101000 && defined CGAL_VERSION_NR < 1050201000 return kernel_.power_center_d_object()(begin, end); +#endif +#if CGAL_VERSION_NR >= 1050201000 + return kernel_.construct_power_sphere_d_object()(begin, end); +#endif } template @@ -112,7 +119,13 @@ class Alpha_kernel_d { } bool is_gabriel(const Sphere& circumcenter, const Weighted_point_d& point) { + // power_center_d_object has been renamed between CGAL 5.1 and 5.2 +#if defined CGAL_VERSION_NR >= 1050101000 && defined CGAL_VERSION_NR < 1050201000 return kernel_.power_distance_d_object()(circumcenter, point) >= 0; +#endif +#if CGAL_VERSION_NR >= 1050201000 + return kernel_.compute_power_product_d_object()(circumcenter, point) >= 0; +#endif } }; -- cgit v1.2.3 From 54e0cec31e556c88d9f8107394ad972883fdbbdf Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 11 Sep 2020 17:41:39 +0200 Subject: Add weighted ctor and its test --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 26 +++++++ src/Alpha_complex/test/CMakeLists.txt | 8 +++ .../test/Weighted_alpha_complex_unit_test.cpp | 82 ++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 4316d9bc..00231e1c 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -31,6 +31,10 @@ #include // for EIGEN_VERSION_AT_LEAST +#include +#include +#include + #include #include #include @@ -179,6 +183,28 @@ class Alpha_complex { init_from_range(points); } + /** \brief Alpha_complex constructor from a list of points and weights. + * + * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. + * + * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d or Kernel::Weighted_point_d. + * + * @param[in] weights Range of points weights. Weights must be in Kernel::FT. + * + * The type InputPointRange must be a range for which std::begin and + * std::end return input iterators on a Kernel::Point_d. + */ + template + Alpha_complex(const InputPointRange& points, WeightRange weights) { + static_assert(Weighted, "This constructor is not available for non-weighted versions of Alpha_complex_3d"); + // FIXME: this test is only valid if we have a forward range + GUDHI_CHECK(boost::size(weights) == boost::size(points), + std::invalid_argument("Points number in range different from weights range number")); + auto weighted_points = boost::range::combine(points, weights) + | boost::adaptors::transformed([](auto const&t){return Point_d(boost::get<0>(t), boost::get<1>(t));}); + init_from_range(weighted_points); + } + /** \brief Alpha_complex destructor deletes the Delaunay triangulation. */ ~Alpha_complex() { diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt index 837d2948..db5d840f 100644 --- a/src/Alpha_complex/test/CMakeLists.txt +++ b/src/Alpha_complex/test/CMakeLists.txt @@ -51,4 +51,12 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) target_link_libraries(Alpha_kernel_d_test_unit ${TBB_LIBRARIES}) endif() gudhi_add_boost_test(Alpha_kernel_d_test_unit) + + add_executable ( Weighted_alpha_complex_test_unit Weighted_alpha_complex_unit_test.cpp ) + target_link_libraries(Weighted_alpha_complex_test_unit ${CGAL_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(Weighted_alpha_complex_test_unit ${TBB_LIBRARIES}) + endif() + gudhi_add_boost_test(Weighted_alpha_complex_test_unit) + endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) \ No newline at end of file diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp new file mode 100644 index 00000000..b4fc76de --- /dev/null +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -0,0 +1,82 @@ +/* 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) 2020 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "weighted_alpha_complex" +#include +#include + +#include +#include + +#include // float comparison +#include +#include + +#include +#include +#include + +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epeck_d< CGAL::Dynamic_dimension_tag > Exact_kernel_d; +// Use static dimension_tag for the user not to be able to set dimension +typedef CGAL::Epeck_d< CGAL::Dimension_tag<4> > Exact_kernel_s; +// Use dynamic_dimension_tag for the user to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Inexact_kernel_d; +// Use static dimension_tag for the user not to be able to set dimension +typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Inexact_kernel_s; +// The triangulation uses the default instantiation of the TriangulationDataStructure template parameter + +typedef boost::mpl::list list_of_kernel_variants; + +BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_kernel_variants) { + // Random points construction + using Point_d = typename Kernel::Point_d; + std::vector points; + std::uniform_real_distribution rd_pts(-10., 10.); + std::random_device rand_dev; + std::mt19937 rand_engine(rand_dev()); + for (int idx = 0; idx < 20; idx++) { + std::vector point {rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine)}; + points.emplace_back(Point_d(point.begin(), point.end())); + } + + // Alpha complex from points + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); + Gudhi::Simplex_tree<> simplex; + BOOST_CHECK(alpha_complex_from_points.create_complex(simplex)); + std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : simplex.filtration_simplex_range()) { + std::clog << " ( "; + for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { + std::clog << vertex << " "; + } + std::clog << ") -> " << "[" << simplex.filtration(f_simplex) << "] "; + std::clog << std::endl; + } + + // Alpha complex from zero weighted points + std::vector weights(20, 0.); + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_zero_weighted_points(points, weights); + Gudhi::Simplex_tree<> zw_simplex; + BOOST_CHECK(alpha_complex_from_zero_weighted_points.create_complex(zw_simplex)); + + std::clog << "Iterator on zero weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : zw_simplex.filtration_simplex_range()) { + std::clog << " ( "; + for (auto vertex : zw_simplex.simplex_vertex_range(f_simplex)) { + std::clog << vertex << " "; + } + std::clog << ") -> " << "[" << zw_simplex.filtration(f_simplex) << "] "; + std::clog << std::endl; + } + + BOOST_CHECK(zw_simplex == simplex); +} \ No newline at end of file -- cgit v1.2.3 From 5e3871c2d99249bd7560faa4e1229d3b3751b0ff Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 14 Sep 2020 11:17:40 +0200 Subject: alpha_complex_persistence utils can use weighted points. Update Alpha_kernel_d_unit_test to work --- .../test/Alpha_kernel_d_unit_test.cpp | 28 ------ .../test/Weighted_alpha_complex_unit_test.cpp | 2 +- .../utilities/alpha_complex_persistence.cpp | 101 ++++++++++++++++----- src/Alpha_complex/utilities/alphacomplex.md | 7 ++ 4 files changed, 84 insertions(+), 54 deletions(-) diff --git a/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp index 70b65aad..192834b3 100644 --- a/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp @@ -102,31 +102,3 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_sphere, TestedKernel, list_of_kerne std::clog << "Squared radius is " << w_sq_rd << std::endl; GUDHI_TEST_FLOAT_EQUALITY_CHECK(cast_to_double(w_sphere.weight()), cast_to_double(w_sq_rd)); } - - -BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_distance, TestedKernel, list_of_kernel_variants) { - using Unweighted_kernel = Gudhi::alpha_complex::Alpha_kernel_d; - - std::vector p0 {1., 0., 0., 0.}; - std::vector p1 {0., 1., 0., 0.}; - - using Point_d = typename Unweighted_kernel::Point_d; - Unweighted_kernel kernel; - auto dist_01 = kernel.get_squared_distance(Point_d(p0.begin(), p0.end()), Point_d(p1.begin(), p1.end())); - std::clog << "Distance is " << dist_01 << std::endl; - - using Weighted_kernel = Gudhi::alpha_complex::Alpha_kernel_d; - - using Weighted_point_d = typename Weighted_kernel::Weighted_point_d; - using Bare_point_d = typename Weighted_kernel::Bare_point_d; - std::vector w_pts; - - Weighted_kernel w_kernel; - auto w_dist_01 = w_kernel.get_squared_distance(Weighted_point_d(Bare_point_d(p0.begin(), p0.end()), 0.), - Weighted_point_d(Bare_point_d(p1.begin(), p1.end()), 0.)); - std::clog << "Distance is " << w_dist_01 << std::endl; - - CGAL::NT_converter cast_to_double; - // The results shall be the same with weights = 0. - GUDHI_TEST_FLOAT_EQUALITY_CHECK(cast_to_double(dist_01), cast_to_double(w_dist_01)); -} diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index b4fc76de..57a57058 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -32,7 +33,6 @@ typedef CGAL::Epeck_d< CGAL::Dimension_tag<4> > Exact_kernel_s; typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Inexact_kernel_d; // Use static dimension_tag for the user not to be able to set dimension typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Inexact_kernel_s; -// The triangulation uses the default instantiation of the TriangulationDataStructure template parameter typedef boost::mpl::list list_of_kernel_variants; diff --git a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp index e17831d9..e86b34e2 100644 --- a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp +++ b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp @@ -17,19 +17,82 @@ #include // to construct a simplex_tree from alpha complex #include +#include #include #include #include // for numeric_limits +#include +#include using Simplex_tree = Gudhi::Simplex_tree<>; using Filtration_value = Simplex_tree::Filtration_value; void program_options(int argc, char *argv[], std::string &off_file_points, bool &exact, bool &fast, - std::string &output_file_diag, Filtration_value &alpha_square_max_value, + std::string &weight_file, std::string &output_file_diag, Filtration_value &alpha_square_max_value, int &coeff_field_characteristic, Filtration_value &min_persistence); +template +std::vector read_off(const std::string &off_file_points) { + Gudhi::Points_off_reader off_reader(off_file_points); + if (!off_reader.is_valid()) { + std::cerr << "Alpha_complex - Unable to read file " << off_file_points << "\n"; + exit(-1); // ----- >> + } + return off_reader.get_point_cloud(); +} + +std::vector read_weight_file(const std::string &weight_file) { + std::vector weights; + // Read weights information from file + std::ifstream weights_ifstr(weight_file); + if (weights_ifstr.good()) { + double weight = 0.0; + // Attempt read the weight in a double format, return false if it fails + while (weights_ifstr >> weight) { + weights.push_back(weight); + } + } else { + std::cerr << "Unable to read weights file " << weight_file << std::endl; + exit(-1); + } + return weights; +} + +template +Simplex_tree create_simplex_tree(const std::string &off_file_points, const std::string &weight_file, + bool exact_version, Filtration_value alpha_square_max_value) { + Simplex_tree stree; + auto points = read_off(off_file_points); + + if (weight_file != std::string()) { + std::vector weights = read_weight_file(weight_file); + if (points.size() != weights.size()) { + std::cerr << "Alpha_complex - Inconsistency between number of points (" << points.size() + << ") and number of weights (" << weights.size() << ")" << "\n"; + exit(-1); // ----- >> + } + // Init of an alpha complex from an OFF file + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(points, weights); + + if (!alpha_complex_from_file.create_complex(stree, alpha_square_max_value, exact_version)) { + std::cerr << "Alpha complex simplicial complex creation failed." << std::endl; + exit(-1); + } + } else { + // Init of an alpha complex from an OFF file + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(points); + + if (!alpha_complex_from_file.create_complex(stree, alpha_square_max_value, exact_version)) { + std::cerr << "Alpha complex simplicial complex creation failed." << std::endl; + exit(-1); + } + } + return stree; +} + int main(int argc, char **argv) { + std::string weight_file; std::string off_file_points; std::string output_file_diag; bool exact_version = false; @@ -38,48 +101,34 @@ int main(int argc, char **argv) { int coeff_field_characteristic; Filtration_value min_persistence; - program_options(argc, argv, off_file_points, exact_version, fast_version, output_file_diag, alpha_square_max_value, - coeff_field_characteristic, min_persistence); + program_options(argc, argv, off_file_points, exact_version, fast_version, weight_file, output_file_diag, + alpha_square_max_value, coeff_field_characteristic, min_persistence); if ((exact_version) && (fast_version)) { std::cerr << "You cannot set the exact and the fast version." << std::endl; exit(-1); } - Simplex_tree simplex; + Simplex_tree stree; if (fast_version) { // WARNING : CGAL::Epick_d is fast but not safe (unlike CGAL::Epeck_d) // (i.e. when the points are on a grid) using Fast_kernel = CGAL::Epick_d; - - // Init of an alpha complex from an OFF file - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_points); - - if (!alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) { - std::cerr << "Fast Alpha complex simplicial complex creation failed." << std::endl; - exit(-1); - } + stree = create_simplex_tree(off_file_points, weight_file, exact_version, alpha_square_max_value); } else { using Kernel = CGAL::Epeck_d; - - // Init of an alpha complex from an OFF file - Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_points); - - if (!alpha_complex_from_file.create_complex(simplex, alpha_square_max_value, exact_version)) { - std::cerr << "Alpha complex simplicial complex creation failed." << std::endl; - exit(-1); - } + stree = create_simplex_tree(off_file_points, weight_file, exact_version, alpha_square_max_value); } // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- - std::clog << "Simplicial complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() - << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; + std::clog << "Simplicial complex is of dimension " << stree.dimension() << " - " << stree.num_simplices() + << " simplices - " << stree.num_vertices() << " vertices." << std::endl; - std::clog << "Simplex_tree dim: " << simplex.dimension() << std::endl; + std::clog << "Simplex_tree dim: " << stree.dimension() << std::endl; // Compute the persistence diagram of the complex Gudhi::persistent_cohomology::Persistent_cohomology pcoh( - simplex); + stree); // initializes the coefficient field for homology pcoh.init_coefficients(coeff_field_characteristic); @@ -98,7 +147,7 @@ int main(int argc, char **argv) { } void program_options(int argc, char *argv[], std::string &off_file_points, bool &exact, bool &fast, - std::string &output_file_diag, Filtration_value &alpha_square_max_value, + std::string &weight_file, std::string &output_file_diag, Filtration_value &alpha_square_max_value, int &coeff_field_characteristic, Filtration_value &min_persistence) { namespace po = boost::program_options; po::options_description hidden("Hidden options"); @@ -111,6 +160,8 @@ void program_options(int argc, char *argv[], std::string &off_file_points, bool "To activate exact version of Alpha complex (default is false, not available if fast is set)")( "fast,f", po::bool_switch(&fast), "To activate fast version of Alpha complex (default is false, not available if exact is set)")( + "weight-file,w", po::value(&weight_file)->default_value(std::string()), + "Name of file containing a point weights. Format is one weight per line:\n W1\n ...\n Wn ")( "output-file,o", po::value(&output_file_diag)->default_value(std::string()), "Name of file in which the persistence diagram is written. Default print in std::clog")( "max-alpha-square-value,r", po::value(&alpha_square_max_value) diff --git a/src/Alpha_complex/utilities/alphacomplex.md b/src/Alpha_complex/utilities/alphacomplex.md index 527598a9..0d3c6027 100644 --- a/src/Alpha_complex/utilities/alphacomplex.md +++ b/src/Alpha_complex/utilities/alphacomplex.md @@ -46,6 +46,9 @@ for the Alpha complex construction. coefficient field Z/pZ for computing homology. * `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals. +* `-w [ --weight-file ]` is the path to the file containing the weights of the +points (one value per line). +Default version is not weighted. * `-e [ --exact ]` for the exact computation version. * `-f [ --fast ]` for the fast computation version. @@ -58,6 +61,10 @@ to be recorded. Enter a negative value to see zero length intervals. N.B.: * Filtration values are alpha square values. +* Weights values are explained on CGAL +[dD Triangulations](https://doc.cgal.org/latest/Triangulation/index.html) +and +[Regular triangulation](https://doc.cgal.org/latest/Triangulation/index.html#title20) documentation. ## alpha_complex_3d_persistence ## -- cgit v1.2.3 From de39546182c20a69e45aa07830351f6e9d2e4b84 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 14 Sep 2020 17:27:40 +0200 Subject: Add but comment a test to compare dD and 3D alpha complex --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 - .../test/Weighted_alpha_complex_unit_test.cpp | 79 +++++++++++++++++++++- 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 00231e1c..e1aae2d4 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -267,8 +267,6 @@ class Alpha_complex { // Save index value as data to retrieve it after insertion pos->data() = index; hint = pos->full_cell(); - } else { - std::cout << "NULLPTR" << std::endl; } } // -------------------------------------------------------------------------------------------- diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index 57a57058..bf659ef7 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -79,4 +79,81 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_kerne } BOOST_CHECK(zw_simplex == simplex); -} \ No newline at end of file +} + +template +bool cgal_3d_point_sort (Point_d a,Point_d b) { + if (a[0] != b[0]) + return a[0] < b[0]; + if (a[1] != b[1]) + return a[1] < b[1]; + return a[2] < b[2]; +} + +/*BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { + // Random points construction + using Kernel_dD = CGAL::Epeck_d< CGAL::Dimension_tag<3> >; + using Bare_point_d = typename Kernel_dD::Point_d; + using Weighted_point_d = typename Kernel_dD::Weighted_point_d; + std::vector w_points_d; + + using Exact_weighted_alpha_complex_3d = + Gudhi::alpha_complex::Alpha_complex_3d; + using Bare_point_3 = typename Exact_weighted_alpha_complex_3d::Bare_point_3; + using Weighted_point_3 = typename Exact_weighted_alpha_complex_3d::Weighted_point_3; + std::vector w_points_3; + + std::uniform_real_distribution rd_pts(-10., 10.); + std::uniform_real_distribution rd_wghts(-0.5, 0.5); + std::random_device rand_dev; + std::mt19937 rand_engine(rand_dev()); + for (int idx = 0; idx < 20; idx++) { + std::vector point {rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine)}; + double weight = rd_wghts(rand_engine); + w_points_d.emplace_back(Weighted_point_d(Bare_point_d(point.begin(), point.end()), weight)); + w_points_3.emplace_back(Weighted_point_3(Bare_point_3(point[0], point[1], point[2]), weight)); + } + + // Weighted alpha complex for dD version + Gudhi::alpha_complex::Alpha_complex alpha_complex_dD_from_weighted_points(w_points_d); + Gudhi::Simplex_tree<> w_simplex_d; + BOOST_CHECK(alpha_complex_dD_from_weighted_points.create_complex(w_simplex_d)); + + std::clog << "Iterator on weighted alpha complex dD simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : w_simplex_d.filtration_simplex_range()) { + std::clog << " ( "; + std::vector points; + for (auto vertex : w_simplex_d.simplex_vertex_range(f_simplex)) { + points.emplace_back(alpha_complex_dD_from_weighted_points.get_point(vertex).point()); + } + std::sort (points.begin(), points.end(), cgal_3d_point_sort); + for (auto point : points) { + std::clog << point[0] << " " << point[1] << " " << point[2] << " | "; + } + std::clog << ") -> " << "[" << w_simplex_d.filtration(f_simplex) << "] "; + std::clog << std::endl; + } + + // Weighted alpha complex for 3D version + Exact_weighted_alpha_complex_3d alpha_complex_3D_from_weighted_points(w_points_3); + Gudhi::Simplex_tree<> w_simplex_3; + BOOST_CHECK(alpha_complex_3D_from_weighted_points.create_complex(w_simplex_3)); + + std::clog << "Iterator on weighted alpha complex 3D simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : w_simplex_3.filtration_simplex_range()) { + std::clog << " ( "; + std::vector points; + for (auto vertex : w_simplex_3.simplex_vertex_range(f_simplex)) { + points.emplace_back(alpha_complex_3D_from_weighted_points.get_point(vertex).point()); + } + std::sort (points.begin(), points.end()); + for (auto point : points) { + std::clog << point[0] << " " << point[1] << " " << point[2] << " | "; + } + std::clog << ") -> " << "[" << w_simplex_3.filtration(f_simplex) << "] "; + std::clog << std::endl; + } + + BOOST_CHECK(w_simplex_d == w_simplex_3); + +}*/ \ No newline at end of file -- cgit v1.2.3 From 53d09e2f7770f7e95d765d527712ef3c0758cf08 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 14 Sep 2020 21:35:23 +0200 Subject: Fix Alpha complex to have the same results than Alpha complex 3d --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 31 +++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index e1aae2d4..f43cd071 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -60,6 +60,27 @@ namespace alpha_complex { template struct Is_Epeck_D { static const bool value = false; }; template struct Is_Epeck_D> { static const bool value = true; }; +template +struct Weight; + +template +struct Weight +{ + typename Kernel::FT operator()(const typename Kernel::Weighted_point_d& p) const + { + return p.weight(); + } +}; + +template +struct Weight +{ + typename Kernel::FT operator()(const typename Kernel::Point_d& p) const + { + return 0.; + } +}; + /** * \class Alpha_complex Alpha_complex.h gudhi/Alpha_complex.h * \brief Alpha complex data structure. @@ -404,6 +425,7 @@ class Alpha_complex { // -------------------------------------------------------------------------------------------- if (!default_filtration_value) { + CGAL::NT_converter cgal_converter; // -------------------------------------------------------------------------------------------- // ### For i : d -> 0 for (int decr_dim = triangulation_->maximal_dimension(); decr_dim >= 0; decr_dim--) { @@ -420,8 +442,7 @@ class Alpha_complex { #if CGAL_VERSION_NR >= 1050000000 if(exact) CGAL::exact(sqrad); #endif - CGAL::NT_converter cv; - alpha_complex_filtration = cv(sqrad); + alpha_complex_filtration = cgal_converter(sqrad); } complex.assign_filtration(f_simplex, alpha_complex_filtration); #ifdef DEBUG_TRACES @@ -431,6 +452,12 @@ class Alpha_complex { // No need to propagate further, unweighted points all have value 0 if (decr_dim > 1) propagate_alpha_filtration(complex, f_simplex); + // For weighted points, assign point weight as filtration value + if (Weighted && decr_dim == 0) { + Vertex_handle vertex = *(complex.simplex_vertex_range(f_simplex).begin()); + FT wght = Weight()(get_point(vertex)); + complex.assign_filtration(f_simplex, cgal_converter(wght)*(-1.)); + } } } old_cache_ = std::move(cache_); -- cgit v1.2.3 From 6db3b5db0f8b6dfae2b9b6eadb8bccdfdc613fb5 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 15 Sep 2020 13:45:37 +0200 Subject: This should be correct and efficient for 0-dimension weighted alpha --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index f43cd071..b66ec20d 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -436,8 +436,8 @@ class Alpha_complex { // ### If filt(Sigma) is NaN : filt(Sigma) = alpha(Sigma) if (std::isnan(complex.filtration(f_simplex))) { Filtration_value alpha_complex_filtration = 0.0; - // No need to compute squared_radius on a single point - alpha is 0.0 - if (f_simplex_dim > 0) { + // No need to compute squared_radius on a non-weighted single point - alpha is 0.0 + if (Weighted || f_simplex_dim > 0) { auto const& sqrad = radius(complex, f_simplex); #if CGAL_VERSION_NR >= 1050000000 if(exact) CGAL::exact(sqrad); @@ -450,14 +450,8 @@ class Alpha_complex { #endif // DEBUG_TRACES } // No need to propagate further, unweighted points all have value 0 - if (decr_dim > 1) + if (decr_dim > !Weighted) propagate_alpha_filtration(complex, f_simplex); - // For weighted points, assign point weight as filtration value - if (Weighted && decr_dim == 0) { - Vertex_handle vertex = *(complex.simplex_vertex_range(f_simplex).begin()); - FT wght = Weight()(get_point(vertex)); - complex.assign_filtration(f_simplex, cgal_converter(wght)*(-1.)); - } } } old_cache_ = std::move(cache_); -- cgit v1.2.3 From 4dacc3d99bfc4a4d31088fe126090038156ab7a0 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 15 Sep 2020 16:56:17 +0200 Subject: Make Kernel available publicly for tests purpose --- src/Alpha_complex/include/gudhi/Alpha_complex_3d.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h index 622b10ee..4e5fc933 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h @@ -154,8 +154,10 @@ class Alpha_complex_3d { using Kernel = CGAL::Periodic_3_regular_triangulation_traits_3; }; + public: using Kernel = typename Kernel_3::Kernel; + private: using TdsVb = typename std::conditional, CGAL::Triangulation_ds_vertex_base_3<>>::type; -- cgit v1.2.3 From 019bc2dc28dd6db3b21a24354051fe3a4d2e1f77 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 15 Sep 2020 16:56:54 +0200 Subject: alpha complex persistence now requires cgal 5.1 --- src/Alpha_complex/utilities/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Alpha_complex/utilities/CMakeLists.txt b/src/Alpha_complex/utilities/CMakeLists.txt index f0ddfc2c..90e5734e 100644 --- a/src/Alpha_complex/utilities/CMakeLists.txt +++ b/src/Alpha_complex/utilities/CMakeLists.txt @@ -1,6 +1,6 @@ project(Alpha_complex_utilities) -if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) +if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) add_executable (alpha_complex_persistence alpha_complex_persistence.cpp) target_link_libraries(alpha_complex_persistence ${CGAL_LIBRARY} Boost::program_options) @@ -27,7 +27,7 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) endif() install(TARGETS alpha_complex_persistence DESTINATION bin) -endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) +endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0) if (NOT CGAL_VERSION VERSION_LESS 4.11.0) add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp) -- cgit v1.2.3 From d6f68d20e975e0cd530cd15ca5f7f782550e6af4 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 15 Sep 2020 16:57:15 +0200 Subject: Test alpha complex dD versus 3d --- .../test/Weighted_alpha_complex_unit_test.cpp | 54 +++++++++++++++++----- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index bf659ef7..e8372656 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -19,6 +19,8 @@ #include // float comparison #include #include +#include +#include // for std::fabs #include #include @@ -90,7 +92,7 @@ bool cgal_3d_point_sort (Point_d a,Point_d b) { return a[2] < b[2]; } -/*BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { +BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { // Random points construction using Kernel_dD = CGAL::Epeck_d< CGAL::Dimension_tag<3> >; using Bare_point_d = typename Kernel_dD::Point_d; @@ -114,6 +116,12 @@ bool cgal_3d_point_sort (Point_d a,Point_d b) { w_points_3.emplace_back(Weighted_point_3(Bare_point_3(point[0], point[1], point[2]), weight)); } + // Structures necessary for comparison + using Points = std::vector>; + using Points_and_filtrations = std::map; + Points_and_filtrations pts_fltr_dD; + Points_and_filtrations pts_fltr_3d; + // Weighted alpha complex for dD version Gudhi::alpha_complex::Alpha_complex alpha_complex_dD_from_weighted_points(w_points_d); Gudhi::Simplex_tree<> w_simplex_d; @@ -121,17 +129,20 @@ bool cgal_3d_point_sort (Point_d a,Point_d b) { std::clog << "Iterator on weighted alpha complex dD simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : w_simplex_d.filtration_simplex_range()) { - std::clog << " ( "; - std::vector points; + Points points; for (auto vertex : w_simplex_d.simplex_vertex_range(f_simplex)) { - points.emplace_back(alpha_complex_dD_from_weighted_points.get_point(vertex).point()); + CGAL::NT_converter cgal_converter; + Bare_point_d pt = alpha_complex_dD_from_weighted_points.get_point(vertex).point(); + points.push_back({cgal_converter(pt[0]), cgal_converter(pt[1]), cgal_converter(pt[2])}); } - std::sort (points.begin(), points.end(), cgal_3d_point_sort); + std::clog << " ( "; + std::sort (points.begin(), points.end()); for (auto point : points) { std::clog << point[0] << " " << point[1] << " " << point[2] << " | "; } std::clog << ") -> " << "[" << w_simplex_d.filtration(f_simplex) << "] "; std::clog << std::endl; + pts_fltr_dD[points] = w_simplex_d.filtration(f_simplex); } // Weighted alpha complex for 3D version @@ -141,19 +152,40 @@ bool cgal_3d_point_sort (Point_d a,Point_d b) { std::clog << "Iterator on weighted alpha complex 3D simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : w_simplex_3.filtration_simplex_range()) { - std::clog << " ( "; - std::vector points; + Points points; for (auto vertex : w_simplex_3.simplex_vertex_range(f_simplex)) { - points.emplace_back(alpha_complex_3D_from_weighted_points.get_point(vertex).point()); + Bare_point_3 pt = alpha_complex_3D_from_weighted_points.get_point(vertex).point(); + CGAL::NT_converter cgal_converter; + points.push_back({cgal_converter(pt[0]), cgal_converter(pt[1]), cgal_converter(pt[2])}); } + std::clog << " ( "; std::sort (points.begin(), points.end()); for (auto point : points) { std::clog << point[0] << " " << point[1] << " " << point[2] << " | "; } std::clog << ") -> " << "[" << w_simplex_3.filtration(f_simplex) << "] "; std::clog << std::endl; + pts_fltr_3d[points] = w_simplex_d.filtration(f_simplex); } - BOOST_CHECK(w_simplex_d == w_simplex_3); - -}*/ \ No newline at end of file + // Compares structures + auto d3_itr = pts_fltr_3d.begin(); + auto dD_itr = pts_fltr_dD.begin(); + for (; d3_itr != pts_fltr_3d.end() && dD_itr != pts_fltr_dD.end(); ++d3_itr) { + if (d3_itr->first != dD_itr->first) { + for(auto point : d3_itr->first) + std::clog << point[0] << " " << point[1] << " " << point[2] << " | "; + std::clog << " versus "; + for(auto point : dD_itr->first) + std::clog << point[0] << " " << point[1] << " " << point[2] << " | "; + std::clog << std::endl; + BOOST_CHECK(false); + } + // I had to make a hard limit as it is converted from Kernel::FT + if (std::fabs(d3_itr->second - dD_itr->second) > 1e-5) { + std::clog << d3_itr->second << " versus " << dD_itr->second << " diff " << std::fabs(d3_itr->second - dD_itr->second) << std::endl; + BOOST_CHECK(false); + } + ++dD_itr; + } +} -- cgit v1.2.3 From cb68f3e4c8ce7724ccb693e5c67dd9928d12d84b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 16 Sep 2020 12:39:00 +0200 Subject: Some documentation about weighted dD Alpha complex. Make examples 3d/dD consistents --- src/Alpha_complex/doc/Intro_alpha_complex.h | 35 +++++++++++++++++++++- .../Weighted_alpha_complex_3d_from_points.cpp | 4 +-- .../example/Weighted_alpha_complex_from_points.cpp | 16 +++++----- .../example/weightedalpha3dfrompoints_for_doc.txt | 4 +-- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 60da7169..f14adee6 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -22,6 +22,17 @@ namespace alpha_complex { * * @{ * + + * \section definition Definition * * Alpha_complex is a simplicial complex @@ -146,6 +157,28 @@ namespace alpha_complex { * `SimplicialComplexForAlpha::prune_above_filtration()`). * In the following example, the value is given by the user as argument of the program. * + * \section weightedversion Weighted specific version + * Requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 5.1.0. + * For performances reasons, it is advised to use \ref eigen ≥ 3.5.8 and \ref cgal ≥ 5.2.0 + * A weighted version for Alpha complex is available (cf. Alpha_complex). + * + * This example builds the CGAL weighted alpha shapes from a small molecule, and initializes the alpha complex with + * it. This example is taken from CGAL 3d + * weighted alpha shapes. + * + * Then, it is asked to display information about the alpha complex. + * + * \include Alpha_complex/Weighted_alpha_complex_from_points.cpp + * + * When launching: + * + * \code $> ./Weighted_alpha_complex_example_from_points + * \endcode + * + * the program output is: + * + * \include Alpha_complex/weightedalpha3dfrompoints_for_doc.txt + * * * \section offexample Example from OFF file * @@ -166,7 +199,7 @@ namespace alpha_complex { * \include Alpha_complex/alphaoffreader_for_doc_32.txt * * - * \section weighted3dexample 3d specific example + * \section weighted3dexample 3d specific version * * A specific module for Alpha complex is available in 3d (cf. Alpha_complex_3d) and allows to construct standard, * weighted, periodic or weighted and periodic versions of alpha complexes. Alpha values computation can be diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp index c044194e..74f0cf30 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp @@ -34,10 +34,10 @@ int main(int argc, char **argv) { // ---------------------------------------------------------------------------- // Display information about the alpha complex // ---------------------------------------------------------------------------- - std::clog << "Alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() + std::clog << "Weighted alpha complex is of dimension " << simplex.dimension() << " - " << simplex.num_simplices() << " simplices - " << simplex.num_vertices() << " vertices." << std::endl; - std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + std::clog << "Iterator on weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : simplex.filtration_simplex_range()) { std::clog << " ( "; for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp index 19a04282..d49d3e93 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp @@ -8,23 +8,21 @@ #include // Explicit dimension 2 Epeck_d kernel -using Kernel = CGAL::Epeck_d< CGAL::Dimension_tag<2> >; +using Kernel = CGAL::Epeck_d< CGAL::Dimension_tag<3> >; using Bare_point = Kernel::Point_d; using Weighted_point = Kernel::Weighted_point_d; using Vector_of_points = std::vector; int main() { // ---------------------------------------------------------------------------- - // Init of a list of points + // Init of a list of points and weights from a small molecule // ---------------------------------------------------------------------------- Vector_of_points points; - points.push_back(Weighted_point(Bare_point(1.0, 1.0) , 1.)); - points.push_back(Weighted_point(Bare_point(7.0, 0.0) , 1.)); - points.push_back(Weighted_point(Bare_point(4.0, 6.0) , 1.)); - points.push_back(Weighted_point(Bare_point(9.0, 6.0) , 1.)); - points.push_back(Weighted_point(Bare_point(0.0, 14.0), 1.)); - points.push_back(Weighted_point(Bare_point(2.0, 19.0), 1.)); - points.push_back(Weighted_point(Bare_point(9.0, 17.0), 1.)); + points.push_back(Weighted_point(Bare_point(1, -1, -1), 4.)); + points.push_back(Weighted_point(Bare_point(-1, 1, -1), 4.)); + points.push_back(Weighted_point(Bare_point(-1, -1, 1), 4.)); + points.push_back(Weighted_point(Bare_point(1, 1, 1), 4.)); + points.push_back(Weighted_point(Bare_point(2, 2, 2), 1.)); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points diff --git a/src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt b/src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt index 7a09998d..f0695f1a 100644 --- a/src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt +++ b/src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt @@ -1,5 +1,5 @@ -Alpha complex is of dimension 3 - 29 simplices - 5 vertices. -Iterator on alpha complex simplices in the filtration order, with [filtration value]: +Weighted alpha complex is of dimension 3 - 29 simplices - 5 vertices. +Iterator on weighted alpha complex simplices in the filtration order, with [filtration value]: ( 0 ) -> [-4] ( 1 ) -> [-4] ( 2 ) -> [-4] -- cgit v1.2.3 From 282934d4f51acac046c04f752534a6a900880df9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 16 Sep 2020 12:43:35 +0200 Subject: Add weighted in toc --- src/Alpha_complex/doc/Intro_alpha_complex.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index f14adee6..b04562e1 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -28,6 +28,7 @@ Table of Contents
  • Definition
  • Example from points
  • Create complex algorithm
  • +
  • Weighted specific version
  • Example from OFF file
  • 3d specific version
  • @@ -214,14 +215,7 @@ Table of Contents * * \include Alpha_complex/Weighted_alpha_complex_3d_from_points.cpp * - * When launching: - * - * \code $> ./Alpha_complex_example_weighted_3d_from_points - * \endcode - * - * the program output is: - * - * \include Alpha_complex/weightedalpha3dfrompoints_for_doc.txt + * The results will be the same as in \ref weightedversion . * */ /** @} */ // end defgroup alpha_complex -- cgit v1.2.3 From 837ffddda60d3f389184fe167710f74ad8adf36b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 17 Sep 2020 09:37:25 +0200 Subject: Some documentation for weighted version --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 7 ++++--- src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index b66ec20d..1d395bd8 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -132,17 +132,18 @@ class Alpha_complex { using Triangulation = typename std::conditional, CGAL::Delaunay_triangulation>::type; + /** \brief CGAL kernel container for computations in function of the weighted or not characteristics.*/ using A_kernel_d = Alpha_kernel_d; // Numeric type of coordinates in the kernel using FT = typename A_kernel_d::FT; - /** \brief If Weighted, the weighted point is cached (point + weight [= squared radius]), - * else a pair of point and squared radius is cached. + /** \brief Sphere is a std::pair (aka. circurmcenter and squared radius). + * If Weighted, Sphere is a Kernel::Weighted_point_d (aka. circurmcenter and the weight value is the squared radius). */ using Sphere = typename A_kernel_d::Sphere; - /** \brief A point in Euclidean space.*/ + /** \brief A point, or a weighted point in Euclidean space.*/ using Point_d = typename std::conditional::type; diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index a4824207..e3567a6d 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -32,6 +32,14 @@ namespace Gudhi { namespace alpha_complex { +/** + * \class Alpha_kernel_d + * \brief Alpha complex kernel container. + * + * \details + * The Alpha complex kernel container stores CGAL Kernel and dispatch basics computations in function of the weighted + * or not version of the Alpha complex. + */ template < typename Kernel, bool Weighted = false > class Alpha_kernel_d { }; -- cgit v1.2.3 From 77c0275031f47bb94f94d02d63182178e46f6570 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 17 Sep 2020 10:24:30 +0200 Subject: Remove useless code --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 1d395bd8..be0a5b95 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -60,27 +60,6 @@ namespace alpha_complex { template struct Is_Epeck_D { static const bool value = false; }; template struct Is_Epeck_D> { static const bool value = true; }; -template -struct Weight; - -template -struct Weight -{ - typename Kernel::FT operator()(const typename Kernel::Weighted_point_d& p) const - { - return p.weight(); - } -}; - -template -struct Weight -{ - typename Kernel::FT operator()(const typename Kernel::Point_d& p) const - { - return 0.; - } -}; - /** * \class Alpha_complex Alpha_complex.h gudhi/Alpha_complex.h * \brief Alpha complex data structure. -- cgit v1.2.3 From 8afdbebe27effb0a9c184a153b645dd85aa0415b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 18 Sep 2020 13:08:37 +0200 Subject: Fix #if cgal_version --- .../include/gudhi/Alpha_complex/Alpha_kernel_d.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index e3567a6d..a6760645 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -108,18 +108,16 @@ class Alpha_kernel_d { template Sphere get_sphere(PointIterator begin, PointIterator end) const { // power_center_d_object has been renamed between CGAL 5.1 and 5.2 -#if defined CGAL_VERSION_NR >= 1050101000 && defined CGAL_VERSION_NR < 1050201000 +#if CGAL_VERSION_NR < 1050201000 return kernel_.power_center_d_object()(begin, end); -#endif -#if CGAL_VERSION_NR >= 1050201000 +#else return kernel_.construct_power_sphere_d_object()(begin, end); #endif } template FT get_squared_radius(PointIterator begin, PointIterator end) const { - Sphere sph = get_sphere(begin, end); - return sph.weight(); + return get_sphere(begin, end).weight(); } FT get_squared_radius(const Sphere& sph) const { @@ -128,10 +126,9 @@ class Alpha_kernel_d { bool is_gabriel(const Sphere& circumcenter, const Weighted_point_d& point) { // power_center_d_object has been renamed between CGAL 5.1 and 5.2 -#if defined CGAL_VERSION_NR >= 1050101000 && defined CGAL_VERSION_NR < 1050201000 +#if CGAL_VERSION_NR < 1050201000 return kernel_.power_distance_d_object()(circumcenter, point) >= 0; -#endif -#if CGAL_VERSION_NR >= 1050201000 +#else return kernel_.compute_power_product_d_object()(circumcenter, point) >= 0; #endif } -- cgit v1.2.3 From c6619e0207abf0fb5198b66a8d8f00f975c3da84 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 18 Sep 2020 16:27:49 +0200 Subject: Use CGAL 5.1 by default on dockers. Update next release --- .github/next_release.md | 6 +++--- Dockerfile_for_circleci_image | 10 +++++++++- Dockerfile_for_pip | 8 ++++---- Dockerfile_gudhi_installation | 12 ++++++++++++ 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.github/next_release.md b/.github/next_release.md index cd2376eb..190f8408 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -1,13 +1,13 @@ We are pleased to announce the release 3.4.0 of the GUDHI library. -As a major new feature, the GUDHI library now offers ... +As a major new feature, the GUDHI library now offers dD weighted alpha complex, ... 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.4.0.tar.gz). Below is a list of changes made since GUDHI 3.3.0: -- [Module](link) - - ... +- [Alpha complex](https://gudhi.inria.fr/doc/latest/group__alpha__complex.html) + - the C++ weighted version for alpha complex is now available in dimension D. - [Module](link) - ... diff --git a/Dockerfile_for_circleci_image b/Dockerfile_for_circleci_image index 87f57071..ec1b8ff8 100644 --- a/Dockerfile_for_circleci_image +++ b/Dockerfile_for_circleci_image @@ -41,7 +41,6 @@ RUN apt-get install -y make \ libgmp3-dev \ libmpfr-dev \ libtbb-dev \ - libcgal-dev \ locales \ python3 \ python3-pip \ @@ -51,6 +50,15 @@ RUN apt-get install -y make \ pkg-config \ curl +RUN curl -LO "https://github.com/CGAL/cgal/releases/download/v5.1/CGAL-5.1.tar.xz" \ + && tar xf CGAL-5.1.tar.xz \ + && mkdir build \ + && cd build \ + && cmake -DCMAKE_BUILD_TYPE=Release ../CGAL-5.1/ \ + && make install \ + && cd .. \ + && rm -rf build CGAL-5.1 + ADD .github/build-requirements.txt / ADD .github/test-requirements.txt / diff --git a/Dockerfile_for_pip b/Dockerfile_for_pip index 8f60e37c..83c6d684 100644 --- a/Dockerfile_for_pip +++ b/Dockerfile_for_pip @@ -23,14 +23,14 @@ RUN git clone -b boost-1.73.0 --depth 1 https://github.com/boostorg/boost.git \ && cd .. \ && rm -rf boost -RUN wget https://github.com/CGAL/cgal/releases/download/releases%2FCGAL-5.0.2/CGAL-5.0.2.tar.xz \ - && tar xf CGAL-5.0.2.tar.xz \ +RUN wget https://github.com/CGAL/cgal/releases/download/v5.1/CGAL-5.1.tar.xz \ + && tar xf CGAL-5.1.tar.xz \ && mkdir build \ && cd build \ - && /opt/cmake/bin/cmake -DCMAKE_BUILD_TYPE=Release ../CGAL-5.0.2/ \ + && /opt/cmake/bin/cmake -DCMAKE_BUILD_TYPE=Release ../CGAL-5.1/ \ && make install \ && cd .. \ - && rm -rf build CGAL-5.0.2 + && rm -rf build CGAL-5.1 ADD .github/build-requirements.txt / diff --git a/Dockerfile_gudhi_installation b/Dockerfile_gudhi_installation index 92430fce..ebd21f8d 100644 --- a/Dockerfile_gudhi_installation +++ b/Dockerfile_gudhi_installation @@ -23,6 +23,9 @@ ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 +# Update again +RUN apt-get update + # Required for Gudhi compilation RUN apt-get install -y make \ g++ \ @@ -47,6 +50,15 @@ RUN apt-get install -y make \ pkg-config \ curl +RUN curl -LO "https://github.com/CGAL/cgal/releases/download/v5.1/CGAL-5.1.tar.xz" \ + && tar xf CGAL-5.1.tar.xz \ + && mkdir build \ + && cd build \ + && cmake -DCMAKE_BUILD_TYPE=Release ../CGAL-5.1/ \ + && make install \ + && cd .. \ + && rm -rf build CGAL-5.1 + RUN pip3 install \ numpy \ matplotlib \ -- cgit v1.2.3 From 4186971033ee43821905cac53791bf074751d3af Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 28 Sep 2020 09:15:52 +0200 Subject: code review: Let the exception propagate --- src/python/gudhi/simplex_tree.pyx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 5250937b..5043c621 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -295,13 +295,9 @@ cdef class SimplexTree: """ cdef pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] it = self.get_ptr().get_boundary_iterators(simplex) - try: - while it.first != it.second: - yield self.get_ptr().get_simplex_and_filtration(dereference(it.first)) - preincrement(it.first) - except RuntimeError: - print("simplex not found - cannot find boundaries") - + while it.first != it.second: + yield self.get_ptr().get_simplex_and_filtration(dereference(it.first)) + preincrement(it.first) def remove_maximal_simplex(self, simplex): """This function removes a given maximal N-simplex from the simplicial -- cgit v1.2.3 From e64dd4039e6dff35322ff01a8aa82d79c77e9c8e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 28 Sep 2020 09:44:43 +0200 Subject: doc review: improve reset_filtration documentation --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 4 ++-- src/python/gudhi/simplex_tree.pyx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 70ef4c66..5afd0e23 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1668,8 +1668,8 @@ class Simplex_tree { } public: - /** \brief This function resets filtration value from a given dimension. Resets all the Simplex_tree when - * `min_dim = 0`. + /** \brief This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all + * the Simplex_tree when `min_dim = 0`. * `reset_filtration` may break the filtration property with `min_dim > 0`, and it is the user's responsibility to * make it a valid filtration (using a large enough `filt_value`, or calling `make_filtration_non_decreasing` * afterwards for instance). diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index f28990cc..910711a9 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -359,8 +359,8 @@ cdef class SimplexTree: return self.get_ptr().make_filtration_non_decreasing() def reset_filtration(self, filtration, min_dim = 0): - """This function resets filtration value from a given dimension. Resets all the simplex tree when - `min_dim = 0`. + """This function resets the filtration value of all the simplices of dimension at least min_dim. Resets all the + simplex tree when `min_dim = 0`. `reset_filtration` may break the filtration property with `min_dim > 0`, and it is the user's responsibility to make it a valid filtration (using a large enough `filt_value`, or calling `make_filtration_non_decreasing` afterwards for instance). -- cgit v1.2.3 From 0c843fd01f0cd1ccff92c8ed40e989b3fbf8f1e9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 28 Sep 2020 09:56:44 +0200 Subject: code review: Simplify recursivity --- src/Simplex_tree/include/gudhi/Simplex_tree.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index 5afd0e23..85d6c3b0 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1677,14 +1677,7 @@ class Simplex_tree { * @param[in] min_dim The minimal dimension. Default value is 0. */ void reset_filtration(Filtration_value filt_value, int min_dim = 0) { - for (auto& simplex : root_.members()) { - if (min_dim <= 0) { - simplex.second.assign_filtration(filt_value); - } - if (has_children(&simplex)) { - rec_reset_filtration(simplex.second.children(), filt_value, min_dim - 1); - } - } + rec_reset_filtration(&root_, filt_value, min_dim); clear_filtration(); // Drop the cache. } -- cgit v1.2.3 From e7b7947adf13ec1dcb8c126a4373fa29baaecb63 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 29 Sep 2020 13:23:56 +0200 Subject: Added tests for wasserstein distance with tensorflow --- .../modules/GUDHI_third_party_libraries.cmake | 1 + src/python/CMakeLists.txt | 8 +++++++ src/python/doc/installation.rst | 5 +++++ src/python/test/test_wasserstein_with_tensors.py | 25 ++++++++++++++++++++++ 4 files changed, 39 insertions(+) create mode 100755 src/python/test/test_wasserstein_with_tensors.py diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 1fbc4244..9dadac4f 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -155,6 +155,7 @@ if( PYTHONINTERP_FOUND ) find_python_module("pykeops") find_python_module("eagerpy") find_python_module_no_version("hnswlib") + find_python_module("tensorflow") endif() if(NOT GUDHI_PYTHON_PATH) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 4f26481e..cc71503f 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -103,6 +103,9 @@ if(PYTHONINTERP_FOUND) if(EAGERPY_FOUND) add_gudhi_debug_info("EagerPy version ${EAGERPY_VERSION}") endif() + if(TENSORFLOW_FOUND) + add_gudhi_debug_info("TensorFlow version ${TENSORFLOW_VERSION}") + endif() set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") @@ -501,6 +504,11 @@ if(PYTHONINTERP_FOUND) endif() add_gudhi_py_test(test_wasserstein_barycenter) endif() + if(OT_FOUND) + if(TENSORFLOW_FOUND AND EAGERPY_FOUND) + add_gudhi_py_test(test_wasserstein_with_tensors) + endif() + endif() # Representations if(SKLEARN_FOUND AND MATPLOTLIB_FOUND) diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 2f161d66..66efe45a 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -394,6 +394,11 @@ mathematics, science, and engineering. :class:`~gudhi.point_cloud.knn.KNearestNeighbors` can use the Python package `SciPy `_ as a backend if explicitly requested. +TensorFlow +---------- + +`TensorFlow `_ is currently only used in some automatic differentiation tests. + Bug reports and contributions ***************************** diff --git a/src/python/test/test_wasserstein_with_tensors.py b/src/python/test/test_wasserstein_with_tensors.py new file mode 100755 index 00000000..8957705d --- /dev/null +++ b/src/python/test/test_wasserstein_with_tensors.py @@ -0,0 +1,25 @@ +""" 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): Mathieu Carriere + + Copyright (C) 2020 Inria + + Modification(s): + - YYYY/MM Author: Description of the modification +""" + +from gudhi.wasserstein import wasserstein_distance as pot +import numpy as np + +def test_wasserstein_distance_grad_tensorflow(): + import tensorflow as tf + + with tf.GradientTape() as tape: + diag4 = tf.convert_to_tensor(tf.Variable(initial_value=np.array([[0., 10.]]), trainable=True)) + diag5 = tf.convert_to_tensor(tf.Variable(initial_value=np.array([[1., 11.], [3., 4.]]), trainable=True)) + dist45 = pot(diag4, diag5, internal_p=1, order=1, enable_autodiff=True) + assert dist45 == 3. + + grads = tape.gradient(dist45, [diag4, diag5]) + assert np.array_equal(grads[0].values, [[-1., -1.]]) + assert np.array_equal(grads[1].values, [[1., 1.], [-1., 1.]]) \ No newline at end of file -- cgit v1.2.3 From b1b0e9afcaf0e282115dddad7b958b6ec7a94a41 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 29 Sep 2020 14:33:28 +0200 Subject: code review: inconsistency between code and comment --- src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp index 74f0cf30..a8d00272 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp @@ -9,7 +9,7 @@ // Complexity = FAST, weighted = true, periodic = false using Weighted_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d; + Gudhi::alpha_complex::Alpha_complex_3d; using Bare_point = Weighted_alpha_complex_3d::Bare_point_3; using Weighted_point = Weighted_alpha_complex_3d::Weighted_point_3; -- cgit v1.2.3 From 6f2ec5ee6572351d3aee5f559ef4cf7ad03bf914 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 29 Sep 2020 15:00:53 +0200 Subject: doc review: fix eigen version and period --- src/Alpha_complex/doc/Intro_alpha_complex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index b04562e1..78486ad6 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -160,7 +160,8 @@ Table of Contents * * \section weightedversion Weighted specific version * Requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 5.1.0. - * For performances reasons, it is advised to use \ref eigen ≥ 3.5.8 and \ref cgal ≥ 5.2.0 + * For performances reasons, it is advised to use \ref eigen ≥ 3.3.5 and \ref cgal ≥ 5.2.0. + * * A weighted version for Alpha complex is available (cf. Alpha_complex). * * This example builds the CGAL weighted alpha shapes from a small molecule, and initializes the alpha complex with -- cgit v1.2.3 From b08a52c3b625e70d1c69834df7253e115da7946e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 29 Sep 2020 15:35:11 +0200 Subject: code review: use of std::conditional_t c++14 helper --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index be0a5b95..e8bf1f74 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -101,15 +101,16 @@ template, bool Weighte class Alpha_complex { public: /** \brief Geometric traits class that provides the geometric types and predicates needed by the triangulations.*/ - using Geom_traits = typename std::conditional, - Kernel>::type; + using Geom_traits = std::conditional_t, Kernel>; + // Add an int in TDS to save point index in the structure using TDS = CGAL::Triangulation_data_structure, CGAL::Triangulation_full_cell >; + /** \brief A (Weighted or not) Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/ - using Triangulation = typename std::conditional, - CGAL::Delaunay_triangulation>::type; + using Triangulation = std::conditional_t, + CGAL::Delaunay_triangulation>; /** \brief CGAL kernel container for computations in function of the weighted or not characteristics.*/ using A_kernel_d = Alpha_kernel_d; @@ -123,8 +124,7 @@ class Alpha_complex { using Sphere = typename A_kernel_d::Sphere; /** \brief A point, or a weighted point in Euclidean space.*/ - using Point_d = typename std::conditional::type; + using Point_d = std::conditional_t; private: // Vertex_iterator type from CGAL. -- cgit v1.2.3 From 44473bcd93892c7034fa21599509d4271f2d8bb2 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 29 Sep 2020 17:16:02 +0200 Subject: doc review: rephrase non contiguous vertices --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index e8bf1f74..38201027 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -171,7 +171,8 @@ class Alpha_complex { /** \brief Alpha_complex constructor from a list of points. * - * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. + * The vertices may be not contiguous as some points may be discarded in the triangulation (duplicate points, + * weighted hidden point, ...). * * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d or Kernel::Weighted_point_d. * @@ -186,7 +187,8 @@ class Alpha_complex { /** \brief Alpha_complex constructor from a list of points and weights. * - * Duplicate points are inserted once in the Alpha_complex. This is the reason why the vertices may be not contiguous. + * The vertices may be not contiguous as some points may be discarded in the triangulation (duplicate points, + * weighted hidden point, ...). * * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d or Kernel::Weighted_point_d. * -- cgit v1.2.3 From dab93ead76f1435f6b74937ef0377aafb0517439 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 29 Sep 2020 17:53:34 +0200 Subject: doc review: Modify ctor with points and weights documentation --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 38201027..a692dbc6 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -176,8 +176,8 @@ class Alpha_complex { * * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d or Kernel::Weighted_point_d. * - * The type InputPointRange must be a range for which std::begin and - * std::end return input iterators on a Kernel::Point_d or Kernel::Weighted_point_d. + * The type InputPointRange must be a range for which std::begin and std::end return input iterators on a + * Kernel::Point_d or Kernel::Weighted_point_d. */ template Alpha_complex(const InputPointRange& points) @@ -190,12 +190,12 @@ class Alpha_complex { * The vertices may be not contiguous as some points may be discarded in the triangulation (duplicate points, * weighted hidden point, ...). * - * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d or Kernel::Weighted_point_d. + * @param[in] points Range of points to triangulate. Points must be in Kernel::Point_d. * * @param[in] weights Range of points weights. Weights must be in Kernel::FT. * - * The type InputPointRange must be a range for which std::begin and - * std::end return input iterators on a Kernel::Point_d. + * The type InputPointRange must be a range for which std::begin and std::end return input iterators on a + * Kernel::Point_d. */ template Alpha_complex(const InputPointRange& points, WeightRange weights) { -- cgit v1.2.3 From c1b317640f81fefff7f7a774b239957fb632fa43 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 30 Sep 2020 09:18:36 +0200 Subject: code review: emplace_back versus push_back --- .../Weighted_alpha_complex_3d_from_points.cpp | 10 +++++----- .../example/Weighted_alpha_complex_from_points.cpp | 10 +++++----- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +++--- src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp | 20 ++++++++++---------- .../utilities/alpha_complex_persistence.cpp | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp index a8d00272..09431d6e 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp @@ -18,11 +18,11 @@ int main(int argc, char **argv) { // Init of a list of points and weights from a small molecule // ---------------------------------------------------------------------------- std::vector weighted_points; - weighted_points.push_back(Weighted_point(Bare_point(1, -1, -1), 4.)); - weighted_points.push_back(Weighted_point(Bare_point(-1, 1, -1), 4.)); - weighted_points.push_back(Weighted_point(Bare_point(-1, -1, 1), 4.)); - weighted_points.push_back(Weighted_point(Bare_point(1, 1, 1), 4.)); - weighted_points.push_back(Weighted_point(Bare_point(2, 2, 2), 1.)); + weighted_points.emplace_back(Bare_point(1, -1, -1), 4.); + weighted_points.emplace_back(Bare_point(-1, 1, -1), 4.); + weighted_points.emplace_back(Bare_point(-1, -1, 1), 4.); + weighted_points.emplace_back(Bare_point(1, 1, 1), 4.); + weighted_points.emplace_back(Bare_point(2, 2, 2), 1.); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp index d49d3e93..d1f3e436 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp @@ -18,11 +18,11 @@ int main() { // Init of a list of points and weights from a small molecule // ---------------------------------------------------------------------------- Vector_of_points points; - points.push_back(Weighted_point(Bare_point(1, -1, -1), 4.)); - points.push_back(Weighted_point(Bare_point(-1, 1, -1), 4.)); - points.push_back(Weighted_point(Bare_point(-1, -1, 1), 4.)); - points.push_back(Weighted_point(Bare_point(1, 1, 1), 4.)); - points.push_back(Weighted_point(Bare_point(2, 2, 2), 1.)); + points.emplace_back(Bare_point(1, -1, -1), 4.); + points.emplace_back(Bare_point(-1, 1, -1), 4.); + points.emplace_back(Bare_point(-1, -1, 1), 4.); + points.emplace_back(Bare_point(1, 1, 1), 4.); + points.emplace_back(Bare_point(2, 2, 2), 1.); // ---------------------------------------------------------------------------- // Init of an alpha complex from the list of points diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index a692dbc6..4f8e3d54 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -310,7 +310,7 @@ class Alpha_complex { thread_local std::vector v; v.clear(); for (auto vertex : cplx.simplex_vertex_range(s)) - v.push_back(get_point_(vertex)); + v.emplace_back(get_point_(vertex)); cache_.emplace_back(kernel_.get_sphere(v.cbegin(), v.cend())); } return cache_[k]; @@ -326,7 +326,7 @@ class Alpha_complex { thread_local std::vector v; v.clear(); for (auto vertex : cplx.simplex_vertex_range(s)) - v.push_back(get_point_(vertex)); + v.emplace_back(get_point_(vertex)); return kernel_.get_squared_radius(v.cbegin(), v.cend()); } @@ -394,7 +394,7 @@ class Alpha_complex { std::clog << " " << (*vit)->data(); #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure - vertexVector.push_back((*vit)->data()); + vertexVector.emplace_back((*vit)->data()); } } #ifdef DEBUG_TRACES diff --git a/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp index 192834b3..6eae103d 100644 --- a/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp @@ -63,11 +63,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_sphere, TestedKernel, list_of_kerne using Point_d = typename Unweighted_kernel::Point_d; std::vector unw_pts; - unw_pts.push_back(Point_d(p0.begin(), p0.end())); - unw_pts.push_back(Point_d(p1.begin(), p1.end())); - unw_pts.push_back(Point_d(p2.begin(), p2.end())); - unw_pts.push_back(Point_d(p3.begin(), p3.end())); - unw_pts.push_back(Point_d(p4.begin(), p4.end())); + unw_pts.emplace_back(p0.begin(), p0.end()); + unw_pts.emplace_back(p1.begin(), p1.end()); + unw_pts.emplace_back(p2.begin(), p2.end()); + unw_pts.emplace_back(p3.begin(), p3.end()); + unw_pts.emplace_back(p4.begin(), p4.end()); Unweighted_kernel kernel; auto unw_sphere = kernel.get_sphere(unw_pts.cbegin(), unw_pts.cend()); @@ -79,11 +79,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_sphere, TestedKernel, list_of_kerne using Weighted_point_d = typename Weighted_kernel::Weighted_point_d; using Bare_point_d = typename Weighted_kernel::Bare_point_d; std::vector w_pts; - w_pts.push_back(Weighted_point_d(Bare_point_d(p0.begin(), p0.end()), 0.)); - w_pts.push_back(Weighted_point_d(Bare_point_d(p1.begin(), p1.end()), 0.)); - w_pts.push_back(Weighted_point_d(Bare_point_d(p2.begin(), p2.end()), 0.)); - w_pts.push_back(Weighted_point_d(Bare_point_d(p3.begin(), p3.end()), 0.)); - w_pts.push_back(Weighted_point_d(Bare_point_d(p4.begin(), p4.end()), 0.)); + w_pts.emplace_back(Bare_point_d(p0.begin(), p0.end()), 0.); + w_pts.emplace_back(Bare_point_d(p1.begin(), p1.end()), 0.); + w_pts.emplace_back(Bare_point_d(p2.begin(), p2.end()), 0.); + w_pts.emplace_back(Bare_point_d(p3.begin(), p3.end()), 0.); + w_pts.emplace_back(Bare_point_d(p4.begin(), p4.end()), 0.); Weighted_kernel w_kernel; auto w_sphere = w_kernel.get_sphere(w_pts.cbegin(), w_pts.cend()); diff --git a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp index e86b34e2..3ce7b440 100644 --- a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp +++ b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp @@ -50,7 +50,7 @@ std::vector read_weight_file(const std::string &weight_file) { double weight = 0.0; // Attempt read the weight in a double format, return false if it fails while (weights_ifstr >> weight) { - weights.push_back(weight); + weights.emplace_back(weight); } } else { std::cerr << "Unable to read weights file " << weight_file << std::endl; -- cgit v1.2.3 From 74143b372d3d93fc2139974fa85906047acee8a7 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 10:33:23 +0200 Subject: code review: push_back versus emplace_back --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 6 +++--- src/Alpha_complex/utilities/alpha_complex_persistence.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 4f8e3d54..a692dbc6 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -310,7 +310,7 @@ class Alpha_complex { thread_local std::vector v; v.clear(); for (auto vertex : cplx.simplex_vertex_range(s)) - v.emplace_back(get_point_(vertex)); + v.push_back(get_point_(vertex)); cache_.emplace_back(kernel_.get_sphere(v.cbegin(), v.cend())); } return cache_[k]; @@ -326,7 +326,7 @@ class Alpha_complex { thread_local std::vector v; v.clear(); for (auto vertex : cplx.simplex_vertex_range(s)) - v.emplace_back(get_point_(vertex)); + v.push_back(get_point_(vertex)); return kernel_.get_squared_radius(v.cbegin(), v.cend()); } @@ -394,7 +394,7 @@ class Alpha_complex { std::clog << " " << (*vit)->data(); #endif // DEBUG_TRACES // Vector of vertex construction for simplex_tree structure - vertexVector.emplace_back((*vit)->data()); + vertexVector.push_back((*vit)->data()); } } #ifdef DEBUG_TRACES diff --git a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp index 3ce7b440..e86b34e2 100644 --- a/src/Alpha_complex/utilities/alpha_complex_persistence.cpp +++ b/src/Alpha_complex/utilities/alpha_complex_persistence.cpp @@ -50,7 +50,7 @@ std::vector read_weight_file(const std::string &weight_file) { double weight = 0.0; // Attempt read the weight in a double format, return false if it fails while (weights_ifstr >> weight) { - weights.emplace_back(weight); + weights.push_back(weight); } } else { std::cerr << "Unable to read weights file " << weight_file << std::endl; -- cgit v1.2.3 From 7b477e78f38324bf1473966d59aab0360bae8066 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 10:38:31 +0200 Subject: code review: promote SAFE mode --- src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp index 09431d6e..ee12d418 100644 --- a/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp +++ b/src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp @@ -7,9 +7,9 @@ #include #include // for numeric limits -// Complexity = FAST, weighted = true, periodic = false +// Complexity = SAFE, weighted = true, periodic = false using Weighted_alpha_complex_3d = - Gudhi::alpha_complex::Alpha_complex_3d; + Gudhi::alpha_complex::Alpha_complex_3d; using Bare_point = Weighted_alpha_complex_3d::Bare_point_3; using Weighted_point = Weighted_alpha_complex_3d::Weighted_point_3; -- cgit v1.2.3 From f0beb329f5a1767e4e0a0575ef3e078bf4563a44 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 11:12:44 +0200 Subject: code review: move test_wasserstein_distance_grad from test_wasserstein_distance.py to test_wasserstein_with_tensors.py --- src/python/CMakeLists.txt | 5 +++-- src/python/test/test_wasserstein_distance.py | 24 ---------------------- src/python/test/test_wasserstein_with_tensors.py | 26 ++++++++++++++++++++++-- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index cc71503f..c09996fe 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -499,13 +499,14 @@ if(PYTHONINTERP_FOUND) # Wasserstein if(OT_FOUND AND PYBIND11_FOUND) - if(TORCH_FOUND AND EAGERPY_FOUND) + # EagerPy dependency because of enable_autodiff=True + if(EAGERPY_FOUND) add_gudhi_py_test(test_wasserstein_distance) endif() add_gudhi_py_test(test_wasserstein_barycenter) endif() if(OT_FOUND) - if(TENSORFLOW_FOUND AND EAGERPY_FOUND) + if(TORCH_FOUND AND TENSORFLOW_FOUND AND EAGERPY_FOUND) add_gudhi_py_test(test_wasserstein_with_tensors) endif() endif() diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py index 90d26809..e3b521d6 100755 --- a/src/python/test/test_wasserstein_distance.py +++ b/src/python/test/test_wasserstein_distance.py @@ -97,27 +97,3 @@ def test_wasserstein_distance_pot(): def test_wasserstein_distance_hera(): _basic_wasserstein(hera_wrap(delta=1e-12), 1e-12, test_matching=False) _basic_wasserstein(hera_wrap(delta=.1), .1, test_matching=False) - -def test_wasserstein_distance_grad(): - import torch - - diag1 = torch.tensor([[2.7, 3.7], [9.6, 14.0], [34.2, 34.974]], requires_grad=True) - diag2 = torch.tensor([[2.8, 4.45], [9.5, 14.1]], requires_grad=True) - diag3 = torch.tensor([[2.8, 4.45], [9.5, 14.1]], requires_grad=True) - assert diag1.grad is None and diag2.grad is None and diag3.grad is None - dist12 = pot(diag1, diag2, internal_p=2, order=2, enable_autodiff=True) - dist30 = pot(diag3, torch.tensor([]), internal_p=2, order=2, enable_autodiff=True) - dist12.backward() - dist30.backward() - assert not torch.isnan(diag1.grad).any() and not torch.isnan(diag2.grad).any() and not torch.isnan(diag3.grad).any() - diag4 = torch.tensor([[0., 10.]], requires_grad=True) - diag5 = torch.tensor([[1., 11.], [3., 4.]], requires_grad=True) - dist45 = pot(diag4, diag5, internal_p=1, order=1, enable_autodiff=True) - assert dist45 == 3. - dist45.backward() - assert np.array_equal(diag4.grad, [[-1., -1.]]) - assert np.array_equal(diag5.grad, [[1., 1.], [-1., 1.]]) - diag6 = torch.tensor([[5., 10.]], requires_grad=True) - pot(diag6, diag6, internal_p=2, order=2, enable_autodiff=True).backward() - # https://github.com/jonasrauber/eagerpy/issues/6 - # assert np.array_equal(diag6.grad, [[0., 0.]]) diff --git a/src/python/test/test_wasserstein_with_tensors.py b/src/python/test/test_wasserstein_with_tensors.py index 8957705d..e3f1411a 100755 --- a/src/python/test/test_wasserstein_with_tensors.py +++ b/src/python/test/test_wasserstein_with_tensors.py @@ -10,10 +10,32 @@ from gudhi.wasserstein import wasserstein_distance as pot import numpy as np +import torch +import tensorflow as tf -def test_wasserstein_distance_grad_tensorflow(): - import tensorflow as tf +def test_wasserstein_distance_grad(): + diag1 = torch.tensor([[2.7, 3.7], [9.6, 14.0], [34.2, 34.974]], requires_grad=True) + diag2 = torch.tensor([[2.8, 4.45], [9.5, 14.1]], requires_grad=True) + diag3 = torch.tensor([[2.8, 4.45], [9.5, 14.1]], requires_grad=True) + assert diag1.grad is None and diag2.grad is None and diag3.grad is None + dist12 = pot(diag1, diag2, internal_p=2, order=2, enable_autodiff=True) + dist30 = pot(diag3, torch.tensor([]), internal_p=2, order=2, enable_autodiff=True) + dist12.backward() + dist30.backward() + assert not torch.isnan(diag1.grad).any() and not torch.isnan(diag2.grad).any() and not torch.isnan(diag3.grad).any() + diag4 = torch.tensor([[0., 10.]], requires_grad=True) + diag5 = torch.tensor([[1., 11.], [3., 4.]], requires_grad=True) + dist45 = pot(diag4, diag5, internal_p=1, order=1, enable_autodiff=True) + assert dist45 == 3. + dist45.backward() + assert np.array_equal(diag4.grad, [[-1., -1.]]) + assert np.array_equal(diag5.grad, [[1., 1.], [-1., 1.]]) + diag6 = torch.tensor([[5., 10.]], requires_grad=True) + pot(diag6, diag6, internal_p=2, order=2, enable_autodiff=True).backward() + # https://github.com/jonasrauber/eagerpy/issues/6 + # assert np.array_equal(diag6.grad, [[0., 0.]]) +def test_wasserstein_distance_grad_tensorflow(): with tf.GradientTape() as tape: diag4 = tf.convert_to_tensor(tf.Variable(initial_value=np.array([[0., 10.]]), trainable=True)) diag5 = tf.convert_to_tensor(tf.Variable(initial_value=np.array([[1., 11.], [3., 4.]]), trainable=True)) -- cgit v1.2.3 From 3b839cae75a7e58b87216ee92356267bbe873e46 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 11:26:24 +0200 Subject: doc review: eigen 3.3.5 and cgal 5.2.0 is advised for perf reasons not only on weighted version --- src/Alpha_complex/doc/Intro_alpha_complex.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 78486ad6..fb051760 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -74,7 +74,7 @@ Table of Contents * [10^12,10^12+10^6]. Using `CGAL::Epick_d` makes the computations slightly faster, and the combinatorics are still * exact, but the computation of filtration values can exceptionally be arbitrarily bad. In all cases, we still * guarantee that the output is a valid filtration (faces have a filtration value no larger than their cofaces). - * - For performances reasons, it is advised to use `Alpha_complex` with \ref cgal ≥ 5.0.0. + * - For performances reasons, it is advised to use \ref eigen ≥ 3.3.5 and \ref cgal ≥ 5.2.0. * * \section pointsexample Example from points * @@ -160,7 +160,6 @@ Table of Contents * * \section weightedversion Weighted specific version * Requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 5.1.0. - * For performances reasons, it is advised to use \ref eigen ≥ 3.3.5 and \ref cgal ≥ 5.2.0. * * A weighted version for Alpha complex is available (cf. Alpha_complex). * -- cgit v1.2.3 From 9bba01c0afb2c931553d2c47af0104f407d22c01 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 13:18:59 +0200 Subject: code review: typename is useless here --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index a692dbc6..ae04e6e8 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -134,7 +134,7 @@ class Alpha_complex { using size_type = typename Triangulation::size_type; // Structure to switch from simplex tree vertex handle to CGAL vertex iterator. - using Vector_vertex_iterator = typename std::vector< CGAL_vertex_iterator >; + using Vector_vertex_iterator = std::vector< CGAL_vertex_iterator >; private: /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator. -- cgit v1.2.3 From f7faba86fced9c75c530c86665ca3c73429d8f12 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 13:19:52 +0200 Subject: code review: include what you use --- src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index a6760645..7c49bb14 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -11,8 +11,6 @@ #ifndef ALPHA_COMPLEX_ALPHA_KERNEL_D_H_ #define ALPHA_COMPLEX_ALPHA_KERNEL_D_H_ -#include // For EXACT or SAFE version -#include // For FAST version #include // for CGAL_VERSION_NR #include // for EIGEN_VERSION_AT_LEAST -- cgit v1.2.3 From 2d80f0e7f3e09167760338c15596b052050ddb55 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 14:00:51 +0200 Subject: code review: roll back include epick --- src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index 7c49bb14..d4dbd68b 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -12,6 +12,8 @@ #define ALPHA_COMPLEX_ALPHA_KERNEL_D_H_ #include // for CGAL_VERSION_NR +#include // For EXACT or SAFE version +#include // For FAST version #include // for EIGEN_VERSION_AT_LEAST -- cgit v1.2.3 From d6ca67fee4f9c2a97b64710a5b70ed66dd307372 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 14:50:57 +0200 Subject: code review: fix include what you use and compute_squared_radius_smallest_orthogonal_sphere_d_object use --- src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index d4dbd68b..fbb931d4 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -12,10 +12,8 @@ #define ALPHA_COMPLEX_ALPHA_KERNEL_D_H_ #include // for CGAL_VERSION_NR -#include // For EXACT or SAFE version -#include // For FAST version -#include // for EIGEN_VERSION_AT_LEAST +#include // for EIGEN_VERSION_AT_LEAST #include // for std::make_pair @@ -117,7 +115,7 @@ class Alpha_kernel_d { template FT get_squared_radius(PointIterator begin, PointIterator end) const { - return get_sphere(begin, end).weight(); + return kernel_.compute_squared_radius_smallest_orthogonal_sphere_d_object()(begin, end); } FT get_squared_radius(const Sphere& sph) const { -- cgit v1.2.3 From 298925b9c2dc3629f2d20ad9b85f5a410dee6fab Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 15:29:25 +0200 Subject: code review: use geom_trait for Point_d type --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index ae04e6e8..1963f02b 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -124,7 +124,7 @@ class Alpha_complex { using Sphere = typename A_kernel_d::Sphere; /** \brief A point, or a weighted point in Euclidean space.*/ - using Point_d = std::conditional_t; + using Point_d = typename Geom_traits::Point_d; private: // Vertex_iterator type from CGAL. -- cgit v1.2.3 From 51f4de9a42cbdf7686a0f36106b31c0d3296ccfa Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 5 Oct 2020 16:11:46 +0200 Subject: doc review: Add some precision about regular triangulations --- src/Alpha_complex/doc/Intro_alpha_complex.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index fb051760..c068b268 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -161,7 +161,9 @@ Table of Contents * \section weightedversion Weighted specific version * Requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 5.1.0. * - * A weighted version for Alpha complex is available (cf. Alpha_complex). + * A weighted version for Alpha complex is available (cf. Alpha_complex). It is like a usual Alpha complex, but based + * on a CGAL regular triangulation instead + * of Delaunay. * * This example builds the CGAL weighted alpha shapes from a small molecule, and initializes the alpha complex with * it. This example is taken from CGAL 3d -- cgit v1.2.3 From 30efe05d095051e14cbaf26d12fc2a67134e5a60 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 15 Oct 2020 16:43:54 +0200 Subject: Use unique_ptr for triangulation_ --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 1963f02b..4f7a7bd2 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -19,6 +19,7 @@ #include #include // isnan, fmax +#include // for std::unique_ptr #include #include // aka. Weighted Delaunay triangulation @@ -141,7 +142,7 @@ class Alpha_complex { * Vertex handles are inserted sequentially, starting at 0.*/ Vector_vertex_iterator vertex_handle_to_iterator_; /** \brief Pointer on the CGAL Delaunay triangulation.*/ - Triangulation* triangulation_; + std::unique_ptr triangulation_; /** \brief Kernel for triangulation_ functions access.*/ A_kernel_d kernel_; @@ -158,8 +159,7 @@ class Alpha_complex { * * @param[in] off_file_name OFF file [path and] name. */ - Alpha_complex(const std::string& off_file_name) - : triangulation_(nullptr) { + Alpha_complex(const std::string& off_file_name) { Gudhi::Points_off_reader off_reader(off_file_name); if (!off_reader.is_valid()) { std::cerr << "Alpha_complex - Unable to read file " << off_file_name << "\n"; @@ -180,8 +180,7 @@ class Alpha_complex { * Kernel::Point_d or Kernel::Weighted_point_d. */ template - Alpha_complex(const InputPointRange& points) - : triangulation_(nullptr) { + Alpha_complex(const InputPointRange& points) { init_from_range(points); } @@ -208,12 +207,6 @@ class Alpha_complex { init_from_range(weighted_points); } - /** \brief Alpha_complex destructor deletes the Delaunay triangulation. - */ - ~Alpha_complex() { - delete triangulation_; - } - // Forbid copy/move constructor/assignment operator Alpha_complex(const Alpha_complex& other) = delete; Alpha_complex& operator= (const Alpha_complex& other) = delete; @@ -249,7 +242,7 @@ class Alpha_complex { if (first != last) { // Delaunay triangulation init with point dimension. - triangulation_ = new Triangulation(kernel_.get_dimension(*first)); + triangulation_ = std::make_unique(kernel_.get_dimension(*first)); std::vector point_cloud(first, last); -- cgit v1.2.3 From 7f2eefc474cb32dc5d566c5c370b03478c1996ac Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 17 Oct 2020 19:14:09 +0200 Subject: Replace diameter (actually max y) with max distance to diagonal --- src/Bottleneck_distance/include/gudhi/Bottleneck.h | 2 +- .../include/gudhi/Persistence_graph.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Bottleneck_distance/include/gudhi/Bottleneck.h b/src/Bottleneck_distance/include/gudhi/Bottleneck.h index e466828a..ad437710 100644 --- a/src/Bottleneck_distance/include/gudhi/Bottleneck.h +++ b/src/Bottleneck_distance/include/gudhi/Bottleneck.h @@ -35,7 +35,7 @@ namespace persistence_diagram { inline double bottleneck_distance_approx(Persistence_graph& g, double e) { double b_lower_bound = 0.; - double b_upper_bound = g.diameter_bound(); + double b_upper_bound = g.max_dist_to_diagonal(); const double alpha = std::pow(g.size(), 1. / 5.); Graph_matching m(g); Graph_matching biggest_unperfect(g); diff --git a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h index e1e3522e..04c7c118 100644 --- a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h +++ b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h @@ -51,8 +51,8 @@ class Persistence_graph { double bottleneck_alive() const; /** \internal \brief Returns the O(n^2) sorted distances between the points. */ std::vector sorted_distances() const; - /** \internal \brief Returns an upper bound for the diameter of the convex hull of all non infinite points */ - double diameter_bound() const; + /** \internal \brief Returns an upper bound for the bottleneck distance of the finite points. */ + double max_dist_to_diagonal() const; /** \internal \brief Returns the corresponding internal point */ Internal_point get_u_point(int u_point_index) const; /** \internal \brief Returns the corresponding internal point */ @@ -160,13 +160,13 @@ inline Internal_point Persistence_graph::get_v_point(int v_point_index) const { return Internal_point(m, m, v_point_index); } -inline double Persistence_graph::diameter_bound() const { +inline double Persistence_graph::max_dist_to_diagonal() const { double max = 0.; - for (auto it = u.cbegin(); it != u.cend(); it++) - max = (std::max)(max, it->y()); - for (auto it = v.cbegin(); it != v.cend(); it++) - max = (std::max)(max, it->y()); - return max; + for (auto& p : u) + max = (std::max)(max, p.y() - p.x()); + for (auto& p : v) + max = (std::max)(max, p.y() - p.x()); + return max / 2; } } // namespace persistence_diagram -- cgit v1.2.3 From 27a488386c6a3b2b4dbac43534a36f18ef04ac80 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 17 Oct 2020 19:15:58 +0200 Subject: Don't put a (useless) point on the diagonal in the example --- src/python/doc/bottleneck_distance_user.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/python/doc/bottleneck_distance_user.rst b/src/python/doc/bottleneck_distance_user.rst index 6c6e08d9..418dd11f 100644 --- a/src/python/doc/bottleneck_distance_user.rst +++ b/src/python/doc/bottleneck_distance_user.rst @@ -35,19 +35,19 @@ The following example explains how the distance is computed: import gudhi - message = "Bottleneck distance = " + '%.1f' % gudhi.bottleneck_distance([[0., 0.]], [[0., 13.]]) + message = "Bottleneck distance = " + '%.1f' % gudhi.bottleneck_distance([[0., 2.]], [[1., 13.]]) print(message) .. testoutput:: - Bottleneck distance = 6.5 + Bottleneck distance = 6.0 .. figure:: ../../doc/Bottleneck_distance/bottleneck_distance_example.png :figclass: align-center - The point (0, 13) is at distance 6.5 from the diagonal and more - specifically from the point (6.5, 6.5) + The point (1, 13) is at distance 6 from the diagonal and more + specifically from the point (7, 7). Basic example -- cgit v1.2.3 From 911b589081831c98040448c489264fabfe8b5558 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 17 Oct 2020 23:29:39 +0200 Subject: Handle diagrams with a single point --- src/Bottleneck_distance/include/gudhi/Bottleneck.h | 6 +++++- src/Bottleneck_distance/include/gudhi/Persistence_graph.h | 2 +- src/Bottleneck_distance/test/bottleneck_unit_test.cpp | 5 +++++ src/python/doc/bottleneck_distance_user.rst | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Bottleneck_distance/include/gudhi/Bottleneck.h b/src/Bottleneck_distance/include/gudhi/Bottleneck.h index ad437710..c916898d 100644 --- a/src/Bottleneck_distance/include/gudhi/Bottleneck.h +++ b/src/Bottleneck_distance/include/gudhi/Bottleneck.h @@ -36,7 +36,11 @@ namespace persistence_diagram { inline double bottleneck_distance_approx(Persistence_graph& g, double e) { double b_lower_bound = 0.; double b_upper_bound = g.max_dist_to_diagonal(); - const double alpha = std::pow(g.size(), 1. / 5.); + int siz = g.size(); + if (siz <= 1) + // The value of alpha would be wrong in this case + return b_upper_bound; + const double alpha = std::pow(siz, 1. / 5.); Graph_matching m(g); Graph_matching biggest_unperfect(g); while (b_upper_bound - b_lower_bound > 2 * e) { diff --git a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h index 04c7c118..33f03b9c 100644 --- a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h +++ b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h @@ -45,7 +45,7 @@ class Persistence_graph { int corresponding_point_in_v(int u_point_index) const; /** \internal \brief Given a point from U and a point from V, returns the distance between those points. */ double distance(int u_point_index, int v_point_index) const; - /** \internal \brief Returns size = |U| = |V|. */ + /** \internal \brief Returns size = |U| + |V|. */ int size() const; /** \internal \brief Is there as many infinite points (alive components) in both diagrams ? */ double bottleneck_alive() const; diff --git a/src/Bottleneck_distance/test/bottleneck_unit_test.cpp b/src/Bottleneck_distance/test/bottleneck_unit_test.cpp index 2c520045..44141baa 100644 --- a/src/Bottleneck_distance/test/bottleneck_unit_test.cpp +++ b/src/Bottleneck_distance/test/bottleneck_unit_test.cpp @@ -153,4 +153,9 @@ BOOST_AUTO_TEST_CASE(global) { BOOST_CHECK(bottleneck_distance(v1, v2, 0.) <= upper_bound / 100.); BOOST_CHECK(bottleneck_distance(v1, v2, upper_bound / 10000.) <= upper_bound / 100. + upper_bound / 10000.); BOOST_CHECK(std::abs(bottleneck_distance(v1, v2, 0.) - bottleneck_distance(v1, v2, upper_bound / 10000.)) <= upper_bound / 10000.); + + std::vector< std::pair > empty; + std::vector< std::pair > one = {{8, 10}}; + BOOST_CHECK(bottleneck_distance(empty, empty) == 0); + BOOST_CHECK(bottleneck_distance(empty, one) == 1); } diff --git a/src/python/doc/bottleneck_distance_user.rst b/src/python/doc/bottleneck_distance_user.rst index 418dd11f..2c74c6dd 100644 --- a/src/python/doc/bottleneck_distance_user.rst +++ b/src/python/doc/bottleneck_distance_user.rst @@ -72,6 +72,6 @@ The output is: .. testoutput:: - Bottleneck distance approximation = 0.81 + Bottleneck distance approximation = 0.72 Bottleneck distance value = 0.75 -- cgit v1.2.3 From c66b9126429e1ff18f9ca69b27c5f357f071a697 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 19 Oct 2020 01:05:04 +0200 Subject: Handle duplicated points --- src/Subsampling/include/gudhi/choose_n_farthest_points.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index 66421a69..38c3a76b 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -111,6 +111,8 @@ void choose_n_farthest_points(Kernel const &k, curr_max_dist = dist_to_L[i]; curr_max_w = i; } + // If all that remains are duplicates of points already taken, stop. + if (curr_max_dist == 0) break; } } -- cgit v1.2.3 From dda7885005c343601c6630796eb56bdcf91a559f Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 22 Oct 2020 22:23:28 +0200 Subject: Document the change It would be possible to emit the duplicate points instead of stopping, but the current implementation makes that inconvenient. --- .../include/gudhi/choose_n_farthest_points.h | 3 ++- src/python/gudhi/subsampling.pyx | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index 38c3a76b..0e13fc5a 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -48,7 +48,8 @@ enum : std::size_t { * \tparam PointOutputIterator Output iterator whose value type is Kernel::Point_d. * \tparam DistanceOutputIterator Output iterator for distances. * \details It chooses `final_size` points from a random access range - * `input_pts` and outputs them in the output iterator `output_it`. It also + * `input_pts` (or the number of distinct points if `final_size` is larger) + * and outputs them in the output iterator `output_it`. It also * outputs the distance from each of those points to the set of previous * points in `dist_it`. * @param[in] k A kernel object. diff --git a/src/python/gudhi/subsampling.pyx b/src/python/gudhi/subsampling.pyx index f77c6f75..b11d07e5 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: Iterable[Iterable[float]]. + :type points: Iterable[Iterable[float]] Or @@ -42,14 +42,15 @@ def choose_n_farthest_points(points=None, off_file='', nb_points=0, starting_poi And in both cases - :param nb_points: Number of points of the subsample. - :type nb_points: unsigned. + :param nb_points: Number of points of the subsample (the subsample may be \ + smaller if there are fewer than nb_points distinct input points) + :type nb_points: int :param starting_point: The iteration starts with the landmark `starting \ - point`,which is the index of the point to start with. If not set, this \ + point`, which is the index of the point to start with. If not set, this \ index is chosen randomly. - :type starting_point: unsigned. + :type starting_point: int :returns: The subsample point set. - :rtype: List[List[float]]. + :rtype: List[List[float]] """ if off_file: if os.path.isfile(off_file): @@ -76,7 +77,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: Iterable[Iterable[float]]. + :type points: Iterable[Iterable[float]] Or @@ -86,7 +87,7 @@ def pick_n_random_points(points=None, off_file='', nb_points=0): And in both cases :param nb_points: Number of points of the subsample. - :type nb_points: unsigned. + :type nb_points: int :returns: The subsample point set. :rtype: List[List[float]] """ @@ -107,7 +108,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: Iterable[Iterable[float]]. + :type points: Iterable[Iterable[float]] Or @@ -118,7 +119,7 @@ def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): :param min_squared_dist: Minimum squared distance separating the output \ points. - :type min_squared_dist: float. + :type min_squared_dist: float :returns: The subsample point set. :rtype: List[List[float]] """ -- cgit v1.2.3 From 8aea376ed0b3c9066fb7e649f1cd66ffbed99a8d Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 22 Oct 2020 22:27:10 +0200 Subject: Simplify strange iterator use the syntax with [] is already used a few lines above --- src/Subsampling/include/gudhi/choose_n_farthest_points.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index 0e13fc5a..b70af8a0 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -100,7 +100,7 @@ void choose_n_farthest_points(Kernel const &k, *dist_it++ = dist_to_L[curr_max_w]; std::size_t i = 0; for (auto&& p : input_pts) { - double curr_dist = sqdist(p, *(std::begin(input_pts) + curr_max_w)); + double curr_dist = sqdist(p, input_pts[curr_max_w]); if (curr_dist < dist_to_L[i]) dist_to_L[i] = curr_dist; ++i; -- cgit v1.2.3 From 3ae0bc89f6ef853c1c52fc609bfe08097d3594db Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 22 Oct 2020 22:49:23 +0200 Subject: test with duplicated point --- src/Subsampling/test/test_choose_n_farthest_points.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Subsampling/test/test_choose_n_farthest_points.cpp b/src/Subsampling/test/test_choose_n_farthest_points.cpp index 5c4bd4cb..08b82d61 100644 --- a/src/Subsampling/test/test_choose_n_farthest_points.cpp +++ b/src/Subsampling/test/test_choose_n_farthest_points.cpp @@ -93,7 +93,15 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of std::vector point2({1.0, 0.0, 0.0, 0.0}); points.push_back(Point_d(point2.begin(), point2.end())); - // Choose all farthest points in a one point cloud + // Choose all farthest points among 2 points + Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + BOOST_CHECK(landmarks.size() == 2 && distances.size() == 2); + BOOST_CHECK(distances[0] == std::numeric_limits::infinity()); + BOOST_CHECK(distances[1] == 1); + landmarks.clear(); distances.clear(); + + // Ignore duplicated points + points.push_back(Point_d(point.begin(), point.end())); Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 2 && distances.size() == 2); BOOST_CHECK(distances[0] == std::numeric_limits::infinity()); -- cgit v1.2.3 From afafd56fdb4a53b66ca3354fc20f787f12340fa4 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 26 Oct 2020 10:56:25 +0100 Subject: for CGAL 5.2 pre-release to work --- src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h index fbb931d4..28d6d7a9 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h @@ -106,7 +106,7 @@ class Alpha_kernel_d { template Sphere get_sphere(PointIterator begin, PointIterator end) const { // power_center_d_object has been renamed between CGAL 5.1 and 5.2 -#if CGAL_VERSION_NR < 1050201000 +#if CGAL_VERSION_NR < 1050200000 return kernel_.power_center_d_object()(begin, end); #else return kernel_.construct_power_sphere_d_object()(begin, end); @@ -124,7 +124,7 @@ class Alpha_kernel_d { bool is_gabriel(const Sphere& circumcenter, const Weighted_point_d& point) { // power_center_d_object has been renamed between CGAL 5.1 and 5.2 -#if CGAL_VERSION_NR < 1050201000 +#if CGAL_VERSION_NR < 1050200000 return kernel_.power_distance_d_object()(circumcenter, point) >= 0; #else return kernel_.compute_power_product_d_object()(circumcenter, point) >= 0; -- cgit v1.2.3 From 699a89819da922222cedcd81b4a1553ee161a633 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 26 Oct 2020 10:58:19 +0100 Subject: code review: bad copy/paste that needs rephrase --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 4f7a7bd2..b315fa99 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -198,7 +198,7 @@ class Alpha_complex { */ template Alpha_complex(const InputPointRange& points, WeightRange weights) { - static_assert(Weighted, "This constructor is not available for non-weighted versions of Alpha_complex_3d"); + static_assert(Weighted, "This constructor is not available for non-weighted versions of Alpha_complex"); // FIXME: this test is only valid if we have a forward range GUDHI_CHECK(boost::size(weights) == boost::size(points), std::invalid_argument("Points number in range different from weights range number")); -- cgit v1.2.3 From 4d8c5c315b79260fbae05d359987c8d39a863d2d Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 27 Oct 2020 11:15:36 +0100 Subject: zero weighted test is guaranteed only for exact version --- src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index e8372656..cae9dbb5 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -29,14 +29,10 @@ // Use dynamic_dimension_tag for the user to be able to set dimension typedef CGAL::Epeck_d< CGAL::Dynamic_dimension_tag > Exact_kernel_d; -// Use static dimension_tag for the user not to be able to set dimension +// Use static dimension_tag to set dimension at 4 typedef CGAL::Epeck_d< CGAL::Dimension_tag<4> > Exact_kernel_s; -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Inexact_kernel_d; -// Use static dimension_tag for the user not to be able to set dimension -typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Inexact_kernel_s; -typedef boost::mpl::list list_of_kernel_variants; +typedef boost::mpl::list list_of_kernel_variants; BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_kernel_variants) { // Random points construction @@ -53,7 +49,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_kerne // Alpha complex from points Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); Gudhi::Simplex_tree<> simplex; - BOOST_CHECK(alpha_complex_from_points.create_complex(simplex)); + BOOST_CHECK(alpha_complex_from_points.create_complex(simplex, std::numeric_limits::Filtration_value>::infinity(), true)); std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : simplex.filtration_simplex_range()) { std::clog << " ( "; @@ -68,7 +64,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_kerne std::vector weights(20, 0.); Gudhi::alpha_complex::Alpha_complex alpha_complex_from_zero_weighted_points(points, weights); Gudhi::Simplex_tree<> zw_simplex; - BOOST_CHECK(alpha_complex_from_zero_weighted_points.create_complex(zw_simplex)); + BOOST_CHECK(alpha_complex_from_zero_weighted_points.create_complex(zw_simplex, std::numeric_limits::Filtration_value>::infinity(), true)); std::clog << "Iterator on zero weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; for (auto f_simplex : zw_simplex.filtration_simplex_range()) { -- cgit v1.2.3 From beaa5c2fa89ed92c84328383ac58f1e71cf510ff Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 27 Oct 2020 12:16:34 +0100 Subject: Add a test for non visible points (hidden by weights) --- .../test/Weighted_alpha_complex_unit_test.cpp | 35 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index cae9dbb5..cc63ac1f 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_kerne std::mt19937 rand_engine(rand_dev()); for (int idx = 0; idx < 20; idx++) { std::vector point {rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine)}; - points.emplace_back(Point_d(point.begin(), point.end())); + points.emplace_back(point.begin(), point.end()); } // Alpha complex from points @@ -108,8 +108,8 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { for (int idx = 0; idx < 20; idx++) { std::vector point {rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine)}; double weight = rd_wghts(rand_engine); - w_points_d.emplace_back(Weighted_point_d(Bare_point_d(point.begin(), point.end()), weight)); - w_points_3.emplace_back(Weighted_point_3(Bare_point_3(point[0], point[1], point[2]), weight)); + w_points_d.emplace_back(Bare_point_d(point.begin(), point.end()), weight); + w_points_3.emplace_back(Bare_point_3(point[0], point[1], point[2]), weight); } // Structures necessary for comparison @@ -185,3 +185,32 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { ++dD_itr; } } + +BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_non_visible_points) { + using Point_d = typename Exact_kernel_d::Point_d; + std::vector points; + std::vector p1 {0.}; + points.emplace_back(p1.begin(), p1.end()); + // closed enough points + std::vector p2 {0.1}; + points.emplace_back(p2.begin(), p2.end()); + std::vector weights {100., 0.01}; + + Gudhi::alpha_complex::Alpha_complex alpha_complex(points, weights); + Gudhi::Simplex_tree<> stree; + BOOST_CHECK(alpha_complex.create_complex(stree)); + + std::clog << "Iterator on weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + for (auto f_simplex : stree.filtration_simplex_range()) { + std::clog << " ( "; + for (auto vertex : stree.simplex_vertex_range(f_simplex)) { + std::clog << vertex << " "; + } + std::clog << ") -> " << "[" << stree.filtration(f_simplex) << "] "; + std::clog << std::endl; + } + + BOOST_CHECK(stree.filtration(stree.find({0})) == -100.); + BOOST_CHECK(stree.filtration(stree.find({1})) == stree.filtration(stree.find({0, 1}))); + +} \ No newline at end of file -- cgit v1.2.3 From 901fbd0ccdee2d9bb7794de8896d35aae8ede989 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 27 Oct 2020 14:45:25 +0100 Subject: Add a test about the filtration --- src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index cc63ac1f..b84ab3de 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -212,5 +212,6 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_non_visible_points) { BOOST_CHECK(stree.filtration(stree.find({0})) == -100.); BOOST_CHECK(stree.filtration(stree.find({1})) == stree.filtration(stree.find({0, 1}))); + BOOST_CHECK(stree.filtration(stree.find({1})) > 100000); } \ No newline at end of file -- cgit v1.2.3 From 705aa3b7ddc0a2bbbcc31c4b45e19792bd4ce9a5 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 28 Oct 2020 00:04:37 +0100 Subject: emplace_back --- src/Subsampling/test/test_choose_n_farthest_points.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Subsampling/test/test_choose_n_farthest_points.cpp b/src/Subsampling/test/test_choose_n_farthest_points.cpp index 08b82d61..b318d58e 100644 --- a/src/Subsampling/test/test_choose_n_farthest_points.cpp +++ b/src/Subsampling/test/test_choose_n_farthest_points.cpp @@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point, Kernel, list_of_tested for (FT k = 0; k < 5; k += 1.0) for (FT l = 0; l < 5; l += 1.0) { std::vector point({i, j, k, l}); - points.push_back(Point_d(point.begin(), point.end())); + points.emplace_back(point.begin(), point.end()); } landmarks.clear(); @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of landmarks.clear(); distances.clear(); std::vector point({0.0, 0.0, 0.0, 0.0}); - points.push_back(Point_d(point.begin(), point.end())); + points.emplace_back(point.begin(), point.end()); // Choose -1 farthest points in a one point cloud Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 1 && distances.size() == 1); @@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of landmarks.clear(); distances.clear(); std::vector point2({1.0, 0.0, 0.0, 0.0}); - points.push_back(Point_d(point2.begin(), point2.end())); + points.emplace_back(point2.begin(), point2.end()); // Choose all farthest points among 2 points Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 2 && distances.size() == 2); @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of landmarks.clear(); distances.clear(); // Ignore duplicated points - points.push_back(Point_d(point.begin(), point.end())); + points.emplace_back(point.begin(), point.end()); Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 2 && distances.size() == 2); BOOST_CHECK(distances[0] == std::numeric_limits::infinity()); -- cgit v1.2.3 From c311cace889373c141dc9c9319501d7ff6888b14 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 31 Oct 2020 22:28:36 +0100 Subject: Clean-ups in subsampling --- .../include/gudhi/pick_n_random_points.h | 10 ++++++--- src/Subsampling/include/gudhi/sparsify_point_set.h | 26 ++++++---------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/Subsampling/include/gudhi/pick_n_random_points.h b/src/Subsampling/include/gudhi/pick_n_random_points.h index a67b2b84..c2c71f83 100644 --- a/src/Subsampling/include/gudhi/pick_n_random_points.h +++ b/src/Subsampling/include/gudhi/pick_n_random_points.h @@ -44,6 +44,12 @@ void pick_n_random_points(Point_container const &points, Gudhi::Clock t; #endif + std::random_device rd; + std::mt19937 g(rd()); + +#if __cplusplus >= 201703L + std::sample(std::begin(points), std::end(points), output_it, final_size, g); +#else std::size_t nbP = boost::size(points); if (final_size > nbP) final_size = nbP; @@ -51,14 +57,12 @@ void pick_n_random_points(Point_container const &points, std::vector landmarks(nbP); std::iota(landmarks.begin(), landmarks.end(), 0); - std::random_device rd; - std::mt19937 g(rd()); - std::shuffle(landmarks.begin(), landmarks.end(), g); landmarks.resize(final_size); for (int l : landmarks) *output_it++ = points[l]; +#endif #ifdef GUDHI_SUBSAMPLING_PROFILING t.end(); diff --git a/src/Subsampling/include/gudhi/sparsify_point_set.h b/src/Subsampling/include/gudhi/sparsify_point_set.h index b30cec80..78e0da4a 100644 --- a/src/Subsampling/include/gudhi/sparsify_point_set.h +++ b/src/Subsampling/include/gudhi/sparsify_point_set.h @@ -11,6 +11,8 @@ #ifndef SPARSIFY_POINT_SET_H_ #define SPARSIFY_POINT_SET_H_ +#include + #include #ifdef GUDHI_SUBSAMPLING_PROFILING #include @@ -63,29 +65,15 @@ sparsify_point_set( // Parse the input points, and add them if they are not too close to // the other points std::size_t pt_idx = 0; - for (typename Point_range::const_iterator it_pt = input_pts.begin(); - it_pt != input_pts.end(); - ++it_pt, ++pt_idx) { - if (dropped_points[pt_idx]) + for (auto const& pt : input_pts) { + if (dropped_points[pt_idx++]) continue; - *output_it++ = *it_pt; - - auto ins_range = points_ds.incremental_nearest_neighbors(*it_pt); + *output_it++ = pt; // If another point Q is closer that min_squared_dist, mark Q to be dropped - for (auto const& neighbor : ins_range) { - std::size_t neighbor_point_idx = neighbor.first; - // If the neighbor is too close, we drop the neighbor - if (neighbor.second < min_squared_dist) { - // N.B.: If neighbor_point_idx < pt_idx, - // dropped_points[neighbor_point_idx] is already true but adding a - // test doesn't make things faster, so why bother? - dropped_points[neighbor_point_idx] = true; - } else { - break; - } - } + auto drop = [&dropped_points] (std::ptrdiff_t neighbor_point_idx) { dropped_points[neighbor_point_idx] = true; }; + points_ds.all_near_neighbors(pt, min_squared_dist, boost::make_function_output_iterator(std::ref(drop))); } #ifdef GUDHI_SUBSAMPLING_PROFILING -- cgit v1.2.3 From 2bbba93e7f0837b42def9bed13a6fa790c0eabda Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 31 Oct 2020 23:39:01 +0100 Subject: s/kernel/distance/ for choose_n_farthest_points argument --- .../include/gudhi/Sparse_rips_complex.h | 14 +---- src/Subsampling/example/CMakeLists.txt | 4 +- .../example/example_choose_n_farthest_points.cpp | 2 +- .../example/example_custom_distance.cpp | 44 +++++++++++++++ src/Subsampling/example/example_custom_kernel.cpp | 63 ---------------------- .../include/gudhi/choose_n_farthest_points.h | 26 +++++---- .../test/test_choose_n_farthest_points.cpp | 20 +++---- src/Witness_complex/doc/Witness_complex_doc.h | 6 +-- .../example/example_strong_witness_complex_off.cpp | 3 +- .../example/example_witness_complex_off.cpp | 3 +- .../example/example_witness_complex_sphere.cpp | 2 +- .../utilities/strong_witness_persistence.cpp | 3 +- .../utilities/weak_witness_persistence.cpp | 3 +- src/common/doc/examples.h | 2 +- src/common/doc/installation.h | 8 +-- src/python/include/Subsampling_interface.h | 10 ++-- 16 files changed, 93 insertions(+), 120 deletions(-) create mode 100644 src/Subsampling/example/example_custom_distance.cpp delete mode 100644 src/Subsampling/example/example_custom_kernel.cpp diff --git a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h index 1b250818..a5501004 100644 --- a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h +++ b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h @@ -67,8 +67,7 @@ class Sparse_rips_complex { : epsilon_(epsilon) { GUDHI_CHECK(epsilon > 0, "epsilon must be positive"); auto dist_fun = [&](Vertex_handle i, Vertex_handle j) { return distance(points[i], points[j]); }; - Ker kernel(dist_fun); - subsampling::choose_n_farthest_points(kernel, boost::irange(0, boost::size(points)), -1, -1, + subsampling::choose_n_farthest_points(dist_fun, boost::irange(0, boost::size(points)), -1, -1, std::back_inserter(sorted_points), std::back_inserter(params)); compute_sparse_graph(dist_fun, epsilon, mini, maxi); } @@ -128,17 +127,6 @@ class Sparse_rips_complex { } private: - // choose_n_farthest_points wants the distance function in this form... - template - struct Ker { - typedef std::size_t Point_d; // index into point range - Ker(Distance& d) : dist(d) {} - // Despite the name, this is not squared... - typedef Distance Squared_distance_d; - Squared_distance_d& squared_distance_d_object() const { return dist; } - Distance& dist; - }; - // PointRange must be random access. template void compute_sparse_graph(Distance& dist, double epsilon, Filtration_value mini, Filtration_value maxi) { diff --git a/src/Subsampling/example/CMakeLists.txt b/src/Subsampling/example/CMakeLists.txt index 28aab103..fb6875e1 100644 --- a/src/Subsampling/example/CMakeLists.txt +++ b/src/Subsampling/example/CMakeLists.txt @@ -3,7 +3,7 @@ project(Subsampling_examples) if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_executable(Subsampling_example_pick_n_random_points example_pick_n_random_points.cpp) add_executable(Subsampling_example_choose_n_farthest_points example_choose_n_farthest_points.cpp) - add_executable(Subsampling_example_custom_kernel example_custom_kernel.cpp) + add_executable(Subsampling_example_custom_distance example_custom_distance.cpp) add_executable(Subsampling_example_sparsify_point_set example_sparsify_point_set.cpp) target_link_libraries(Subsampling_example_sparsify_point_set ${CGAL_LIBRARY}) @@ -16,7 +16,7 @@ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) install(TARGETS Subsampling_example_pick_n_random_points DESTINATION bin) install(TARGETS Subsampling_example_choose_n_farthest_points DESTINATION bin) - install(TARGETS Subsampling_example_custom_kernel DESTINATION bin) + install(TARGETS Subsampling_example_custom_distance DESTINATION bin) install(TARGETS Subsampling_example_sparsify_point_set DESTINATION bin) endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/Subsampling/example/example_choose_n_farthest_points.cpp b/src/Subsampling/example/example_choose_n_farthest_points.cpp index 27cf5d4e..e8b3ce2d 100644 --- a/src/Subsampling/example/example_choose_n_farthest_points.cpp +++ b/src/Subsampling/example/example_choose_n_farthest_points.cpp @@ -20,7 +20,7 @@ int main(void) { K k; std::vector results; - Gudhi::subsampling::choose_n_farthest_points(k, points, 100, + Gudhi::subsampling::choose_n_farthest_points(k.squared_distance_d_object(), points, 100, Gudhi::subsampling::random_starting_point, std::back_inserter(results)); std::clog << "Before sparsification: " << points.size() << " points.\n"; diff --git a/src/Subsampling/example/example_custom_distance.cpp b/src/Subsampling/example/example_custom_distance.cpp new file mode 100644 index 00000000..3325b12d --- /dev/null +++ b/src/Subsampling/example/example_custom_distance.cpp @@ -0,0 +1,44 @@ +#include + +#include +#include +#include + + +typedef unsigned Point; + +/* The class Distance contains a distance function defined on the set of points {0, 1, 2, 3} + * and computes a distance according to the matrix: + * 0 1 2 4 + * 1 0 4 2 + * 2 4 0 1 + * 4 2 1 0 + */ +class Distance { + private: + std::vector> matrix_; + + public: + Distance() { + matrix_.push_back({0, 1, 2, 4}); + matrix_.push_back({1, 0, 4, 2}); + matrix_.push_back({2, 4, 0, 1}); + matrix_.push_back({4, 2, 1, 0}); + } + + double operator()(Point p1, Point p2) const { + return matrix_[p1][p2]; + } +}; + +int main(void) { + std::vector points = {0, 1, 2, 3}; + std::vector results; + + Gudhi::subsampling::choose_n_farthest_points(Distance(), points, 2, + Gudhi::subsampling::random_starting_point, + std::back_inserter(results)); + std::clog << "Before sparsification: " << points.size() << " points.\n"; + std::clog << "After sparsification: " << results.size() << " points.\n"; + std::clog << "Result table: {" << results[0] << "," << results[1] << "}\n"; +} diff --git a/src/Subsampling/example/example_custom_kernel.cpp b/src/Subsampling/example/example_custom_kernel.cpp deleted file mode 100644 index 535bf42a..00000000 --- a/src/Subsampling/example/example_custom_kernel.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include - -#include -#include -#include - - -/* The class Kernel contains a distance function defined on the set of points {0, 1, 2, 3} - * and computes a distance according to the matrix: - * 0 1 2 4 - * 1 0 4 2 - * 2 4 0 1 - * 4 2 1 0 - */ -class Kernel { - public: - typedef double FT; - typedef unsigned Point_d; - - // Class Squared_distance_d - class Squared_distance_d { - private: - std::vector> matrix_; - - public: - Squared_distance_d() { - matrix_.push_back(std::vector({0, 1, 2, 4})); - matrix_.push_back(std::vector({1, 0, 4, 2})); - matrix_.push_back(std::vector({2, 4, 0, 1})); - matrix_.push_back(std::vector({4, 2, 1, 0})); - } - - FT operator()(Point_d p1, Point_d p2) { - return matrix_[p1][p2]; - } - }; - - // Constructor - Kernel() {} - - // Object of type Squared_distance_d - Squared_distance_d squared_distance_d_object() const { - return Squared_distance_d(); - } -}; - -int main(void) { - typedef Kernel K; - typedef typename K::Point_d Point_d; - - K k; - std::vector points = {0, 1, 2, 3}; - std::vector results; - - Gudhi::subsampling::choose_n_farthest_points(k, points, 2, - Gudhi::subsampling::random_starting_point, - std::back_inserter(results)); - std::clog << "Before sparsification: " << points.size() << " points.\n"; - std::clog << "After sparsification: " << results.size() << " points.\n"; - std::clog << "Result table: {" << results[0] << "," << results[1] << "}\n"; - - return 0; -} diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index b70af8a0..561dcf3e 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -38,33 +38,33 @@ enum : std::size_t { * \ingroup subsampling * \brief Subsample by a greedy strategy of iteratively adding the farthest point from the * current chosen point set to the subsampling. - * The iteration starts with the landmark `starting point` or, if `starting point==random_starting_point`, with a random landmark. - * \tparam Kernel must provide a type Kernel::Squared_distance_d which is a model of the - * concept Kernel_d::Squared_distance_d (despite the name, taken from CGAL, this can be any kind of metric or proximity measure). - * It must also contain a public member `squared_distance_d_object()` that returns an object of this type. - * \tparam Point_range Range whose value type is Kernel::Point_d. It must provide random-access - * via `operator[]` and the points should be stored contiguously in memory. - * \tparam PointOutputIterator Output iterator whose value type is Kernel::Point_d. + * The iteration starts with the landmark `starting point` or, if `starting point==random_starting_point`, + * with a random landmark. + * \tparam Distance must provide an operator() that takes 2 points (value type of the range) + * and returns their distance (or some more general proximity measure). + * \tparam Point_range Random access range of points. + * \tparam PointOutputIterator Output iterator whose value type is the point type. * \tparam DistanceOutputIterator Output iterator for distances. * \details It chooses `final_size` points from a random access range * `input_pts` (or the number of distinct points if `final_size` is larger) * and outputs them in the output iterator `output_it`. It also * outputs the distance from each of those points to the set of previous * points in `dist_it`. - * @param[in] k A kernel object. + * @param[in] dist A distance function. * @param[in] input_pts Const reference to the input points. * @param[in] final_size The size of the subsample to compute. * @param[in] starting_point The seed in the farthest point algorithm. * @param[out] output_it The output iterator for points. * @param[out] dist_it The optional output iterator for distances. + * + * \warning Older versions of this function took a CGAL kernel as argument. Users need to replace `k` with `k.squared_distance_d_object()` in the first argument of every call to `choose_n_farthest_points`. * */ -template < typename Kernel, +template < typename Distance, typename Point_range, typename PointOutputIterator, typename DistanceOutputIterator = Null_output_iterator> -void choose_n_farthest_points(Kernel const &k, +void choose_n_farthest_points(Distance dist, Point_range const &input_pts, std::size_t final_size, std::size_t starting_point, @@ -86,8 +86,6 @@ void choose_n_farthest_points(Kernel const &k, starting_point = dis(gen); } - typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object(); - std::size_t current_number_of_landmarks = 0; // counter for landmarks const double infty = std::numeric_limits::infinity(); // infinity (see next entry) std::vector< double > dist_to_L(nb_points, infty); // vector of current distances to L from input_pts @@ -100,7 +98,7 @@ void choose_n_farthest_points(Kernel const &k, *dist_it++ = dist_to_L[curr_max_w]; std::size_t i = 0; for (auto&& p : input_pts) { - double curr_dist = sqdist(p, input_pts[curr_max_w]); + double curr_dist = dist(p, input_pts[curr_max_w]); if (curr_dist < dist_to_L[i]) dist_to_L[i] = curr_dist; ++i; diff --git a/src/Subsampling/test/test_choose_n_farthest_points.cpp b/src/Subsampling/test/test_choose_n_farthest_points.cpp index b318d58e..94793295 100644 --- a/src/Subsampling/test/test_choose_n_farthest_points.cpp +++ b/src/Subsampling/test/test_choose_n_farthest_points.cpp @@ -44,7 +44,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point, Kernel, list_of_tested landmarks.clear(); Kernel k; - Gudhi::subsampling::choose_n_farthest_points(k, points, 100, Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); + auto d = k.squared_distance_d_object(); + Gudhi::subsampling::choose_n_farthest_points(d, points, 100, Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); BOOST_CHECK(landmarks.size() == 100); for (auto landmark : landmarks) @@ -61,32 +62,33 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of std::vector< FT > distances; landmarks.clear(); Kernel k; + auto d = k.squared_distance_d_object(); // Choose -1 farthest points in an empty point cloud - Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + Gudhi::subsampling::choose_n_farthest_points(d, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 0); landmarks.clear(); distances.clear(); // Choose 0 farthest points in an empty point cloud - Gudhi::subsampling::choose_n_farthest_points(k, points, 0, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + Gudhi::subsampling::choose_n_farthest_points(d, points, 0, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 0); landmarks.clear(); distances.clear(); // Choose 1 farthest points in an empty point cloud - Gudhi::subsampling::choose_n_farthest_points(k, points, 1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + Gudhi::subsampling::choose_n_farthest_points(d, points, 1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 0); landmarks.clear(); distances.clear(); std::vector point({0.0, 0.0, 0.0, 0.0}); points.emplace_back(point.begin(), point.end()); // Choose -1 farthest points in a one point cloud - Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + Gudhi::subsampling::choose_n_farthest_points(d, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 1 && distances.size() == 1); BOOST_CHECK(distances[0] == std::numeric_limits::infinity()); landmarks.clear(); distances.clear(); // Choose 0 farthest points in a one point cloud - Gudhi::subsampling::choose_n_farthest_points(k, points, 0, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + Gudhi::subsampling::choose_n_farthest_points(d, points, 0, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 0 && distances.size() == 0); landmarks.clear(); distances.clear(); // Choose 1 farthest points in a one point cloud - Gudhi::subsampling::choose_n_farthest_points(k, points, 1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + Gudhi::subsampling::choose_n_farthest_points(d, points, 1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 1 && distances.size() == 1); BOOST_CHECK(distances[0] == std::numeric_limits::infinity()); landmarks.clear(); distances.clear(); @@ -94,7 +96,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of std::vector point2({1.0, 0.0, 0.0, 0.0}); points.emplace_back(point2.begin(), point2.end()); // Choose all farthest points among 2 points - Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + Gudhi::subsampling::choose_n_farthest_points(d, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 2 && distances.size() == 2); BOOST_CHECK(distances[0] == std::numeric_limits::infinity()); BOOST_CHECK(distances[1] == 1); @@ -102,7 +104,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_choose_farthest_point_limits, Kernel, list_of // Ignore duplicated points points.emplace_back(point.begin(), point.end()); - Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); + Gudhi::subsampling::choose_n_farthest_points(d, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances)); BOOST_CHECK(landmarks.size() == 2 && distances.size() == 2); BOOST_CHECK(distances[0] == std::numeric_limits::infinity()); BOOST_CHECK(distances[1] == 1); diff --git a/src/Witness_complex/doc/Witness_complex_doc.h b/src/Witness_complex/doc/Witness_complex_doc.h index 62203054..202f4539 100644 --- a/src/Witness_complex/doc/Witness_complex_doc.h +++ b/src/Witness_complex/doc/Witness_complex_doc.h @@ -92,11 +92,11 @@ int main(int argc, char * const argv[]) { // Choose landmarks (one can choose either of the two methods below) // Gudhi::subsampling::pick_n_random_points(point_vector, nbL, std::back_inserter(landmarks)); - Gudhi::subsampling::choose_n_farthest_points(K(), point_vector, nbL, Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); + Gudhi::subsampling::choose_n_farthest_points(K().squared_distance_d_object(), point_vector, nbL, + Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); // Compute witness complex - Witness_complex witness_complex(landmarks, - point_vector); + Witness_complex witness_complex(landmarks, point_vector); witness_complex.create_complex(simplex_tree, alpha2, lim_dim); } diff --git a/src/Witness_complex/example/example_strong_witness_complex_off.cpp b/src/Witness_complex/example/example_strong_witness_complex_off.cpp index 583a04ab..2bb135bf 100644 --- a/src/Witness_complex/example/example_strong_witness_complex_off.cpp +++ b/src/Witness_complex/example/example_strong_witness_complex_off.cpp @@ -43,7 +43,8 @@ int main(int argc, char* const argv[]) { // Choose landmarks (decomment one of the following two lines) // Gudhi::subsampling::pick_n_random_points(point_vector, nbL, std::back_inserter(landmarks)); - Gudhi::subsampling::choose_n_farthest_points(K(), point_vector, nbL, Gudhi::subsampling::random_starting_point, + Gudhi::subsampling::choose_n_farthest_points(K().squared_distance_d_object(), point_vector, + nbL, Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); // Compute witness complex diff --git a/src/Witness_complex/example/example_witness_complex_off.cpp b/src/Witness_complex/example/example_witness_complex_off.cpp index 3635da78..e1384c73 100644 --- a/src/Witness_complex/example/example_witness_complex_off.cpp +++ b/src/Witness_complex/example/example_witness_complex_off.cpp @@ -47,7 +47,8 @@ int main(int argc, char * const argv[]) { // Choose landmarks (decomment one of the following two lines) // Gudhi::subsampling::pick_n_random_points(point_vector, nbL, std::back_inserter(landmarks)); - Gudhi::subsampling::choose_n_farthest_points(K(), point_vector, nbL, Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); + Gudhi::subsampling::choose_n_farthest_points(K().squared_distance_d_object(), point_vector, nbL, + Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); // Compute witness complex start = clock(); diff --git a/src/Witness_complex/example/example_witness_complex_sphere.cpp b/src/Witness_complex/example/example_witness_complex_sphere.cpp index 78d5db4f..12a56de4 100644 --- a/src/Witness_complex/example/example_witness_complex_sphere.cpp +++ b/src/Witness_complex/example/example_witness_complex_sphere.cpp @@ -53,7 +53,7 @@ int main(int argc, char* const argv[]) { // Choose landmarks start = clock(); // Gudhi::subsampling::pick_n_random_points(point_vector, number_of_landmarks, std::back_inserter(landmarks)); - Gudhi::subsampling::choose_n_farthest_points(K(), point_vector, number_of_landmarks, + Gudhi::subsampling::choose_n_farthest_points(K().squared_distance_d_object(), point_vector, number_of_landmarks, Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); diff --git a/src/Witness_complex/utilities/strong_witness_persistence.cpp b/src/Witness_complex/utilities/strong_witness_persistence.cpp index 1f61c77c..614de0d4 100644 --- a/src/Witness_complex/utilities/strong_witness_persistence.cpp +++ b/src/Witness_complex/utilities/strong_witness_persistence.cpp @@ -61,7 +61,8 @@ int main(int argc, char* argv[]) { // Choose landmarks (decomment one of the following two lines) // Gudhi::subsampling::pick_n_random_points(point_vector, nbL, std::back_inserter(landmarks)); - Gudhi::subsampling::choose_n_farthest_points(K(), witnesses, nbL, Gudhi::subsampling::random_starting_point, + Gudhi::subsampling::choose_n_farthest_points(K().squared_distance_d_object(), witnesses, nbL, + Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); // Compute witness complex diff --git a/src/Witness_complex/utilities/weak_witness_persistence.cpp b/src/Witness_complex/utilities/weak_witness_persistence.cpp index 93050af5..5ea31d6b 100644 --- a/src/Witness_complex/utilities/weak_witness_persistence.cpp +++ b/src/Witness_complex/utilities/weak_witness_persistence.cpp @@ -61,7 +61,8 @@ int main(int argc, char* argv[]) { // Choose landmarks (decomment one of the following two lines) // Gudhi::subsampling::pick_n_random_points(point_vector, nbL, std::back_inserter(landmarks)); - Gudhi::subsampling::choose_n_farthest_points(K(), witnesses, nbL, Gudhi::subsampling::random_starting_point, + Gudhi::subsampling::choose_n_farthest_points(K().squared_distance_d_object(), witnesses, nbL, + Gudhi::subsampling::random_starting_point, std::back_inserter(landmarks)); // Compute witness complex diff --git a/src/common/doc/examples.h b/src/common/doc/examples.h index c19b3444..474f8699 100644 --- a/src/common/doc/examples.h +++ b/src/common/doc/examples.h @@ -42,7 +42,7 @@ * @example Persistence_representations/persistence_landscape.cpp * @example Tangential_complex/example_basic.cpp * @example Tangential_complex/example_with_perturb.cpp - * @example Subsampling/example_custom_kernel.cpp + * @example Subsampling/example_custom_distance.cpp * @example Subsampling/example_choose_n_farthest_points.cpp * @example Subsampling/example_sparsify_point_set.cpp * @example Subsampling/example_pick_n_random_points.cpp diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index 9df1c2f0..a6b9292b 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -113,8 +113,8 @@ make doxygen * Spatial_searching/example_spatial_searching.cpp * \li * Subsampling/example_choose_n_farthest_points.cpp - * \li - * Subsampling/example_custom_kernel.cpp + * \li + * Subsampling/example_custom_distance.cpp * \li * Subsampling/example_pick_n_random_points.cpp * \li @@ -153,8 +153,8 @@ make doxygen * Spatial_searching/example_spatial_searching.cpp * \li * Subsampling/example_choose_n_farthest_points.cpp - * \li - * Subsampling/example_custom_kernel.cpp + * \li + * Subsampling/example_custom_distance.cpp * \li * Subsampling/example_pick_n_random_points.cpp * \li diff --git a/src/python/include/Subsampling_interface.h b/src/python/include/Subsampling_interface.h index cdda851f..6aee7231 100644 --- a/src/python/include/Subsampling_interface.h +++ b/src/python/include/Subsampling_interface.h @@ -11,6 +11,7 @@ #ifndef INCLUDE_SUBSAMPLING_INTERFACE_H_ #define INCLUDE_SUBSAMPLING_INTERFACE_H_ +#include #include #include #include @@ -27,14 +28,13 @@ namespace subsampling { using Subsampling_dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; using Subsampling_point_d = Subsampling_dynamic_kernel::Point_d; -using Subsampling_ft = Subsampling_dynamic_kernel::FT; // ------ choose_n_farthest_points ------ std::vector> subsampling_n_farthest_points(const std::vector>& points, unsigned nb_points) { std::vector> landmarks; - Subsampling_dynamic_kernel k; - choose_n_farthest_points(k, points, nb_points, random_starting_point, std::back_inserter(landmarks)); + choose_n_farthest_points(Euclidean_distance(), points, nb_points, + random_starting_point, std::back_inserter(landmarks)); return landmarks; } @@ -42,8 +42,8 @@ std::vector> subsampling_n_farthest_points(const std::vector std::vector> subsampling_n_farthest_points(const std::vector>& points, unsigned nb_points, unsigned starting_point) { std::vector> landmarks; - Subsampling_dynamic_kernel k; - choose_n_farthest_points(k, points, nb_points, starting_point, std::back_inserter(landmarks)); + choose_n_farthest_points(Euclidean_distance(), points, nb_points, + starting_point, std::back_inserter(landmarks)); return landmarks; } -- cgit v1.2.3 From e3492366b040a0cac046498cdb8c2ecddfd818a9 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 31 Oct 2020 23:55:57 +0100 Subject: long line --- src/Subsampling/include/gudhi/choose_n_farthest_points.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index 561dcf3e..f22cb2d7 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -57,7 +57,8 @@ enum : std::size_t { * @param[out] output_it The output iterator for points. * @param[out] dist_it The optional output iterator for distances. * - * \warning Older versions of this function took a CGAL kernel as argument. Users need to replace `k` with `k.squared_distance_d_object()` in the first argument of every call to `choose_n_farthest_points`. + * \warning Older versions of this function took a CGAL kernel as argument. Users need to replace `k` with + * `k.squared_distance_d_object()` in the first argument of every call to `choose_n_farthest_points`. * */ template < typename Distance, -- cgit v1.2.3 From c1579e92d6cc78958522604769b0bc595c5f0eae Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 1 Nov 2020 00:13:10 +0100 Subject: release notes --- .github/next_release.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/next_release.md b/.github/next_release.md index cd2376eb..54f389d1 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -12,6 +12,9 @@ Below is a list of changes made since GUDHI 3.3.0: - [Module](link) - ... +- [Subsampling](https://gudhi.inria.fr/doc/latest/group__subsampling.html) + - The C++ function `choose_n_farthest_points()` now takes a distance function instead of a kernel as first argument, users can replace `k` with `k.squared_distance_d_object()` in each call in their code. + - Miscellaneous - The [list of bugs that were solved since GUDHI-3.3.0](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.4.0+is%3Aclosed) is available on GitHub. -- cgit v1.2.3 From c54a40fc6293fd746e1842f6811efae96df36bed Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 1 Nov 2020 20:42:43 +0100 Subject: Document that only double is supported. --- src/Subsampling/include/gudhi/choose_n_farthest_points.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index f22cb2d7..bdd2993a 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -41,7 +41,7 @@ enum : std::size_t { * The iteration starts with the landmark `starting point` or, if `starting point==random_starting_point`, * with a random landmark. * \tparam Distance must provide an operator() that takes 2 points (value type of the range) - * and returns their distance (or some more general proximity measure). + * and returns their distance (or some more general proximity measure) as a `double`. * \tparam Point_range Random access range of points. * \tparam PointOutputIterator Output iterator whose value type is the point type. * \tparam DistanceOutputIterator Output iterator for distances. @@ -88,6 +88,8 @@ void choose_n_farthest_points(Distance dist, } std::size_t current_number_of_landmarks = 0; // counter for landmarks + static_assert(std::numeric_limits::has_infinity); + // FIXME: don't hard-code the type as double. For Epeck_d, we also want to handle types that do not have an infinity. const double infty = std::numeric_limits::infinity(); // infinity (see next entry) std::vector< double > dist_to_L(nb_points, infty); // vector of current distances to L from input_pts -- cgit v1.2.3 From 7d8e6d025436f269bc2e09292f118c4d8a035660 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 1 Nov 2020 20:50:40 +0100 Subject: Doc tweaks. --- src/Subsampling/include/gudhi/choose_n_farthest_points.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index bdd2993a..3c337025 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -38,20 +38,21 @@ enum : std::size_t { * \ingroup subsampling * \brief Subsample by a greedy strategy of iteratively adding the farthest point from the * current chosen point set to the subsampling. + * \details * The iteration starts with the landmark `starting point` or, if `starting point==random_starting_point`, * with a random landmark. + * It chooses `final_size` points from a random access range + * `input_pts` (or the number of distinct points if `final_size` is larger) + * and outputs them in the output iterator `output_it`. It also + * outputs the distance from each of those points to the set of previous + * points in `dist_it`. * \tparam Distance must provide an operator() that takes 2 points (value type of the range) * and returns their distance (or some more general proximity measure) as a `double`. * \tparam Point_range Random access range of points. * \tparam PointOutputIterator Output iterator whose value type is the point type. * \tparam DistanceOutputIterator Output iterator for distances. - * \details It chooses `final_size` points from a random access range - * `input_pts` (or the number of distinct points if `final_size` is larger) - * and outputs them in the output iterator `output_it`. It also - * outputs the distance from each of those points to the set of previous - * points in `dist_it`. * @param[in] dist A distance function. - * @param[in] input_pts Const reference to the input points. + * @param[in] input_pts The input points. * @param[in] final_size The size of the subsample to compute. * @param[in] starting_point The seed in the farthest point algorithm. * @param[out] output_it The output iterator for points. -- cgit v1.2.3 From 20c50414163aabe6216c638b25c9568cfd1db458 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 1 Nov 2020 21:04:21 +0100 Subject: The example does not need CGAL/eigen anymore. I had done a search and replace without checking. I don't understand why there are "install" directives for examples... --- src/Subsampling/example/CMakeLists.txt | 5 +++-- src/common/doc/installation.h | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Subsampling/example/CMakeLists.txt b/src/Subsampling/example/CMakeLists.txt index fb6875e1..bb02b37d 100644 --- a/src/Subsampling/example/CMakeLists.txt +++ b/src/Subsampling/example/CMakeLists.txt @@ -3,7 +3,6 @@ project(Subsampling_examples) if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_executable(Subsampling_example_pick_n_random_points example_pick_n_random_points.cpp) add_executable(Subsampling_example_choose_n_farthest_points example_choose_n_farthest_points.cpp) - add_executable(Subsampling_example_custom_distance example_custom_distance.cpp) add_executable(Subsampling_example_sparsify_point_set example_sparsify_point_set.cpp) target_link_libraries(Subsampling_example_sparsify_point_set ${CGAL_LIBRARY}) @@ -16,7 +15,9 @@ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) install(TARGETS Subsampling_example_pick_n_random_points DESTINATION bin) install(TARGETS Subsampling_example_choose_n_farthest_points DESTINATION bin) - install(TARGETS Subsampling_example_custom_distance DESTINATION bin) install(TARGETS Subsampling_example_sparsify_point_set DESTINATION bin) endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + +add_executable(Subsampling_example_custom_distance example_custom_distance.cpp) +install(TARGETS Subsampling_example_custom_distance DESTINATION bin) diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index a6b9292b..c2e63a24 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -113,8 +113,6 @@ make doxygen * Spatial_searching/example_spatial_searching.cpp * \li * Subsampling/example_choose_n_farthest_points.cpp - * \li - * Subsampling/example_custom_distance.cpp * \li * Subsampling/example_pick_n_random_points.cpp * \li @@ -153,8 +151,6 @@ make doxygen * Spatial_searching/example_spatial_searching.cpp * \li * Subsampling/example_choose_n_farthest_points.cpp - * \li - * Subsampling/example_custom_distance.cpp * \li * Subsampling/example_pick_n_random_points.cpp * \li -- cgit v1.2.3 From 666f3f54498f47f1bc1cddbd522e5f53b9aae63a Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Nov 2020 09:27:21 +0100 Subject: Add comment in code for get_boundaries if not interested in filtration values --- src/python/gudhi/simplex_tree.pyx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index c671da56..813dc5c2 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -287,6 +287,8 @@ cdef class SimplexTree: def get_boundaries(self, simplex): """This function returns a generator with the boundaries of a given N-simplex. + If you do not need the filtration values, the boundary can also be obtained as + :code:`itertools.combinations(simplex,len(simplex)-1)`. :param simplex: The N-simplex, represented by a list of vertex. :type simplex: list of int. -- cgit v1.2.3 From 69c70afd0442774582b7e930bdab603600a3e750 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Nov 2020 11:33:39 +0100 Subject: doc review: explain briefly test aims --- .../test/Alpha_kernel_d_unit_test.cpp | 5 ++++ .../test/Weighted_alpha_complex_unit_test.cpp | 30 ++++++++++++++-------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp index 6eae103d..6da4c084 100644 --- a/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp @@ -37,6 +37,8 @@ typedef CGAL::Epick_d< CGAL::Dimension_tag<4> > Inexact_kernel_s; typedef boost::mpl::list list_of_kernel_variants; BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_dimension, TestedKernel, list_of_kernel_variants) { + // Test for a point (weighted or not) in 4d, that the dimension is 4. + Gudhi::alpha_complex::Alpha_kernel_d kernel; std::vector p0 {0., 1., 2., 3.}; typename TestedKernel::Point_d p0_d(p0.begin(), p0.end()); @@ -52,6 +54,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_dimension, TestedKernel, list_of_ke } BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_kernel_d_sphere, TestedKernel, list_of_kernel_variants) { + // Test with 5 points on a 3-sphere, that get_sphere returns the same center and squared radius + // for dD unweighted and for dD weighted with all weights at 0. + using Unweighted_kernel = Gudhi::alpha_complex::Alpha_kernel_d; // Sphere: (x-1)² + (y-1)² + z² + t² = 1 // At least 5 points for a 3-sphere diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index b84ab3de..2cd66963 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -27,14 +27,14 @@ #include #include -// Use dynamic_dimension_tag for the user to be able to set dimension -typedef CGAL::Epeck_d< CGAL::Dynamic_dimension_tag > Exact_kernel_d; -// Use static dimension_tag to set dimension at 4 -typedef CGAL::Epeck_d< CGAL::Dimension_tag<4> > Exact_kernel_s; +using list_of_exact_kernel_variants = boost::mpl::list, + CGAL::Epeck_d< CGAL::Dimension_tag<4> > + > ; -typedef boost::mpl::list list_of_kernel_variants; +BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_exact_kernel_variants) { + // Check that in exact mode for static dimension 4 the code for dD unweighted and for dD weighted with all weights + // 0 give exactly the same simplex tree (simplices and filtration values). -BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_kernel_variants) { // Random points construction using Point_d = typename Kernel::Point_d; std::vector points; @@ -89,6 +89,8 @@ bool cgal_3d_point_sort (Point_d a,Point_d b) { } BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { + // check that for random weighted 3d points in safe mode the 3D and dD codes give the same result with some tolerance + // Random points construction using Kernel_dD = CGAL::Epeck_d< CGAL::Dimension_tag<3> >; using Bare_point_d = typename Kernel_dD::Point_d; @@ -186,17 +188,25 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { } } -BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_non_visible_points) { - using Point_d = typename Exact_kernel_d::Point_d; +using list_of_1d_kernel_variants = boost::mpl::list, + CGAL::Epeck_d< CGAL::Dimension_tag<1>>, + CGAL::Epick_d< CGAL::Dynamic_dimension_tag >, + CGAL::Epick_d< CGAL::Dimension_tag<1>> + >; + +BOOST_AUTO_TEST_CASE_TEMPLATE(Weighted_alpha_complex_non_visible_points, Kernel, list_of_1d_kernel_variants) { + // check that for 2 closed weighted 1-d points, one with a high weight to hide the second one with a small weight, + // that the point with a small weight has the same high filtration value than the edge formed by the 2 points + using Point_d = typename Kernel::Point_d; std::vector points; std::vector p1 {0.}; points.emplace_back(p1.begin(), p1.end()); // closed enough points std::vector p2 {0.1}; points.emplace_back(p2.begin(), p2.end()); - std::vector weights {100., 0.01}; + std::vector weights {100., 0.01}; - Gudhi::alpha_complex::Alpha_complex alpha_complex(points, weights); + Gudhi::alpha_complex::Alpha_complex alpha_complex(points, weights); Gudhi::Simplex_tree<> stree; BOOST_CHECK(alpha_complex.create_complex(stree)); -- cgit v1.2.3 From baaf350869dbd5ff78e22cc4c3de9b8ab35b75ba Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Nov 2020 11:56:52 +0100 Subject: code review: use relative error --- src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index 2cd66963..3df76dbf 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -179,8 +179,8 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { std::clog << std::endl; BOOST_CHECK(false); } - // I had to make a hard limit as it is converted from Kernel::FT - if (std::fabs(d3_itr->second - dD_itr->second) > 1e-5) { + // In safe mode, relative error is less than 1e-5 (can be changed with set_relative_precision_of_to_double) + if (std::fabs(d3_itr->second - dD_itr->second) / std::fabs(d3_itr->second) > 1e-5) { std::clog << d3_itr->second << " versus " << dD_itr->second << " diff " << std::fabs(d3_itr->second - dD_itr->second) << std::endl; BOOST_CHECK(false); } -- cgit v1.2.3 From 05e28e39717c4ca5871b13a350c4b142ec9a173b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Nov 2020 14:09:05 +0100 Subject: code review: use Marc's trick to test relative error --- .../test/Weighted_alpha_complex_unit_test.cpp | 38 ++++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp index 3df76dbf..d267276c 100644 --- a/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp @@ -49,31 +49,32 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Zero_weighted_alpha_complex, Kernel, list_of_exact // Alpha complex from points Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); Gudhi::Simplex_tree<> simplex; - BOOST_CHECK(alpha_complex_from_points.create_complex(simplex, std::numeric_limits::Filtration_value>::infinity(), true)); - std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + Gudhi::Simplex_tree<>::Filtration_value infty = std::numeric_limits::Filtration_value>::infinity(); + BOOST_CHECK(alpha_complex_from_points.create_complex(simplex, infty, true)); + std::clog << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" + << std::endl; for (auto f_simplex : simplex.filtration_simplex_range()) { std::clog << " ( "; for (auto vertex : simplex.simplex_vertex_range(f_simplex)) { std::clog << vertex << " "; } - std::clog << ") -> " << "[" << simplex.filtration(f_simplex) << "] "; - std::clog << std::endl; + std::clog << ") -> " << "[" << simplex.filtration(f_simplex) << "] " << std::endl; } // Alpha complex from zero weighted points std::vector weights(20, 0.); Gudhi::alpha_complex::Alpha_complex alpha_complex_from_zero_weighted_points(points, weights); Gudhi::Simplex_tree<> zw_simplex; - BOOST_CHECK(alpha_complex_from_zero_weighted_points.create_complex(zw_simplex, std::numeric_limits::Filtration_value>::infinity(), true)); + BOOST_CHECK(alpha_complex_from_zero_weighted_points.create_complex(zw_simplex, infty, true)); - std::clog << "Iterator on zero weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + std::clog << "Iterator on zero weighted alpha complex simplices in the filtration order, with [filtration value]:" + << std::endl; for (auto f_simplex : zw_simplex.filtration_simplex_range()) { std::clog << " ( "; for (auto vertex : zw_simplex.simplex_vertex_range(f_simplex)) { std::clog << vertex << " "; } - std::clog << ") -> " << "[" << zw_simplex.filtration(f_simplex) << "] "; - std::clog << std::endl; + std::clog << ") -> " << "[" << zw_simplex.filtration(f_simplex) << "] " << std::endl; } BOOST_CHECK(zw_simplex == simplex); @@ -125,7 +126,8 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { Gudhi::Simplex_tree<> w_simplex_d; BOOST_CHECK(alpha_complex_dD_from_weighted_points.create_complex(w_simplex_d)); - std::clog << "Iterator on weighted alpha complex dD simplices in the filtration order, with [filtration value]:" << std::endl; + std::clog << "Iterator on weighted alpha complex dD simplices in the filtration order, with [filtration value]:" + << std::endl; for (auto f_simplex : w_simplex_d.filtration_simplex_range()) { Points points; for (auto vertex : w_simplex_d.simplex_vertex_range(f_simplex)) { @@ -148,7 +150,8 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { Gudhi::Simplex_tree<> w_simplex_3; BOOST_CHECK(alpha_complex_3D_from_weighted_points.create_complex(w_simplex_3)); - std::clog << "Iterator on weighted alpha complex 3D simplices in the filtration order, with [filtration value]:" << std::endl; + std::clog << "Iterator on weighted alpha complex 3D simplices in the filtration order, with [filtration value]:" + << std::endl; for (auto f_simplex : w_simplex_3.filtration_simplex_range()) { Points points; for (auto vertex : w_simplex_3.simplex_vertex_range(f_simplex)) { @@ -161,8 +164,7 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { for (auto point : points) { std::clog << point[0] << " " << point[1] << " " << point[2] << " | "; } - std::clog << ") -> " << "[" << w_simplex_3.filtration(f_simplex) << "] "; - std::clog << std::endl; + std::clog << ") -> " << "[" << w_simplex_3.filtration(f_simplex) << "] " << std::endl; pts_fltr_3d[points] = w_simplex_d.filtration(f_simplex); } @@ -180,8 +182,9 @@ BOOST_AUTO_TEST_CASE(Weighted_alpha_complex_3d_comparison) { BOOST_CHECK(false); } // In safe mode, relative error is less than 1e-5 (can be changed with set_relative_precision_of_to_double) - if (std::fabs(d3_itr->second - dD_itr->second) / std::fabs(d3_itr->second) > 1e-5) { - std::clog << d3_itr->second << " versus " << dD_itr->second << " diff " << std::fabs(d3_itr->second - dD_itr->second) << std::endl; + if (std::fabs(d3_itr->second - dD_itr->second) > 1e-5 * (std::fabs(d3_itr->second) + std::fabs(dD_itr->second))) { + std::clog << d3_itr->second << " versus " << dD_itr->second << " diff " + << std::fabs(d3_itr->second - dD_itr->second) << std::endl; BOOST_CHECK(false); } ++dD_itr; @@ -210,18 +213,17 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Weighted_alpha_complex_non_visible_points, Kernel, Gudhi::Simplex_tree<> stree; BOOST_CHECK(alpha_complex.create_complex(stree)); - std::clog << "Iterator on weighted alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; + std::clog << "Iterator on weighted alpha complex simplices in the filtration order, with [filtration value]:" + << std::endl; for (auto f_simplex : stree.filtration_simplex_range()) { std::clog << " ( "; for (auto vertex : stree.simplex_vertex_range(f_simplex)) { std::clog << vertex << " "; } - std::clog << ") -> " << "[" << stree.filtration(f_simplex) << "] "; - std::clog << std::endl; + std::clog << ") -> " << "[" << stree.filtration(f_simplex) << "] " << std::endl; } BOOST_CHECK(stree.filtration(stree.find({0})) == -100.); BOOST_CHECK(stree.filtration(stree.find({1})) == stree.filtration(stree.find({0, 1}))); BOOST_CHECK(stree.filtration(stree.find({1})) > 100000); - } \ No newline at end of file -- cgit v1.2.3 From 2d4c69d698df7e40709ec0e38463b4cf30ee388d Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Nov 2020 17:39:07 +0100 Subject: Fix #416 by adding full path to introduction.rst - maybe strange with conda or pip installation --- 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 98d058fc..1d6745fd 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -65,7 +65,7 @@ for module in pybind11_modules: )) # read the contents of introduction.rst -with open("introduction.rst", "r") as fh: +with open("@CMAKE_CURRENT_BINARY_DIR@/introduction.rst", "r") as fh: long_description = fh.read() setup( -- cgit v1.2.3 From 85c66c66e6c8dfe9ba74b3bfa0012a550e8466ec Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Nov 2020 17:39:51 +0100 Subject: Fix #415 by removing all install cmake targets from examples --- src/Bitmap_cubical_complex/example/CMakeLists.txt | 2 -- src/Nerve_GIC/example/CMakeLists.txt | 3 --- src/Persistence_representations/example/CMakeLists.txt | 6 ------ src/Persistent_cohomology/example/CMakeLists.txt | 7 ------- src/Rips_complex/example/CMakeLists.txt | 5 ----- src/Skeleton_blocker/example/CMakeLists.txt | 4 ---- src/Spatial_searching/example/CMakeLists.txt | 1 - src/Subsampling/example/CMakeLists.txt | 5 ----- src/Tangential_complex/example/CMakeLists.txt | 2 -- src/Witness_complex/example/CMakeLists.txt | 7 ------- 10 files changed, 42 deletions(-) diff --git a/src/Bitmap_cubical_complex/example/CMakeLists.txt b/src/Bitmap_cubical_complex/example/CMakeLists.txt index dc659f2d..0ff290ef 100644 --- a/src/Bitmap_cubical_complex/example/CMakeLists.txt +++ b/src/Bitmap_cubical_complex/example/CMakeLists.txt @@ -6,5 +6,3 @@ if (TBB_FOUND) endif() add_test(NAME Bitmap_cubical_complex_example_random COMMAND $ "2" "100" "100") - -install(TARGETS Random_bitmap_cubical_complex DESTINATION bin) diff --git a/src/Nerve_GIC/example/CMakeLists.txt b/src/Nerve_GIC/example/CMakeLists.txt index 1667472f..4b0f4677 100644 --- a/src/Nerve_GIC/example/CMakeLists.txt +++ b/src/Nerve_GIC/example/CMakeLists.txt @@ -22,7 +22,4 @@ if (NOT CGAL_VERSION VERSION_LESS 4.11.0) "${CMAKE_CURRENT_BINARY_DIR}/lucky_cat.off" "${CMAKE_CURRENT_BINARY_DIR}/lucky_cat_PCA1") - install(TARGETS CoordGIC DESTINATION bin) - install(TARGETS FuncGIC DESTINATION bin) - endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) diff --git a/src/Persistence_representations/example/CMakeLists.txt b/src/Persistence_representations/example/CMakeLists.txt index a7c6ef39..997f85dc 100644 --- a/src/Persistence_representations/example/CMakeLists.txt +++ b/src/Persistence_representations/example/CMakeLists.txt @@ -3,30 +3,24 @@ project(Persistence_representations_example) add_executable ( Persistence_representations_example_landscape_on_grid persistence_landscape_on_grid.cpp ) add_test(NAME Persistence_representations_example_landscape_on_grid COMMAND $) -install(TARGETS Persistence_representations_example_landscape_on_grid DESTINATION bin) add_executable ( Persistence_representations_example_landscape persistence_landscape.cpp ) add_test(NAME Persistence_representations_example_landscape COMMAND $) -install(TARGETS Persistence_representations_example_landscape DESTINATION bin) add_executable ( Persistence_representations_example_intervals persistence_intervals.cpp ) add_test(NAME Persistence_representations_example_intervals COMMAND $ "${CMAKE_SOURCE_DIR}/data/persistence_diagram/first.pers") -install(TARGETS Persistence_representations_example_intervals DESTINATION bin) add_executable ( Persistence_representations_example_vectors persistence_vectors.cpp ) add_test(NAME Persistence_representations_example_vectors COMMAND $) -install(TARGETS Persistence_representations_example_vectors DESTINATION bin) add_executable ( Persistence_representations_example_heat_maps persistence_heat_maps.cpp ) add_test(NAME Persistence_representations_example_heat_maps COMMAND $) -install(TARGETS Persistence_representations_example_heat_maps DESTINATION bin) add_executable ( Sliced_Wasserstein sliced_wasserstein.cpp ) add_test(NAME Sliced_Wasserstein COMMAND $) -install(TARGETS Sliced_Wasserstein DESTINATION bin) diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index d6a92ed6..c68c6524 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -5,7 +5,6 @@ if (TBB_FOUND) target_link_libraries(plain_homology ${TBB_LIBRARIES}) endif() add_test(NAME Persistent_cohomology_example_plain_homology COMMAND $) -install(TARGETS plain_homology DESTINATION bin) add_executable(persistence_from_simple_simplex_tree persistence_from_simple_simplex_tree.cpp) if (TBB_FOUND) @@ -13,7 +12,6 @@ if (TBB_FOUND) endif() add_test(NAME Persistent_cohomology_example_from_simple_simplex_tree COMMAND $ "1" "0") -install(TARGETS persistence_from_simple_simplex_tree DESTINATION bin) if(TARGET Boost::program_options) add_executable(rips_persistence_step_by_step rips_persistence_step_by_step.cpp) @@ -23,7 +21,6 @@ if(TARGET Boost::program_options) endif() add_test(NAME Persistent_cohomology_example_from_rips_step_by_step_on_tore_3D COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3") - install(TARGETS rips_persistence_step_by_step DESTINATION bin) endif() if(TARGET Boost::program_options) @@ -34,7 +31,6 @@ if(TARGET Boost::program_options) endif() add_test(NAME Persistent_cohomology_example_via_boundary_matrix COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/Kl.off" "-r" "0.16" "-d" "3" "-p" "3" "-m" "100") - install(TARGETS rips_persistence_via_boundary_matrix DESTINATION bin) endif() if(TARGET Boost::program_options) @@ -47,7 +43,6 @@ if(TARGET Boost::program_options) "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc" "-p" "2" "-m" "0") add_test(NAME Persistent_cohomology_example_from_file_3_3_100 COMMAND $ "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc" "-p" "3" "-m" "100") - install(TARGETS persistence_from_file DESTINATION bin) endif() if(GMP_FOUND) @@ -61,7 +56,6 @@ if(GMP_FOUND) endif(TBB_FOUND) add_test(NAME Persistent_cohomology_example_multifield_2_71 COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "2" "-q" "71") - install(TARGETS rips_multifield_persistence DESTINATION bin) endif() endif(GMPXX_FOUND) endif(GMP_FOUND) @@ -73,5 +67,4 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) target_link_libraries(custom_persistence_sort ${TBB_LIBRARIES}) endif(TBB_FOUND) add_test(NAME Persistent_cohomology_example_custom_persistence_sort COMMAND $) - install(TARGETS custom_persistence_sort DESTINATION bin) endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/Rips_complex/example/CMakeLists.txt b/src/Rips_complex/example/CMakeLists.txt index 244a93ec..206f4c11 100644 --- a/src/Rips_complex/example/CMakeLists.txt +++ b/src/Rips_complex/example/CMakeLists.txt @@ -72,8 +72,3 @@ if (DIFF_PATH) endif() -install(TARGETS Rips_complex_example_from_off DESTINATION bin) -install(TARGETS Rips_complex_example_one_skeleton_from_points DESTINATION bin) -install(TARGETS Rips_complex_example_one_skeleton_from_distance_matrix DESTINATION bin) -install(TARGETS Rips_complex_example_from_csv_distance_matrix DESTINATION bin) -install(TARGETS Rips_complex_example_one_skeleton_rips_from_correlation_matrix DESTINATION bin) diff --git a/src/Skeleton_blocker/example/CMakeLists.txt b/src/Skeleton_blocker/example/CMakeLists.txt index 0e5d2f11..456612df 100644 --- a/src/Skeleton_blocker/example/CMakeLists.txt +++ b/src/Skeleton_blocker/example/CMakeLists.txt @@ -7,7 +7,3 @@ add_executable(Skeleton_blocker_example_link Skeleton_blocker_link.cpp) add_test(NAME Skeleton_blocker_example_from_simplices COMMAND $) add_test(NAME Skeleton_blocker_example_iteration COMMAND $) add_test(NAME Skeleton_blocker_example_link COMMAND $) - -install(TARGETS Skeleton_blocker_example_from_simplices DESTINATION bin) -install(TARGETS Skeleton_blocker_example_iteration DESTINATION bin) -install(TARGETS Skeleton_blocker_example_link DESTINATION bin) diff --git a/src/Spatial_searching/example/CMakeLists.txt b/src/Spatial_searching/example/CMakeLists.txt index eeb3e85f..308afa00 100644 --- a/src/Spatial_searching/example/CMakeLists.txt +++ b/src/Spatial_searching/example/CMakeLists.txt @@ -5,5 +5,4 @@ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) target_link_libraries(Spatial_searching_example_spatial_searching ${CGAL_LIBRARY}) add_test(NAME Spatial_searching_example_spatial_searching COMMAND $) - install(TARGETS Spatial_searching_example_spatial_searching DESTINATION bin) endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/Subsampling/example/CMakeLists.txt b/src/Subsampling/example/CMakeLists.txt index 28aab103..dfac055c 100644 --- a/src/Subsampling/example/CMakeLists.txt +++ b/src/Subsampling/example/CMakeLists.txt @@ -14,9 +14,4 @@ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_test(NAME Subsampling_example_sparsify_point_set COMMAND $) - install(TARGETS Subsampling_example_pick_n_random_points DESTINATION bin) - install(TARGETS Subsampling_example_choose_n_farthest_points DESTINATION bin) - install(TARGETS Subsampling_example_custom_kernel DESTINATION bin) - install(TARGETS Subsampling_example_sparsify_point_set DESTINATION bin) - endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/Tangential_complex/example/CMakeLists.txt b/src/Tangential_complex/example/CMakeLists.txt index cb1486a4..b66b5f39 100644 --- a/src/Tangential_complex/example/CMakeLists.txt +++ b/src/Tangential_complex/example/CMakeLists.txt @@ -15,6 +15,4 @@ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_test(NAME Tangential_complex_example_with_perturb COMMAND $) - install(TARGETS Tangential_complex_example_basic DESTINATION bin) - install(TARGETS Tangential_complex_example_with_perturb DESTINATION bin) endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 2659798e..5e9736ed 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -7,8 +7,6 @@ endif() add_test(NAME Witness_complex_example_nearest_landmark_table COMMAND $) -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 ) @@ -33,10 +31,5 @@ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_test(NAME Witness_complex_example_strong_off_test_torus COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "20" "1.0" "3") - - install(TARGETS Witness_complex_example_off DESTINATION bin) - install(TARGETS Witness_complex_example_sphere DESTINATION bin) - install(TARGETS Witness_complex_example_strong_off DESTINATION bin) - endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) -- cgit v1.2.3 From ef30f636af892a2e226162af9072f0741caba886 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Nov 2020 22:46:50 +0100 Subject: import matplotlib only when necessary in examples, in function of args. Tests are without matplotlib, so no need to test if present --- src/python/CMakeLists.txt | 76 ++++++++++------------ ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...arcode_persistence_from_perseus_file_example.py | 2 +- ...istence_from_correlation_matrix_file_example.py | 2 +- ...ersistence_from_distance_matrix_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...complex_plain_homology_from_off_file_example.py | 2 +- 9 files changed, 42 insertions(+), 50 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index c09996fe..1f101d87 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -345,29 +345,27 @@ if(PYTHONINTERP_FOUND) 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 - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/tangential_complex_plain_homology_from_off_file_example.py" - --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) + # Tangential + add_test(NAME tangential_complex_plain_homology_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/tangential_complex_plain_homology_from_off_file_example.py" + --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) add_gudhi_py_test(test_tangential_complex) - # Witness complex AND Subsampling - add_test(NAME euclidean_strong_witness_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/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) - - add_test(NAME euclidean_witness_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/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) - endif() + # Witness complex + add_test(NAME euclidean_strong_witness_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/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + + add_test(NAME euclidean_witness_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/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) # Subsampling add_gudhi_py_test(test_subsampling) @@ -422,13 +420,11 @@ if(PYTHONINTERP_FOUND) 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 + 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) @@ -445,30 +441,26 @@ if(PYTHONINTERP_FOUND) ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py" --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) - if(NUMPY_FOUND) - add_test(NAME random_cubical_complex_persistence_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/random_cubical_complex_persistence_example.py" - 10 10 10) - endif() + add_test(NAME random_cubical_complex_persistence_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/random_cubical_complex_persistence_example.py" + 10 10 10) add_gudhi_py_test(test_cubical_complex) # Rips - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) - add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_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/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3) + add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_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/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3) - add_test(NAME rips_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/rips_complex_diagram_persistence_from_off_file_example.py - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) - endif() + add_test(NAME rips_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/rips_complex_diagram_persistence_from_off_file_example.py + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) add_test(NAME rips_complex_from_points_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} diff --git a/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py b/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py index 727af4fa..1e0273b3 100755 --- a/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py +++ b/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -65,6 +64,7 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: 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 e1e572df..4e97cfe3 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 @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -82,6 +81,7 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: 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 58cb2bb5..29076c74 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 @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -79,6 +78,7 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: diff --git a/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py b/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py index 499171df..ee3290c6 100755 --- a/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py +++ b/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py @@ -1,7 +1,6 @@ #!/usr/bin/env python import argparse -import matplotlib.pyplot as plot import errno import os import gudhi @@ -75,6 +74,7 @@ if is_file_perseus(args.file): print("betti_numbers()=") print(periodic_cubical_complex.betti_numbers()) if args.no_barcode == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_barcode(diag) plot.show() else: diff --git a/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py b/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py index 1acb187c..ea2eb7e1 100755 --- a/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py +++ b/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py @@ -2,7 +2,6 @@ import sys import argparse -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. @@ -84,5 +83,6 @@ invert_diag = [ ] if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(invert_diag, band=args.band) plot.show() diff --git a/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py b/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py index 79ccca96..236d085d 100755 --- a/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py +++ b/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py @@ -1,7 +1,6 @@ #!/usr/bin/env python import argparse -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. @@ -60,5 +59,6 @@ print("betti_numbers()=") print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() 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 6f992508..e80233a9 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 @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -70,6 +69,7 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: diff --git a/src/python/example/tangential_complex_plain_homology_from_off_file_example.py b/src/python/example/tangential_complex_plain_homology_from_off_file_example.py index 85bade4a..a4b4e9f5 100755 --- a/src/python/example/tangential_complex_plain_homology_from_off_file_example.py +++ b/src/python/example/tangential_complex_plain_homology_from_off_file_example.py @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -62,6 +61,7 @@ with open(args.file, "r") as f: print(st.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: -- cgit v1.2.3 From 4d26e7220bdd9a3f95beacd8a33b0fbda461ebfa Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Nov 2020 22:49:56 +0100 Subject: Revert "import matplotlib only when necessary in examples, in function of args. Tests are without matplotlib, so no need to test if present" This reverts commit ef30f636af892a2e226162af9072f0741caba886. --- src/python/CMakeLists.txt | 76 ++++++++++++---------- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...arcode_persistence_from_perseus_file_example.py | 2 +- ...istence_from_correlation_matrix_file_example.py | 2 +- ...ersistence_from_distance_matrix_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...complex_plain_homology_from_off_file_example.py | 2 +- 9 files changed, 50 insertions(+), 42 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 1f101d87..c09996fe 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -345,27 +345,29 @@ if(PYTHONINTERP_FOUND) 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) - # Tangential - add_test(NAME tangential_complex_plain_homology_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/tangential_complex_plain_homology_from_off_file_example.py" - --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) + if(MATPLOTLIB_FOUND AND NUMPY_FOUND) + # Tangential + add_test(NAME tangential_complex_plain_homology_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/tangential_complex_plain_homology_from_off_file_example.py" + --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) add_gudhi_py_test(test_tangential_complex) - # Witness complex - add_test(NAME euclidean_strong_witness_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/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) - - add_test(NAME euclidean_witness_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/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + # Witness complex AND Subsampling + add_test(NAME euclidean_strong_witness_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/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + + add_test(NAME euclidean_witness_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/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + endif() # Subsampling add_gudhi_py_test(test_subsampling) @@ -420,11 +422,13 @@ if(PYTHONINTERP_FOUND) 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") - add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test + 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) @@ -441,26 +445,30 @@ if(PYTHONINTERP_FOUND) ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py" --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) - add_test(NAME random_cubical_complex_persistence_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/random_cubical_complex_persistence_example.py" - 10 10 10) + if(NUMPY_FOUND) + add_test(NAME random_cubical_complex_persistence_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/random_cubical_complex_persistence_example.py" + 10 10 10) + endif() add_gudhi_py_test(test_cubical_complex) # Rips - add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_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/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3) + if(MATPLOTLIB_FOUND AND NUMPY_FOUND) + add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_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/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3) - add_test(NAME rips_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/rips_complex_diagram_persistence_from_off_file_example.py - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) + add_test(NAME rips_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/rips_complex_diagram_persistence_from_off_file_example.py + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) + endif() add_test(NAME rips_complex_from_points_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} diff --git a/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py b/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py index 1e0273b3..727af4fa 100755 --- a/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py +++ b/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py @@ -3,6 +3,7 @@ import argparse import errno import os +import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -64,7 +65,6 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: - import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: 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 4e97cfe3..e1e572df 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 @@ -3,6 +3,7 @@ import argparse import errno import os +import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -81,7 +82,6 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: - import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: 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 29076c74..58cb2bb5 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 @@ -3,6 +3,7 @@ import argparse import errno import os +import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -78,7 +79,6 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: - import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: diff --git a/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py b/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py index ee3290c6..499171df 100755 --- a/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py +++ b/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import argparse +import matplotlib.pyplot as plot import errno import os import gudhi @@ -74,7 +75,6 @@ if is_file_perseus(args.file): print("betti_numbers()=") print(periodic_cubical_complex.betti_numbers()) if args.no_barcode == False: - import matplotlib.pyplot as plot gudhi.plot_persistence_barcode(diag) plot.show() else: diff --git a/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py b/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py index ea2eb7e1..1acb187c 100755 --- a/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py +++ b/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py @@ -2,6 +2,7 @@ import sys import argparse +import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. @@ -83,6 +84,5 @@ invert_diag = [ ] if args.no_diagram == False: - import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(invert_diag, band=args.band) plot.show() diff --git a/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py b/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py index 236d085d..79ccca96 100755 --- a/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py +++ b/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import argparse +import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. @@ -59,6 +60,5 @@ print("betti_numbers()=") print(simplex_tree.betti_numbers()) if args.no_diagram == False: - import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() 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 e80233a9..6f992508 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 @@ -3,6 +3,7 @@ import argparse import errno import os +import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -69,7 +70,6 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: - import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: diff --git a/src/python/example/tangential_complex_plain_homology_from_off_file_example.py b/src/python/example/tangential_complex_plain_homology_from_off_file_example.py index a4b4e9f5..85bade4a 100755 --- a/src/python/example/tangential_complex_plain_homology_from_off_file_example.py +++ b/src/python/example/tangential_complex_plain_homology_from_off_file_example.py @@ -3,6 +3,7 @@ import argparse import errno import os +import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -61,7 +62,6 @@ with open(args.file, "r") as f: print(st.betti_numbers()) if args.no_diagram == False: - import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: -- cgit v1.2.3 From a539b1a800b29ee1b67eb256b8f38558a0ee6995 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 4 Nov 2020 00:27:43 +0100 Subject: Build python first This subdirectory is built sequentially and takes a very long time. Starting it first, in a parallel build, it is still the last to end, but since it started earlier it also ends earlier. Usually I build the plugin directly with python3 setup.py build_ext --inplace -j20 But I don't think there is a natural way to do that from the makefile (except for the unlimited -j), since I doubt setuptools knows how to cooperate with make, ninja, etc to share a pool of workers. --- src/CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc230531..79ec42c1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -50,6 +50,14 @@ include_directories(include) # Include module CMake subdirectories # GUDHI_SUB_DIRECTORIES is managed in CMAKE_MODULE_PATH/GUDHI_modules.cmake +if (WITH_GUDHI_PYTHON) + # specific for cython module + add_subdirectory(${GUDHI_PYTHON_PATH}) +else() + message("++ Python module will not be compiled because WITH_GUDHI_PYTHON is set to OFF") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python") +endif() + foreach(GUDHI_MODULE ${GUDHI_MODULES}) foreach(GUDHI_SUB_DIRECTORY ${GUDHI_SUB_DIRECTORIES}) if(EXISTS ${CMAKE_SOURCE_DIR}/${GUDHI_SUB_DIRECTORY}/${GUDHI_MODULE}/CMakeLists.txt) @@ -60,14 +68,6 @@ endforeach() add_subdirectory(GudhUI) -if (WITH_GUDHI_PYTHON) - # specific for cython module - add_subdirectory(${GUDHI_PYTHON_PATH}) -else() - message("++ Python module will not be compiled because WITH_GUDHI_PYTHON is set to OFF") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python") -endif() - message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"") message("++ GUDHI_MISSING_MODULES list is:\"${GUDHI_MISSING_MODULES}\"") -- cgit v1.2.3 From 7959734c6302e9b63e3b91780130c896127eaebe Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 4 Nov 2020 07:36:23 +0100 Subject: Revert "Fix #416 by adding full path to introduction.rst - maybe strange with conda or pip installation" This reverts commit 2d4c69d698df7e40709ec0e38463b4cf30ee388d. --- 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 1d6745fd..98d058fc 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -65,7 +65,7 @@ for module in pybind11_modules: )) # read the contents of introduction.rst -with open("@CMAKE_CURRENT_BINARY_DIR@/introduction.rst", "r") as fh: +with open("introduction.rst", "r") as fh: long_description = fh.read() setup( -- cgit v1.2.3 From 92361d9a117a33e0d922417cfbb2e1653f2537df Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 4 Nov 2020 07:58:01 +0100 Subject: import matplotlib only when necessary in examples, in function of args. Tests are without matplotlib, so no need to test if present --- src/python/CMakeLists.txt | 90 ++++++++++------------ ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...arcode_persistence_from_perseus_file_example.py | 2 +- ...istence_from_correlation_matrix_file_example.py | 2 +- ...ersistence_from_distance_matrix_file_example.py | 2 +- ...ex_diagram_persistence_from_off_file_example.py | 2 +- ...complex_plain_homology_from_off_file_example.py | 2 +- 9 files changed, 49 insertions(+), 57 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index c09996fe..56b6876c 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -345,29 +345,27 @@ if(PYTHONINTERP_FOUND) 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 - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/tangential_complex_plain_homology_from_off_file_example.py" - --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) - - add_gudhi_py_test(test_tangential_complex) - - # Witness complex AND Subsampling - add_test(NAME euclidean_strong_witness_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/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) - - add_test(NAME euclidean_witness_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/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) - endif() + # Tangential + add_test(NAME tangential_complex_plain_homology_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/tangential_complex_plain_homology_from_off_file_example.py" + --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) + + add_gudhi_py_test(test_tangential_complex) + + # Witness complex + add_test(NAME euclidean_strong_witness_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/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + + add_test(NAME euclidean_witness_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/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) # Subsampling add_gudhi_py_test(test_subsampling) @@ -422,13 +420,11 @@ if(PYTHONINTERP_FOUND) 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_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) add_gudhi_py_test(test_alpha_complex) endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) @@ -445,30 +441,26 @@ if(PYTHONINTERP_FOUND) ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py" --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) - if(NUMPY_FOUND) - add_test(NAME random_cubical_complex_persistence_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/random_cubical_complex_persistence_example.py" - 10 10 10) - endif() + add_test(NAME random_cubical_complex_persistence_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/random_cubical_complex_persistence_example.py" + 10 10 10) add_gudhi_py_test(test_cubical_complex) # Rips - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) - add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_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/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3) + add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_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/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3) - add_test(NAME rips_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/rips_complex_diagram_persistence_from_off_file_example.py - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) - endif() + add_test(NAME rips_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/rips_complex_diagram_persistence_from_off_file_example.py + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) add_test(NAME rips_complex_from_points_example_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} diff --git a/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py b/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py index 727af4fa..1e0273b3 100755 --- a/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py +++ b/src/python/example/alpha_complex_diagram_persistence_from_off_file_example.py @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -65,6 +64,7 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: 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 e1e572df..4e97cfe3 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 @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -82,6 +81,7 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: 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 58cb2bb5..29076c74 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 @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -79,6 +78,7 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: diff --git a/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py b/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py index 499171df..ee3290c6 100755 --- a/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py +++ b/src/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py @@ -1,7 +1,6 @@ #!/usr/bin/env python import argparse -import matplotlib.pyplot as plot import errno import os import gudhi @@ -75,6 +74,7 @@ if is_file_perseus(args.file): print("betti_numbers()=") print(periodic_cubical_complex.betti_numbers()) if args.no_barcode == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_barcode(diag) plot.show() else: diff --git a/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py b/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py index 1acb187c..ea2eb7e1 100755 --- a/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py +++ b/src/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py @@ -2,7 +2,6 @@ import sys import argparse -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. @@ -84,5 +83,6 @@ invert_diag = [ ] if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(invert_diag, band=args.band) plot.show() diff --git a/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py b/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py index 79ccca96..236d085d 100755 --- a/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py +++ b/src/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py @@ -1,7 +1,6 @@ #!/usr/bin/env python import argparse -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. @@ -60,5 +59,6 @@ print("betti_numbers()=") print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() 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 6f992508..e80233a9 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 @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -70,6 +69,7 @@ with open(args.file, "r") as f: print(simplex_tree.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: diff --git a/src/python/example/tangential_complex_plain_homology_from_off_file_example.py b/src/python/example/tangential_complex_plain_homology_from_off_file_example.py index 85bade4a..a4b4e9f5 100755 --- a/src/python/example/tangential_complex_plain_homology_from_off_file_example.py +++ b/src/python/example/tangential_complex_plain_homology_from_off_file_example.py @@ -3,7 +3,6 @@ import argparse import errno import os -import matplotlib.pyplot as plot import gudhi """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - @@ -62,6 +61,7 @@ with open(args.file, "r") as f: print(st.betti_numbers()) if args.no_diagram == False: + import matplotlib.pyplot as plot gudhi.plot_persistence_diagram(diag, band=args.band) plot.show() else: -- cgit v1.2.3 From 9ea9ae8f72c26dbe37319168cfce64afa01d0fd9 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 5 Nov 2020 01:00:56 +0100 Subject: More numpy in BettiCurve suggested by @raphaeltinarrage --- src/python/gudhi/representations/vector_methods.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index 5ca127f6..6a1f61ef 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -323,22 +323,15 @@ class BettiCurve(BaseEstimator, TransformerMixin): Returns: numpy array with shape (number of diagrams) x (**resolution**): output Betti curves. """ - num_diag, Xfit = len(X), [] + Xfit = [] x_values = np.linspace(self.sample_range[0], self.sample_range[1], self.resolution) step_x = x_values[1] - x_values[0] - for i in range(num_diag): - - diagram, num_pts_in_diag = X[i], X[i].shape[0] - + for diagram in X: + diagram_int = np.clip(np.ceil((diagram[:,:2] - self.sample_range[0]) / step_x).astype(int), 0, self.resolution) bc = np.zeros(self.resolution) - for j in range(num_pts_in_diag): - [px,py] = diagram[j,:2] - min_idx = np.clip(np.ceil((px - self.sample_range[0]) / step_x).astype(int), 0, self.resolution) - max_idx = np.clip(np.ceil((py - self.sample_range[0]) / step_x).astype(int), 0, self.resolution) - for k in range(min_idx, max_idx): - bc[k] += 1 - + for interval in diagram_int: + bc[interval[0]:interval[1]] += 1 Xfit.append(np.reshape(bc,[1,-1])) Xfit = np.concatenate(Xfit, 0) -- cgit v1.2.3 From a81be6810159493933cbc0159feae191ae7d0cc3 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 7 Nov 2020 11:10:09 +0100 Subject: Swap clip with int conversion This allows correct handling of infinite values. --- src/python/gudhi/representations/vector_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index 6a1f61ef..cdcb1fde 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -328,7 +328,7 @@ class BettiCurve(BaseEstimator, TransformerMixin): step_x = x_values[1] - x_values[0] for diagram in X: - diagram_int = np.clip(np.ceil((diagram[:,:2] - self.sample_range[0]) / step_x).astype(int), 0, self.resolution) + diagram_int = np.clip(np.ceil((diagram[:,:2] - self.sample_range[0]) / step_x), 0, self.resolution).astype(int) bc = np.zeros(self.resolution) for interval in diagram_int: bc[interval[0]:interval[1]] += 1 -- cgit v1.2.3 From 0022442a303f297ac773e262abd2661d2ce0a614 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 8 Nov 2020 22:08:21 +0100 Subject: Test BettiCurve with infinite value + black reformatting --- src/python/test/test_representations.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index e5c211a0..43c914f3 100755 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -39,11 +39,11 @@ def test_multiple(): d2 = BottleneckDistance(epsilon=0.00001).fit_transform(l1) d3 = pairwise_persistence_diagram_distances(l1, l1b, e=0.00001, n_jobs=4) assert d1 == pytest.approx(d2) - assert d3 == pytest.approx(d2, abs=1e-5) # Because of 0 entries (on the diagonal) + assert d3 == pytest.approx(d2, abs=1e-5) # Because of 0 entries (on the diagonal) d1 = pairwise_persistence_diagram_distances(l1, l2, metric="wasserstein", order=2, internal_p=2) d2 = WassersteinDistance(order=2, internal_p=2, n_jobs=4).fit(l2).transform(l1) print(d1.shape, d2.shape) - assert d1 == pytest.approx(d2, rel=.02) + assert d1 == pytest.approx(d2, rel=0.02) def test_dummy_atol(): @@ -53,8 +53,22 @@ def test_dummy_atol(): for weighting_method in ["cloud", "iidproba"]: for contrast in ["gaussian", "laplacian", "indicator"]: - atol_vectoriser = Atol(quantiser=KMeans(n_clusters=1, random_state=202006), weighting_method=weighting_method, contrast=contrast) + atol_vectoriser = Atol( + quantiser=KMeans(n_clusters=1, random_state=202006), + weighting_method=weighting_method, + contrast=contrast, + ) atol_vectoriser.fit([a, b, c]) atol_vectoriser(a) atol_vectoriser.transform(X=[a, b, c]) + +from gudhi.representations.vector_methods import BettiCurve + + +def test_infinity(): + a = np.array([[1.0, 8.0], [2.0, np.inf], [3.0, 4.0]]) + c = BettiCurve(20, [0.0, 10.0])(a) + assert c[1] == 0 + assert c[7] == 3 + assert c[9] == 2 -- cgit v1.2.3 From 78100c3f35e6d05da3313fc8b28e24e550c8240a Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 9 Nov 2020 18:21:36 +0100 Subject: static_assert message --- src/Subsampling/include/gudhi/choose_n_farthest_points.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index 3c337025..e6347d96 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -89,7 +89,7 @@ void choose_n_farthest_points(Distance dist, } std::size_t current_number_of_landmarks = 0; // counter for landmarks - static_assert(std::numeric_limits::has_infinity); + static_assert(std::numeric_limits::has_infinity, "the number type needs to support infinity()"); // FIXME: don't hard-code the type as double. For Epeck_d, we also want to handle types that do not have an infinity. const double infty = std::numeric_limits::infinity(); // infinity (see next entry) std::vector< double > dist_to_L(nb_points, infty); // vector of current distances to L from input_pts -- cgit v1.2.3 From 0a071114ad08d2ce149f8b484dd8ff1b96b61fb1 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 9 Nov 2020 22:55:00 +0100 Subject: Don't test the equality case in sparsify_point_set. sqrt. --- src/Subsampling/include/gudhi/sparsify_point_set.h | 6 ++++-- src/python/gudhi/subsampling.pyx | 2 +- src/python/test/test_subsampling.py | 16 ++++++++++------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Subsampling/include/gudhi/sparsify_point_set.h b/src/Subsampling/include/gudhi/sparsify_point_set.h index 78e0da4a..afa6d45a 100644 --- a/src/Subsampling/include/gudhi/sparsify_point_set.h +++ b/src/Subsampling/include/gudhi/sparsify_point_set.h @@ -29,7 +29,7 @@ namespace subsampling { * \ingroup subsampling * \brief Outputs a subset of the input points so that the * squared distance between any two points - * is greater than or equal to `min_squared_dist`. + * is greater than `min_squared_dist`. * * \tparam Kernel must be a model of the SearchTraits @@ -53,6 +53,7 @@ sparsify_point_set( OutputIterator output_it) { typedef typename Gudhi::spatial_searching::Kd_tree_search< Kernel, Point_range> Points_ds; + using std::sqrt; #ifdef GUDHI_SUBSAMPLING_PROFILING Gudhi::Clock t; @@ -73,7 +74,8 @@ sparsify_point_set( // If another point Q is closer that min_squared_dist, mark Q to be dropped auto drop = [&dropped_points] (std::ptrdiff_t neighbor_point_idx) { dropped_points[neighbor_point_idx] = true; }; - points_ds.all_near_neighbors(pt, min_squared_dist, boost::make_function_output_iterator(std::ref(drop))); + // FIXME: what if FT does not support sqrt? + points_ds.all_near_neighbors(pt, sqrt(min_squared_dist), boost::make_function_output_iterator(std::ref(drop))); } #ifdef GUDHI_SUBSAMPLING_PROFILING diff --git a/src/python/gudhi/subsampling.pyx b/src/python/gudhi/subsampling.pyx index b11d07e5..46f32335 100644 --- a/src/python/gudhi/subsampling.pyx +++ b/src/python/gudhi/subsampling.pyx @@ -105,7 +105,7 @@ def pick_n_random_points(points=None, off_file='', nb_points=0): def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): """Outputs a subset of the input points so that the squared distance - between any two points is greater than or equal to min_squared_dist. + between any two points is greater than min_squared_dist. :param points: The input point set. :type points: Iterable[Iterable[float]] diff --git a/src/python/test/test_subsampling.py b/src/python/test/test_subsampling.py index 31f64e32..4019852e 100755 --- a/src/python/test/test_subsampling.py +++ b/src/python/test/test_subsampling.py @@ -141,12 +141,16 @@ def test_simple_sparsify_points(): # assert gudhi.sparsify_point_set(points = [], min_squared_dist = 0.0) == [] # assert gudhi.sparsify_point_set(points = [], min_squared_dist = 10.0) == [] assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=0.0) == point_set - assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=1.0) == point_set - assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=2.0) == [ + assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=0.999) == point_set + assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=1.001) == [ [0, 1], [1, 0], ] - assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=2.01) == [[0, 1]] + assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=1.999) == [ + [0, 1], + [1, 0], + ] + assert gudhi.sparsify_point_set(points=point_set, min_squared_dist=2.001) == [[0, 1]] assert ( len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=0.0)) @@ -157,11 +161,11 @@ def test_simple_sparsify_points(): == 5 ) assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=40.0)) + len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=40.1)) == 4 ) assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=90.0)) + len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=89.9)) == 3 ) assert ( @@ -169,7 +173,7 @@ def test_simple_sparsify_points(): == 2 ) assert ( - len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=325.0)) + len(gudhi.sparsify_point_set(off_file="subsample.off", min_squared_dist=324.9)) == 2 ) assert ( -- cgit v1.2.3 From b4df19e0555c0b60c4f074ed0baf642a7d1bdc8b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 10 Nov 2020 00:55:34 +0100 Subject: Revert change to the example It would require updating the figure. --- src/python/doc/bottleneck_distance_user.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/python/doc/bottleneck_distance_user.rst b/src/python/doc/bottleneck_distance_user.rst index 2c74c6dd..7baa76cc 100644 --- a/src/python/doc/bottleneck_distance_user.rst +++ b/src/python/doc/bottleneck_distance_user.rst @@ -35,19 +35,19 @@ The following example explains how the distance is computed: import gudhi - message = "Bottleneck distance = " + '%.1f' % gudhi.bottleneck_distance([[0., 2.]], [[1., 13.]]) + message = "Bottleneck distance = " + '%.1f' % gudhi.bottleneck_distance([[0., 0.]], [[0., 13.]]) print(message) .. testoutput:: - Bottleneck distance = 6.0 + Bottleneck distance = 6.5 .. figure:: ../../doc/Bottleneck_distance/bottleneck_distance_example.png :figclass: align-center - The point (1, 13) is at distance 6 from the diagonal and more - specifically from the point (7, 7). + The point (0, 13) is at distance 6.5 from the diagonal and more + specifically from the point (6.5, 6.5). Basic example -- cgit v1.2.3 From 53376fde3f35576af18fac33d731e8398da7522e Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 13 Nov 2020 12:39:27 +0100 Subject: Test with negative coordinates --- src/python/test/test_bottleneck_distance.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/python/test/test_bottleneck_distance.py b/src/python/test/test_bottleneck_distance.py index 6915bea8..07fcc9cc 100755 --- a/src/python/test/test_bottleneck_distance.py +++ b/src/python/test/test_bottleneck_distance.py @@ -25,3 +25,15 @@ def test_basic_bottleneck(): assert gudhi.bottleneck_distance(diag1, diag2, 0.1) == pytest.approx(0.75, abs=0.1) assert gudhi.hera.bottleneck_distance(diag1, diag2, 0) == 0.75 assert gudhi.hera.bottleneck_distance(diag1, diag2, 0.1) == pytest.approx(0.75, rel=0.1) + + import numpy as np + + # Translating both diagrams along the diagonal should not affect the distance, + # checks that negative numbers are not an issue + diag1 = np.array(diag1) - 100 + diag2 = np.array(diag2) - 100 + + assert gudhi.bottleneck_distance(diag1, diag2) == 0.75 + assert gudhi.bottleneck_distance(diag1, diag2, 0.1) == pytest.approx(0.75, abs=0.1) + assert gudhi.hera.bottleneck_distance(diag1, diag2, 0) == 0.75 + assert gudhi.hera.bottleneck_distance(diag1, diag2, 0.1) == pytest.approx(0.75, rel=0.1) -- cgit v1.2.3 From 3df4648996a4c30f4587115c57aee13ba3c96da7 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 13 Nov 2020 14:40:01 +0100 Subject: Add tensorflow-addons as test requirement --- .github/test-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/test-requirements.txt b/.github/test-requirements.txt index 7d69c0b9..688a2a11 100644 --- a/.github/test-requirements.txt +++ b/.github/test-requirements.txt @@ -8,6 +8,7 @@ scipy scikit-learn POT tensorflow +tensorflow-addons torch<1.5 pykeops hnswlib -- cgit v1.2.3 From 4a34c0b7b8be8b8e275b13823da31127bbd5f3b2 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 22 Nov 2020 23:37:18 +0100 Subject: Handle squared radius Make it work without a breaking change, we can always make a change later in a separate PR. --- .../include/gudhi/Kd_tree_search.h | 98 ++++++++++++++++++++-- .../include/gudhi/pick_n_random_points.h | 4 +- src/Subsampling/include/gudhi/sparsify_point_set.h | 3 +- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/Spatial_searching/include/gudhi/Kd_tree_search.h b/src/Spatial_searching/include/gudhi/Kd_tree_search.h index 87969dd9..a50a8537 100644 --- a/src/Spatial_searching/include/gudhi/Kd_tree_search.h +++ b/src/Spatial_searching/include/gudhi/Kd_tree_search.h @@ -12,11 +12,12 @@ #ifndef KD_TREE_SEARCH_H_ #define KD_TREE_SEARCH_H_ +#include + #include #include #include #include -#include #include #include // for CGAL_VERSION_NR @@ -40,7 +41,6 @@ namespace Gudhi { namespace spatial_searching { - /** * \class Kd_tree_search Kd_tree_search.h gudhi/Kd_tree_search.h * \brief Spatial tree data structure to perform (approximate) nearest and furthest neighbor search. @@ -83,7 +83,8 @@ class Kd_tree_search { typedef CGAL::Search_traits< FT, Point, typename Traits::Cartesian_const_iterator_d, - typename Traits::Construct_cartesian_const_iterator_d> Traits_base; + typename Traits::Construct_cartesian_const_iterator_d, + typename Traits::Dimension> Traits_base; typedef CGAL::Search_traits_adapter< std::ptrdiff_t, @@ -110,7 +111,76 @@ class Kd_tree_search { /// of a point P and `second` is the squared distance between P and the query point. typedef Incremental_neighbor_search INS_range; - typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + // Because CGAL::Fuzzy_sphere takes the radius and not its square + struct Sphere_for_kdtree_search + { + typedef typename Traits::Point_d Point_d; + typedef typename Traits::FT FT; + typedef typename Traits::Dimension D; + typedef D Dimension; + + private: + STraits traits; + Point_d c; + FT sqradmin, sqradmax; + bool use_max; + + public: + // `prefer_max` means that we prefer outputting more points at squared distance between r2min and r2max, + // while `!prefer_max` means we prefer fewer. + Sphere_for_kdtree_search(Point_d const& c_, FT const& r2min, FT const& r2max, bool prefer_max=true, STraits const& traits_ = {}) + : traits(traits_), c(c_), sqradmin(r2min), sqradmax(r2max), use_max(prefer_max) + { GUDHI_CHECK(r2min >= 0 && r2max >= r2min, "0 <= r2min <= r2max"); } + + bool contains(std::ptrdiff_t i) const { + const Point_d& p = get(traits.point_property_map(), i); + auto ccci = traits.construct_cartesian_const_iterator_d_object(); + return contains_point_given_as_coordinates(ccci(p), ccci(p, 0)); + } + + template + bool contains_point_given_as_coordinates(Coord_iterator pi, Coord_iterator CGAL_UNUSED) const { + FT distance = 0; + auto ccci = traits.construct_cartesian_const_iterator_d_object(); + auto ci = ccci(c); + auto ce = ccci(c, 0); + FT const& limit = use_max ? sqradmax : sqradmin; + while (ci != ce) { + distance += CGAL::square(*pi++ - *ci++); + // I think Clément advised to check the distance at every step instead of + // just at the end, especially when the dimension becomes large. Distance + // isn't part of the concept anyway. + if (distance > limit) return false; + } + return true; + } + + bool inner_range_intersects(CGAL::Kd_tree_rectangle const& rect) const { + auto ccci = traits.construct_cartesian_const_iterator_d_object(); + FT distance = 0; + auto ci = ccci(c); + auto ce = ccci(c, 0); + for (int i = 0; ci != ce; ++i, ++ci) { + distance += CGAL::square(CGAL::max(CGAL::max(*ci - rect.max_coord(i), rect.min_coord(i) - *ci), 0 )); + if (distance > sqradmin) return false; + } + return true; + } + + + bool outer_range_contains(CGAL::Kd_tree_rectangle const& rect) const { + auto ccci = traits.construct_cartesian_const_iterator_d_object(); + FT distance = 0; + auto ci = ccci(c); + auto ce = ccci(c, 0); + for (int i = 0; ci != ce; ++i, ++ci) { + distance += CGAL::square(CGAL::max(*ci - rect.min_coord(i), rect.max_coord(i) - *ci)); + if (distance > sqradmax) return false; + } + return true; + } + }; + /// \brief Constructor /// @param[in] points Const reference to the point range. This range /// is not copied, so it should not be destroyed or modified afterwards. @@ -266,10 +336,26 @@ class Kd_tree_search { /// @param[in] eps Approximation factor. template void all_near_neighbors(Point const& p, - FT radius, + FT const& radius, OutputIterator it, FT eps = FT(0)) const { - m_tree.search(it, Fuzzy_sphere(p, radius, eps, m_tree.traits())); + all_near_neighbors2(p, CGAL::square(radius - eps), CGAL::square(radius + eps), it); + } + + /// \brief Search for all the neighbors in a ball. This is similar to `all_near_neighbors` but takes directly + /// the square of the minimum distance below which points must be considered neighbors and square of the + /// maximum distance above which they cannot be. + /// @param[in] p The query point. + /// @param[in] sq_radius_min The square of the minimum search radius + /// @param[in] sq_radius_max The square of the maximum search radius + /// @param[out] it The points that lie inside the sphere of center `p` and squared radius `sq_radius`. + /// Note: `it` is used this way: `*it++ = each_point`. + template + void all_near_neighbors2(Point const& p, + FT const& sq_radius_min, + FT const& sq_radius_max, + OutputIterator it) const { + m_tree.search(it, Sphere_for_kdtree_search(p, sq_radius_min, sq_radius_max, true, m_tree.traits())); } int tree_depth() const { diff --git a/src/Subsampling/include/gudhi/pick_n_random_points.h b/src/Subsampling/include/gudhi/pick_n_random_points.h index c2c71f83..e4246c29 100644 --- a/src/Subsampling/include/gudhi/pick_n_random_points.h +++ b/src/Subsampling/include/gudhi/pick_n_random_points.h @@ -11,7 +11,9 @@ #ifndef PICK_N_RANDOM_POINTS_H_ #define PICK_N_RANDOM_POINTS_H_ -#include +#ifdef GUDHI_SUBSAMPLING_PROFILING +# include +#endif #include diff --git a/src/Subsampling/include/gudhi/sparsify_point_set.h b/src/Subsampling/include/gudhi/sparsify_point_set.h index afa6d45a..71e8917b 100644 --- a/src/Subsampling/include/gudhi/sparsify_point_set.h +++ b/src/Subsampling/include/gudhi/sparsify_point_set.h @@ -74,8 +74,7 @@ sparsify_point_set( // If another point Q is closer that min_squared_dist, mark Q to be dropped auto drop = [&dropped_points] (std::ptrdiff_t neighbor_point_idx) { dropped_points[neighbor_point_idx] = true; }; - // FIXME: what if FT does not support sqrt? - points_ds.all_near_neighbors(pt, sqrt(min_squared_dist), boost::make_function_output_iterator(std::ref(drop))); + points_ds.all_near_neighbors2(pt, min_squared_dist, min_squared_dist, boost::make_function_output_iterator(std::ref(drop))); } #ifdef GUDHI_SUBSAMPLING_PROFILING -- cgit v1.2.3 From 23cd685d7a46cc5d601c9b937f6a849c8753fa32 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 26 Nov 2020 22:20:53 +0100 Subject: handle old boost --- src/Subsampling/include/gudhi/sparsify_point_set.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Subsampling/include/gudhi/sparsify_point_set.h b/src/Subsampling/include/gudhi/sparsify_point_set.h index 71e8917b..4571b8f3 100644 --- a/src/Subsampling/include/gudhi/sparsify_point_set.h +++ b/src/Subsampling/include/gudhi/sparsify_point_set.h @@ -11,7 +11,12 @@ #ifndef SPARSIFY_POINT_SET_H_ #define SPARSIFY_POINT_SET_H_ -#include +#include +#if BOOST_VERSION < 106600 +# include +#else +# include +#endif #include #ifdef GUDHI_SUBSAMPLING_PROFILING @@ -53,7 +58,6 @@ sparsify_point_set( OutputIterator output_it) { typedef typename Gudhi::spatial_searching::Kd_tree_search< Kernel, Point_range> Points_ds; - using std::sqrt; #ifdef GUDHI_SUBSAMPLING_PROFILING Gudhi::Clock t; -- cgit v1.2.3 From dbb885175a27399c0b6cd1848801a2c5c9fa91cf Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 30 Nov 2020 11:30:57 +0100 Subject: Test this fix for pip build --- .github/workflows/pip-build-windows.yml | 9 ++------- .github/workflows/pip-packaging-windows.yml | 8 ++------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pip-build-windows.yml b/.github/workflows/pip-build-windows.yml index 11f1ace9..995d52dd 100644 --- a/.github/workflows/pip-build-windows.yml +++ b/.github/workflows/pip-build-windows.yml @@ -18,18 +18,13 @@ jobs: with: python-version: ${{ matrix.python-version }} architecture: x64 - - name: Patch - run: | - (new-object System.Net.WebClient).DownloadFile('https://github.com/microsoft/vcpkg/files/4978792/vcpkg_fixup_pkgconfig.cmake.txt','c:\vcpkg\scripts\cmake\vcpkg_fixup_pkgconfig.cmake') - (new-object System.Net.WebClient).DownloadFile('https://github.com/microsoft/vcpkg/files/4978796/vcpkg_acquire_msys.cmake.txt','c:\vcpkg\scripts\cmake\vcpkg_acquire_msys.cmake') - shell: powershell - name: Install dependencies run: | vcpkg update vcpkg upgrade --no-dry-run - vcpkg install boost-graph boost-serialization boost-date-time boost-system boost-filesystem boost-units boost-thread boost-program-options eigen3 mpfr mpir cgal --triplet x64-windows + type c:/vcpkg/ports/cgal/portfile.cmake + vcpkg install eigen3 cgal --triplet x64-windows python -m pip install --user -r .github/build-requirements.txt - python -m pip install --user twine python -m pip list - name: Build python wheel run: | diff --git a/.github/workflows/pip-packaging-windows.yml b/.github/workflows/pip-packaging-windows.yml index 2e45ad71..8f4ab6e7 100644 --- a/.github/workflows/pip-packaging-windows.yml +++ b/.github/workflows/pip-packaging-windows.yml @@ -20,16 +20,12 @@ jobs: with: python-version: ${{ matrix.python-version }} architecture: x64 - - name: Patch - run: | - (new-object System.Net.WebClient).DownloadFile('https://github.com/microsoft/vcpkg/files/4978792/vcpkg_fixup_pkgconfig.cmake.txt','c:\vcpkg\scripts\cmake\vcpkg_fixup_pkgconfig.cmake') - (new-object System.Net.WebClient).DownloadFile('https://github.com/microsoft/vcpkg/files/4978796/vcpkg_acquire_msys.cmake.txt','c:\vcpkg\scripts\cmake\vcpkg_acquire_msys.cmake') - shell: powershell - name: Install dependencies run: | vcpkg update vcpkg upgrade --no-dry-run - vcpkg install boost-graph boost-serialization boost-date-time boost-system boost-filesystem boost-units boost-thread boost-program-options eigen3 mpfr mpir cgal --triplet x64-windows + type c:/vcpkg/ports/cgal/portfile.cmake + vcpkg install eigen3 cgal --triplet x64-windows python -m pip install --user -r .github/build-requirements.txt python -m pip install --user twine python -m pip list -- cgit v1.2.3 From eed023832e1b917d022fa8fa1a62dac40e88f121 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 30 Nov 2020 15:31:45 +0100 Subject: Fix pykeops 1.4.2 where version is very verbose on 2 lines --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 9dadac4f..e1566877 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -106,8 +106,8 @@ function( find_python_module PYTHON_MODULE_NAME ) OUTPUT_VARIABLE PYTHON_MODULE_VERSION ERROR_VARIABLE PYTHON_MODULE_ERROR) if(PYTHON_MODULE_RESULT EQUAL 0) - # Remove carriage return - string(STRIP ${PYTHON_MODULE_VERSION} PYTHON_MODULE_VERSION) + # Remove all carriage returns as it can be multiline + string(REGEX REPLACE "\n" " " PYTHON_MODULE_VERSION "${PYTHON_MODULE_VERSION}") message ("++ Python module ${PYTHON_MODULE_NAME} - Version ${PYTHON_MODULE_VERSION} found") set(${PYTHON_MODULE_NAME_UP}_VERSION ${PYTHON_MODULE_VERSION} PARENT_SCOPE) -- cgit v1.2.3 From dc489cc28347bbc434fab62ff2158897bcb2e232 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Dec 2020 12:03:11 +0100 Subject: Add build and tests wo cgal and eigen and wo cgal --- .circleci/config.yml | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 285a66a5..c2c6a478 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -95,10 +95,136 @@ jobs: path: /tmp/doxygen destination: doxygen + examples_without_cgal_eigen: + docker: + - image: gudhi/ci_for_gudhi_wo_cgal:latest + steps: + - checkout + - run: + name: Build and test examples without cgal and eigen + command: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure + + tests_without_cgal_eigen: + docker: + - image: gudhi/ci_for_gudhi_wo_cgal:latest + steps: + - checkout + - run: + name: Build and test unitary tests without cgal and eigen + command: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure + + utils_without_cgal_eigen: + docker: + - image: gudhi/ci_for_gudhi_wo_cgal:latest + steps: + - checkout + - run: + name: Build and test utilities without cgal and eigen + command: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure + + python_without_cgal_eigen: + docker: + - image: gudhi/ci_for_gudhi_wo_cgal:latest + steps: + - checkout + - run: + name: Build and test python module without cgal and eigen + command: | + git submodule init + git submodule update + 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 src/python + python3 setup.py build_ext --inplace + ctest --output-on-failure + + examples_without_cgal: + docker: + - image: gudhi/ci_for_gudhi_wo_cgal:latest + steps: + - checkout + - run: + name: Build and test examples without cgal + command: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/eigen-3.3.9 -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure + + tests_without_cgal: + docker: + - image: gudhi/ci_for_gudhi_wo_cgal:latest + steps: + - checkout + - run: + name: Build and test unitary tests without cgal + command: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/eigen-3.3.9 -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure + + utils_without_cgal: + docker: + - image: gudhi/ci_for_gudhi_wo_cgal:latest + steps: + - checkout + - run: + name: Build and test utilities without cgal + command: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/eigen-3.3.9 -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=OFF .. + make all + ctest --output-on-failure + + python_without_cgal: + docker: + - image: gudhi/ci_for_gudhi_wo_cgal:latest + steps: + - checkout + - run: + name: Build and test python module without cgal + command: | + git submodule init + git submodule update + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/eigen-3.3.9 -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 . + cd src/python + python3 setup.py build_ext --inplace + ctest --output-on-failure + workflows: version: 2 build: jobs: + - examples_without_cgal_eigen + - tests_without_cgal_eigen + - utils_without_cgal_eigen + - python_without_cgal_eigen + - examples_without_cgal + - tests_without_cgal + - utils_without_cgal + - python_without_cgal - examples - tests - utils -- cgit v1.2.3 From aa5ba4c9c4c72cfe650b82952785f7ae7955af5e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Dec 2020 13:45:02 +0100 Subject: Bad path for python version --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c2c6a478..d95b8d36 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -149,7 +149,7 @@ jobs: git submodule update 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 . + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 .. cd src/python python3 setup.py build_ext --inplace ctest --output-on-failure @@ -208,7 +208,7 @@ jobs: git submodule update mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/eigen-3.3.9 -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 . + cmake -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/eigen-3.3.9 -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 .. cd src/python python3 setup.py build_ext --inplace ctest --output-on-failure -- cgit v1.2.3 From 55e2b2e55bc50a7cfea9ca1edfca632488cf016a Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Dec 2020 15:49:43 +0100 Subject: Make representations tests work if CGAL and/or POT is not there --- .../diagram_vectorizations_distances_kernels.py | 19 +++++++++++++------ src/python/test/test_representations.py | 10 +++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/python/example/diagram_vectorizations_distances_kernels.py b/src/python/example/diagram_vectorizations_distances_kernels.py index c4a71a7a..2801576e 100755 --- a/src/python/example/diagram_vectorizations_distances_kernels.py +++ b/src/python/example/diagram_vectorizations_distances_kernels.py @@ -5,11 +5,11 @@ import numpy as np from sklearn.kernel_approximation import RBFSampler from sklearn.preprocessing import MinMaxScaler -from gudhi.representations import DiagramSelector, Clamping, Landscape, Silhouette, BettiCurve, ComplexPolynomial,\ +from gudhi.representations import (DiagramSelector, Clamping, Landscape, Silhouette, BettiCurve, ComplexPolynomial,\ TopologicalVector, DiagramScaler, BirthPersistenceTransform,\ PersistenceImage, PersistenceWeightedGaussianKernel, Entropy, \ PersistenceScaleSpaceKernel, SlicedWassersteinDistance,\ - SlicedWassersteinKernel, BottleneckDistance, PersistenceFisherKernel, WassersteinDistance + SlicedWassersteinKernel, PersistenceFisherKernel, WassersteinDistance) D1 = np.array([[0.,4.],[1.,2.],[3.,8.],[6.,8.], [0., np.inf], [5., np.inf]]) @@ -93,14 +93,21 @@ print("SW distance is " + str(sW(D1, D2))) SW = SlicedWassersteinKernel(num_directions=100, bandwidth=1.) print("SW kernel is " + str(SW(D1, D2))) -W = WassersteinDistance(order=2, internal_p=2, mode="pot") -print("Wasserstein distance (POT) is " + str(W(D1, D2))) +try: + W = WassersteinDistance(order=2, internal_p=2, mode="pot") + print("Wasserstein distance (POT) is " + str(W(D1, D2))) +except ImportError: + print("WassersteinDistance (POT) is not available, you may be missing pot.") W = WassersteinDistance(order=2, internal_p=2, mode="hera", delta=0.0001) print("Wasserstein distance (hera) is " + str(W(D1, D2))) -W = BottleneckDistance(epsilon=.001) -print("Bottleneck distance is " + str(W(D1, D2))) +try: + from gudhi.representations import BottleneckDistance + W = BottleneckDistance(epsilon=.001) + print("Bottleneck distance is " + str(W(D1, D2))) +except ImportError: + print("BottleneckDistance is not available, you may be missing CGAL.") PF = PersistenceFisherKernel(bandwidth_fisher=1., bandwidth=1.) print("PF kernel is " + str(PF(D1, D2))) diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index 43c914f3..8ebd7888 100755 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -41,7 +41,15 @@ def test_multiple(): assert d1 == pytest.approx(d2) assert d3 == pytest.approx(d2, abs=1e-5) # Because of 0 entries (on the diagonal) d1 = pairwise_persistence_diagram_distances(l1, l2, metric="wasserstein", order=2, internal_p=2) - d2 = WassersteinDistance(order=2, internal_p=2, n_jobs=4).fit(l2).transform(l1) + mode = "" + try: + import ot + mode = "pot" + except ImportError: + print("POT is not available, try with hera") + mode = "hera" + + d2 = WassersteinDistance(order=2, internal_p=2, mode=mode, n_jobs=4).fit(l2).transform(l1) print(d1.shape, d2.shape) assert d1 == pytest.approx(d2, rel=0.02) -- cgit v1.2.3 From 366813c651d871c5b95d9bc8e7ea227f8015fc55 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Dec 2020 16:35:48 +0100 Subject: rollback test_representation and a CGAL condition to launch it --- src/python/CMakeLists.txt | 2 +- src/python/test/test_representations.py | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 56b6876c..4dca3908 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -504,7 +504,7 @@ if(PYTHONINTERP_FOUND) endif() # Representations - if(SKLEARN_FOUND AND MATPLOTLIB_FOUND) + if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND NOT CGAL_VERSION VERSION_LESS 4.11.0) add_gudhi_py_test(test_representations) endif() diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index 8ebd7888..43c914f3 100755 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -41,15 +41,7 @@ def test_multiple(): assert d1 == pytest.approx(d2) assert d3 == pytest.approx(d2, abs=1e-5) # Because of 0 entries (on the diagonal) d1 = pairwise_persistence_diagram_distances(l1, l2, metric="wasserstein", order=2, internal_p=2) - mode = "" - try: - import ot - mode = "pot" - except ImportError: - print("POT is not available, try with hera") - mode = "hera" - - d2 = WassersteinDistance(order=2, internal_p=2, mode=mode, n_jobs=4).fit(l2).transform(l1) + d2 = WassersteinDistance(order=2, internal_p=2, n_jobs=4).fit(l2).transform(l1) print(d1.shape, d2.shape) assert d1 == pytest.approx(d2, rel=0.02) -- cgit v1.2.3 From dbfe80623c89904ed18fbc8b408858175dbd0474 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Dec 2020 16:42:52 +0100 Subject: do not launch test_representation when no pot --- src/python/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 4dca3908..2d5f793a 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -504,7 +504,7 @@ if(PYTHONINTERP_FOUND) endif() # Representations - if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND NOT CGAL_VERSION VERSION_LESS 4.11.0) + if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND OT_FOUND AND NOT CGAL_VERSION VERSION_LESS 4.11.0) add_gudhi_py_test(test_representations) endif() -- cgit v1.2.3 From 6279ac91dd7e2d3206e8a380d38cb2e5d503e9dc Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 8 Dec 2020 17:54:46 +0100 Subject: Fix #388 for the tests to pass --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 1 + src/python/gudhi/simplex_tree.pyx | 3 +++ src/python/include/Simplex_tree_interface.h | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index e1566877..e2684aa4 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -58,6 +58,7 @@ endif(WITH_GUDHI_USE_TBB) set(CGAL_WITH_EIGEN3_VERSION 0.0.0) find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) + add_definitions(-DGUDHI_USE_EIGEN3) include( ${EIGEN3_USE_FILE} ) set(CGAL_WITH_EIGEN3_VERSION ${CGAL_VERSION}) endif (EIGEN3_FOUND) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index cdd2e87b..7d6ab89a 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -627,6 +627,9 @@ cdef class SimplexTree: :param nb_iterations: The number of edge collapse iterations to perform. Default is 1. :type nb_iterations: int + + :note: collapse_edges function requires `Eigen `_ >= 3.1.0, otherwise no action is + performed. """ # Backup old pointer cdef Simplex_tree_interface_full_featured* ptr = self.get_ptr() diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index baff3850..2bd704b4 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -15,7 +15,9 @@ #include #include #include +#ifdef GUDHI_USE_EIGEN3 #include +#endif #include #include @@ -162,6 +164,7 @@ class Simplex_tree_interface : public Simplex_tree { } Simplex_tree_interface* collapse_edges(int nb_collapse_iteration) { +#ifdef GUDHI_USE_EIGEN3 using Filtered_edge = std::tuple; std::vector edges; for (Simplex_handle sh : Base::skeleton_simplex_range(1)) { @@ -187,6 +190,9 @@ class Simplex_tree_interface : public Simplex_tree { collapsed_stree_ptr->insert({std::get<0>(remaining_edge), std::get<1>(remaining_edge)}, std::get<2>(remaining_edge)); } return collapsed_stree_ptr; +#else + return this; +#endif } // Iterator over the simplex tree -- cgit v1.2.3 From fda0084941ece5d41a258d19ca4eb0b3d87384a4 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 9 Dec 2020 09:41:13 +0100 Subject: Fix #388 --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 1 - src/python/CMakeLists.txt | 1 + src/python/gudhi/simplex_tree.pxd | 2 ++ src/python/gudhi/simplex_tree.pyx | 3 +++ src/python/include/Simplex_tree_interface.h | 10 +++++++++- src/python/test/test_simplex_tree.py | 14 +++++++++----- 6 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index e2684aa4..e1566877 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -58,7 +58,6 @@ endif(WITH_GUDHI_USE_TBB) set(CGAL_WITH_EIGEN3_VERSION 0.0.0) find_package(Eigen3 3.1.0) if (EIGEN3_FOUND) - add_definitions(-DGUDHI_USE_EIGEN3) include( ${EIGEN3_USE_FILE} ) set(CGAL_WITH_EIGEN3_VERSION ${CGAL_VERSION}) endif (EIGEN3_FOUND) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 2d5f793a..45c89609 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -133,6 +133,7 @@ if(PYTHONINTERP_FOUND) add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}") # No problem, even if no CGAL found set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_EIGEN3', ") endif (EIGEN3_FOUND) set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_reader', ") diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 3c4cbed3..283830ff 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -74,6 +74,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) nogil pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] get_boundary_iterators(vector[int] simplex) nogil except + + + cdef int _GUDHI_USE_EIGEN3 cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 7d6ab89a..eb44c0fc 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -17,6 +17,9 @@ __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" +# For unitary tests purpose +__GUDHI_USE_EIGEN3 = _GUDHI_USE_EIGEN3 + # SimplexTree python interface cdef class SimplexTree: """The simplex tree is an efficient and flexible data structure for diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 2bd704b4..50592e25 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -27,6 +27,12 @@ namespace Gudhi { +#ifdef GUDHI_USE_EIGEN3 +const int _GUDHI_USE_EIGEN3 = 1; +#else +const int _GUDHI_USE_EIGEN3 = 0; +#endif + template class Simplex_tree_interface : public Simplex_tree { public: @@ -191,7 +197,9 @@ class Simplex_tree_interface : public Simplex_tree { } return collapsed_stree_ptr; #else - return this; + // If no Eigen3, return a copy, as it will be deleted in pyx + Simplex_tree_interface* collapsed_stree_ptr = new Simplex_tree_interface(*this); + return collapsed_stree_ptr; #endif } diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 3b23fa0b..15b472ee 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -8,7 +8,7 @@ - YYYY/MM Author: Description of the modification """ -from gudhi import SimplexTree +from gudhi import SimplexTree, simplex_tree import pytest __author__ = "Vincent Rouvreau" @@ -353,11 +353,15 @@ def test_collapse_edges(): assert st.num_simplices() == 10 + # If no Eigen3, collapse_edges just return a copy, no action. Maybe it would require some user warning st.collapse_edges() - assert st.num_simplices() == 9 - assert st.find([1, 3]) == False - for simplex in st.get_skeleton(0): - assert simplex[1] == 1. + if simplex_tree.__GUDHI_USE_EIGEN3: + assert st.num_simplices() == 9 + assert st.find([1, 3]) == False + for simplex in st.get_skeleton(0): + assert simplex[1] == 1. + else: + assert st.num_simplices() == 10 def test_reset_filtration(): st = SimplexTree() -- cgit v1.2.3 From 315b0e1b4301ffab98bbc36d064344fba72076c5 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 10 Dec 2020 09:24:05 +0100 Subject: Fix memory leak --- src/python/include/Alpha_complex_factory.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/python/include/Alpha_complex_factory.h b/src/python/include/Alpha_complex_factory.h index d699ad9b..3405fdd6 100644 --- a/src/python/include/Alpha_complex_factory.h +++ b/src/python/include/Alpha_complex_factory.h @@ -48,11 +48,14 @@ static CgalPointType pt_cython_to_cgal(std::vector const& vec) { class Abstract_alpha_complex { public: virtual std::vector get_point(int vh) = 0; + virtual bool create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool default_filtration_value) = 0; + + virtual ~Abstract_alpha_complex() = default; }; -class Exact_Alphacomplex_dD : public Abstract_alpha_complex { +class Exact_Alphacomplex_dD final : public Abstract_alpha_complex { private: using Kernel = CGAL::Epeck_d; using Point = typename Kernel::Point_d; @@ -78,7 +81,7 @@ class Exact_Alphacomplex_dD : public Abstract_alpha_complex { Alpha_complex alpha_complex_; }; -class Inexact_Alphacomplex_dD : public Abstract_alpha_complex { +class Inexact_Alphacomplex_dD final : public Abstract_alpha_complex { private: using Kernel = CGAL::Epick_d; using Point = typename Kernel::Point_d; @@ -104,7 +107,7 @@ class Inexact_Alphacomplex_dD : public Abstract_alpha_complex { }; template -class Alphacomplex_3D : public Abstract_alpha_complex { +class Alphacomplex_3D final : public Abstract_alpha_complex { private: using Point = typename Alpha_complex_3d::Bare_point_3; -- cgit v1.2.3 From ed7dcbebad7dd6fee114723eb34601b292a2e72c Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 10 Dec 2020 09:52:17 +0100 Subject: Build python 3.9 pip package and use python 3.9 as default test package --- .github/workflows/pip-build-linux.yml | 10 +++++----- .github/workflows/pip-build-osx.yml | 2 +- .github/workflows/pip-build-windows.yml | 2 +- .github/workflows/pip-packaging-linux.yml | 17 +++++++++++++---- .github/workflows/pip-packaging-osx.yml | 2 +- .github/workflows/pip-packaging-windows.yml | 2 +- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pip-build-linux.yml b/.github/workflows/pip-build-linux.yml index 14fdc8d2..cf8ddadf 100644 --- a/.github/workflows/pip-build-linux.yml +++ b/.github/workflows/pip-build-linux.yml @@ -11,11 +11,11 @@ jobs: - uses: actions/checkout@v1 with: submodules: true - - name: Build wheels for Python 3.8 + - name: Build wheels for Python 3.9 run: | - mkdir build_38 - cd build_38 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON38/bin/python .. + mkdir build_39 + cd build_39 + cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON39/bin/python .. cd src/python - $PYTHON38/bin/python setup.py bdist_wheel + $PYTHON39/bin/python setup.py bdist_wheel auditwheel repair dist/*.whl \ No newline at end of file diff --git a/.github/workflows/pip-build-osx.yml b/.github/workflows/pip-build-osx.yml index 15b8880a..50b8b09c 100644 --- a/.github/workflows/pip-build-osx.yml +++ b/.github/workflows/pip-build-osx.yml @@ -8,7 +8,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.8'] + python-version: ['3.9'] name: Build wheels for Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/pip-build-windows.yml b/.github/workflows/pip-build-windows.yml index 995d52dd..aacbbc52 100644 --- a/.github/workflows/pip-build-windows.yml +++ b/.github/workflows/pip-build-windows.yml @@ -8,7 +8,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.8'] + python-version: ['3.9'] name: Build wheels for Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/pip-packaging-linux.yml b/.github/workflows/pip-packaging-linux.yml index bd524af9..469c3b3b 100644 --- a/.github/workflows/pip-packaging-linux.yml +++ b/.github/workflows/pip-packaging-linux.yml @@ -45,12 +45,21 @@ jobs: cd src/python $PYTHON38/bin/python setup.py bdist_wheel auditwheel repair dist/*.whl + - name: Build wheels for Python 3.9 + run: | + mkdir build_39 + cd build_39 + cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON39/bin/python .. + cd src/python + $PYTHON39/bin/python setup.py bdist_wheel + auditwheel repair dist/*.whl - name: Publish on PyPi env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | - $PYTHON38/bin/python -m twine upload build_35/src/python/wheelhouse/* - $PYTHON38/bin/python -m twine upload build_36/src/python/wheelhouse/* - $PYTHON38/bin/python -m twine upload build_37/src/python/wheelhouse/* - $PYTHON38/bin/python -m twine upload build_38/src/python/wheelhouse/* \ No newline at end of file + $PYTHON39/bin/python -m twine upload build_35/src/python/wheelhouse/* + $PYTHON39/bin/python -m twine upload build_36/src/python/wheelhouse/* + $PYTHON39/bin/python -m twine upload build_37/src/python/wheelhouse/* + $PYTHON39/bin/python -m twine upload build_38/src/python/wheelhouse/* + $PYTHON39/bin/python -m twine upload build_39/src/python/wheelhouse/* \ No newline at end of file diff --git a/.github/workflows/pip-packaging-osx.yml b/.github/workflows/pip-packaging-osx.yml index c94369ac..46441e65 100644 --- a/.github/workflows/pip-packaging-osx.yml +++ b/.github/workflows/pip-packaging-osx.yml @@ -10,7 +10,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.5', '3.6', '3.7', '3.8'] + python-version: ['3.5', '3.6', '3.7', '3.8', '3.9'] name: Build wheels for Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/pip-packaging-windows.yml b/.github/workflows/pip-packaging-windows.yml index 8f4ab6e7..3a751486 100644 --- a/.github/workflows/pip-packaging-windows.yml +++ b/.github/workflows/pip-packaging-windows.yml @@ -10,7 +10,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.5', '3.6', '3.7', '3.8'] + python-version: ['3.5', '3.6', '3.7', '3.8', '3.9'] name: Build wheels for Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v1 -- cgit v1.2.3 From 0f8d2bde932f350e25bed760db52ebfafef111fc Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 10 Dec 2020 11:18:44 +0100 Subject: Need to rebuild gudhi/pip_for_gudhi docker image --- Dockerfile_for_pip | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile_for_pip b/Dockerfile_for_pip index 98668a04..8f9f2443 100644 --- a/Dockerfile_for_pip +++ b/Dockerfile_for_pip @@ -39,12 +39,14 @@ RUN /opt/python/cp35-cp35m/bin/pip install -r build-requirements.txt \ && /opt/python/cp36-cp36m/bin/pip install -r build-requirements.txt\ && /opt/python/cp37-cp37m/bin/pip install -r build-requirements.txt\ && /opt/python/cp38-cp38/bin/pip install -r build-requirements.txt\ - && /opt/python/cp38-cp38/bin/pip install twine + && /opt/python/cp39-cp39/bin/pip install -r build-requirements.txt\ + && /opt/python/cp39-cp39/bin/pip install twine ENV PYTHON35="/opt/python/cp35-cp35m/" ENV PYTHON36="/opt/python/cp36-cp36m/" ENV PYTHON37="/opt/python/cp37-cp37m/" ENV PYTHON38="/opt/python/cp38-cp38/" +ENV PYTHON38="/opt/python/cp39-cp39/" ENV PATH="/opt/cmake/bin:${PATH}" ENV PATH="/opt/rh/devtoolset-8/root/usr/bin:${PATH}" -- cgit v1.2.3 From ec4fe178813119fc4a37c5893e038d2c7b9736f1 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 10 Dec 2020 13:57:19 +0100 Subject: Typo for python 3.9 --- Dockerfile_for_pip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile_for_pip b/Dockerfile_for_pip index 8f9f2443..d5ae6417 100644 --- a/Dockerfile_for_pip +++ b/Dockerfile_for_pip @@ -46,7 +46,7 @@ ENV PYTHON35="/opt/python/cp35-cp35m/" ENV PYTHON36="/opt/python/cp36-cp36m/" ENV PYTHON37="/opt/python/cp37-cp37m/" ENV PYTHON38="/opt/python/cp38-cp38/" -ENV PYTHON38="/opt/python/cp39-cp39/" +ENV PYTHON39="/opt/python/cp39-cp39/" ENV PATH="/opt/cmake/bin:${PATH}" ENV PATH="/opt/rh/devtoolset-8/root/usr/bin:${PATH}" -- cgit v1.2.3 From 957da77f9484972ce34d0415502887f92080878e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 11 Dec 2020 09:38:12 +0100 Subject: code review: GUDHI_USE_EIGEN3 generated by CMake in __init__.py as suggested and roll back the other solution --- src/python/CMakeLists.txt | 2 ++ src/python/gudhi/__init__.py.in | 4 ++++ src/python/gudhi/simplex_tree.pxd | 2 -- src/python/gudhi/simplex_tree.pyx | 3 --- src/python/include/Simplex_tree_interface.h | 6 ------ src/python/test/test_simplex_tree.py | 4 ++-- 6 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 45c89609..5a245aac 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -129,11 +129,13 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") endif() + set(GUDHI_USE_EIGEN3 "False") if (EIGEN3_FOUND) add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}") # No problem, even if no CGAL found set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_EIGEN3', ") + set(GUDHI_USE_EIGEN3 "True") endif (EIGEN3_FOUND) set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_reader', ") diff --git a/src/python/gudhi/__init__.py.in b/src/python/gudhi/__init__.py.in index 79e12fbc..3043201a 100644 --- a/src/python/gudhi/__init__.py.in +++ b/src/python/gudhi/__init__.py.in @@ -23,6 +23,10 @@ __all__ = [@GUDHI_PYTHON_MODULES@ @GUDHI_PYTHON_MODULES_EXTRA@] __available_modules = '' __missing_modules = '' +# For unitary tests purpose +# could use "if 'collapse_edges' in gudhi.__all__" when collapse edges will have a python module +__GUDHI_USE_EIGEN3 = @GUDHI_USE_EIGEN3@ + # Try to import * from gudhi.__module_name for default modules. # Extra modules require an explicit import by the user (mostly because of # unusual dependencies, but also to avoid cluttering namespace gudhi and diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 283830ff..3c4cbed3 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -74,8 +74,6 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) nogil pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] get_boundary_iterators(vector[int] simplex) nogil except + - - cdef int _GUDHI_USE_EIGEN3 cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index eb44c0fc..7d6ab89a 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -17,9 +17,6 @@ __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" -# For unitary tests purpose -__GUDHI_USE_EIGEN3 = _GUDHI_USE_EIGEN3 - # SimplexTree python interface cdef class SimplexTree: """The simplex tree is an efficient and flexible data structure for diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 50592e25..82444609 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -27,12 +27,6 @@ namespace Gudhi { -#ifdef GUDHI_USE_EIGEN3 -const int _GUDHI_USE_EIGEN3 = 1; -#else -const int _GUDHI_USE_EIGEN3 = 0; -#endif - template class Simplex_tree_interface : public Simplex_tree { public: diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 15b472ee..0c072baa 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -8,7 +8,7 @@ - YYYY/MM Author: Description of the modification """ -from gudhi import SimplexTree, simplex_tree +from gudhi import SimplexTree, __GUDHI_USE_EIGEN3 import pytest __author__ = "Vincent Rouvreau" @@ -355,7 +355,7 @@ def test_collapse_edges(): # If no Eigen3, collapse_edges just return a copy, no action. Maybe it would require some user warning st.collapse_edges() - if simplex_tree.__GUDHI_USE_EIGEN3: + if __GUDHI_USE_EIGEN3: assert st.num_simplices() == 9 assert st.find([1, 3]) == False for simplex in st.get_skeleton(0): -- cgit v1.2.3 From 40e0976e8dae27f0e30f3c9df1fd7de1a7343948 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 11 Dec 2020 10:31:09 +0100 Subject: code review: throw an eception if collapse_edges when no Eigen3 --- src/python/gudhi/simplex_tree.pxd | 2 +- src/python/gudhi/simplex_tree.pyx | 4 ++-- src/python/include/Simplex_tree_interface.h | 4 +--- src/python/test/test_simplex_tree.py | 7 ++++--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 3c4cbed3..000323af 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -63,7 +63,7 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": bool make_filtration_non_decreasing() nogil void compute_extended_filtration() nogil vector[vector[pair[int, pair[double, double]]]] compute_extended_persistence_subdiagrams(vector[pair[int, pair[double, double]]] dgm, double min_persistence) nogil - Simplex_tree_interface_full_featured* collapse_edges(int nb_collapse_iteration) nogil + Simplex_tree_interface_full_featured* collapse_edges(int nb_collapse_iteration) nogil except + void reset_filtration(double filtration, int dimension) nogil # Iterators over Simplex tree pair[vector[int], double] get_simplex_and_filtration(Simplex_tree_simplex_handle f_simplex) nogil diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 7d6ab89a..665d41e6 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -628,8 +628,8 @@ cdef class SimplexTree: :param nb_iterations: The number of edge collapse iterations to perform. Default is 1. :type nb_iterations: int - :note: collapse_edges function requires `Eigen `_ >= 3.1.0, otherwise no action is - performed. + :note: collapse_edges method requires `Eigen `_ >= 3.1.0 and an exception is thrown + if this method is not available. """ # Backup old pointer cdef Simplex_tree_interface_full_featured* ptr = self.get_ptr() diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 82444609..629f6083 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -191,9 +191,7 @@ class Simplex_tree_interface : public Simplex_tree { } return collapsed_stree_ptr; #else - // If no Eigen3, return a copy, as it will be deleted in pyx - Simplex_tree_interface* collapsed_stree_ptr = new Simplex_tree_interface(*this); - return collapsed_stree_ptr; + throw std::runtime_error("Unable to collapse edges as it requires Eigen3 >= 3.1.0."); #endif } diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 0c072baa..a3eacaa9 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -353,15 +353,16 @@ def test_collapse_edges(): assert st.num_simplices() == 10 - # If no Eigen3, collapse_edges just return a copy, no action. Maybe it would require some user warning - st.collapse_edges() if __GUDHI_USE_EIGEN3: + st.collapse_edges() assert st.num_simplices() == 9 assert st.find([1, 3]) == False for simplex in st.get_skeleton(0): assert simplex[1] == 1. else: - assert st.num_simplices() == 10 + # If no Eigen3, collapse_edges throws an exception + with pytest.raises(RuntimeError): + st.collapse_edges() def test_reset_filtration(): st = SimplexTree() -- cgit v1.2.3 From ba3be8d118a9720677b7776ae9a22c10cfcc0cef Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 11 Dec 2020 17:49:00 +0100 Subject: code review: else branch --- src/python/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 5a245aac..5c1402a6 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -129,13 +129,14 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") endif() - set(GUDHI_USE_EIGEN3 "False") if (EIGEN3_FOUND) add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION}") # No problem, even if no CGAL found set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_EIGEN3', ") set(GUDHI_USE_EIGEN3 "True") + else (EIGEN3_FOUND) + set(GUDHI_USE_EIGEN3 "False") endif (EIGEN3_FOUND) set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_reader', ") -- cgit v1.2.3 From ed925ed2068623ea4bacc539084deda1ebf95344 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 14 Dec 2020 11:27:14 +0100 Subject: Release note 3.4.0 --- .github/next_release.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/next_release.md b/.github/next_release.md index 7e7fe03b..96886627 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -9,8 +9,9 @@ Below is a list of changes made since GUDHI 3.3.0: - [Alpha complex](https://gudhi.inria.fr/doc/latest/group__alpha__complex.html) - the C++ weighted version for alpha complex is now available in dimension D. -- [Module](link) - - ... +- Simplex tree [C++](https://gudhi.inria.fr/doc/latest/class_gudhi_1_1_simplex__tree.html) [Python](http://gudhi.gforge.inria.fr/python/latest/simplex_tree_ref.html) + - A new method to reset the filtrations + - A new method to get the boundaries of a simplex - [Subsampling](https://gudhi.inria.fr/doc/latest/group__subsampling.html) - The C++ function `choose_n_farthest_points()` now takes a distance function instead of a kernel as first argument, users can replace `k` with `k.squared_distance_d_object()` in each call in their code. -- cgit v1.2.3 From 8a6f8fab73050a540b8b21e580b697f172165399 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 14 Dec 2020 11:31:36 +0100 Subject: teasing --- .github/next_release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/next_release.md b/.github/next_release.md index 96886627..d8f53f0f 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -1,6 +1,6 @@ We are pleased to announce the release 3.4.0 of the GUDHI library. -As a major new feature, the GUDHI library now offers dD weighted alpha complex, ... +As a major new feature, the GUDHI library now offers dD weighted alpha complex, pip and conda packages for Python 3.9. 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.4.0.tar.gz). -- cgit v1.2.3 From 5c9cf5fbb2d6fabbacf67a53d250d53d3d0c3899 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 14 Dec 2020 15:29:14 +0100 Subject: Fix sphinx warning and doc identation --- src/python/gudhi/simplex_tree.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 665d41e6..d7991417 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -629,7 +629,7 @@ cdef class SimplexTree: :type nb_iterations: int :note: collapse_edges method requires `Eigen `_ >= 3.1.0 and an exception is thrown - if this method is not available. + if this method is not available. """ # Backup old pointer cdef Simplex_tree_interface_full_featured* ptr = self.get_ptr() -- cgit v1.2.3 From 34e95e0853daa3dd897f08824cebc8ca77d5cef9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 14 Dec 2020 15:29:48 +0100 Subject: Fix sphinx error on Azure and Appveyor --- src/python/doc/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/python/doc/conf.py b/src/python/doc/conf.py index 3cc5d1d6..b06baf9c 100755 --- a/src/python/doc/conf.py +++ b/src/python/doc/conf.py @@ -44,6 +44,8 @@ extensions = [ 'sphinx_paramlinks', ] +bibtex_bibfiles = ['../../biblio/bibliography.bib'] + todo_include_todos = True # plot option : do not show hyperlinks (Source code, png, hires.png, pdf) plot_html_show_source_link = False -- cgit v1.2.3 From c0d3261505574d886c01fc73c8d09838a825f438 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 14 Dec 2020 16:38:32 +0100 Subject: Release candidate 1 for gudhi version 3.4.0 --- CMakeGUDHIVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index 5f1eaacf..e1ae0b43 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -2,7 +2,7 @@ set (GUDHI_MAJOR_VERSION 3) set (GUDHI_MINOR_VERSION 4) # GUDHI_PATCH_VERSION can be 'ZaN' for Alpha release, 'ZbN' for Beta release, 'ZrcN' for release candidate or 'Z' for a final release. -set (GUDHI_PATCH_VERSION 0a0) +set (GUDHI_PATCH_VERSION 0rc1) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) message(STATUS "GUDHI version : ${GUDHI_VERSION}") -- cgit v1.2.3 From 0ef1266a5357f85322ceb1b0aedb431efadd7b6c Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 15 Dec 2020 15:33:15 +0100 Subject: release note review: 'in any dimension' --- .github/next_release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/next_release.md b/.github/next_release.md index d8f53f0f..5a74966d 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -7,7 +7,7 @@ We are now using GitHub to develop the GUDHI library, do not hesitate to [fork t Below is a list of changes made since GUDHI 3.3.0: - [Alpha complex](https://gudhi.inria.fr/doc/latest/group__alpha__complex.html) - - the C++ weighted version for alpha complex is now available in dimension D. + - the C++ weighted version for alpha complex is now available in any dimension D. - Simplex tree [C++](https://gudhi.inria.fr/doc/latest/class_gudhi_1_1_simplex__tree.html) [Python](http://gudhi.gforge.inria.fr/python/latest/simplex_tree_ref.html) - A new method to reset the filtrations -- cgit v1.2.3 From cf36a3971fb6a0ed37577295d7f1f13a930d1dba Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 15 Dec 2020 15:37:16 +0100 Subject: 3.4.0 Release --- CMakeGUDHIVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index e1ae0b43..e191ad96 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -2,7 +2,7 @@ set (GUDHI_MAJOR_VERSION 3) set (GUDHI_MINOR_VERSION 4) # GUDHI_PATCH_VERSION can be 'ZaN' for Alpha release, 'ZbN' for Beta release, 'ZrcN' for release candidate or 'Z' for a final release. -set (GUDHI_PATCH_VERSION 0rc1) +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