summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml205
-rw-r--r--.github/for_maintainers/new_gudhi_version_creation.md41
-rw-r--r--.github/next_release.md49
-rw-r--r--.github/test-requirements.txt2
-rw-r--r--.github/workflows/pip-build-linux.yml21
-rw-r--r--.github/workflows/pip-build-osx.yml34
-rw-r--r--.github/workflows/pip-build-windows.yml37
-rw-r--r--.github/workflows/pip-packaging-linux.yml17
-rw-r--r--.github/workflows/pip-packaging-osx.yml2
-rw-r--r--.github/workflows/pip-packaging-windows.yml10
-rw-r--r--CMakeGUDHIVersion.txt2
-rw-r--r--CMakeLists.txt2
-rw-r--r--Dockerfile_for_circleci_image13
-rw-r--r--Dockerfile_for_pip25
-rw-r--r--Dockerfile_gudhi_installation18
-rw-r--r--src/Alpha_complex/doc/Intro_alpha_complex.h49
-rw-r--r--src/Alpha_complex/example/CMakeLists.txt17
-rw-r--r--src/Alpha_complex/example/Weighted_alpha_complex_3d_from_points.cpp16
-rw-r--r--src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp52
-rw-r--r--src/Alpha_complex/example/weightedalpha3dfrompoints_for_doc.txt4
-rw-r--r--src/Alpha_complex/include/gudhi/Alpha_complex.h162
-rw-r--r--src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h141
-rw-r--r--src/Alpha_complex/include/gudhi/Alpha_complex_3d.h8
-rw-r--r--src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp109
-rw-r--r--src/Alpha_complex/test/CMakeLists.txt23
-rw-r--r--src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp229
-rw-r--r--src/Alpha_complex/utilities/CMakeLists.txt134
-rw-r--r--src/Alpha_complex/utilities/alpha_complex_persistence.cpp101
-rw-r--r--src/Alpha_complex/utilities/alphacomplex.md7
-rw-r--r--src/Bitmap_cubical_complex/example/CMakeLists.txt2
-rw-r--r--src/Bitmap_cubical_complex/include/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h6
-rw-r--r--src/Bottleneck_distance/example/CMakeLists.txt20
-rw-r--r--src/Bottleneck_distance/include/gudhi/Bottleneck.h8
-rw-r--r--src/Bottleneck_distance/include/gudhi/Persistence_graph.h18
-rw-r--r--src/Bottleneck_distance/test/bottleneck_unit_test.cpp5
-rw-r--r--src/CMakeLists.txt18
-rw-r--r--src/Cech_complex/benchmark/CMakeLists.txt15
-rw-r--r--src/Cech_complex/example/CMakeLists.txt15
-rw-r--r--src/Cech_complex/test/CMakeLists.txt3
-rw-r--r--src/Cech_complex/utilities/CMakeLists.txt19
-rw-r--r--src/Collapse/example/CMakeLists.txt41
-rw-r--r--src/Collapse/include/gudhi/Flag_complex_edge_collapser.h6
-rw-r--r--src/Collapse/test/CMakeLists.txt16
-rw-r--r--src/Collapse/utilities/CMakeLists.txt64
-rw-r--r--src/Nerve_GIC/example/CMakeLists.txt3
-rw-r--r--src/Persistence_representations/example/CMakeLists.txt6
-rw-r--r--src/Persistent_cohomology/benchmark/CMakeLists.txt14
-rw-r--r--src/Persistent_cohomology/example/CMakeLists.txt76
-rw-r--r--src/Rips_complex/example/CMakeLists.txt5
-rw-r--r--src/Rips_complex/include/gudhi/Sparse_rips_complex.h14
-rw-r--r--src/Rips_complex/utilities/CMakeLists.txt67
-rw-r--r--src/Simplex_tree/example/CMakeLists.txt14
-rw-r--r--src/Simplex_tree/include/gudhi/Simplex_tree.h31
-rw-r--r--src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h6
-rw-r--r--src/Simplex_tree/test/simplex_tree_unit_test.cpp51
-rw-r--r--src/Skeleton_blocker/example/CMakeLists.txt4
-rw-r--r--src/Spatial_searching/example/CMakeLists.txt1
-rw-r--r--src/Spatial_searching/include/gudhi/Kd_tree_search.h98
-rw-r--r--src/Subsampling/example/CMakeLists.txt9
-rw-r--r--src/Subsampling/example/example_choose_n_farthest_points.cpp2
-rw-r--r--src/Subsampling/example/example_custom_distance.cpp44
-rw-r--r--src/Subsampling/example/example_custom_kernel.cpp63
-rw-r--r--src/Subsampling/include/gudhi/choose_n_farthest_points.h41
-rw-r--r--src/Subsampling/include/gudhi/pick_n_random_points.h14
-rw-r--r--src/Subsampling/include/gudhi/sparsify_point_set.h33
-rw-r--r--src/Subsampling/test/test_choose_n_farthest_points.cpp34
-rw-r--r--src/Tangential_complex/example/CMakeLists.txt2
-rw-r--r--src/Witness_complex/doc/Witness_complex_doc.h6
-rw-r--r--src/Witness_complex/example/CMakeLists.txt7
-rw-r--r--src/Witness_complex/example/example_strong_witness_complex_off.cpp3
-rw-r--r--src/Witness_complex/example/example_witness_complex_off.cpp3
-rw-r--r--src/Witness_complex/example/example_witness_complex_sphere.cpp2
-rw-r--r--src/Witness_complex/utilities/CMakeLists.txt36
-rw-r--r--src/Witness_complex/utilities/strong_witness_persistence.cpp3
-rw-r--r--src/Witness_complex/utilities/weak_witness_persistence.cpp3
-rw-r--r--src/cmake/modules/GUDHI_modules.cmake7
-rw-r--r--src/cmake/modules/GUDHI_third_party_libraries.cmake44
-rw-r--r--src/common/doc/examples.h2
-rw-r--r--src/common/doc/installation.h22
-rw-r--r--src/python/CMakeLists.txt107
-rw-r--r--src/python/doc/bottleneck_distance_user.rst4
-rwxr-xr-xsrc/python/doc/conf.py2
-rw-r--r--src/python/doc/cubical_complex_user.rst22
-rw-r--r--src/python/doc/installation.rst9
-rw-r--r--src/python/doc/representations.rst64
-rw-r--r--src/python/doc/rips_complex_sum.inc22
-rw-r--r--src/python/doc/rips_complex_user.rst6
-rw-r--r--src/python/doc/wasserstein_distance_user.rst7
-rwxr-xr-xsrc/python/example/alpha_complex_diagram_persistence_from_off_file_example.py2
-rwxr-xr-xsrc/python/example/diagram_vectorizations_distances_kernels.py19
-rwxr-xr-xsrc/python/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py2
-rwxr-xr-xsrc/python/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py2
-rwxr-xr-xsrc/python/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py2
-rwxr-xr-xsrc/python/example/rips_complex_diagram_persistence_from_correlation_matrix_file_example.py2
-rwxr-xr-xsrc/python/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py2
-rwxr-xr-xsrc/python/example/rips_complex_diagram_persistence_from_off_file_example.py2
-rwxr-xr-xsrc/python/example/tangential_complex_plain_homology_from_off_file_example.py2
-rw-r--r--src/python/gudhi/__init__.py.in4
-rw-r--r--src/python/gudhi/representations/vector_methods.py17
-rw-r--r--src/python/gudhi/simplex_tree.pxd10
-rw-r--r--src/python/gudhi/simplex_tree.pyx78
-rw-r--r--src/python/gudhi/subsampling.pyx23
-rw-r--r--src/python/include/Alpha_complex_factory.h9
-rw-r--r--src/python/include/Simplex_tree_interface.h16
-rw-r--r--src/python/include/Subsampling_interface.h10
-rwxr-xr-xsrc/python/test/test_bottleneck_distance.py12
-rwxr-xr-xsrc/python/test/test_representations.py20
-rwxr-xr-xsrc/python/test/test_simplex_tree.py58
-rwxr-xr-xsrc/python/test/test_subsampling.py16
-rwxr-xr-xsrc/python/test/test_wasserstein_distance.py24
-rwxr-xr-xsrc/python/test/test_wasserstein_with_tensors.py47
111 files changed, 2238 insertions, 940 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index b04efd52..d95b8d36 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,24 +52,26 @@ jobs:
command: |
git submodule init
git submodule update
- mkdir build;
- cd build;
- 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 ..;
- 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;
-
+ 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:
@@ -81,21 +83,148 @@ 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
+
+ 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
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..5a74966d 100644
--- a/.github/next_release.md
+++ b/.github/next_release.md
@@ -1,47 +1,23 @@
-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 dD weighted alpha complex, pip and conda packages for Python 3.9.
-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.
+- [Alpha complex](https://gudhi.inria.fr/doc/latest/group__alpha__complex.html)
+ - the C++ weighted version for alpha complex is now available in any dimension D.
-- [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
+- 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
-- [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
+- [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.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 +29,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/.github/test-requirements.txt b/.github/test-requirements.txt
index 98f1007e..688a2a11 100644
--- a/.github/test-requirements.txt
+++ b/.github/test-requirements.txt
@@ -1,4 +1,5 @@
pytest
+pytest-cov
sphinx
sphinxcontrib-bibtex
sphinx-paramlinks
@@ -7,6 +8,7 @@ scipy
scikit-learn
POT
tensorflow
+tensorflow-addons
torch<1.5
pykeops
hnswlib
diff --git a/.github/workflows/pip-build-linux.yml b/.github/workflows/pip-build-linux.yml
new file mode 100644
index 00000000..cf8ddadf
--- /dev/null
+++ b/.github/workflows/pip-build-linux.yml
@@ -0,0 +1,21 @@
+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.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 \ 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..50b8b09c
--- /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.9']
+ 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..aacbbc52
--- /dev/null
+++ b/.github/workflows/pip-build-windows.yml
@@ -0,0 +1,37 @@
+name: pip build windows
+
+on: [push, pull_request]
+
+jobs:
+ build:
+ runs-on: windows-latest
+ strategy:
+ max-parallel: 4
+ matrix:
+ python-version: ['3.9']
+ 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: |
+ vcpkg update
+ vcpkg upgrade --no-dry-run
+ 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 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
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 2e45ad71..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
@@ -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
diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt
index a08b7b4d..e191ad96 100644
--- a/CMakeGUDHIVersion.txt
+++ b/CMakeGUDHIVersion.txt
@@ -1,6 +1,6 @@
# 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_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION})
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/Dockerfile_for_circleci_image b/Dockerfile_for_circleci_image
index 464097e7..ec1b8ff8 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 \
@@ -38,7 +41,6 @@ RUN apt-get install -y make \
libgmp3-dev \
libmpfr-dev \
libtbb-dev \
- libcgal-dev \
locales \
python3 \
python3-pip \
@@ -48,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..d5ae6417 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 /
@@ -38,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 PYTHON39="/opt/python/cp39-cp39/"
ENV PATH="/opt/cmake/bin:${PATH}"
ENV PATH="/opt/rh/devtoolset-8/root/usr/bin:${PATH}"
diff --git a/Dockerfile_gudhi_installation b/Dockerfile_gudhi_installation
index 996dd06b..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 \
@@ -58,9 +70,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 . \
diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h
index 60da7169..c068b268 100644
--- a/src/Alpha_complex/doc/Intro_alpha_complex.h
+++ b/src/Alpha_complex/doc/Intro_alpha_complex.h
@@ -22,6 +22,18 @@ namespace alpha_complex {
*
* @{
*
+<div class="toc">
+Table of Contents
+<ul>
+<li class="level1"><a href="#definition">Definition</a></li>
+<li class="level1"><a href="#pointsexample">Example from points</a></li>
+<li class="level1"><a href="#createcomplexalgorithm">Create complex algorithm</a></li>
+<li class="level1"><a href="#weightedversion">Weighted specific version</a></li>
+<li class="level1"><a href="#offexample">Example from OFF file</a></li>
+<li class="level1"><a href="#weighted3dexample">3d specific version</a></li>
+</ul>
+</div>
+
* \section definition Definition
*
* Alpha_complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
@@ -62,7 +74,7 @@ namespace alpha_complex {
* [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 &ge; 5.0.0.
+ * - For performances reasons, it is advised to use \ref eigen &ge; 3.3.5 and \ref cgal &ge; 5.2.0.
*
* \section pointsexample Example from points
*
@@ -146,6 +158,30 @@ 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
+ * <b>Requires:</b> \ref eigen &ge; 3.1.0 and \ref cgal &ge; 5.1.0.
+ *
+ * A weighted version for Alpha complex is available (cf. Alpha_complex). It is like a usual Alpha complex, but based
+ * on a <a href="https://doc.cgal.org/latest/Triangulation/index.html#title20">CGAL regular triangulation</a> 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 <a href="https://doc.cgal.org/latest/Alpha_shapes_3/index.html#title13">CGAL 3d
+ * weighted alpha shapes</a>.
+ *
+ * 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 +202,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
@@ -181,14 +217,7 @@ namespace alpha_complex {
*
* \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
diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt
index 2eecd50c..1fc2330a 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 $<TARGET_FILE:Alpha_complex_example_fast_from_off>
"${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,13 @@ endif()
add_test(NAME Alpha_complex_example_3d_from_points
COMMAND $<TARGET_FILE:Alpha_complex_example_3d_from_points>)
-endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+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 $<TARGET_FILE:Weighted_alpha_complex_example_from_points>)
+endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0)
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..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,7 +7,7 @@
#include <vector>
#include <limits> // 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::complexity::SAFE, true, false>;
using Bare_point = Weighted_alpha_complex_3d::Bare_point_3;
@@ -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_point> 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
@@ -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
new file mode 100644
index 00000000..d1f3e436
--- /dev/null
+++ b/src/Alpha_complex/example/Weighted_alpha_complex_from_points.cpp
@@ -0,0 +1,52 @@
+#include <gudhi/Alpha_complex.h>
+// to construct a simplex_tree from alpha complex
+#include <gudhi/Simplex_tree.h>
+
+#include <CGAL/Epeck_d.h>
+
+#include <iostream>
+#include <vector>
+
+// Explicit dimension 2 Epeck_d kernel
+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<Weighted_point>;
+
+int main() {
+ // ----------------------------------------------------------------------------
+ // Init of a list of points and weights from a small molecule
+ // ----------------------------------------------------------------------------
+ Vector_of_points points;
+ 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
+ // ----------------------------------------------------------------------------
+ Gudhi::alpha_complex::Alpha_complex<Kernel, true> 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/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]
diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h
index ba91998d..b315fa99 100644
--- a/src/Alpha_complex/include/gudhi/Alpha_complex.h
+++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h
@@ -12,14 +12,17 @@
#ifndef ALPHA_COMPLEX_H_
#define ALPHA_COMPLEX_H_
+#include <gudhi/Alpha_complex/Alpha_kernel_d.h>
#include <gudhi/Debug_utils.h>
// to construct Alpha_complex from a OFF file of points
#include <gudhi/Points_off_io.h>
#include <stdlib.h>
#include <math.h> // isnan, fmax
+#include <memory> // for std::unique_ptr
#include <CGAL/Delaunay_triangulation.h>
+#include <CGAL/Regular_triangulation.h> // aka. Weighted Delaunay triangulation
#include <CGAL/Epeck_d.h> // For EXACT or SAFE version
#include <CGAL/Epick_d.h> // For FAST version
#include <CGAL/Spatial_sort_traits_adapter_d.h>
@@ -29,6 +32,10 @@
#include <Eigen/src/Core/util/Macros.h> // for EIGEN_VERSION_AT_LEAST
+#include <boost/range/size.hpp>
+#include <boost/range/combine.hpp>
+#include <boost/range/adaptor/transformed.hpp>
+
#include <iostream>
#include <vector>
#include <string>
@@ -91,49 +98,56 @@ template<typename D> struct Is_Epeck_D<CGAL::Epeck_d<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 &ge; 5.0.0.
*/
-template<class Kernel = CGAL::Epeck_d<CGAL::Dynamic_dimension_tag>>
+template<class Kernel = CGAL::Epeck_d<CGAL::Dynamic_dimension_tag>, 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 = std::conditional_t<Weighted, CGAL::Regular_triangulation_traits_adapter<Kernel>, Kernel>;
+
// Add an int in TDS to save point index in the structure
- typedef CGAL::Triangulation_data_structure<typename Kernel::Dimension,
- CGAL::Triangulation_vertex<Kernel, std::ptrdiff_t>,
- CGAL::Triangulation_full_cell<Kernel> > TDS;
- /** \brief A Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/
- typedef CGAL::Delaunay_triangulation<Kernel, TDS> Delaunay_triangulation;
-
- /** \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 TDS = CGAL::Triangulation_data_structure<typename Geom_traits::Dimension,
+ CGAL::Triangulation_vertex<Geom_traits, std::ptrdiff_t>,
+ CGAL::Triangulation_full_cell<Geom_traits> >;
- 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;
+ /** \brief A (Weighted or not) Delaunay triangulation of a set of points in \f$ \mathbb{R}^D\f$.*/
+ using Triangulation = std::conditional_t<Weighted, CGAL::Regular_triangulation<Kernel, TDS>,
+ CGAL::Delaunay_triangulation<Kernel, TDS>>;
+
+ /** \brief CGAL kernel container for computations in function of the weighted or not characteristics.*/
+ using A_kernel_d = Alpha_kernel_d<Kernel, Weighted>;
+
+ // Numeric type of coordinates in the kernel
+ using FT = typename A_kernel_d::FT;
+ /** \brief Sphere is a std::pair<Kernel::Point_d, Kernel::FT> (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, or a weighted point in Euclidean space.*/
+ using Point_d = typename Geom_traits::Point_d;
+
+ private:
// 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 = 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_;
+ std::unique_ptr<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<std::pair<Point_d, FT>> cache_, old_cache_;
+ std::vector<Sphere> cache_, old_cache_;
public:
/** \brief Alpha_complex constructor from an OFF file name.
@@ -145,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<Point_d> off_reader(off_file_name);
if (!off_reader.is_valid()) {
std::cerr << "Alpha_complex - Unable to read file " << off_file_name << "\n";
@@ -158,23 +171,40 @@ 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
+ * @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.
+ * 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<typename InputPointRange >
- Alpha_complex(const InputPointRange& points)
- : triangulation_(nullptr) {
+ Alpha_complex(const InputPointRange& points) {
init_from_range(points);
}
- /** \brief Alpha_complex destructor deletes the Delaunay triangulation.
+ /** \brief Alpha_complex constructor from a list of points and weights.
+ *
+ * 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.
+ *
+ * @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.
*/
- ~Alpha_complex() {
- delete triangulation_;
+ template <typename InputPointRange, typename WeightRange>
+ Alpha_complex(const InputPointRange& points, WeightRange weights) {
+ 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"));
+ 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);
}
// Forbid copy/move constructor/assignment operator
@@ -202,15 +232,17 @@ 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);
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_ = std::make_unique<Triangulation>(kernel_.get_dimension(*first));
std::vector<Point_d> point_cloud(first, last);
@@ -218,18 +250,20 @@ class Alpha_complex {
std::vector<std::ptrdiff_t> indices(boost::counting_iterator<std::ptrdiff_t>(0),
boost::counting_iterator<std::ptrdiff_t>(point_cloud.size()));
- typedef boost::iterator_property_map<typename std::vector<Point_d>::iterator,
- CGAL::Identity_property_map<std::ptrdiff_t>> Point_property_map;
- typedef CGAL::Spatial_sort_traits_adapter_d<Kernel, Point_property_map> Search_traits_d;
+ using Point_property_map = boost::iterator_property_map<typename std::vector<Point_d>::iterator,
+ CGAL::Identity_property_map<std::ptrdiff_t>>;
+ using Search_traits_d = CGAL::Spatial_sort_traits_adapter_d<Geom_traits, Point_property_map>;
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();
+ }
}
// --------------------------------------------------------------------------------------------
// structure to retrieve CGAL points from vertex handle - one vertex handle per point.
@@ -270,9 +304,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 +314,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<Point_d> 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 +354,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<Vertex_handle> Vector_vertex;
+ using Vertex_handle = typename SimplicialComplexForAlpha::Vertex_handle;
+ using Simplex_handle = typename SimplicialComplexForAlpha::Simplex_handle;
+ using Vector_vertex = std::vector<Vertex_handle>;
if (triangulation_ == nullptr) {
std::cerr << "Alpha_complex cannot create_complex from a NULL triangulation\n";
@@ -368,6 +400,7 @@ class Alpha_complex {
// --------------------------------------------------------------------------------------------
if (!default_filtration_value) {
+ CGAL::NT_converter<FT, Filtration_value> cgal_converter;
// --------------------------------------------------------------------------------------------
// ### For i : d -> 0
for (int decr_dim = triangulation_->maximal_dimension(); decr_dim >= 0; decr_dim--) {
@@ -378,14 +411,13 @@ 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);
#endif
- CGAL::NT_converter<FT, Filtration_value> cv;
- alpha_complex_filtration = cv(sqrad);
+ alpha_complex_filtration = cgal_converter(sqrad);
}
complex.assign_filtration(f_simplex, alpha_complex_filtration);
#ifdef DEBUG_TRACES
@@ -393,7 +425,7 @@ 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);
}
}
@@ -416,8 +448,8 @@ class Alpha_complex {
template <typename SimplicialComplexForAlpha, typename Simplex_handle>
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 +482,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_.squared_distance_d_object()(cache.first, get_point_(extra)) >= cache.second;
+ 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
new file mode 100644
index 00000000..28d6d7a9
--- /dev/null
+++ b/src/Alpha_complex/include/gudhi/Alpha_complex/Alpha_kernel_d.h
@@ -0,0 +1,141 @@
+/* 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 <CGAL/version.h> // for CGAL_VERSION_NR
+
+#include <Eigen/Core> // for EIGEN_VERSION_AT_LEAST
+
+#include <utility> // 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 {
+
+/**
+ * \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 {
+};
+
+// Unweighted Kernel_d version
+template < typename Kernel >
+class Alpha_kernel_d<Kernel, false> {
+ 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<Point_d, FT>;
+
+ int get_dimension(const Point_d& p0) const {
+ return kernel_.point_dimension_d_object()(p0);
+ }
+
+ template<class PointIterator>
+ 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<class PointIterator>
+ 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;
+ }
+
+ bool is_gabriel(const Sphere& circumcenter, const Point_d& point) {
+ return kernel_.squared_distance_d_object()(circumcenter.first, point) >= circumcenter.second;
+ }
+};
+
+// Weighted Kernel_d version
+template < typename Kernel >
+class Alpha_kernel_d<Kernel, true> {
+ 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<class PointIterator>
+ 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 < 1050200000
+ return kernel_.power_center_d_object()(begin, end);
+#else
+ return kernel_.construct_power_sphere_d_object()(begin, end);
+#endif
+ }
+
+ template<class PointIterator>
+ FT get_squared_radius(PointIterator begin, PointIterator end) const {
+ return kernel_.compute_squared_radius_smallest_orthogonal_sphere_d_object()(begin, end);
+ }
+
+ FT get_squared_radius(const Sphere& sph) const {
+ return sph.weight();
+ }
+
+ 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 < 1050200000
+ return kernel_.power_distance_d_object()(circumcenter, point) >= 0;
+#else
+ return kernel_.compute_power_product_d_object()(circumcenter, point) >= 0;
+#endif
+ }
+};
+
+} // 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/include/gudhi/Alpha_complex_3d.h b/src/Alpha_complex/include/gudhi/Alpha_complex_3d.h
index f56e12d0..4e5fc933 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 <CGAL/iterator.h>
#include <CGAL/version.h> // for CGAL_VERSION_NR
-#include <Eigen/src/Core/util/Macros.h> // for EIGEN_VERSION_AT_LEAST
-
#include <boost/container/static_vector.hpp>
#include <iostream>
@@ -56,10 +54,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 {
@@ -160,8 +154,10 @@ class Alpha_complex_3d {
using Kernel = CGAL::Periodic_3_regular_triangulation_traits_3<Predicates>;
};
+ public:
using Kernel = typename Kernel_3<Predicates, Weighted, Periodic>::Kernel;
+ private:
using TdsVb = typename std::conditional<Periodic, CGAL::Periodic_3_triangulation_ds_vertex_base_3<>,
CGAL::Triangulation_ds_vertex_base_3<>>::type;
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..6da4c084
--- /dev/null
+++ b/src/Alpha_complex/test/Alpha_kernel_d_unit_test.cpp
@@ -0,0 +1,109 @@
+/* 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 <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Epeck_d.h>
+#include <CGAL/NT_converter.h>
+
+#include <iostream>
+#include <vector>
+#include <utility> // for std::pair
+
+#include <gudhi/Alpha_complex/Alpha_kernel_d.h>
+#include <gudhi/Unitary_tests_utils.h>
+
+// 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<Exact_kernel_d, Exact_kernel_s, Inexact_kernel_d, Inexact_kernel_s> 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<TestedKernel, false> kernel;
+ std::vector<double> 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<TestedKernel, true> 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) {
+ // 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<TestedKernel, false>;
+ // Sphere: (x-1)² + (y-1)² + z² + t² = 1
+ // At least 5 points for a 3-sphere
+ std::vector<double> p0 {1., 0., 0., 0.};
+ std::vector<double> p1 {0., 1., 0., 0.};
+ std::vector<double> p2 {1., 1., 1., 0.};
+ std::vector<double> p3 {1., 1., 0., 1.};
+ std::vector<double> p4 {1., 1., -1., 0.};
+
+ using Point_d = typename Unweighted_kernel::Point_d;
+ std::vector<Point_d> unw_pts;
+ 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());
+
+ std::clog << "Center is " << unw_sphere.first << " - squared radius is " << unw_sphere.second << std::endl;
+
+ using Weighted_kernel = Gudhi::alpha_complex::Alpha_kernel_d<TestedKernel, true>;
+
+ using Weighted_point_d = typename Weighted_kernel::Weighted_point_d;
+ using Bare_point_d = typename Weighted_kernel::Bare_point_d;
+ std::vector<Weighted_point_d> w_pts;
+ 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());
+
+ std::clog << "Center is " << w_sphere.point() << " - squared radius is " << w_sphere.weight() << std::endl;
+
+ CGAL::NT_converter<typename Weighted_kernel::FT, double> 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));
+}
diff --git a/src/Alpha_complex/test/CMakeLists.txt b/src/Alpha_complex/test/CMakeLists.txt
index fe4b23e4..db5d840f 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,21 @@ 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)
+
+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)
+
+ 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..d267276c
--- /dev/null
+++ b/src/Alpha_complex/test/Weighted_alpha_complex_unit_test.cpp
@@ -0,0 +1,229 @@
+/* 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 <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <CGAL/Epick_d.h>
+#include <CGAL/Epeck_d.h>
+
+#include <cmath> // float comparison
+#include <vector>
+#include <random>
+#include <array>
+#include <cmath> // for std::fabs
+
+#include <gudhi/Alpha_complex.h>
+#include <gudhi/Alpha_complex_3d.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Unitary_tests_utils.h>
+
+using list_of_exact_kernel_variants = boost::mpl::list<CGAL::Epeck_d< CGAL::Dynamic_dimension_tag >,
+ CGAL::Epeck_d< CGAL::Dimension_tag<4> >
+ > ;
+
+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).
+
+ // Random points construction
+ using Point_d = typename Kernel::Point_d;
+ std::vector<Point_d> points;
+ std::uniform_real_distribution<double> rd_pts(-10., 10.);
+ std::random_device rand_dev;
+ std::mt19937 rand_engine(rand_dev());
+ for (int idx = 0; idx < 20; idx++) {
+ std::vector<double> point {rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine)};
+ points.emplace_back(point.begin(), point.end());
+ }
+
+ // Alpha complex from points
+ Gudhi::alpha_complex::Alpha_complex<Kernel, false> alpha_complex_from_points(points);
+ Gudhi::Simplex_tree<> simplex;
+ Gudhi::Simplex_tree<>::Filtration_value infty = std::numeric_limits<Gudhi::Simplex_tree<>::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::endl;
+ }
+
+ // Alpha complex from zero weighted points
+ std::vector<typename Kernel::FT> weights(20, 0.);
+ Gudhi::alpha_complex::Alpha_complex<Kernel, true> 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, infty, 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()) {
+ std::clog << " ( ";
+ for (auto vertex : zw_simplex.simplex_vertex_range(f_simplex)) {
+ std::clog << vertex << " ";
+ }
+ std::clog << ") -> " << "[" << zw_simplex.filtration(f_simplex) << "] " << std::endl;
+ }
+
+ BOOST_CHECK(zw_simplex == simplex);
+}
+
+template <typename Point_d>
+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) {
+ // 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;
+ using Weighted_point_d = typename Kernel_dD::Weighted_point_d;
+ std::vector<Weighted_point_d> w_points_d;
+
+ using Exact_weighted_alpha_complex_3d =
+ Gudhi::alpha_complex::Alpha_complex_3d<Gudhi::alpha_complex::complexity::EXACT, true, false>;
+ 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<Weighted_point_3> w_points_3;
+
+ std::uniform_real_distribution<double> rd_pts(-10., 10.);
+ std::uniform_real_distribution<double> 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<double> point {rd_pts(rand_engine), rd_pts(rand_engine), rd_pts(rand_engine)};
+ double weight = rd_wghts(rand_engine);
+ 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
+ using Points = std::vector<std::array<double,3>>;
+ using Points_and_filtrations = std::map<Points, double>;
+ Points_and_filtrations pts_fltr_dD;
+ Points_and_filtrations pts_fltr_3d;
+
+ // Weighted alpha complex for dD version
+ Gudhi::alpha_complex::Alpha_complex<Kernel_dD, true> 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()) {
+ Points points;
+ for (auto vertex : w_simplex_d.simplex_vertex_range(f_simplex)) {
+ CGAL::NT_converter<Kernel_dD::RT, double> 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::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
+ 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()) {
+ Points points;
+ for (auto vertex : w_simplex_3.simplex_vertex_range(f_simplex)) {
+ Bare_point_3 pt = alpha_complex_3D_from_weighted_points.get_point(vertex).point();
+ CGAL::NT_converter<Exact_weighted_alpha_complex_3d::Kernel::RT, double> 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::endl;
+ pts_fltr_3d[points] = w_simplex_d.filtration(f_simplex);
+ }
+
+ // 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);
+ }
+ // 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) > 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;
+ }
+}
+
+using list_of_1d_kernel_variants = boost::mpl::list<CGAL::Epeck_d< CGAL::Dynamic_dimension_tag >,
+ 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<Point_d> points;
+ std::vector<double> p1 {0.};
+ points.emplace_back(p1.begin(), p1.end());
+ // closed enough points
+ std::vector<double> p2 {0.1};
+ points.emplace_back(p2.begin(), p2.end());
+ std::vector<typename Kernel::FT> weights {100., 0.01};
+
+ Gudhi::alpha_complex::Alpha_complex<Kernel, true> 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::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
diff --git a/src/Alpha_complex/utilities/CMakeLists.txt b/src/Alpha_complex/utilities/CMakeLists.txt
index 2ffbdde0..303bd0a6 100644
--- a/src/Alpha_complex/utilities/CMakeLists.txt
+++ b/src/Alpha_complex/utilities/CMakeLists.txt
@@ -1,78 +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 (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0)
+ 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 $<TARGET_FILE:alpha_complex_persistence>
- "${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 $<TARGET_FILE:alpha_complex_persistence>
- "${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 $<TARGET_FILE:alpha_complex_persistence>
- "${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 $<TARGET_FILE:alpha_complex_persistence>
+ "${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 $<TARGET_FILE:alpha_complex_persistence>
+ "${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 $<TARGET_FILE:alpha_complex_persistence>
+ "${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")
- endif()
-
- install(TARGETS alpha_complex_persistence DESTINATION bin)
+ 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()
- 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)
+ install(TARGETS alpha_complex_persistence DESTINATION bin)
+ endif()
+endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 5.1.0)
- add_test(NAME Alpha_complex_utilities_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
- "-p" "2" "-m" "0.45" "-o" "safe_3d.pers")
+if (NOT CGAL_VERSION VERSION_LESS 4.11.0)
+ 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_exact_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
- "-p" "2" "-m" "0.45" "-o" "exact_3d.pers" "-e")
+ add_test(NAME Alpha_complex_utilities_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
+ "-p" "2" "-m" "0.45" "-o" "safe_3d.pers")
- add_test(NAME Alpha_complex_utilities_fast_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
- "-p" "2" "-m" "0.45" "-o" "fast_3d.pers" "-f")
+ add_test(NAME Alpha_complex_utilities_exact_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
+ "-p" "2" "-m" "0.45" "-o" "exact_3d.pers" "-e")
- 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 $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${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 $<TARGET_FILE:alpha_complex_3d_persistence>
- "${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 $<TARGET_FILE:alpha_complex_3d_persistence>
- "${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 $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${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 $<TARGET_FILE:alpha_complex_3d_persistence>
- "${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")
+ add_test(NAME Alpha_complex_utilities_weighted_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${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")
- install(TARGETS alpha_complex_3d_persistence DESTINATION bin)
-
-endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ add_test(NAME Alpha_complex_utilities_weighted_periodic_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ "${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/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 <gudhi/Persistent_cohomology.h>
// to construct a simplex_tree from alpha complex
#include <gudhi/Simplex_tree.h>
+#include <gudhi/Points_off_io.h>
#include <iostream>
#include <string>
#include <limits> // for numeric_limits
+#include <vector>
+#include <fstream>
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<class Point_d>
+std::vector<Point_d> read_off(const std::string &off_file_points) {
+ Gudhi::Points_off_reader<Point_d> 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<double> read_weight_file(const std::string &weight_file) {
+ std::vector<double> 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<class Kernel>
+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<typename Kernel::Point_d>(off_file_points);
+
+ if (weight_file != std::string()) {
+ std::vector<double> 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<Kernel, true> 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<Kernel> 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<CGAL::Dynamic_dimension_tag>;
-
- // Init of an alpha complex from an OFF file
- Gudhi::alpha_complex::Alpha_complex<Fast_kernel> 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<Fast_kernel>(off_file_points, weight_file, exact_version, alpha_square_max_value);
} else {
using Kernel = CGAL::Epeck_d<CGAL::Dynamic_dimension_tag>;
-
- // Init of an alpha complex from an OFF file
- Gudhi::alpha_complex::Alpha_complex<Kernel> 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<Kernel>(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<Simplex_tree, Gudhi::persistent_cohomology::Field_Zp> 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<std::string>(&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<std::string>(&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<Filtration_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 ##
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 $<TARGET_FILE:Random_bitmap_cubical_complex>
"2" "100" "100")
-
-install(TARGETS Random_bitmap_cubical_complex DESTINATION bin)
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..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 std::vector<std::size_t> get_boundary_of_a_cell(std::size_t cell) const;
+ virtual std::vector<std::size_t> 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 std::vector<std::size_t> get_coboundary_of_a_cell(std::size_t cell) const;
+ virtual std::vector<std::size_t> 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) {
+ 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<unsigned> coface_counter = this->compute_counter_for_given_cell(coface);
std::vector<unsigned> face_counter = this->compute_counter_for_given_cell(face);
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 $<TARGET_FILE:alpha_rips_persistence_bottleneck_distance>
- "${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 $<TARGET_FILE:alpha_rips_persistence_bottleneck_distance>
+ "${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/Bottleneck_distance/include/gudhi/Bottleneck.h b/src/Bottleneck_distance/include/gudhi/Bottleneck.h
index e466828a..c916898d 100644
--- a/src/Bottleneck_distance/include/gudhi/Bottleneck.h
+++ b/src/Bottleneck_distance/include/gudhi/Bottleneck.h
@@ -35,8 +35,12 @@ 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();
- const double alpha = std::pow(g.size(), 1. / 5.);
+ double b_upper_bound = g.max_dist_to_diagonal();
+ 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 e1e3522e..33f03b9c 100644
--- a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h
+++ b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h
@@ -45,14 +45,14 @@ 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;
/** \internal \brief Returns the O(n^2) sorted distances between the points. */
std::vector<double> 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
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<double, double> > empty;
+ std::vector< std::pair<double, double> > one = {{8, 10}};
+ BOOST_CHECK(bottleneck_distance(empty, empty) == 0);
+ BOOST_CHECK(bottleneck_distance(empty, one) == 1);
}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9e4d78ac..79ec42c1 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)
@@ -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}\"")
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 $<TARGET_FILE:Cech_complex_example_step_by_step>
+ "${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 $<TARGET_FILE:Cech_complex_example_step_by_step>
- "${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 $<TARGET_FILE:cech_persistence>
- "${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 $<TARGET_FILE:cech_persistence>
+ "${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/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 $<TARGET_FILE:Edge_collapse_example_basic>)
+ # 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 $<TARGET_FILE:Edge_collapse_example_basic>)
+
+ # 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 $<TARGET_FILE:Edge_collapse_conserve_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "0.2")
+
+ add_test(NAME Edge_collapse_conserve_persistence_2 COMMAND $<TARGET_FILE:Edge_collapse_conserve_persistence>
+ "${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 $<TARGET_FILE:Edge_collapse_conserve_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" "0.2")
-
-add_test(NAME Edge_collapse_conserve_persistence_2 COMMAND $<TARGET_FILE:Edge_collapse_conserve_persistence>
- "${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..713c6608 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 <boost/iterator/iterator_facade.hpp>
#include <Eigen/Sparse>
+#include <Eigen/src/Core/util/Macros.h> // for EIGEN_VERSION_AT_LEAST
#ifdef GUDHI_USE_TBB
#include <tbb/parallel_sort.h>
@@ -34,6 +35,11 @@
#include <iterator> // for std::inserter
#include <type_traits> // 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 Edge Collapse is only available for Eigen3 >= 3.1.0
+#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..bce99e90 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 (NOT EIGEN3_VERSION VERSION_LESS 3.1.0)
+ 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 $<TARGET_FILE:point_cloud_edge_collapse_rips_persistence>
+ "${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 $<TARGET_FILE:distance_matrix_edge_collapse_rips_persistence>
+ "${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()
-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 $<TARGET_FILE:point_cloud_edge_collapse_rips_persistence>
- "${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 $<TARGET_FILE:distance_matrix_edge_collapse_rips_persistence>
- "${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
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 $<TARGET_FILE:Persistence_representations_example_landscape_on_grid>)
-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 $<TARGET_FILE:Persistence_representations_example_landscape>)
-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 $<TARGET_FILE:Persistence_representations_example_intervals>
"${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 $<TARGET_FILE:Persistence_representations_example_vectors>)
-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 $<TARGET_FILE:Persistence_representations_example_heat_maps>)
-install(TARGETS Persistence_representations_example_heat_maps DESTINATION bin)
add_executable ( Sliced_Wasserstein sliced_wasserstein.cpp )
add_test(NAME Sliced_Wasserstein
COMMAND $<TARGET_FILE:Sliced_Wasserstein>)
-install(TARGETS Sliced_Wasserstein DESTINATION bin)
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..c68c6524 100644
--- a/src/Persistent_cohomology/example/CMakeLists.txt
+++ b/src/Persistent_cohomology/example/CMakeLists.txt
@@ -1,46 +1,53 @@
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 $<TARGET_FILE:plain_homology>)
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 $<TARGET_FILE:plain_homology>)
add_test(NAME Persistent_cohomology_example_from_simple_simplex_tree COMMAND $<TARGET_FILE:persistence_from_simple_simplex_tree>
"1" "0")
-add_test(NAME Persistent_cohomology_example_from_rips_step_by_step_on_tore_3D COMMAND $<TARGET_FILE:rips_persistence_step_by_step>
- "${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 $<TARGET_FILE:rips_persistence_via_boundary_matrix>
- "${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 $<TARGET_FILE:persistence_from_file>
- "${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 $<TARGET_FILE:persistence_from_file>
- "${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 $<TARGET_FILE:rips_persistence_step_by_step>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3")
+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 $<TARGET_FILE:rips_persistence_via_boundary_matrix>
+ "${CMAKE_SOURCE_DIR}/data/points/Kl.off" "-r" "0.16" "-d" "3" "-p" "3" "-m" "100")
+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 $<TARGET_FILE:persistence_from_file>
+ "${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 $<TARGET_FILE:persistence_from_file>
+ "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc" "-p" "3" "-m" "100")
+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})
@@ -49,20 +56,15 @@ if(GMP_FOUND)
endif(TBB_FOUND)
add_test(NAME Persistent_cohomology_example_multifield_2_71 COMMAND $<TARGET_FILE:rips_multifield_persistence>
"${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 $<TARGET_FILE:custom_persistence_sort>)
-
- 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/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<decltype(dist_fun)> kernel(dist_fun);
- subsampling::choose_n_farthest_points(kernel, boost::irange<Vertex_handle>(0, boost::size(points)), -1, -1,
+ subsampling::choose_n_farthest_points(dist_fun, boost::irange<Vertex_handle>(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 <class Distance>
- 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 <typename Distance>
void compute_sparse_graph(Distance& dist, double epsilon, Filtration_value mini, Filtration_value maxi) {
diff --git a/src/Rips_complex/utilities/CMakeLists.txt b/src/Rips_complex/utilities/CMakeLists.txt
index d2448d7b..d8c8e0b8 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 $<TARGET_FILE:rips_distance_matrix_persistence>
+ "${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 $<TARGET_FILE:rips_persistence>
+ "${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 $<TARGET_FILE:rips_distance_matrix_persistence>
- "${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 $<TARGET_FILE:rips_persistence>
- "${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 $<TARGET_FILE:rips_correlation_matrix_persistence>
- "${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 $<TARGET_FILE:sparse_rips_persistence>
- "${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::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 $<TARGET_FILE:rips_correlation_matrix_persistence>
+ "${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 $<TARGET_FILE:sparse_rips_persistence>
+ "${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 $<TARGET_FILE:Simplex_tree_example_cech_complex_cgal_mini_sphere_3d>
+ "${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 $<TARGET_FILE:Simplex_tree_example_cech_complex_cgal_mini_sphere_3d>
- "${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/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h
index 889dbd00..85d6c3b0 100644
--- a/src/Simplex_tree/include/gudhi/Simplex_tree.h
+++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h
@@ -1667,6 +1667,37 @@ class Simplex_tree {
return sh; // None of its faces has the same filtration.
}
+ public:
+ /** \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).
+ * @param[in] filt_value The new filtration value.
+ * @param[in] min_dim The minimal dimension. Default value is 0.
+ */
+ void reset_filtration(Filtration_value filt_value, int min_dim = 0) {
+ rec_reset_filtration(&root_, filt_value, min_dim);
+ clear_filtration(); // Drop the cache.
+ }
+
+ private:
+ /** \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_depth The minimal depth.
+ */
+ 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_depth <= 0) {
+ sh->second.assign_filtration(filt_value);
+ }
+ if (has_children(sh)) {
+ rec_reset_filtration(sh->second.children(), filt_value, min_depth - 1);
+ }
+ }
+ }
+
private:
Vertex_handle null_vertex_;
/** \brief Total number of simplices in the complex, without the empty simplex.*/
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..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,12 @@ 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) {
+ }
+
// any end() iterator
explicit Simplex_tree_boundary_simplex_iterator(SimplexTree * st)
: last_(st->null_vertex()),
diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp
index 9b5fa8fe..bdd41d34 100644
--- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp
+++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp
@@ -940,3 +940,54 @@ 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::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 = 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::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/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 $<TARGET_FILE:Skeleton_blocker_example_from_simplices>)
add_test(NAME Skeleton_blocker_example_iteration COMMAND $<TARGET_FILE:Skeleton_blocker_example_iteration>)
add_test(NAME Skeleton_blocker_example_link COMMAND $<TARGET_FILE:Skeleton_blocker_example_link>)
-
-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 $<TARGET_FILE:Spatial_searching_example_spatial_searching>)
- install(TARGETS Spatial_searching_example_spatial_searching DESTINATION bin)
endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
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 <gudhi/Debug_utils.h>
+
#include <CGAL/Orthogonal_k_neighbor_search.h>
#include <CGAL/Orthogonal_incremental_neighbor_search.h>
#include <CGAL/Search_traits.h>
#include <CGAL/Search_traits_adapter.h>
-#include <CGAL/Fuzzy_sphere.h>
#include <CGAL/property_map.h>
#include <CGAL/version.h> // 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<STraits> 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 <typename Coord_iterator>
+ 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<FT, D> 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<FT>(CGAL::max<FT>(*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<FT, D> 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<FT>(*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 <typename OutputIterator>
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 <typename OutputIterator>
+ 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/example/CMakeLists.txt b/src/Subsampling/example/CMakeLists.txt
index 28aab103..f4a23d22 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_kernel example_custom_kernel.cpp)
add_executable(Subsampling_example_sparsify_point_set example_sparsify_point_set.cpp)
target_link_libraries(Subsampling_example_sparsify_point_set ${CGAL_LIBRARY})
@@ -13,10 +12,6 @@ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
COMMAND $<TARGET_FILE:Subsampling_example_choose_n_farthest_points>)
add_test(NAME Subsampling_example_sparsify_point_set
COMMAND $<TARGET_FILE:Subsampling_example_sparsify_point_set>)
-
- 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)
+
+add_executable(Subsampling_example_custom_distance example_custom_distance.cpp)
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<Point_d> 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 <gudhi/choose_n_farthest_points.h>
+
+#include <iostream>
+#include <vector>
+#include <iterator>
+
+
+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<std::vector<double>> 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<Point> points = {0, 1, 2, 3};
+ std::vector<Point> 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 <gudhi/choose_n_farthest_points.h>
-
-#include <iostream>
-#include <vector>
-#include <iterator>
-
-
-/* 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<std::vector<FT>> matrix_;
-
- public:
- Squared_distance_d() {
- matrix_.push_back(std::vector<FT>({0, 1, 2, 4}));
- matrix_.push_back(std::vector<FT>({1, 0, 4, 2}));
- matrix_.push_back(std::vector<FT>({2, 4, 0, 1}));
- matrix_.push_back(std::vector<FT>({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<Point_d> points = {0, 1, 2, 3};
- std::vector<Point_d> 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 66421a69..e6347d96 100644
--- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h
+++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h
@@ -38,32 +38,35 @@ 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 <a target="_blank"
- * href="http://doc.cgal.org/latest/Kernel_d/classKernel__d_1_1Squared__distance__d.html">Kernel_d::Squared_distance_d</a> (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.
- * \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
+ * \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`.
- * @param[in] k A kernel object.
- * @param[in] input_pts Const reference to the input points.
+ * \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.
+ * @param[in] dist A distance function.
+ * @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.
* @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,
@@ -85,9 +88,9 @@ 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
+ static_assert(std::numeric_limits<double>::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<double>::infinity(); // infinity (see next entry)
std::vector< double > dist_to_L(nb_points, infty); // vector of current distances to L from input_pts
@@ -99,7 +102,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 = dist(p, input_pts[curr_max_w]);
if (curr_dist < dist_to_L[i])
dist_to_L[i] = curr_dist;
++i;
@@ -111,6 +114,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;
}
}
diff --git a/src/Subsampling/include/gudhi/pick_n_random_points.h b/src/Subsampling/include/gudhi/pick_n_random_points.h
index a67b2b84..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 <gudhi/Clock.h>
+#ifdef GUDHI_SUBSAMPLING_PROFILING
+# include <gudhi/Clock.h>
+#endif
#include <boost/range/size.hpp>
@@ -44,6 +46,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 +59,12 @@ void pick_n_random_points(Point_container const &points,
std::vector<int> 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..4571b8f3 100644
--- a/src/Subsampling/include/gudhi/sparsify_point_set.h
+++ b/src/Subsampling/include/gudhi/sparsify_point_set.h
@@ -11,6 +11,13 @@
#ifndef SPARSIFY_POINT_SET_H_
#define SPARSIFY_POINT_SET_H_
+#include <boost/version.hpp>
+#if BOOST_VERSION < 106600
+# include <boost/function_output_iterator.hpp>
+#else
+# include <boost/iterator/function_output_iterator.hpp>
+#endif
+
#include <gudhi/Kd_tree_search.h>
#ifdef GUDHI_SUBSAMPLING_PROFILING
#include <gudhi/Clock.h>
@@ -27,7 +34,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 <a target="_blank"
* href="http://doc.cgal.org/latest/Spatial_searching/classSearchTraits.html">SearchTraits</a>
@@ -63,29 +70,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_neighbors2(pt, min_squared_dist, min_squared_dist, boost::make_function_output_iterator(std::ref(drop)));
}
#ifdef GUDHI_SUBSAMPLING_PROFILING
diff --git a/src/Subsampling/test/test_choose_n_farthest_points.cpp b/src/Subsampling/test/test_choose_n_farthest_points.cpp
index 5c4bd4cb..94793295 100644
--- a/src/Subsampling/test/test_choose_n_farthest_points.cpp
+++ b/src/Subsampling/test/test_choose_n_farthest_points.cpp
@@ -39,12 +39,13 @@ 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<FT> point({i, j, k, l});
- points.push_back(Point_d(point.begin(), point.end()));
+ points.emplace_back(point.begin(), point.end());
}
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,40 +62,49 @@ 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<FT> 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));
+ 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<FT>::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<FT>::infinity());
landmarks.clear(); distances.clear();
std::vector<FT> 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
- Gudhi::subsampling::choose_n_farthest_points(k, points, -1, -1, std::back_inserter(landmarks), std::back_inserter(distances));
+ points.emplace_back(point2.begin(), point2.end());
+ // Choose all farthest points among 2 points
+ 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<FT>::infinity());
+ BOOST_CHECK(distances[1] == 1);
+ landmarks.clear(); distances.clear();
+
+ // Ignore duplicated points
+ points.emplace_back(point.begin(), point.end());
+ 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<FT>::infinity());
BOOST_CHECK(distances[1] == 1);
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 $<TARGET_FILE:Tangential_complex_example_with_perturb>)
- 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/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/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 $<TARGET_FILE:Witness_complex_example_nearest_landmark_table>)
-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 $<TARGET_FILE:Witness_complex_example_strong_off>
"${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)
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/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 $<TARGET_FILE:Witness_complex_strong_witness_persistence>
- "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-l" "20" "-a" "0.5")
- add_test(NAME Witness_complex_weak_test_torus_persistence
- COMMAND $<TARGET_FILE:Witness_complex_weak_witness_persistence>
- "${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 $<TARGET_FILE:Witness_complex_strong_witness_persistence>
+ "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-l" "20" "-a" "0.5")
+ add_test(NAME Witness_complex_weak_test_torus_persistence
+ COMMAND $<TARGET_FILE:Witness_complex_weak_witness_persistence>
+ "${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/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/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..e1566877 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 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)
@@ -137,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)
@@ -186,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/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 ce2c5448..c2e63a24 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 <a target="_blank" href="http://www.boost.org/">Boost</a> &ge; 1.56.0
- * and <a target="_blank" href="https://www.cmake.org/">CMake</a> &ge; 3.1.
+ * and <a target="_blank" href="https://www.cmake.org/">CMake</a> &ge; 3.5.
* It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015.
*
* \subsection utilities Utilities and examples
@@ -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
- * <a href="https://cmake.org/cmake/help/v3.0/manual/ccmake.1.html">ccmake</a> (on Linux and Mac OSX),
- * <a href="https://cmake.org/cmake/help/v3.0/manual/cmake-gui.1.html">cmake-gui</a> (on Windows) or by modifying the
+ * <a href="https://cmake.org/cmake/help/latest/manual/ccmake.1.html">ccmake</a> (on Linux and Mac OSX),
+ * <a href="https://cmake.org/cmake/help/latest/manual/cmake-gui.1.html">cmake-gui</a> (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 <a href="examples.html">here</a>.
*
@@ -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 <a href="https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html">CMAKE_INSTALL_PREFIX</a>.
+ * of <a href="https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html">CMAKE_INSTALL_PREFIX</a>.
*
* \subsection testsuites Test suites
* To test your build, run the following command in a terminal:
@@ -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 <CODE>cmake . && make</CODE> CGAL (or even
- * <CODE>cmake -DCGAL_HEADER_ONLY=ON .</CODE>), thereafter you will be able to compile
- * GUDHI by calling <CODE>cmake -DCGAL_DIR=/your/path/to/CGAL-X.Y .. && make</CODE>
+ * \note There is no need to install CGAL, you can just <CODE>cmake -DCMAKE_BUILD_TYPE=Release . && make</CODE> CGAL
+ * (or even <CODE>cmake -DCMAKE_BUILD_TYPE=Release -DCGAL_HEADER_ONLY=ON .</CODE>), thereafter you will be able to
+ * compile GUDHI by calling <CODE>cmake -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=/your/path/to/CGAL-X.Y .. && make</CODE>
*
* The procedure to install this library according to
* your operating system is detailed here http://doc.cgal.org/latest/Manual/installation.html
@@ -113,8 +113,6 @@ make doxygen
* Spatial_searching/example_spatial_searching.cpp</a>
* \li <a href="_subsampling_2example_choose_n_farthest_points_8cpp-example.html">
* Subsampling/example_choose_n_farthest_points.cpp</a>
- * \li <a href="_subsampling_2example_custom_kernel_8cpp-example.html">
- * Subsampling/example_custom_kernel.cpp</a>
* \li <a href="_subsampling_2example_pick_n_random_points_8cpp-example.html">
* Subsampling/example_pick_n_random_points.cpp</a>
* \li <a href="_subsampling_2example_sparsify_point_set_8cpp-example.html">
@@ -153,8 +151,6 @@ make doxygen
* Spatial_searching/example_spatial_searching.cpp</a>
* \li <a href="_subsampling_2example_choose_n_farthest_points_8cpp-example.html">
* Subsampling/example_choose_n_farthest_points.cpp</a>
- * \li <a href="_subsampling_2example_custom_kernel_8cpp-example.html">
- * Subsampling/example_custom_kernel.cpp</a>
* \li <a href="_subsampling_2example_pick_n_random_points_8cpp-example.html">
* Subsampling/example_pick_n_random_points.cpp</a>
* \li <a href="_subsampling_2example_sparsify_point_set_8cpp-example.html">
diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt
index 4f26481e..5c1402a6 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', ")
@@ -130,6 +133,10 @@ 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', ")
+ 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', ")
@@ -342,29 +349,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)
@@ -419,13 +424,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)
@@ -442,30 +445,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}
@@ -496,14 +495,20 @@ 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(TORCH_FOUND AND TENSORFLOW_FOUND AND EAGERPY_FOUND)
+ add_gudhi_py_test(test_wasserstein_with_tensors)
+ endif()
+ endif()
# Representations
- if(SKLEARN_FOUND AND MATPLOTLIB_FOUND)
+ 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()
diff --git a/src/python/doc/bottleneck_distance_user.rst b/src/python/doc/bottleneck_distance_user.rst
index 6c6e08d9..7baa76cc 100644
--- a/src/python/doc/bottleneck_distance_user.rst
+++ b/src/python/doc/bottleneck_distance_user.rst
@@ -47,7 +47,7 @@ The following example explains how the distance is computed:
: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)
+ specifically from the point (6.5, 6.5).
Basic example
@@ -72,6 +72,6 @@ The output is:
.. testoutput::
- Bottleneck distance approximation = 0.81
+ Bottleneck distance approximation = 0.72
Bottleneck distance value = 0.75
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
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 <https://github.com/GUDHI/TDA-tutorial/blob/master/Tuto-GUDHI-cubical-complexes.ipynb>`_
+explains how to represent sublevels sets of functions using cubical complexes. \ No newline at end of file
diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst
index 78e1af73..66efe45a 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 <https://www.boost.org/>`_ :math:`\geq` 1.56.0,
-`CMake <https://www.cmake.org/>`_ :math:`\geq` 3.1 to generate makefiles,
+`CMake <https://www.cmake.org/>`_ :math:`\geq` 3.5 to generate makefiles,
`NumPy <http://numpy.org>`_, `Cython <https://www.cython.org/>`_ and
`pybind11 <https://github.com/pybind/pybind11>`_ to compile
the GUDHI Python module.
@@ -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
@@ -394,6 +394,11 @@ mathematics, science, and engineering.
:class:`~gudhi.point_cloud.knn.KNearestNeighbors` can use the Python package
`SciPy <http://scipy.org>`_ as a backend if explicitly requested.
+TensorFlow
+----------
+
+`TensorFlow <https://www.tensorflow.org>`_ is currently only used in some automatic differentiation tests.
+
Bug reports and contributions
*****************************
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 <https://github.com/GUDHI/TDA-tutorial/blob/master/Tuto-GUDHI-representations.ipynb>`_ explains how to
+efficiently combine machine learning and topological data analysis with the
+:doc:`representations module<representations>`.
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]]
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` |
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 <https://github.com/GUDHI/TDA-tutorial/blob/master/Tuto-GUDHI-Barycenters-of-persistence-diagrams.ipynb>`_
+presents the concept of barycenter, or Fréchet mean, of a family of persistence diagrams. \ No newline at end of file
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/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/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:
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/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py
index 5ca127f6..cdcb1fde 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), 0, self.resolution).astype(int)
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)
diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd
index 75e94e0b..000323af 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<Gudhi::Simplex_tree_options_full_featured>::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<Gudhi::Simplex_tree_options_full_featured>":
Simplex_tree() nogil
@@ -57,7 +63,8 @@ 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
Simplex_tree_simplices_iterator get_simplices_iterator_begin() nogil
@@ -66,6 +73,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
+ 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<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>":
diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx
index dfb1d985..d7991417 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.
+ 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.
+ :returns: The (simplices of the) boundary of a simplex
+ :rtype: generator with tuples(simplex, filtration)
+ """
+ cdef pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] it = self.get_ptr().get_boundary_iterators(simplex)
+
+ 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
complex.
@@ -328,7 +344,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 +354,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,38 +374,54 @@ cdef class SimplexTree:
"""
return self.get_ptr().make_filtration_non_decreasing()
+ def reset_filtration(self, filtration, 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).
+
+ :param filtration: New threshold value.
+ :type filtration: float.
+ :param min_dim: The minimal dimension. Default value is 0.
+ :type min_dim: int.
+ """
+ self.get_ptr().reset_filtration(filtration, min_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
- 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 <https://github.com/GUDHI/TDA-tutorial/blob/master/Tuto-GUDHI-extended-persistence.ipynb>`_
+ 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 +432,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 <https://github.com/GUDHI/TDA-tutorial/blob/master/Tuto-GUDHI-extended-persistence.ipynb>`_
+ explains how to compute an extension of persistence called extended persistence.
"""
cdef vector[pair[int, pair[double, double]]] persistence_result
if self.pcohptr != NULL:
@@ -592,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 method requires `Eigen <installation.html#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/gudhi/subsampling.pyx b/src/python/gudhi/subsampling.pyx
index f77c6f75..46f32335 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]]
"""
@@ -104,10 +105,10 @@ 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]].
+ :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]]
"""
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<double> const& vec) {
class Abstract_alpha_complex {
public:
virtual std::vector<double> 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<CGAL::Dynamic_dimension_tag>;
using Point = typename Kernel::Point_d;
@@ -78,7 +81,7 @@ class Exact_Alphacomplex_dD : public Abstract_alpha_complex {
Alpha_complex<Kernel> 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<CGAL::Dynamic_dimension_tag>;
using Point = typename Kernel::Point_d;
@@ -104,7 +107,7 @@ class Inexact_Alphacomplex_dD : public Abstract_alpha_complex {
};
template <complexity Complexity>
-class Alphacomplex_3D : public Abstract_alpha_complex {
+class Alphacomplex_3D final : public Abstract_alpha_complex {
private:
using Point = typename Alpha_complex_3d<Complexity, false, false>::Bare_point_3;
diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h
index e288a8cf..629f6083 100644
--- a/src/python/include/Simplex_tree_interface.h
+++ b/src/python/include/Simplex_tree_interface.h
@@ -15,7 +15,9 @@
#include <gudhi/distance_functions.h>
#include <gudhi/Simplex_tree.h>
#include <gudhi/Points_off_io.h>
+#ifdef GUDHI_USE_EIGEN3
#include <gudhi/Flag_complex_edge_collapser.h>
+#endif
#include <iostream>
#include <vector>
@@ -39,6 +41,7 @@ class Simplex_tree_interface : public Simplex_tree<SimplexTreeOptions> {
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:
@@ -161,6 +164,7 @@ class Simplex_tree_interface : public Simplex_tree<SimplexTreeOptions> {
}
Simplex_tree_interface* collapse_edges(int nb_collapse_iteration) {
+#ifdef GUDHI_USE_EIGEN3
using Filtered_edge = std::tuple<Vertex_handle, Vertex_handle, Filtration_value>;
std::vector<Filtered_edge> edges;
for (Simplex_handle sh : Base::skeleton_simplex_range(1)) {
@@ -186,6 +190,9 @@ class Simplex_tree_interface : public Simplex_tree<SimplexTreeOptions> {
collapsed_stree_ptr->insert({std::get<0>(remaining_edge), std::get<1>(remaining_edge)}, std::get<2>(remaining_edge));
}
return collapsed_stree_ptr;
+#else
+ throw std::runtime_error("Unable to collapse edges as it requires Eigen3 >= 3.1.0.");
+#endif
}
// Iterator over the simplex tree
@@ -219,6 +226,15 @@ class Simplex_tree_interface : public Simplex_tree<SimplexTreeOptions> {
// 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();
}
+
+ std::pair<Boundary_simplex_iterator, Boundary_simplex_iterator> 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
+ auto boundary_srange = Base::boundary_simplex_range(bd_sh);
+ return std::make_pair(boundary_srange.begin(), boundary_srange.end());
+ }
};
} // namespace Gudhi
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 <gudhi/distance_functions.h>
#include <gudhi/choose_n_farthest_points.h>
#include <gudhi/pick_n_random_points.h>
#include <gudhi/sparsify_point_set.h>
@@ -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<std::vector<double>> subsampling_n_farthest_points(const std::vector<std::vector<double>>& points,
unsigned nb_points) {
std::vector<std::vector<double>> 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<std::vector<double>> subsampling_n_farthest_points(const std::vector
std::vector<std::vector<double>> subsampling_n_farthest_points(const std::vector<std::vector<double>>& points,
unsigned nb_points, unsigned starting_point) {
std::vector<std::vector<double>> 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;
}
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)
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
diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py
index 83be0602..a3eacaa9 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, __GUDHI_USE_EIGEN3
import pytest
__author__ = "Vincent Rouvreau"
@@ -353,8 +353,54 @@ def test_collapse_edges():
assert st.num_simplices() == 10
- 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 __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:
+ # If no Eigen3, collapse_edges throws an exception
+ with pytest.raises(RuntimeError):
+ st.collapse_edges()
+
+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
+
+ # Guaranteed by construction
+ for simplex in st.get_simplices():
+ 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(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]) >= 2.
+ else:
+ assert st.filtration(simplex[0]) == 0.
+
+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)]
+ 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
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 (
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
new file mode 100755
index 00000000..e3f1411a
--- /dev/null
+++ b/src/python/test/test_wasserstein_with_tensors.py
@@ -0,0 +1,47 @@
+""" 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
+import torch
+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))
+ 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