summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml3
-rw-r--r--.circleci/config.yml16
-rw-r--r--.github/CONTRIBUTING.md48
-rw-r--r--.github/build-requirements.txt5
-rw-r--r--.github/code_conventions.md (renamed from code_conventions.md)23
-rw-r--r--.github/copyright_template.h14
-rw-r--r--.github/copyright_template.py8
-rw-r--r--.github/for_maintainers/new_gudhi_version_creation.md94
-rw-r--r--.github/for_maintainers/next_release_template.md (renamed from next_release.md)8
-rw-r--r--.github/how_to_use_github_to_contribute_to_gudhi.md125
-rw-r--r--.github/next_release.md29
-rw-r--r--.github/test-requirements.txt8
-rw-r--r--.gitmodules3
-rw-r--r--.travis.yml78
-rw-r--r--CMakeGUDHIVersion.txt2
-rw-r--r--CMakeLists.txt2
-rw-r--r--Dockerfile_for_circleci_image24
-rw-r--r--Dockerfile_gudhi_installation13
-rw-r--r--README.md15
-rw-r--r--azure-pipelines.yml38
-rw-r--r--biblio/bibliography.bib12
m---------ext/hera0
-rw-r--r--src/Alpha_complex/example/CMakeLists.txt6
-rw-r--r--src/Alpha_complex/utilities/CMakeLists.txt16
-rw-r--r--src/Bottleneck_distance/example/CMakeLists.txt2
-rw-r--r--src/Bottleneck_distance/include/gudhi/Persistence_graph.h2
-rw-r--r--src/Cech_complex/benchmark/CMakeLists.txt2
-rw-r--r--src/Cech_complex/example/CMakeLists.txt2
-rw-r--r--src/Cech_complex/utilities/CMakeLists.txt2
-rw-r--r--src/Contraction/example/CMakeLists.txt1
-rw-r--r--src/Doxyfile.in1
-rw-r--r--src/Nerve_GIC/include/gudhi/GIC.h8
-rw-r--r--src/Persistence_representations/utilities/CMakeLists.txt10
-rw-r--r--src/Persistence_representations/utilities/persistence_heat_maps/CMakeLists.txt19
-rw-r--r--src/Persistence_representations/utilities/persistence_intervals/CMakeLists.txt7
-rw-r--r--src/Persistence_representations/utilities/persistence_landscapes/CMakeLists.txt8
-rw-r--r--src/Persistence_representations/utilities/persistence_landscapes_on_grid/CMakeLists.txt8
-rw-r--r--src/Persistence_representations/utilities/persistence_vectors/CMakeLists.txt8
-rw-r--r--src/Persistent_cohomology/benchmark/CMakeLists.txt2
-rw-r--r--src/Persistent_cohomology/example/CMakeLists.txt8
-rw-r--r--src/Rips_complex/example/CMakeLists.txt8
-rw-r--r--src/Rips_complex/utilities/CMakeLists.txt8
-rw-r--r--src/Simplex_tree/example/CMakeLists.txt5
-rw-r--r--src/Simplex_tree/include/gudhi/Simplex_tree.h6
-rw-r--r--src/Simplex_tree/test/CMakeLists.txt6
-rw-r--r--src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp148
-rw-r--r--src/Simplex_tree/test/simplex_tree_unit_test.cpp84
-rw-r--r--src/Tangential_complex/include/gudhi/Tangential_complex.h4
-rw-r--r--src/Witness_complex/example/CMakeLists.txt10
-rw-r--r--src/Witness_complex/utilities/CMakeLists.txt4
-rw-r--r--src/cmake/modules/GUDHI_boost_test.cmake7
-rw-r--r--src/cmake/modules/GUDHI_third_party_libraries.cmake39
-rw-r--r--src/cmake/modules/GUDHI_user_version_target.cmake5
-rw-r--r--src/common/doc/header.html2
-rw-r--r--src/common/example/CMakeLists.txt1
-rw-r--r--src/python/CMakeLists.txt62
-rw-r--r--src/python/doc/_templates/layout.html2
-rw-r--r--src/python/doc/alpha_complex_sum.inc15
-rw-r--r--src/python/doc/installation.rst5
-rw-r--r--src/python/doc/persistence_graphical_tools_sum.inc8
-rw-r--r--src/python/doc/persistence_graphical_tools_user.rst32
-rw-r--r--src/python/doc/wasserstein_distance_user.rst17
-rw-r--r--src/python/gudhi/hera.cc71
-rw-r--r--src/python/gudhi/nerve_gic.pyx4
-rw-r--r--src/python/gudhi/persistence_graphical_tools.py124
-rw-r--r--src/python/gudhi/wasserstein.py6
-rw-r--r--src/python/setup.py.in21
-rwxr-xr-xsrc/python/test/test_wasserstein_distance.py61
68 files changed, 1082 insertions, 363 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 4a76ea0a..34f42dea 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -39,6 +39,7 @@ init:
install:
+ - git submodule update --init
- vcpkg install tbb:x64-windows boost-disjoint-sets:x64-windows boost-serialization:x64-windows boost-date-time:x64-windows boost-system:x64-windows boost-filesystem:x64-windows boost-units:x64-windows boost-thread:x64-windows boost-program-options:x64-windows eigen3:x64-windows mpfr:x64-windows mpir:x64-windows cgal:x64-windows
- SET PATH=c:\Tools\vcpkg\installed\x64-windows\bin;%PATH%
- SET PATH=%PYTHON%;%PYTHON%\Scripts;%PYTHON%\Library\bin;%PATH%
@@ -48,7 +49,7 @@ install:
- pip --version
- python -m pip install --upgrade pip
- pip install -U setuptools numpy matplotlib scipy Cython pytest
- - pip install -U POT
+ - pip install -U POT pybind11
build_script:
- mkdir build
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 5e45bc14..4f86cb12 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -45,11 +45,14 @@ jobs:
python:
docker:
- image: gudhi/ci_for_gudhi:latest
+ parallelism: 4
steps:
- checkout
- run:
name: Build and test python module. Generates and tests the python documentation
command: |
+ git submodule init
+ git submodule update
mkdir build;
cd build;
cmake -DUSER_VERSION_DIR=version ..;
@@ -58,10 +61,13 @@ jobs:
mkdir build;
cd build;
cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 ..;
- make all;
- ctest --output-on-failure;
+ cd python;
+ python3 setup.py build_ext -j 4 --inplace;
make sphinx;
- cp -R python/sphinx /tmp/sphinx;
+ cp -R sphinx /tmp/sphinx;
+ python3 setup.py install;
+ python3 setup.py clean --all;
+ ctest -j 4 --output-on-failure;
- store_artifacts:
path: /tmp/sphinx
@@ -74,6 +80,8 @@ jobs:
- run:
name: Generates the C++ documentation with doxygen
command: |
+ git submodule init
+ git submodule update
mkdir build;
cd build;
cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF -DUSER_VERSION_DIR=version ..;
@@ -93,4 +101,4 @@ workflows:
- tests
- utils
- python
- - doxygen \ No newline at end of file
+ - doxygen
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 00000000..a18ff8bd
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1,48 @@
+# Contributing to GUDHI
+
+First of all, thank you for the time you may take to contribute to GUDHI !
+
+# In case you have a question
+
+Please, check our [contact web page](https://gudhi.inria.fr/contact/).
+
+# In case you found an issue
+
+Please, first check [opened issues on GUDHI](https://github.com/GUDHI/gudhi-devel/issues).
+
+If the problem you are facing is not referenced, do not hesitate to open a [new issue](https://github.com/GUDHI/gudhi-devel/issues/new).
+
+This place is also a good place if you have some enhancement you want to propose.
+There is a label **enhancement** in the [new issue](https://github.com/GUDHI/gudhi-devel/issues/new) page.
+
+# In case you want to contribute to GUDHI
+
+## You are not familiar with GitHub ?
+
+Please take some time to read our [how to use GitHub to contribute to GUDHI](how_to_use_github_to_contribute_to_gudhi.md).
+
+## Something you want to improve in the documentation
+
+For C++ documentation, you can find it in the directories:
+* *src/common/doc* for the main page and installation instructions
+* *src/NAME_OF_THE_MODULE/doc* for the main page of a module
+* *src/NAME_OF_THE_MODULE/include/gudhi* for the documentation generated from the code.
+We use Doxygen to generate the code and you will be able to verify the result in CircleCI Doxygen target in the artifacts.
+
+For Python documentation, you can find it in the directories:
+* *src/python/doc* for the main page, installation instructionsand for the main pages of the modules
+* *src/python/gudhi/NAME_OF_THE_MODULE.pyx* for the documentation generated from the code.
+We use Sphinx to generate the code and you will be able to verify the result in CircleCI Sphinx target in the artifacts.
+
+## Something you want to improve in the code
+
+We don't ask for any paperwork but we expect you don't submit anything you are not allowed to:
+* check that your work contract and your employer allow you to contribute to this open source project.
+* insure you do not violate someone's intellectual property.
+* ...
+
+Please, take some time to read our [code conventions](code_conventions.md)
+
+As a convention, we set a Pull Request as a **Draft Pull Request** when we work on something we want the other contributors to see.
+
+We click on **Ready for review** to ask for a peer review of the contribution.
diff --git a/.github/build-requirements.txt b/.github/build-requirements.txt
new file mode 100644
index 00000000..7de60d23
--- /dev/null
+++ b/.github/build-requirements.txt
@@ -0,0 +1,5 @@
+setuptools
+wheel
+numpy
+Cython
+pybind11 \ No newline at end of file
diff --git a/code_conventions.md b/.github/code_conventions.md
index 5882f78e..9724f722 100644
--- a/code_conventions.md
+++ b/.github/code_conventions.md
@@ -21,6 +21,27 @@
* The name of the "project" should be in this form: `Package_[tests|examples|…]`. E.g. `project(Simplex_tree_examples)`.
* The name if each "target" (first parameter of add_executable) should be in this form: `Package_{name of the cpp file without extension}`. E.g `add_executable(Subsampling_test_sparsify_point_set test_sparsify_point_set.cpp)`.
+### Code style
+We are using [google c++ style guide](https://google.github.io/styleguide/cppguide.html) recommendations with 120 characters per line of code.
+[clang-format](https://clang.llvm.org/docs/ClangFormat.html) can be used to format automatically your code:
+```bash
+cd src # there is a .clang-format file with these specifications
+clang-format -style=file -i Simplex_tree/include/gudhi/Simplex_tree.h # -i means in place, your file will be modified
+```
+
+### Template
+Please use the file [following template](copyright_template.h).
+
## Python
-In progress... \ No newline at end of file
+In progress...
+
+### Code style
+We are using [PEP8 Python style guide](https://www.python.org/dev/peps/pep-0008/) recommendations with 120 characters per line of code.
+[black](https://black.readthedocs.io/en/stable/) can be used to format automatically your code:
+```bash
+black -l 120 src/python/example/bottleneck_basic_example.py
+```
+
+### Template
+Please use the file [following template](copyright_template.py).
diff --git a/.github/copyright_template.h b/.github/copyright_template.h
new file mode 100644
index 00000000..30034f1b
--- /dev/null
+++ b/.github/copyright_template.h
@@ -0,0 +1,14 @@
+/* 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): [AUTHOR NAME]
+ *
+ * Copyright (C) [YEAR] [COPYRIGHT]
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef [FILE_NAME]_H_
+#define [FILE_NAME]_H_
+
+#endif // [FILE_NAME]_H_ \ No newline at end of file
diff --git a/.github/copyright_template.py b/.github/copyright_template.py
new file mode 100644
index 00000000..667f985d
--- /dev/null
+++ b/.github/copyright_template.py
@@ -0,0 +1,8 @@
+# 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): [AUTHOR NAME]
+#
+# Copyright (C) [YEAR] [COPYRIGHT]
+#
+# Modification(s):
+# - YYYY/MM Author: Description of the modification
diff --git a/.github/for_maintainers/new_gudhi_version_creation.md b/.github/for_maintainers/new_gudhi_version_creation.md
new file mode 100644
index 00000000..f176d392
--- /dev/null
+++ b/.github/for_maintainers/new_gudhi_version_creation.md
@@ -0,0 +1,94 @@
+# Create a new GUDHI version
+
+We will consider that all operations will be performed in a brand new clone of the main project:
+```bash
+git clone https://github.com/GUDHI/gudhi-devel.git
+cd gudhi-devel
+```
+
+## Version file modification
+
+**Edit the file CMakeGUDHIVersion.txt**, and increment major, minor, or patch version number, in function of the version new delivery.
+```bash
+# cf. .gitignore - ignore this if it is a fresh clone version
+rm -rf data/points/COIL_database/lucky_cat.off_dist data/points/COIL_database/lucky_cat.off_sc.dot data/points/KleinBottle5D.off_dist data/points/KleinBottle5D.off_sc.dot data/points/human.off_dist data/points/human.off_sc.off data/points/human.off_sc.txt
+```
+
+Checkin the modifications, build and test the version:
+```bash
+mkdir build
+cd build
+cmake -DCGAL_DIR=/your/path/to/CGAL -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_BENCHMARK=ON -DUSER_VERSION_DIR=gudhi.@GUDHI_VERSION@ -DPython_ADDITIONAL_VERSIONS=3 ..
+make user_version
+date +"%d-%m-%Y-%T" > gudhi.@GUDHI_VERSION@/timestamp.txt
+tar -czvf gudhi.@GUDHI_VERSION@.tar.gz gudhi.@GUDHI_VERSION@
+md5sum gudhi.@GUDHI_VERSION@.tar.gz > md5sum.txt
+sha256sum gudhi.@GUDHI_VERSION@.tar.gz > sha256sum.txt
+sha512sum gudhi.@GUDHI_VERSION@.tar.gz > sha512sum.txt
+
+make -j all test
+```
+
+***[Check there are no error]***
+
+## Create the documentation
+```bash
+mkdir gudhi.doc.@GUDHI_VERSION@
+make doxygen 2>&1 | tee dox.log && grep warning dox.log
+```
+
+***[Check there are no error and the warnings]***
+
+```bash
+cp -R gudhi.@GUDHI_VERSION@/doc/html gudhi.doc.@GUDHI_VERSION@/cpp
+cd gudhi.@GUDHI_VERSION@
+rm -rf build; mkdir build; cd build; cmake -DCGAL_DIR=/your/path/to/CGAL -DWITH_GUDHI_EXAMPLE=ON -DPython_ADDITIONAL_VERSIONS=3 ..
+export LC_ALL=en_US.UTF-8 # cf. bug
+make sphinx
+```
+
+***[Check there are no error]***
+
+```bash
+cp -R python/sphinx ../../gudhi.doc.@GUDHI_VERSION@/python
+cd ../..
+tar -czvf gudhi.doc.@GUDHI_VERSION@.tar.gz gudhi.doc.@GUDHI_VERSION@
+
+cd gudhi.@GUDHI_VERSION@/build
+make all test
+```
+
+***[Check there are no error]***
+
+## Upload the documentation
+
+Upload by ftp the content of the directory gudhi.doc.@GUDHI_VERSION@/cpp in a new directory on ForgeLogin@scm.gforge.inria.fr:/home/groups/gudhi/htdocs/doc/@GUDHI_VERSION@
+
+Upload by ftp the content of the directory gudhi.doc.@GUDHI_VERSION@/python in a new directory on ForgeLogin@scm.gforge.inria.fr:/home/groups/gudhi/htdocs/python/@GUDHI_VERSION@
+
+Through ssh, make the **latest** link to your new version of the documentation:
+```bash
+ssh ForgeLogin@scm.gforge.inria.fr
+cd /home/groups/gudhi/htdocs/doc
+rm latest
+ln -s @GUDHI_VERSION@ latest
+cd /home/groups/gudhi/htdocs/python
+rm latest
+ln -s @GUDHI_VERSION@ latest
+```
+
+## Put a version label on files
+
+* Go on page https://github.com/GUDHI/gudhi-devel/releases/new
+* Name the tag: tags/gudhi-release-@GUDHI_VERSION@
+* Name the release GUDHI @GUDHI_VERSION@
+* Write the release note
+* Drag'n drop *gudhi.@GUDHI_VERSION@.tar.gz*, *md5sum.txt*, *sha256sum.txt*, *sha512sum.txt* files
+* Tick the *This is a pre-release* check button if this is a release candidate (untick if this is an official version)
+* Click the *Publish the release* button
+
+## 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/next_release.md b/.github/for_maintainers/next_release_template.md
index 26d4fca5..a2805a55 100644
--- a/next_release.md
+++ b/.github/for_maintainers/next_release_template.md
@@ -4,7 +4,7 @@ As a major new feature, the GUDHI library now offers ...
We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.X.X.tar.gz).
-Below is a list of changes made since Gudhi 3.1.0:
+Below is a list of changes made since GUDHI 3.X-1.X-1:
- [Module](link)
- ...
@@ -13,8 +13,7 @@ Below is a list of changes made since Gudhi 3.1.0:
- ...
- Miscellaneous
- - See the list of [bug fixes](https://github.com/GUDHI/gudhi-devel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A3.X.X+).
-
+ - The [list of bugs that were solved since GUDHI-3.X-1.X-1](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.1.1+is%3Aclosed) is available on GitHub.
All modules are distributed under the terms of the MIT license.
However, there are still GPL dependencies for many modules. We invite you to check our [license dedicated web page](https://gudhi.inria.fr/licensing/) for further details.
@@ -25,4 +24,5 @@ We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) fo
Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks.
-For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.0.rc1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.0.rc1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/).
+For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/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/how_to_use_github_to_contribute_to_gudhi.md b/.github/how_to_use_github_to_contribute_to_gudhi.md
new file mode 100644
index 00000000..747ca39b
--- /dev/null
+++ b/.github/how_to_use_github_to_contribute_to_gudhi.md
@@ -0,0 +1,125 @@
+# How to use github to contribute to gudhi
+
+Similar information is available in many places:
+* https://jarv.is/notes/how-to-pull-request-fork-github/ (this one is using `upstream/master` when creating a new branch)
+* https://help.github.com/en/github/getting-started-with-github/fork-a-repo
+* https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/
+* https://gist.github.com/Chaser324/ce0505fbed06b947d962
+* etc
+
+## Get a github account
+I assume the account is called **LOGIN**, please replace as appropriate below. Log in to github.com using this account.
+
+## Fork GUDHI/gudhi-devel project
+Go to https://github.com/GUDHI/gudhi-devel and click on **fork** (top right).
+Feel free to also click on the star next to it to show you like the project!
+You can see your fork at https://github.com/LOGIN/gudhi-devel
+
+## Create a local clone on your computer
+```bash
+git clone https://github.com/LOGIN/gudhi-devel.git
+```
+
+This creates a directory gudhi-devel, which you are free to move around or rename. For the following, change to that directory:
+```bash
+cd gudhi-devel
+```
+
+When you clone the repository, you also need to download the *submodules*.
+
+## Submodules
+Hera, used for Wasserstein distance, is available on an external git repository. To download it:
+```bash
+git submodule update --init
+```
+
+## Configuring a remote for a fork
+```bash
+git remote add upstream https://github.com/GUDHI/gudhi-devel.git
+```
+
+because you want to see the real gudhi, not just your clone.
+(It is perfectly possible to do things in the reverse order, clone from GUDHI and add the one in LOGIN as extra remote, but the names of the remotes may not match the rest of this document. You can change the name of a remote with `git remote rename oldname newname`)
+
+## Optional remotes
+Optional, if you are interested in one of the old branches
+```bash
+git remote add oldies https://github.com/GUDHI/branches.git
+```
+
+Or if you want to spy on someone's work. I assume the someone's account is called **SOMEONE**
+```bash
+git remote add someone https://github.com/SOMEONE/gudhi-devel.git
+```
+
+## Stay up-to-date
+```bash
+git fetch -p --all
+```
+This is a command you can run quite regularly.
+It tells git to check all that happened on github.
+It is safe, it will not mess with your files.
+
+**Reminder:** If the version of a submodule has changed, or if a submodule was added, you may need to:
+```bash
+git submodule sync
+git submodule update --init
+```
+
+## Create a branch, based on the current master
+```bash
+git checkout -b some-fancy-name --no-track upstream/master
+```
+Your local branch `master` and the one on your github clone are useless and often outdated, but for technical reasons there has to exist at least one branch at all times, it might as well be that one. upstream/master is the real deal, that's what you want to base your new branch on.
+
+## The real coding is here!
+Edit files, test, etc.
+
+## Commit your changes (locally)
+The basic command is just `git commit`, but it will do nothing by default.
+You need `git add my_new_file` for every new file you want to commit.
+And usually you'll want to use `git commit -a` so that all files that git already knows about and that have been modified get committed.
+
+## Push your changes (remotely)
+```bash
+git push -u origin some-fancy-name
+```
+This puts a copy of your branch on your online clone of gudhi-devel.
+Because of `-u`, it will remember where you like to push this branch, and next time you can just use `git push`.
+
+## Play again!
+Possibly iterate a few times, add more commits and push them.
+
+## Your pull request is ready
+Do not forget to update `.github/next_release.md` to announce your development in the next release note.
+
+Get your web browser to https://github.com/LOGIN/gudhi-devel, click on the button that says **Branch: some-name** (below the number of commits, above the list of files) and select the branch you are so proud of.
+Click on **New pull request** next to it.
+
+## Follow the instructions ;-)
+Note that if your branch is not quite ready, you can make a **draft pull request** (see the arrow next to the confirmation button), and later you will have access to a button to say that the branch is ready for reviews now.
+Draft pull requests can be a way to advertise that you are working on something, and possibly ask others for comments or help.
+
+## Code review
+Make sure you follow the discussion on your pull request, answer questions, take comments into account.
+You can keep pushing new commits on your branch to your fork of gudhi-devel, the pull request will automatically notice the new commits there.
+There is no need to create a new pull request.
+Once the branch is under review, fixing issues is good, but please refrain from adding extra features, that just makes the reviewers' job harder and thus slower.
+You may want to look at https://github.com/settings/notifications (and other settings nearby) if you don't receive emails when people comment on your pull request.
+Some bold reviewer might make changes to your branch. You will then need `git pull` for your local branch to reflect those.
+
+## Your work is merged!
+Once your pull request has been closed (your branch merged), you can remove your branch, both locally and also the branch on your github fork:
+```bash
+git checkout master # or any other branch, but you cannot remove the branch you are currently in
+git branch -d some-fancy-name # local branch delete
+git push origin --delete some-fancy-name # remote branch delete
+```
+If you add @VincentRouvreau or @mglisse as collaborator (https://github.com/LOGIN/gudhi-devel/settings/collaboration), they may remove the branch on your clone at the same time as they merge the branch, so you only have the local one to remove (or keep if you are nostalgic).
+
+## Keep in touch
+Create a new branch and keep contributing!
+
+Do not try to reuse an old branch that has already been merged.
+Make sure you run the fetch command just before creating any new branch, so you don't base it on some outdated version of master.
+You can also work on several branches at the same time, using `git checkout some-fancy-name` and `git checkout name-of-other-branch` to switch between them (commit before switching or things may get complicated).
diff --git a/.github/next_release.md b/.github/next_release.md
new file mode 100644
index 00000000..3166b0a8
--- /dev/null
+++ b/.github/next_release.md
@@ -0,0 +1,29 @@
+We are pleased to announce the release 3.X.X of the GUDHI library.
+
+As a major new feature, the GUDHI library now offers a Python interface to [Hera](https://bitbucket.org/grey_narn/hera/src/master/) to compute the Wasserstein distance.
+[PyBind11](https://github.com/pybind/pybind11) is now required to build the Python module.
+
+We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.X.X.tar.gz).
+
+Below is a list of changes made since GUDHI 3.1.1:
+
+- [Wassertein distance](https://gudhi.inria.fr/python/latest/wasserstein_distance_user.html)
+ - An another implementation comes from Hera (BSD-3-Clause) which is based on [Geometry Helps to Compare Persistence Diagrams](http://doi.acm.org/10.1145/3064175) by Michael Kerber, Dmitriy Morozov, and Arnur Nigmetov.
+
+- [Module](link)
+ - ...
+
+- Miscellaneous
+ - The [list of bugs that were solved since GUDHI-3.1.1](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.2.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.
+
+We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages.
+
+We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library.
+
+Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks.
+
+For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/latest/installation.html) or [Python](https://gudhi.inria.fr/python/latest/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/).
+
diff --git a/.github/test-requirements.txt b/.github/test-requirements.txt
new file mode 100644
index 00000000..bd03f98e
--- /dev/null
+++ b/.github/test-requirements.txt
@@ -0,0 +1,8 @@
+pytest
+sphinx
+sphinxcontrib-bibtex
+sphinx-paramlinks
+matplotlib
+scipy
+scikit-learn
+POT \ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..f70c570d
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "ext/hera"]
+ path = ext/hera
+ url = https://github.com/grey-narn/hera.git
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 60d32ef8..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-language: cpp
-
-sudo: required
-
-git:
- depth: 3
-
-os: osx
-osx_image: xcode10.2
-compiler: clang
-
-matrix:
- include:
- - env:
- # 1. Only examples and associated tests
- - CMAKE_EXAMPLE='ON' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='all' CTEST_COMMAND='ctest --output-on-failure'
- - env:
- # 2. Only unitary tests
- - CMAKE_EXAMPLE='OFF' CMAKE_TEST='ON' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='all' CTEST_COMMAND='ctest --output-on-failure'
- - env:
- # 3. Only utilities and associated tests
- - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='ON' CMAKE_PYTHON='OFF' MAKE_TARGET='all' CTEST_COMMAND='ctest --output-on-failure'
- - env:
- # 4. Only doxygen documentation
- - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='OFF' MAKE_TARGET='doxygen' CTEST_COMMAND='echo No tests for doxygen target'
- - env:
- # 5. Only Python, associated tests and sphinx documentation
- # $ which python3 => /usr/local/bin/python3
- # cmake => -- Found PythonInterp: /usr/local/bin/python3 (found version "3.7.5")
- # In python3-sphinx-build.py, print(sys.executable) => /usr/local/opt/python/bin/python3.7 ???
- # should be : MAKE_TARGET='all sphinx' CTEST_COMMAND='ctest --output-on-failure'
- - CMAKE_EXAMPLE='OFF' CMAKE_TEST='OFF' CMAKE_UTILITIES='OFF' CMAKE_PYTHON='ON' MAKE_TARGET='all' CTEST_COMMAND='ctest --output-on-failure -E sphinx'
-
-cache:
- directories:
- - $HOME/.cache/pip
- - $HOME/Library/Caches/Homebrew
-
-before_install:
- - brew update && brew unlink python@2 && brew upgrade python
-
-addons:
- homebrew:
- packages:
- - python3
- - cmake
- - graphviz
- - doxygen
- - boost
- - eigen
- - gmp
- - mpfr
- - tbb
- - cgal
-
-before_cache:
- - rm -f $HOME/.cache/pip/log/debug.log
- - brew cleanup
-
-# When installing through libcgal-dev apt, CMake Error at CGAL Exports.cmake The imported target "CGAL::CGAL Qt5" references the file
-install:
- - python3 -m pip install --upgrade pip setuptools wheel
- - python3 -m pip install --user pytest Cython sphinx sphinxcontrib-bibtex sphinx-paramlinks matplotlib numpy scipy scikit-learn
- - python3 -m pip install --user POT
-
-script:
- - rm -rf build
- - mkdir -p build
- - cd build
- - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=${CMAKE_EXAMPLE} -DWITH_GUDHI_TEST=${CMAKE_TEST} -DWITH_GUDHI_UTILITIES=${CMAKE_UTILITIES} -DWITH_GUDHI_PYTHON=${CMAKE_PYTHON} -DUSER_VERSION_DIR=version -DPython_ADDITIONAL_VERSIONS=3 ..
- - make ${MAKE_TARGET}
- - ${CTEST_COMMAND}
- - cd ..
-
-notifications:
- email:
- on_success: change # default: always
- on_failure: always # default: always
diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt
index ed19ecfb..0f827b9e 100644
--- a/CMakeGUDHIVersion.txt
+++ b/CMakeGUDHIVersion.txt
@@ -1,6 +1,6 @@
set (GUDHI_MAJOR_VERSION 3)
set (GUDHI_MINOR_VERSION 1)
-set (GUDHI_PATCH_VERSION 0)
+set (GUDHI_PATCH_VERSION 1)
set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION})
message(STATUS "GUDHI version : ${GUDHI_VERSION}")
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5dcc6803..0b5f5144 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,5 +65,7 @@ include(GUDHI_user_version_target)
# For "make doxygen" - Requires GUDHI_USER_VERSION_DIR to be set - Done in GUDHI_user_version_target for dev version
include(GUDHI_doxygen_target)
+configure_file(${CMAKE_SOURCE_DIR}/.github/for_maintainers/new_gudhi_version_creation.md "${CMAKE_CURRENT_BINARY_DIR}/" @ONLY)
+
message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"")
message("++ GUDHI_MISSING_MODULES list is:\"${GUDHI_MISSING_MODULES}\"")
diff --git a/Dockerfile_for_circleci_image b/Dockerfile_for_circleci_image
index ff4e6018..1eededb5 100644
--- a/Dockerfile_for_circleci_image
+++ b/Dockerfile_for_circleci_image
@@ -30,7 +30,7 @@ RUN apt-get install -y make \
cmake \
graphviz \
perl \
- texlive-bibtex-extra \
+ texlive-full \
biber \
doxygen \
libboost-all-dev \
@@ -42,22 +42,16 @@ RUN apt-get install -y make \
locales \
python3 \
python3-pip \
- python3-pytest \
python3-tk \
- python3-pybind11 \
libfreetype6-dev \
- pkg-config
-
-RUN pip3 install \
- numpy \
- matplotlib \
- scipy \
- Cython \
- POT \
- scikit-learn \
- sphinx \
- sphinx-paramlinks \
- sphinxcontrib-bibtex
+ pkg-config \
+ curl
+
+ADD .github/build-requirements.txt /
+ADD .github/test-requirements.txt /
+
+RUN pip3 install -r build-requirements.txt
+RUN pip3 install -r test-requirements.txt
# apt clean up
RUN apt autoremove && rm -rf /var/lib/apt/lists/*
diff --git a/Dockerfile_gudhi_installation b/Dockerfile_gudhi_installation
index 9fe20730..f9e8813b 100644
--- a/Dockerfile_gudhi_installation
+++ b/Dockerfile_gudhi_installation
@@ -42,6 +42,7 @@ RUN apt-get install -y make \
python3-pip \
python3-pytest \
python3-tk \
+ python3-pybind11 \
libfreetype6-dev \
pkg-config \
curl
@@ -50,16 +51,18 @@ RUN pip3 install \
numpy \
matplotlib \
scipy \
- Cython
+ Cython \
+ POT \
+ scikit-learn
# apt clean up
RUN apt autoremove && rm -rf /var/lib/apt/lists/*
-RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudhi-release-3.0.0/gudhi.3.0.0.tar.gz" \
-&& tar xf gudhi.3.0.0.tar.gz \
-&& cd gudhi.3.0.0 \
+RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudhi-release-3.1.1/gudhi.3.1.1.tar.gz" \
+&& tar xf gudhi.3.1.1.tar.gz \
+&& cd gudhi.3.1.1 \
&& mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_PYTHON=OFF -DPython_ADDITIONAL_VERSIONS=3 .. \
&& make all test install \
&& cmake -DWITH_GUDHI_PYTHON=ON . \
&& cd python \
-&& python3 setup.py install \ No newline at end of file
+&& python3 setup.py install
diff --git a/README.md b/README.md
index 167a38b3..279953e1 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-[![Build Status](https://travis-ci.org/GUDHI/gudhi-devel.svg?branch=master)](https://travis-ci.org/GUDHI/gudhi-devel)
-[![CircleCI](https://circleci.com/gh/GUDHI/gudhi-devel/tree/master.svg?style=svg)](https://circleci.com/gh/GUDHI/gudhi-devel/tree/master)
-[![Build status](https://ci.appveyor.com/api/projects/status/976j2uut8xgalvx2/branch/master?svg=true)](https://ci.appveyor.com/project/GUDHI/gudhi-devel/branch/master)
+[![OSx on Azure](https://dev.azure.com/GUDHI/gudhi-devel/_apis/build/status/GUDHI.gudhi-devel?branchName=master)](https://dev.azure.com/GUDHI/gudhi-devel/_build/latest?definitionId=1&branchName=master)
+[![Linux on CircleCI](https://circleci.com/gh/GUDHI/gudhi-devel/tree/master.svg?style=svg)](https://circleci.com/gh/GUDHI/gudhi-devel/tree/master)
+[![Win on Appveyor](https://ci.appveyor.com/api/projects/status/976j2uut8xgalvx2/branch/master?svg=true)](https://ci.appveyor.com/project/GUDHI/gudhi-devel/branch/master)
[![Anaconda Cloud](https://anaconda.org/conda-forge/gudhi/badges/version.svg)](https://anaconda.org/conda-forge/gudhi)
[![Anaconda downloads](https://anaconda.org/conda-forge/gudhi/badges/downloads.svg)](https://anaconda.org/conda-forge/gudhi)
@@ -10,6 +10,15 @@
The GUDHI library is a generic open source C++ library, with a Python interface, for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding. The library offers state-of-the-art data structures and algorithms to construct simplicial complexes and compute persistent homology.
+# Source code
+
+We recommend that users get official releases from [the GUDHI website](https://gudhi.inria.fr/).
+
+For potential contributors, to fully checkout GUDHI, after cloning the git repository, you may also need to checkout its submodules using
+```sh
+git submodule update --init
+```
+
# Compilation and installation
To install GUDHI, you can follow the [C++ compilation procedure](https://gudhi.inria.fr/doc/latest/installation.html), the [Python compilation procedure](https://gudhi.inria.fr/python/latest/installation.html), use our [conda-forge package](https://gudhi.inria.fr/conda/), or [go with Docker](https://gudhi.inria.fr/dockerfile/).
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
new file mode 100644
index 00000000..95b15db2
--- /dev/null
+++ b/azure-pipelines.yml
@@ -0,0 +1,38 @@
+jobs:
+
+ - job: 'Test'
+ displayName: "Build and test"
+ timeoutInMinutes: 0
+ cancelTimeoutInMinutes: 60
+
+ strategy:
+ matrix:
+ macOSrelease:
+ imageName: 'macos-10.14'
+ CMakeBuildType: Release
+ customInstallation: 'brew update && brew install graphviz doxygen boost eigen gmp mpfr tbb cgal'
+
+ pool:
+ vmImage: $(imageName)
+
+ steps:
+ - task: UsePythonVersion@0
+ inputs:
+ versionSpec: '3.7'
+ architecture: 'x64'
+
+ - script: |
+ $(customInstallation)
+ git submodule update --init
+ python -m pip install --upgrade pip
+ python -m pip install --user -r .github/build-requirements.txt
+ python -m pip install --user -r .github/test-requirements.txt
+ displayName: 'Install build dependencies'
+ - script: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_BUILD_TYPE:STRING=$(CMakeBuildType) -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 ..
+ make
+ make doxygen
+ ctest -j 8 --output-on-failure -E sphinx # remove sphinx build as it fails
+ displayName: 'Build, test and documentation generation'
diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib
index a1b951e0..3bbe7960 100644
--- a/biblio/bibliography.bib
+++ b/biblio/bibliography.bib
@@ -1180,3 +1180,15 @@ language={English}
booktitle = {In Neural Information Processing Systems},
year = {2007}
}
+@inproceedings{10.5555/3327546.3327645,
+author = {Lacombe, Th\'{e}o and Cuturi, Marco and Oudot, Steve},
+title = {Large Scale Computation of Means and Clusters for Persistence Diagrams Using Optimal Transport},
+year = {2018},
+publisher = {Curran Associates Inc.},
+address = {Red Hook, NY, USA},
+booktitle = {Proceedings of the 32nd International Conference on Neural Information Processing Systems},
+pages = {9792–9802},
+numpages = {11},
+location = {Montr\'{e}al, Canada},
+series = {NIPS’18}
+}
diff --git a/ext/hera b/ext/hera
new file mode 160000
+Subproject 0019cae9dc1e9d11aa03bc59681435ba7f21eea
diff --git a/src/Alpha_complex/example/CMakeLists.txt b/src/Alpha_complex/example/CMakeLists.txt
index b0337934..2eecd50c 100644
--- a/src/Alpha_complex/example/CMakeLists.txt
+++ b/src/Alpha_complex/example/CMakeLists.txt
@@ -32,14 +32,18 @@ if (DIFF_PATH)
add_test(Alpha_complex_example_from_off_60_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_60.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_60.txt)
+ set_tests_properties(Alpha_complex_example_from_off_60_diff_files PROPERTIES DEPENDS Alpha_complex_example_from_off_60)
add_test(Alpha_complex_example_from_off_32_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_result_32.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_32.txt)
+ set_tests_properties(Alpha_complex_example_from_off_32_diff_files PROPERTIES DEPENDS Alpha_complex_example_from_off_32)
add_test(Alpha_complex_example_fast_from_off_60_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/fastalphaoffreader_result_60.txt ${CMAKE_CURRENT_BINARY_DIR}/alphaoffreader_for_doc_60.txt)
+ set_tests_properties(Alpha_complex_example_fast_from_off_60_diff_files PROPERTIES DEPENDS Alpha_complex_example_fast_from_off_60)
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)
- endif()
+ set_tests_properties(Alpha_complex_example_fast_from_off_32_diff_files PROPERTIES DEPENDS Alpha_complex_example_fast_from_off_32)
+endif()
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})
diff --git a/src/Alpha_complex/utilities/CMakeLists.txt b/src/Alpha_complex/utilities/CMakeLists.txt
index 57b92942..2ffbdde0 100644
--- a/src/Alpha_complex/utilities/CMakeLists.txt
+++ b/src/Alpha_complex/utilities/CMakeLists.txt
@@ -2,7 +2,7 @@ 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_LIBRARY})
+ target_link_libraries(alpha_complex_persistence ${CGAL_LIBRARY} Boost::program_options)
if (TBB_FOUND)
target_link_libraries(alpha_complex_persistence ${TBB_LIBRARIES})
@@ -16,14 +16,20 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
if (DIFF_PATH)
add_test(Alpha_complex_utilities_diff_exact_alpha_complex ${DIFF_PATH}
"exact.pers" "safe.pers")
+ set_tests_properties(Alpha_complex_utilities_diff_exact_alpha_complex PROPERTIES DEPENDS
+ "Alpha_complex_utilities_exact_alpha_complex_persistence;Alpha_complex_utilities_safe_alpha_complex_persistence")
+
add_test(Alpha_complex_utilities_diff_fast_alpha_complex ${DIFF_PATH}
"fast.pers" "safe.pers")
+ set_tests_properties(Alpha_complex_utilities_diff_fast_alpha_complex PROPERTIES DEPENDS
+ "Alpha_complex_utilities_fast_alpha_complex_persistence;Alpha_complex_utilities_safe_alpha_complex_persistence")
+
endif()
install(TARGETS alpha_complex_persistence DESTINATION bin)
add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp)
- target_link_libraries(alpha_complex_3d_persistence ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+ 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)
@@ -36,15 +42,19 @@ if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
"${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off"
"-p" "2" "-m" "0.45" "-o" "exact_3d.pers" "-e")
- add_test(NAME Alpha_complex_utilities_safe_alpha_complex_3d COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
+ 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")
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_periodic_alpha_complex_3d_persistence COMMAND $<TARGET_FILE:alpha_complex_3d_persistence>
diff --git a/src/Bottleneck_distance/example/CMakeLists.txt b/src/Bottleneck_distance/example/CMakeLists.txt
index 3d65963a..9839c59d 100644
--- a/src/Bottleneck_distance/example/CMakeLists.txt
+++ b/src/Bottleneck_distance/example/CMakeLists.txt
@@ -13,7 +13,7 @@ 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_LIBRARY})
+ target_link_libraries(alpha_rips_persistence_bottleneck_distance Boost::program_options)
if (TBB_FOUND)
target_link_libraries(alpha_rips_persistence_bottleneck_distance ${TBB_LIBRARIES})
diff --git a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h
index f791e37c..e1e3522e 100644
--- a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h
+++ b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h
@@ -25,7 +25,7 @@ namespace Gudhi {
namespace persistence_diagram {
-/** \internal \brief Structure representing an euclidean bipartite graph containing
+/** \internal \brief Structure representing a Euclidean bipartite graph containing
* the points from the two persistence diagrams (including the projections).
*
* \ingroup bottleneck_distance
diff --git a/src/Cech_complex/benchmark/CMakeLists.txt b/src/Cech_complex/benchmark/CMakeLists.txt
index b7697764..c04bca53 100644
--- a/src/Cech_complex/benchmark/CMakeLists.txt
+++ b/src/Cech_complex/benchmark/CMakeLists.txt
@@ -5,7 +5,7 @@ project(Cech_complex_benchmark)
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_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY})
+target_link_libraries(cech_complex_benchmark Boost::filesystem)
if (TBB_FOUND)
target_link_libraries(cech_complex_benchmark ${TBB_LIBRARIES})
diff --git a/src/Cech_complex/example/CMakeLists.txt b/src/Cech_complex/example/CMakeLists.txt
index ab391215..98757988 100644
--- a/src/Cech_complex/example/CMakeLists.txt
+++ b/src/Cech_complex/example/CMakeLists.txt
@@ -2,7 +2,7 @@ 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_LIBRARY})
+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()
diff --git a/src/Cech_complex/utilities/CMakeLists.txt b/src/Cech_complex/utilities/CMakeLists.txt
index 30b99729..253d7304 100644
--- a/src/Cech_complex/utilities/CMakeLists.txt
+++ b/src/Cech_complex/utilities/CMakeLists.txt
@@ -2,7 +2,7 @@ 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_LIBRARY})
+target_link_libraries(cech_persistence Boost::program_options)
if (TBB_FOUND)
target_link_libraries(cech_persistence ${TBB_LIBRARIES})
diff --git a/src/Contraction/example/CMakeLists.txt b/src/Contraction/example/CMakeLists.txt
index f0dc885d..c5d31aca 100644
--- a/src/Contraction/example/CMakeLists.txt
+++ b/src/Contraction/example/CMakeLists.txt
@@ -4,7 +4,6 @@ if (NOT CGAL_VERSION VERSION_LESS 4.11.0)
add_executable(RipsContraction Rips_contraction.cpp)
add_executable(GarlandHeckbert Garland_heckbert.cpp)
- target_link_libraries(GarlandHeckbert ${Boost_TIMER_LIBRARY})
add_test(NAME Contraction_example_tore3D_0.2 COMMAND $<TARGET_FILE:RipsContraction>
"${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "0.2")
diff --git a/src/Doxyfile.in b/src/Doxyfile.in
index ec551882..49e781bd 100644
--- a/src/Doxyfile.in
+++ b/src/Doxyfile.in
@@ -785,6 +785,7 @@ EXCLUDE = data/ \
GudhUI/ \
cmake/ \
python/ \
+ ext/ \
README.md
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
diff --git a/src/Nerve_GIC/include/gudhi/GIC.h b/src/Nerve_GIC/include/gudhi/GIC.h
index a47d6889..2a6d4788 100644
--- a/src/Nerve_GIC/include/gudhi/GIC.h
+++ b/src/Nerve_GIC/include/gudhi/GIC.h
@@ -14,7 +14,7 @@
#ifdef GUDHI_USE_TBB
#include <tbb/parallel_for.h>
-#include <tbb/mutex.h>
+#include <mutex>
#endif
#include <gudhi/Debug_utils.h>
@@ -459,7 +459,7 @@ class Cover_complex {
// This cannot be parallelized if thread_local is not defined
// thread_local is not defined for XCode < v.8
#if defined(GUDHI_USE_TBB) && defined(GUDHI_CAN_USE_CXX11_THREAD_LOCAL)
- tbb::mutex deltamutex;
+ std::mutex deltamutex;
tbb::parallel_for(0, N, [&](int i){
std::vector<int> samples(m);
SampleWithoutReplacement(n, m, samples);
@@ -765,7 +765,7 @@ class Cover_complex {
#ifdef GUDHI_USE_TBB
if (verbose) std::cout << "Computing connected components (parallelized)..." << std::endl;
- tbb::mutex covermutex, idmutex;
+ std::mutex covermutex, idmutex;
tbb::parallel_for(0, res, [&](int i){
// Compute connected components
Graph G = one_skeleton.create_subgraph();
@@ -895,7 +895,7 @@ class Cover_complex {
// Compute the geodesic distances to subsamples with Dijkstra
#ifdef GUDHI_USE_TBB
if (verbose) std::cout << "Computing geodesic distances (parallelized)..." << std::endl;
- tbb::mutex coverMutex; tbb::mutex mindistMutex;
+ std::mutex coverMutex; std::mutex mindistMutex;
tbb::parallel_for(0, m, [&](int i){
int seed = voronoi_subsamples[i];
std::vector<double> dmap(n);
diff --git a/src/Persistence_representations/utilities/CMakeLists.txt b/src/Persistence_representations/utilities/CMakeLists.txt
index fc51b1d6..85633b7b 100644
--- a/src/Persistence_representations/utilities/CMakeLists.txt
+++ b/src/Persistence_representations/utilities/CMakeLists.txt
@@ -14,7 +14,7 @@ function(add_persistence_representation_creation_utility creation_utility)
install(TARGETS ${creation_utility} DESTINATION bin)
endfunction(add_persistence_representation_creation_utility)
-function(add_persistence_representation_plot_utility plot_utility tool_extension)
+function(add_persistence_representation_plot_utility creation_utility plot_utility tool_extension)
add_executable ( ${plot_utility} ${plot_utility}.cpp )
# as the function is called in a subdirectory level, need to '../' to find persistence heat maps files
@@ -22,17 +22,21 @@ function(add_persistence_representation_plot_utility plot_utility tool_extension
"${CMAKE_CURRENT_BINARY_DIR}/../first.pers${tool_extension}")
#add_test(NAME Persistence_representation_utilities_${plot_utility}_second COMMAND $<TARGET_FILE:${plot_utility}>
# "${CMAKE_CURRENT_BINARY_DIR}/../second.pers${tool_extension}")
+ set_tests_properties(Persistence_representation_utilities_${plot_utility}_first PROPERTIES DEPENDS
+ Persistence_representation_utilities_${creation_utility})
if(GNUPLOT_PATH)
add_test(NAME Persistence_representation_utilities_${plot_utility}_first_gnuplot COMMAND ${GNUPLOT_PATH}
"-e" "load '${CMAKE_CURRENT_BINARY_DIR}/../first.pers${tool_extension}_GnuplotScript'")
#add_test(NAME Persistence_representation_utilities_${plot_utility}_second_gnuplot COMMAND ${GNUPLOT_PATH}
# "-e" "load '${CMAKE_CURRENT_BINARY_DIR}/../second.pers${tool_extension}_GnuplotScript'")
+ set_tests_properties(Persistence_representation_utilities_${plot_utility}_first_gnuplot PROPERTIES DEPENDS
+ Persistence_representation_utilities_${plot_utility}_first)
endif()
install(TARGETS ${plot_utility} DESTINATION bin)
endfunction(add_persistence_representation_plot_utility)
-function(add_persistence_representation_function_utility function_utility tool_extension)
+function(add_persistence_representation_function_utility creation_utility function_utility tool_extension)
add_executable ( ${function_utility} ${function_utility}.cpp )
# ARGV2 is an optional argument
@@ -48,6 +52,8 @@ function(add_persistence_representation_function_utility function_utility tool_e
"${CMAKE_CURRENT_BINARY_DIR}/../first.pers${tool_extension}"
"${CMAKE_CURRENT_BINARY_DIR}/../second.pers${tool_extension}")
endif()
+ set_tests_properties(Persistence_representation_utilities_${function_utility} PROPERTIES DEPENDS
+ Persistence_representation_utilities_${creation_utility})
install(TARGETS ${function_utility} DESTINATION bin)
endfunction(add_persistence_representation_function_utility)
diff --git a/src/Persistence_representations/utilities/persistence_heat_maps/CMakeLists.txt b/src/Persistence_representations/utilities/persistence_heat_maps/CMakeLists.txt
index 89ef232f..e4c471c2 100644
--- a/src/Persistence_representations/utilities/persistence_heat_maps/CMakeLists.txt
+++ b/src/Persistence_representations/utilities/persistence_heat_maps/CMakeLists.txt
@@ -2,13 +2,24 @@ project(Persistence_representations_heat_maps_utilities)
add_persistence_representation_creation_utility(create_pssk "10" "-1" "-1" "4" "-1")
add_persistence_representation_creation_utility(create_p_h_m_weighted_by_arctan_of_their_persistence "10" "-1" "-1" "4" "-1")
+
add_persistence_representation_creation_utility(create_p_h_m_weighted_by_distance_from_diagonal "10" "-1" "-1" "4" "-1")
+# Tests output the same file
+set_tests_properties(Persistence_representation_utilities_create_p_h_m_weighted_by_distance_from_diagonal PROPERTIES DEPENDS
+ Persistence_representation_utilities_create_p_h_m_weighted_by_arctan_of_their_persistence)
+
add_persistence_representation_creation_utility(create_p_h_m_weighted_by_squared_diag_distance "10" "-1" "-1" "4" "-1")
+# Tests output the same file
+set_tests_properties(Persistence_representation_utilities_create_p_h_m_weighted_by_squared_diag_distance PROPERTIES DEPENDS
+ Persistence_representation_utilities_create_p_h_m_weighted_by_distance_from_diagonal)
+
# Need to set grid min and max for further average, distance and scalar_product
add_persistence_representation_creation_utility(create_persistence_heat_maps "10" "0" "35" "10" "-1")
+set_tests_properties(Persistence_representation_utilities_create_persistence_heat_maps PROPERTIES DEPENDS
+ Persistence_representation_utilities_create_p_h_m_weighted_by_squared_diag_distance)
-add_persistence_representation_plot_utility(plot_persistence_heat_map ".mps")
+add_persistence_representation_plot_utility(create_persistence_heat_maps plot_persistence_heat_map ".mps")
-add_persistence_representation_function_utility(average_persistence_heat_maps ".mps")
-add_persistence_representation_function_utility(compute_distance_of_persistence_heat_maps ".mps" "1")
-add_persistence_representation_function_utility(compute_scalar_product_of_persistence_heat_maps ".mps")
+add_persistence_representation_function_utility(create_persistence_heat_maps average_persistence_heat_maps ".mps")
+add_persistence_representation_function_utility(create_persistence_heat_maps compute_distance_of_persistence_heat_maps ".mps" "1")
+add_persistence_representation_function_utility(create_persistence_heat_maps compute_scalar_product_of_persistence_heat_maps ".mps")
diff --git a/src/Persistence_representations/utilities/persistence_intervals/CMakeLists.txt b/src/Persistence_representations/utilities/persistence_intervals/CMakeLists.txt
index a025183e..118c1e9b 100644
--- a/src/Persistence_representations/utilities/persistence_intervals/CMakeLists.txt
+++ b/src/Persistence_representations/utilities/persistence_intervals/CMakeLists.txt
@@ -3,17 +3,16 @@ project(Persistence_representations_intervals_utilities)
add_executable ( plot_histogram_of_intervals_lengths plot_histogram_of_intervals_lengths.cpp )
-add_test(NAME plot_histogram_of_intervals_lengths COMMAND $<TARGET_FILE:plot_histogram_of_intervals_lengths>
+add_test(NAME Persistence_representation_utilities_plot_histogram_of_intervals_lengths COMMAND $<TARGET_FILE:plot_histogram_of_intervals_lengths>
"${CMAKE_CURRENT_BINARY_DIR}/../first.pers" "-1")
install(TARGETS plot_histogram_of_intervals_lengths DESTINATION bin)
-add_persistence_representation_plot_utility(plot_persistence_intervals "")
-add_persistence_representation_plot_utility(plot_persistence_Betti_numbers "")
+add_persistence_representation_plot_utility(plot_histogram_of_intervals_lengths plot_persistence_intervals "")
+add_persistence_representation_plot_utility(plot_histogram_of_intervals_lengths plot_persistence_Betti_numbers "")
add_persistence_representation_creation_utility(compute_birth_death_range_in_persistence_diagram "-1")
-
add_executable ( compute_number_of_dominant_intervals compute_number_of_dominant_intervals.cpp )
add_test(NAME Persistence_representation_utilities_compute_number_of_dominant_intervals
COMMAND $<TARGET_FILE:compute_number_of_dominant_intervals>
diff --git a/src/Persistence_representations/utilities/persistence_landscapes/CMakeLists.txt b/src/Persistence_representations/utilities/persistence_landscapes/CMakeLists.txt
index 6b24d032..4df84d36 100644
--- a/src/Persistence_representations/utilities/persistence_landscapes/CMakeLists.txt
+++ b/src/Persistence_representations/utilities/persistence_landscapes/CMakeLists.txt
@@ -2,8 +2,8 @@ project(Persistence_representations_landscapes_utilities)
add_persistence_representation_creation_utility(create_landscapes "-1")
-add_persistence_representation_plot_utility(plot_landscapes ".land")
+add_persistence_representation_plot_utility(create_landscapes plot_landscapes ".land")
-add_persistence_representation_function_utility(average_landscapes ".land")
-add_persistence_representation_function_utility(compute_distance_of_landscapes ".land" "1")
-add_persistence_representation_function_utility(compute_scalar_product_of_landscapes ".land")
+add_persistence_representation_function_utility(create_landscapes average_landscapes ".land")
+add_persistence_representation_function_utility(create_landscapes compute_distance_of_landscapes ".land" "1")
+add_persistence_representation_function_utility(create_landscapes compute_scalar_product_of_landscapes ".land")
diff --git a/src/Persistence_representations/utilities/persistence_landscapes_on_grid/CMakeLists.txt b/src/Persistence_representations/utilities/persistence_landscapes_on_grid/CMakeLists.txt
index 36f3196b..8cd965f1 100644
--- a/src/Persistence_representations/utilities/persistence_landscapes_on_grid/CMakeLists.txt
+++ b/src/Persistence_representations/utilities/persistence_landscapes_on_grid/CMakeLists.txt
@@ -3,8 +3,8 @@ project(Persistence_representations_lanscapes_on_grid_utilities)
# Need to set grid min and max for further average, distance and scalar_product
add_persistence_representation_creation_utility(create_landscapes_on_grid "100" "0" "35" "-1")
-add_persistence_representation_plot_utility(plot_landscapes_on_grid ".g_land")
+add_persistence_representation_plot_utility(create_landscapes_on_grid plot_landscapes_on_grid ".g_land")
-add_persistence_representation_function_utility(average_landscapes_on_grid ".g_land")
-add_persistence_representation_function_utility(compute_distance_of_landscapes_on_grid ".g_land" "1")
-add_persistence_representation_function_utility(compute_scalar_product_of_landscapes_on_grid ".g_land")
+add_persistence_representation_function_utility(create_landscapes_on_grid average_landscapes_on_grid ".g_land")
+add_persistence_representation_function_utility(create_landscapes_on_grid compute_distance_of_landscapes_on_grid ".g_land" "1")
+add_persistence_representation_function_utility(create_landscapes_on_grid compute_scalar_product_of_landscapes_on_grid ".g_land")
diff --git a/src/Persistence_representations/utilities/persistence_vectors/CMakeLists.txt b/src/Persistence_representations/utilities/persistence_vectors/CMakeLists.txt
index bc982094..5b22ca84 100644
--- a/src/Persistence_representations/utilities/persistence_vectors/CMakeLists.txt
+++ b/src/Persistence_representations/utilities/persistence_vectors/CMakeLists.txt
@@ -2,8 +2,8 @@ project(Persistence_vectors_utilities)
add_persistence_representation_creation_utility(create_persistence_vectors "-1")
-add_persistence_representation_plot_utility(plot_persistence_vectors ".vect")
+add_persistence_representation_plot_utility(create_persistence_vectors plot_persistence_vectors ".vect")
-add_persistence_representation_function_utility(average_persistence_vectors ".vect")
-add_persistence_representation_function_utility(compute_distance_of_persistence_vectors ".vect" "1")
-add_persistence_representation_function_utility(compute_scalar_product_of_persistence_vectors ".vect")
+add_persistence_representation_function_utility(create_persistence_vectors average_persistence_vectors ".vect")
+add_persistence_representation_function_utility(create_persistence_vectors compute_distance_of_persistence_vectors ".vect" "1")
+add_persistence_representation_function_utility(create_persistence_vectors compute_scalar_product_of_persistence_vectors ".vect")
diff --git a/src/Persistent_cohomology/benchmark/CMakeLists.txt b/src/Persistent_cohomology/benchmark/CMakeLists.txt
index 2bb3b0c7..f38cc543 100644
--- a/src/Persistent_cohomology/benchmark/CMakeLists.txt
+++ b/src/Persistent_cohomology/benchmark/CMakeLists.txt
@@ -3,7 +3,7 @@ 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_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
+ 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)
diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt
index 94ec13c5..4c08cd68 100644
--- a/src/Persistent_cohomology/example/CMakeLists.txt
+++ b/src/Persistent_cohomology/example/CMakeLists.txt
@@ -5,13 +5,13 @@ add_executable(plain_homology plain_homology.cpp)
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_LIBRARY})
+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_LIBRARY})
+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_LIBRARY})
+target_link_libraries(persistence_from_file Boost::program_options)
if (TBB_FOUND)
target_link_libraries(plain_homology ${TBB_LIBRARIES})
@@ -43,7 +43,7 @@ if(GMP_FOUND)
if(GMPXX_FOUND)
add_executable(rips_multifield_persistence rips_multifield_persistence.cpp )
target_link_libraries(rips_multifield_persistence
- ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
+ Boost::program_options ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
if (TBB_FOUND)
target_link_libraries(rips_multifield_persistence ${TBB_LIBRARIES})
endif(TBB_FOUND)
diff --git a/src/Rips_complex/example/CMakeLists.txt b/src/Rips_complex/example/CMakeLists.txt
index e7772bdb..244a93ec 100644
--- a/src/Rips_complex/example/CMakeLists.txt
+++ b/src/Rips_complex/example/CMakeLists.txt
@@ -53,15 +53,23 @@ if (DIFF_PATH)
add_test(Rips_complex_example_from_off_doc_12_1_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/ripsoffreader_result_12_1.txt
${CMAKE_CURRENT_BINARY_DIR}/one_skeleton_rips_for_doc.txt)
+ set_tests_properties(Rips_complex_example_from_off_doc_12_1_diff_files PROPERTIES DEPENDS Rips_complex_example_from_off_doc_12_1)
+
add_test(Rips_complex_example_from_off_doc_12_3_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/ripsoffreader_result_12_3.txt
${CMAKE_CURRENT_BINARY_DIR}/full_skeleton_rips_for_doc.txt)
+ set_tests_properties(Rips_complex_example_from_off_doc_12_3_diff_files PROPERTIES DEPENDS Rips_complex_example_from_off_doc_12_3)
+
add_test(Rips_complex_example_from_csv_distance_matrix_doc_12_1_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/ripscsvreader_result_12_1.txt
${CMAKE_CURRENT_BINARY_DIR}/one_skeleton_rips_for_doc.txt)
+ set_tests_properties(Rips_complex_example_from_csv_distance_matrix_doc_12_1_diff_files PROPERTIES DEPENDS Rips_complex_example_from_csv_distance_matrix_doc_12_1)
+
add_test(Rips_complex_example_from_csv_distance_matrix_doc_12_3_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/ripscsvreader_result_12_3.txt
${CMAKE_CURRENT_BINARY_DIR}/full_skeleton_rips_for_doc.txt)
+ set_tests_properties(Rips_complex_example_from_csv_distance_matrix_doc_12_3_diff_files PROPERTIES DEPENDS Rips_complex_example_from_csv_distance_matrix_doc_12_3)
+
endif()
install(TARGETS Rips_complex_example_from_off DESTINATION bin)
diff --git a/src/Rips_complex/utilities/CMakeLists.txt b/src/Rips_complex/utilities/CMakeLists.txt
index 4b565628..d2448d7b 100644
--- a/src/Rips_complex/utilities/CMakeLists.txt
+++ b/src/Rips_complex/utilities/CMakeLists.txt
@@ -1,16 +1,16 @@
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_LIBRARY})
+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_LIBRARY})
+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_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+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_LIBRARY})
+target_link_libraries(sparse_rips_persistence Boost::program_options)
if (TBB_FOUND)
target_link_libraries(rips_distance_matrix_persistence ${TBB_LIBRARIES})
diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt
index f99b164c..a0aabee2 100644
--- a/src/Simplex_tree/example/CMakeLists.txt
+++ b/src/Simplex_tree/example/CMakeLists.txt
@@ -16,6 +16,9 @@ endif()
add_test(NAME Simplex_tree_example_simple_simplex_tree COMMAND $<TARGET_FILE:Simplex_tree_example_simple_simplex_tree>)
add_executable ( Simplex_tree_example_mini_simplex_tree mini_simplex_tree.cpp )
+if (TBB_FOUND)
+ target_link_libraries(Simplex_tree_example_mini_simplex_tree ${TBB_LIBRARIES})
+endif()
add_test(NAME Simplex_tree_example_mini_simplex_tree COMMAND $<TARGET_FILE:Simplex_tree_example_mini_simplex_tree>)
# An example with Simplex-tree using CGAL alpha_shapes_3
@@ -32,7 +35,7 @@ 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_LIBRARY} ${CGAL_LIBRARY})
+ 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()
diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h
index 76608008..7b39a500 100644
--- a/src/Simplex_tree/include/gudhi/Simplex_tree.h
+++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h
@@ -1317,6 +1317,8 @@ class Simplex_tree {
* \post Some simplex tree functions require the filtration to be valid. `make_filtration_non_decreasing()`
* function is not launching `initialize_filtration()` but returns the filtration modification information. If the
* complex has changed , please call `initialize_filtration()` to recompute it.
+ *
+ * If a simplex has a `NaN` filtration value, it is considered lower than any other defined filtration value.
*/
bool make_filtration_non_decreasing() {
bool modified = false;
@@ -1347,7 +1349,9 @@ class Simplex_tree {
});
Filtration_value max_filt_border_value = filtration(*max_border);
- if (simplex.second.filtration() < max_filt_border_value) {
+ // Replacing if(f<max) with if(!(f>=max)) would mean that if f is NaN, we replace it with the max of the children.
+ // That seems more useful than keeping NaN.
+ if (!(simplex.second.filtration() >= max_filt_border_value)) {
// Store the filtration modification information
modified = true;
simplex.second.assign_filtration(max_filt_border_value);
diff --git a/src/Simplex_tree/test/CMakeLists.txt b/src/Simplex_tree/test/CMakeLists.txt
index 8b9163f5..cf2b0153 100644
--- a/src/Simplex_tree/test/CMakeLists.txt
+++ b/src/Simplex_tree/test/CMakeLists.txt
@@ -28,3 +28,9 @@ if (TBB_FOUND)
target_link_libraries(Simplex_tree_ctor_and_move_test_unit ${TBB_LIBRARIES})
endif()
gudhi_add_boost_test(Simplex_tree_ctor_and_move_test_unit)
+
+add_executable ( Simplex_tree_make_filtration_non_decreasing_test_unit simplex_tree_make_filtration_non_decreasing_unit_test.cpp )
+if (TBB_FOUND)
+ target_link_libraries(Simplex_tree_make_filtration_non_decreasing_test_unit ${TBB_LIBRARIES})
+endif()
+gudhi_add_boost_test(Simplex_tree_make_filtration_non_decreasing_test_unit)
diff --git a/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp
new file mode 100644
index 00000000..4697ec05
--- /dev/null
+++ b/src/Simplex_tree/test/simplex_tree_make_filtration_non_decreasing_unit_test.cpp
@@ -0,0 +1,148 @@
+/* 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
+ */
+
+#include <iostream>
+#include <limits> // for NaN
+#include <cmath> // for isNaN
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "simplex_tree_make_filtration_non_decreasing"
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/list.hpp>
+
+// ^
+// /!\ Nothing else from Simplex_tree shall be included to test includes are well defined.
+#include "gudhi/Simplex_tree.h"
+
+using namespace Gudhi;
+
+typedef boost::mpl::list<Simplex_tree<>, Simplex_tree<Simplex_tree_options_fast_persistence>> list_of_tested_variants;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(make_filtration_non_decreasing, typeST, list_of_tested_variants) {
+ typeST st;
+
+ st.insert_simplex_and_subfaces({2, 1, 0}, 2.0);
+ st.insert_simplex_and_subfaces({3, 0}, 2.0);
+ st.insert_simplex_and_subfaces({3, 4, 5}, 2.0);
+
+ /* Inserted simplex: */
+ /* 1 */
+ /* o */
+ /* /X\ */
+ /* o---o---o---o */
+ /* 2 0 3\X/4 */
+ /* o */
+ /* 5 */
+
+ std::cout << "Check default insertion ensures the filtration values are non decreasing" << std::endl;
+ BOOST_CHECK(!st.make_filtration_non_decreasing());
+
+ // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 2.0
+ // to 1.0
+ st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0);
+
+ // Inserted simplex:
+ // 1 6
+ // o---o
+ // /X\7/
+ // o---o---o---o
+ // 2 0 3\X/4
+ // o
+ // 5
+
+ std::cout << "Check default second insertion ensures the filtration values are non decreasing" << std::endl;
+ BOOST_CHECK(!st.make_filtration_non_decreasing());
+
+ // Copy original simplex tree
+ typeST st_copy = st;
+
+ // Modify specific values for st to become like st_copy thanks to make_filtration_non_decreasing
+ st.assign_filtration(st.find({0,1,6,7}), 0.8);
+ st.assign_filtration(st.find({0,1,6}), 0.9);
+ st.assign_filtration(st.find({0,6}), 0.6);
+ st.assign_filtration(st.find({3,4,5}), 1.2);
+ st.assign_filtration(st.find({3,4}), 1.1);
+ st.assign_filtration(st.find({4,5}), 1.99);
+
+ std::cout << "Check the simplex_tree is rolled back in case of decreasing filtration values" << std::endl;
+ BOOST_CHECK(st.make_filtration_non_decreasing());
+ BOOST_CHECK(st == st_copy);
+
+ // Other simplex tree
+ typeST st_other;
+ st_other.insert_simplex_and_subfaces({2, 1, 0}, 3.0); // This one is different from st
+ st_other.insert_simplex_and_subfaces({3, 0}, 2.0);
+ st_other.insert_simplex_and_subfaces({3, 4, 5}, 2.0);
+ st_other.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0);
+
+ // Modify specific values for st to become like st_other thanks to make_filtration_non_decreasing
+ st.assign_filtration(st.find({2}), 3.0);
+ // By modifying just the simplex {2}
+ // {0,1,2}, {1,2} and {0,2} will be modified
+
+ std::cout << "Check the simplex_tree is repaired in case of decreasing filtration values" << std::endl;
+ BOOST_CHECK(st.make_filtration_non_decreasing());
+ BOOST_CHECK(st == st_other);
+
+ // Modify specific values for st still to be non-decreasing
+ st.assign_filtration(st.find({0,1,2}), 10.0);
+ st.assign_filtration(st.find({0,2}), 9.0);
+ st.assign_filtration(st.find({0,1,6,7}), 50.0);
+ st.assign_filtration(st.find({0,1,6}), 49.0);
+ st.assign_filtration(st.find({0,1,7}), 48.0);
+ // Other copy simplex tree
+ typeST st_other_copy = st;
+
+ std::cout << "Check the simplex_tree is not modified in case of non-decreasing filtration values" << std::endl;
+ BOOST_CHECK(!st.make_filtration_non_decreasing());
+ BOOST_CHECK(st == st_other_copy);
+
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(make_filtration_non_decreasing_on_nan_values, typeST, list_of_tested_variants) {
+ typeST st;
+
+ st.insert_simplex_and_subfaces({2, 1, 0}, std::numeric_limits<double>::quiet_NaN());
+ st.insert_simplex_and_subfaces({3, 0}, std::numeric_limits<double>::quiet_NaN());
+ st.insert_simplex_and_subfaces({3, 4, 5}, std::numeric_limits<double>::quiet_NaN());
+
+ /* Inserted simplex: */
+ /* 1 */
+ /* o */
+ /* /X\ */
+ /* o---o---o---o */
+ /* 2 0 3\X/4 */
+ /* o */
+ /* 5 */
+
+ std::cout << "SPECIFIC CASE:" << std::endl;
+ std::cout << "Insertion with NaN values does not ensure the filtration values are non decreasing" << std::endl;
+ st.make_filtration_non_decreasing();
+
+ std::cout << "Check all filtration values are NaN" << std::endl;
+ for (auto f_simplex : st.complex_simplex_range()) {
+ BOOST_CHECK(std::isnan(st.filtration(f_simplex)));
+ }
+
+ st.assign_filtration(st.find({0}), 0.);
+ st.assign_filtration(st.find({1}), 0.);
+ st.assign_filtration(st.find({2}), 0.);
+ st.assign_filtration(st.find({3}), 0.);
+ st.assign_filtration(st.find({4}), 0.);
+ st.assign_filtration(st.find({5}), 0.);
+
+ std::cout << "Check make_filtration_non_decreasing is modifying the simplicial complex" << std::endl;
+ BOOST_CHECK(st.make_filtration_non_decreasing());
+
+ std::cout << "Check all filtration values are now defined" << std::endl;
+ for (auto f_simplex : st.complex_simplex_range()) {
+ BOOST_CHECK(!std::isnan(st.filtration(f_simplex)));
+ }
+} \ No newline at end of file
diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp
index 58bfa8db..e739ad0a 100644
--- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp
+++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp
@@ -791,90 +791,6 @@ BOOST_AUTO_TEST_CASE(non_contiguous) {
BOOST_CHECK(++i == std::end(b));
}
-BOOST_AUTO_TEST_CASE(make_filtration_non_decreasing) {
- std::cout << "********************************************************************" << std::endl;
- std::cout << "MAKE FILTRATION NON DECREASING" << std::endl;
- typedef Simplex_tree<> typeST;
- typeST st;
-
- st.insert_simplex_and_subfaces({2, 1, 0}, 2.0);
- st.insert_simplex_and_subfaces({3, 0}, 2.0);
- st.insert_simplex_and_subfaces({3, 4, 5}, 2.0);
-
- /* Inserted simplex: */
- /* 1 */
- /* o */
- /* /X\ */
- /* o---o---o---o */
- /* 2 0 3\X/4 */
- /* o */
- /* 5 */
-
- std::cout << "Check default insertion ensures the filtration values are non decreasing" << std::endl;
- BOOST_CHECK(!st.make_filtration_non_decreasing());
-
- // Because of non decreasing property of simplex tree, { 0 } , { 1 } and { 0, 1 } are going to be set from value 2.0
- // to 1.0
- st.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0);
-
- // Inserted simplex:
- // 1 6
- // o---o
- // /X\7/
- // o---o---o---o
- // 2 0 3\X/4
- // o
- // 5
-
- std::cout << "Check default second insertion ensures the filtration values are non decreasing" << std::endl;
- BOOST_CHECK(!st.make_filtration_non_decreasing());
-
- // Copy original simplex tree
- typeST st_copy = st;
-
- // Modify specific values for st to become like st_copy thanks to make_filtration_non_decreasing
- st.assign_filtration(st.find({0,1,6,7}), 0.8);
- st.assign_filtration(st.find({0,1,6}), 0.9);
- st.assign_filtration(st.find({0,6}), 0.6);
- st.assign_filtration(st.find({3,4,5}), 1.2);
- st.assign_filtration(st.find({3,4}), 1.1);
- st.assign_filtration(st.find({4,5}), 1.99);
-
- std::cout << "Check the simplex_tree is rolled back in case of decreasing filtration values" << std::endl;
- BOOST_CHECK(st.make_filtration_non_decreasing());
- BOOST_CHECK(st == st_copy);
-
- // Other simplex tree
- typeST st_other;
- st_other.insert_simplex_and_subfaces({2, 1, 0}, 3.0); // This one is different from st
- st_other.insert_simplex_and_subfaces({3, 0}, 2.0);
- st_other.insert_simplex_and_subfaces({3, 4, 5}, 2.0);
- st_other.insert_simplex_and_subfaces({0, 1, 6, 7}, 1.0);
-
- // Modify specific values for st to become like st_other thanks to make_filtration_non_decreasing
- st.assign_filtration(st.find({2}), 3.0);
- // By modifying just the simplex {2}
- // {0,1,2}, {1,2} and {0,2} will be modified
-
- std::cout << "Check the simplex_tree is repaired in case of decreasing filtration values" << std::endl;
- BOOST_CHECK(st.make_filtration_non_decreasing());
- BOOST_CHECK(st == st_other);
-
- // Modify specific values for st still to be non-decreasing
- st.assign_filtration(st.find({0,1,2}), 10.0);
- st.assign_filtration(st.find({0,2}), 9.0);
- st.assign_filtration(st.find({0,1,6,7}), 50.0);
- st.assign_filtration(st.find({0,1,6}), 49.0);
- st.assign_filtration(st.find({0,1,7}), 48.0);
- // Other copy simplex tree
- typeST st_other_copy = st;
-
- std::cout << "Check the simplex_tree is not modified in case of non-decreasing filtration values" << std::endl;
- BOOST_CHECK(!st.make_filtration_non_decreasing());
- BOOST_CHECK(st == st_other_copy);
-
-}
-
typedef boost::mpl::list<boost::adjacency_list<boost::setS, boost::vecS, boost::directedS,
boost::property<vertex_filtration_t, double>,
diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h
index f058fa9f..f007bdd5 100644
--- a/src/Tangential_complex/include/gudhi/Tangential_complex.h
+++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h
@@ -60,7 +60,7 @@
#ifdef GUDHI_USE_TBB
#include <tbb/parallel_for.h>
#include <tbb/combinable.h>
-#include <tbb/mutex.h>
+#include <mutex>
#endif
// #define GUDHI_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3)
@@ -147,7 +147,7 @@ class Tangential_complex {
typedef typename Tr_traits::Vector_d Tr_vector;
#if defined(GUDHI_USE_TBB)
- typedef tbb::mutex Mutex_for_perturb;
+ typedef std::mutex Mutex_for_perturb;
typedef Vector Translation_for_perturb;
typedef std::vector<Atomic_wrapper<FT> > Weights;
#else
diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt
index 5860f3a3..2659798e 100644
--- a/src/Witness_complex/example/CMakeLists.txt
+++ b/src/Witness_complex/example/CMakeLists.txt
@@ -12,10 +12,18 @@ install(TARGETS Witness_complex_example_nearest_landmark_table DESTINATION bin)
# CGAL and Eigen3 are required for Euclidean version of Witness
if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
add_executable( Witness_complex_example_off example_witness_complex_off.cpp )
+ if (TBB_FOUND)
+ target_link_libraries(Witness_complex_example_off ${TBB_LIBRARIES})
+ endif()
add_executable ( Witness_complex_example_sphere example_witness_complex_sphere.cpp )
+ if (TBB_FOUND)
+ target_link_libraries(Witness_complex_example_sphere ${TBB_LIBRARIES})
+ endif()
add_executable( Witness_complex_example_strong_off example_strong_witness_complex_off.cpp )
- target_link_libraries(Witness_complex_example_strong_off)
+ if (TBB_FOUND)
+ target_link_libraries(Witness_complex_example_strong_off ${TBB_LIBRARIES})
+ endif()
add_test(NAME Witness_complex_example_off_test_torus
COMMAND $<TARGET_FILE:Witness_complex_example_off>
diff --git a/src/Witness_complex/utilities/CMakeLists.txt b/src/Witness_complex/utilities/CMakeLists.txt
index 3ee0c2f6..d986d2d1 100644
--- a/src/Witness_complex/utilities/CMakeLists.txt
+++ b/src/Witness_complex/utilities/CMakeLists.txt
@@ -4,10 +4,10 @@ project(Witness_complex_utilities)
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_LIBRARY})
+ 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_LIBRARY})
+ target_link_libraries(Witness_complex_weak_witness_persistence Boost::program_options)
if (TBB_FOUND)
target_link_libraries(Witness_complex_strong_witness_persistence ${TBB_LIBRARIES})
diff --git a/src/cmake/modules/GUDHI_boost_test.cmake b/src/cmake/modules/GUDHI_boost_test.cmake
index c3b29883..4a13404b 100644
--- a/src/cmake/modules/GUDHI_boost_test.cmake
+++ b/src/cmake/modules/GUDHI_boost_test.cmake
@@ -9,7 +9,6 @@ if (WITH_GUDHI_BOOST_TEST_COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
endif()
set(GUDHI_UT_LOG_FORMAT "--log_format=XML")
- set(GUDHI_UT_LOG_SINK "--log_sink=${CMAKE_BINARY_DIR}/${unitary_test}_UT.xml")
set(GUDHI_UT_LOG_LEVEL "--log_level=test_suite")
set(GUDHI_UT_REPORT_LEVEL "--report_level=no")
else (WITH_GUDHI_BOOST_TEST_COVERAGE)
@@ -19,7 +18,11 @@ else (WITH_GUDHI_BOOST_TEST_COVERAGE)
endif(WITH_GUDHI_BOOST_TEST_COVERAGE)
function(gudhi_add_boost_test unitary_test)
- target_link_libraries(${unitary_test} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ if (WITH_GUDHI_BOOST_TEST_COVERAGE)
+ set(GUDHI_UT_LOG_SINK "--log_sink=${CMAKE_BINARY_DIR}/${unitary_test}_UT.xml")
+ endif(WITH_GUDHI_BOOST_TEST_COVERAGE)
+
+ target_link_libraries(${unitary_test} Boost::unit_test_framework)
add_test(NAME ${unitary_test} COMMAND $<TARGET_FILE:${unitary_test}>
${GUDHI_UT_LOG_FORMAT} ${GUDHI_UT_LOG_SINK}
${GUDHI_UT_LOG_LEVEL} ${GUDHI_UT_REPORT_LEVEL})
diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake
index 24a34150..2d010483 100644
--- a/src/cmake/modules/GUDHI_third_party_libraries.cmake
+++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake
@@ -6,6 +6,38 @@ if(NOT Boost_FOUND)
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()
+
find_package(GMP)
if(GMP_FOUND)
INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR})
@@ -35,6 +67,9 @@ if(CGAL_FOUND)
include( ${CGAL_USE_FILE} )
endif()
+# For those who dislike bundled dependencies, this indicates where to find a preinstalled Hera.
+set(HERA_WASSERSTEIN_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/ext/hera/wasserstein/include CACHE PATH "Directory where one can find Hera's wasserstein.h")
+
option(WITH_GUDHI_USE_TBB "Build with Intel TBB parallelization" ON)
# Find TBB package for parallel sort - not mandatory, just optional.
@@ -82,9 +117,6 @@ add_definitions( -DBOOST_ALL_DYN_LINK )
# problem on Mac with boost_system and boost_thread
add_definitions( -DBOOST_SYSTEM_NO_DEPRECATED )
-INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
-LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
-
message(STATUS "boost include dirs:" ${Boost_INCLUDE_DIRS})
message(STATUS "boost library dirs:" ${Boost_LIBRARY_DIRS})
@@ -127,6 +159,7 @@ if( PYTHONINTERP_FOUND )
find_python_module("sphinx")
find_python_module("sklearn")
find_python_module("ot")
+ find_python_module("pybind11")
endif()
if(NOT GUDHI_PYTHON_PATH)
diff --git a/src/cmake/modules/GUDHI_user_version_target.cmake b/src/cmake/modules/GUDHI_user_version_target.cmake
index 0b361a0f..257d1939 100644
--- a/src/cmake/modules/GUDHI_user_version_target.cmake
+++ b/src/cmake/modules/GUDHI_user_version_target.cmake
@@ -54,6 +54,9 @@ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
copy_directory ${CMAKE_SOURCE_DIR}/src/GudhUI ${GUDHI_USER_VERSION_DIR}/GudhUI)
+add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
+ copy_directory ${CMAKE_SOURCE_DIR}/ext/hera/wasserstein/include ${GUDHI_USER_VERSION_DIR}/ext/hera/wasserstein/include)
+
set(GUDHI_DIRECTORIES "doc;example;concept;utilities")
set(GUDHI_INCLUDE_DIRECTORIES "include/gudhi")
@@ -93,4 +96,4 @@ foreach(GUDHI_MODULE ${GUDHI_MODULES_FULL_LIST})
endforeach()
endforeach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES})
-endforeach(GUDHI_MODULE ${GUDHI_MODULES_FULL_LIST}) \ No newline at end of file
+endforeach(GUDHI_MODULE ${GUDHI_MODULES_FULL_LIST})
diff --git a/src/common/doc/header.html b/src/common/doc/header.html
index 9fdb2321..99ab6bb7 100644
--- a/src/common/doc/header.html
+++ b/src/common/doc/header.html
@@ -56,7 +56,7 @@ $extrastylesheet
<a href="#">Download</a>
<ul class="dropdown">
<li><a href="/licensing/">Licensing</a></li>
- <li><a href="https://gforge.inria.fr/frs/download.php/latestzip/5253/library-latest.zip" target="_blank">Get the latest sources</a></li>
+ <li><a href="https://github.com/GUDHI/gudhi-devel/releases/latest" target="_blank">Get the latest sources</a></li>
<li><a href="/conda/">Conda package</a></li>
<li><a href="/dockerfile/">Dockerfile</a></li>
</ul>
diff --git a/src/common/example/CMakeLists.txt b/src/common/example/CMakeLists.txt
index 583a0027..fa8eb98c 100644
--- a/src/common/example/CMakeLists.txt
+++ b/src/common/example/CMakeLists.txt
@@ -12,6 +12,7 @@ if (DIFF_PATH)
add_test(Common_example_vector_double_off_reader_diff_files ${DIFF_PATH}
${CMAKE_CURRENT_BINARY_DIR}/vectordoubleoffreader_result.txt ${CMAKE_CURRENT_BINARY_DIR}/alphacomplexdoc.off.txt)
+ set_tests_properties(Common_example_vector_double_off_reader_diff_files PROPERTIES DEPENDS Common_example_vector_double_off_reader)
endif()
if(NOT CGAL_VERSION VERSION_LESS 4.11.0)
diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt
index 798e2907..22af3ec9 100644
--- a/src/python/CMakeLists.txt
+++ b/src/python/CMakeLists.txt
@@ -32,6 +32,10 @@ function( add_gudhi_debug_info DEBUG_INFO )
endfunction( add_gudhi_debug_info )
if(PYTHONINTERP_FOUND)
+ if(PYBIND11_FOUND)
+ add_gudhi_debug_info("Pybind11 version ${PYBIND11_VERSION}")
+ set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'hera', ")
+ endif()
if(CYTHON_FOUND)
set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_reader', ")
set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'simplex_tree', ")
@@ -87,6 +91,7 @@ if(PYTHONINTERP_FOUND)
endif(MSVC)
if(CMAKE_COMPILER_IS_GNUCXX)
set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ")
+ set(GUDHI_PYBIND11_EXTRA_COMPILE_ARGS "${GUDHI_PYBIND11_EXTRA_COMPILE_ARGS}'-fvisibility=hidden', ")
endif(CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_CXX_COMPILER_ID MATCHES Intel)
set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ")
@@ -177,7 +182,7 @@ if(PYTHONINTERP_FOUND)
set(GUDHI_PYTHON_LIBRARY_DIRS "${GUDHI_PYTHON_LIBRARY_DIRS}'${MPFR_LIBRARIES_DIR}', ")
message("** Add mpfr ${MPFR_LIBRARIES}")
endif(MPFR_FOUND)
-endif(CGAL_FOUND)
+ endif(CGAL_FOUND)
# Specific for Mac
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
@@ -392,9 +397,9 @@ endif(CGAL_FOUND)
add_gudhi_py_test(test_reader_utils)
# Wasserstein
- if(OT_FOUND)
+ if(OT_FOUND AND PYBIND11_FOUND)
add_gudhi_py_test(test_wasserstein_distance)
- endif(OT_FOUND)
+ endif()
# Representations
if(SKLEARN_FOUND AND MATPLOTLIB_FOUND)
@@ -411,32 +416,37 @@ endif(CGAL_FOUND)
if(SCIPY_FOUND)
if(SKLEARN_FOUND)
if(OT_FOUND)
- if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
- set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/")
- # User warning - Sphinx is a static pages generator, and configured to work fine with user_version
- # Images and biblio warnings because not found on developper version
- if (GUDHI_PYTHON_PATH STREQUAL "src/python")
- set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developper version. Images and biblio will miss")
- endif()
- # sphinx target requires gudhi.so, because conf.py reads gudhi version from it
- add_custom_target(sphinx
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx
- DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so"
- COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM)
+ if(PYBIND11_FOUND)
+ if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/")
+ # User warning - Sphinx is a static pages generator, and configured to work fine with user_version
+ # Images and biblio warnings because not found on developper version
+ if (GUDHI_PYTHON_PATH STREQUAL "src/python")
+ set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developper version. Images and biblio will miss")
+ endif()
+ # sphinx target requires gudhi.so, because conf.py reads gudhi version from it
+ add_custom_target(sphinx
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx
+ DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so"
+ COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM)
- add_test(NAME sphinx_py_test
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
- ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest)
+ add_test(NAME sphinx_py_test
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}"
+ ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest)
- # Set missing or not modules
- set(GUDHI_MODULES ${GUDHI_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MODULES")
- else(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
- message("++ Python documentation module will not be compiled because it requires a Eigen3 and CGAL version >= 4.11.0")
+ # Set missing or not modules
+ set(GUDHI_MODULES ${GUDHI_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MODULES")
+ else(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ message("++ Python documentation module will not be compiled because it requires a Eigen3 and CGAL version >= 4.11.0")
+ set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
+ endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ else(PYBIND11_FOUND)
+ message("++ Python documentation module will not be compiled because pybind11 was not found")
set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
- endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ endif(PYBIND11_FOUND)
else(OT_FOUND)
message("++ Python documentation module will not be compiled because POT was not found")
set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES")
diff --git a/src/python/doc/_templates/layout.html b/src/python/doc/_templates/layout.html
index 2f2d9c72..a672a281 100644
--- a/src/python/doc/_templates/layout.html
+++ b/src/python/doc/_templates/layout.html
@@ -201,7 +201,7 @@
<a href="#">Download</a>
<ul class="dropdown">
<li><a href="/licensing/">Licensing</a></li>
- <li><a href="https://gforge.inria.fr/frs/download.php/latestzip/5253/library-latest.zip" target="_blank">Get the latest sources</a></li>
+ <li><a href="https://github.com/GUDHI/gudhi-devel/releases/latest" target="_blank">Get the latest sources</a></li>
<li><a href="/conda/">Conda package</a></li>
<li><a href="/dockerfile/">Dockerfile</a></li>
</ul>
diff --git a/src/python/doc/alpha_complex_sum.inc b/src/python/doc/alpha_complex_sum.inc
index a1184663..b5af0d27 100644
--- a/src/python/doc/alpha_complex_sum.inc
+++ b/src/python/doc/alpha_complex_sum.inc
@@ -5,16 +5,13 @@
| .. figure:: | Alpha complex is a simplicial complex constructed from the finite | :Author: Vincent Rouvreau |
| ../../doc/Alpha_complex/alpha_complex_representation.png | cells of a Delaunay Triangulation. | |
| :alt: Alpha complex representation | | :Introduced in: GUDHI 2.0.0 |
- | :figclass: align-center | The filtration value of each simplex is computed as the square of the | |
- | | circumradius of the simplex if the circumsphere is empty (the simplex | :Copyright: MIT (`GPL v3 </licensing/>`_) |
- | | is then said to be Gabriel), and as the minimum of the filtration | |
- | | values of the codimension 1 cofaces that make it not Gabriel | :Requires: `Eigen <installation.html#eigen>`__ :math:`\geq` 3.1.0 and `CGAL <installation.html#cgal>`__ :math:`\geq` 4.11.0 |
- | | otherwise. All simplices that have a filtration value | |
- | | :math:`> \alpha^2` are removed from the Delaunay complex | |
- | | when creating the simplicial complex if it is specified. | |
+ | :figclass: align-center | The filtration value of each simplex is computed as the **square** of | |
+ | | the circumradius of the simplex if the circumsphere is empty (the | :Copyright: MIT (`GPL v3 </licensing/>`_) |
+ | | simplex is then said to be Gabriel), and as the minimum of the | |
+ | | filtration values of the codimension 1 cofaces that make it not | :Requires: `Eigen <installation.html#eigen>`__ :math:`\geq` 3.1.0 and `CGAL <installation.html#cgal>`__ :math:`\geq` 4.11.0 |
+ | | Gabriel otherwise. | |
| | | |
- | | This package requires having CGAL version 4.7 or higher (4.8.1 is | |
- | | advised for better performance). | |
+ | | For performances reasons, it is advised to use CGAL ≥ 5.0.0. | |
+----------------------------------------------------------------+------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| * :doc:`alpha_complex_user` | * :doc:`alpha_complex_ref` |
+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst
index 40f3f44b..d459145b 100644
--- a/src/python/doc/installation.rst
+++ b/src/python/doc/installation.rst
@@ -14,10 +14,11 @@ Compiling
*********
The library uses c++14 and requires `Boost <https://www.boost.org/>`_ ≥ 1.56.0,
`CMake <https://www.cmake.org/>`_ ≥ 3.1 to generate makefiles,
-`NumPy <http://numpy.org>`_ and `Cython <https://www.cython.org/>`_ to compile
+`NumPy <http://numpy.org>`_, `Cython <https://www.cython.org/>`_ and
+`pybind11 <https://github.com/pybind/pybind11>`_ to compile
the GUDHI Python module.
It is a multi-platform library and compiles on Linux, Mac OSX and Visual
-Studio 2015.
+Studio 2017.
On `Windows <https://wiki.python.org/moin/WindowsCompilers>`_ , only Python
≥ 3.5 are available because of the required Visual Studio version.
diff --git a/src/python/doc/persistence_graphical_tools_sum.inc b/src/python/doc/persistence_graphical_tools_sum.inc
index 0cdf8072..ef376802 100644
--- a/src/python/doc/persistence_graphical_tools_sum.inc
+++ b/src/python/doc/persistence_graphical_tools_sum.inc
@@ -2,11 +2,11 @@
:widths: 30 50 20
+-----------------------------------------------------------------+-----------------------------------------------------------------------+-----------------------------------------------+
- | .. figure:: | These graphical tools comes on top of persistence results and allows | :Author: Vincent Rouvreau |
- | img/graphical_tools_representation.png | the user to build easily persistence barcode, diagram or density. | |
+ | .. figure:: | These graphical tools comes on top of persistence results and allows | :Author: Vincent Rouvreau, Theo Lacombe |
+ | img/graphical_tools_representation.png | the user to display easily persistence barcode, diagram or density. | |
| | | :Introduced in: GUDHI 2.0.0 |
- | | | |
- | | | :Copyright: MIT |
+ | | Note that these functions return the matplotlib axis, allowing | |
+ | | for further modifications (title, aspect, etc.) | :Copyright: MIT |
| | | |
| | | :Requires: matplotlib, numpy and scipy |
+-----------------------------------------------------------------+-----------------------------------------------------------------------+-----------------------------------------------+
diff --git a/src/python/doc/persistence_graphical_tools_user.rst b/src/python/doc/persistence_graphical_tools_user.rst
index 80002db6..91e52703 100644
--- a/src/python/doc/persistence_graphical_tools_user.rst
+++ b/src/python/doc/persistence_graphical_tools_user.rst
@@ -20,7 +20,7 @@ This function can display the persistence result as a barcode:
.. plot::
:include-source:
- import matplotlib.pyplot as plot
+ import matplotlib.pyplot as plt
import gudhi
off_file = gudhi.__root_source_dir__ + '/data/points/tore3D_300.off'
@@ -31,7 +31,7 @@ This function can display the persistence result as a barcode:
diag = simplex_tree.persistence(min_persistence=0.4)
gudhi.plot_persistence_barcode(diag)
- plot.show()
+ plt.show()
Show persistence as a diagram
-----------------------------
@@ -44,15 +44,31 @@ This function can display the persistence result as a diagram:
.. plot::
:include-source:
- import matplotlib.pyplot as plot
+ import matplotlib.pyplot as plt
import gudhi
# rips_on_tore3D_1307.pers obtained from write_persistence_diagram method
persistence_file=gudhi.__root_source_dir__ + \
'/data/persistence_diagram/rips_on_tore3D_1307.pers'
- gudhi.plot_persistence_diagram(persistence_file=persistence_file,
+ ax = gudhi.plot_persistence_diagram(persistence_file=persistence_file,
legend=True)
- plot.show()
+ # We can modify the title, aspect, etc.
+ ax.set_title("Persistence diagram of a torus")
+ ax.set_aspect("equal") # forces to be square shaped
+ plt.show()
+
+Note that (as barcode and density) it can also take a simple `np.array`
+of shape (N x 2) encoding a persistence diagram (in a given dimension).
+
+.. plot::
+ :include-source:
+
+ import matplotlib.pyplot as plt
+ import gudhi
+ import numpy as np
+ d = np.array([[0, 1], [1, 2], [1, np.inf]])
+ gudhi.plot_persistence_diagram(d)
+ plt.show()
Persistence density
-------------------
@@ -65,7 +81,7 @@ If you want more information on a specific dimension, for instance:
.. plot::
:include-source:
- import matplotlib.pyplot as plot
+ import matplotlib.pyplot as plt
import gudhi
# rips_on_tore3D_1307.pers obtained from write_persistence_diagram method
persistence_file=gudhi.__root_source_dir__ + \
@@ -75,9 +91,9 @@ If you want more information on a specific dimension, for instance:
only_this_dim=1)
pers_diag = [(1, elt) for elt in birth_death]
# Use subplots to display diagram and density side by side
- fig, axes = plot.subplots(nrows=1, ncols=2, figsize=(12, 5))
+ fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 5))
gudhi.plot_persistence_diagram(persistence=pers_diag,
axes=axes[0])
gudhi.plot_persistence_density(persistence=pers_diag,
dimension=1, legend=True, axes=axes[1])
- plot.show()
+ plt.show()
diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst
index 32999a0c..94b454e2 100644
--- a/src/python/doc/wasserstein_distance_user.rst
+++ b/src/python/doc/wasserstein_distance_user.rst
@@ -9,17 +9,26 @@ Definition
.. include:: wasserstein_distance_sum.inc
-This implementation is based on ideas from "Large Scale Computation of Means and Cluster for Persistence Diagrams via Optimal Transport".
+Functions
+---------
+This implementation uses the Python Optimal Transport library and is based on
+ideas from "Large Scale Computation of Means and Cluster for Persistence
+Diagrams via Optimal Transport" :cite:`10.5555/3327546.3327645`.
-Function
---------
.. autofunction:: gudhi.wasserstein.wasserstein_distance
+This other implementation comes from `Hera
+<https://bitbucket.org/grey_narn/hera/src/master/>`_ (BSD-3-Clause) which is
+based on "Geometry Helps to Compare Persistence Diagrams"
+:cite:`Kerber:2017:GHC:3047249.3064175` by Michael Kerber, Dmitriy
+Morozov, and Arnur Nigmetov.
+
+.. autofunction:: gudhi.hera.wasserstein_distance
Basic example
-------------
-This example computes the 1-Wasserstein distance from 2 persistence diagrams with euclidean ground metric.
+This example computes the 1-Wasserstein distance from 2 persistence diagrams with Euclidean ground metric.
Note that persistence diagrams must be submitted as (n x 2) numpy arrays and must not contain inf values.
.. testcode::
diff --git a/src/python/gudhi/hera.cc b/src/python/gudhi/hera.cc
new file mode 100644
index 00000000..0d562b4c
--- /dev/null
+++ b/src/python/gudhi/hera.cc
@@ -0,0 +1,71 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Marc Glisse
+ *
+ * Copyright (C) 2020 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <pybind11/pybind11.h>
+#include <pybind11/numpy.h>
+
+#include <boost/range/iterator_range.hpp>
+
+#include <wasserstein.h> // Hera
+
+#include <array>
+
+namespace py = pybind11;
+typedef py::array_t<double, py::array::c_style | py::array::forcecast> Dgm;
+
+double wasserstein_distance(
+ Dgm d1, Dgm d2,
+ double wasserstein_power, double internal_p,
+ double delta)
+{
+ py::buffer_info buf1 = d1.request();
+ py::buffer_info buf2 = d2.request();
+ // shape (n,2) or (0) for empty
+ if((buf1.ndim!=2 || buf1.shape[1]!=2) && (buf1.ndim!=1 || buf1.shape[0]!=0))
+ throw std::runtime_error("Diagram 1 must be an array of size n x 2");
+ if((buf2.ndim!=2 || buf2.shape[1]!=2) && (buf2.ndim!=1 || buf2.shape[0]!=0))
+ throw std::runtime_error("Diagram 2 must be an array of size n x 2");
+ typedef std::array<double, 2> Point;
+ auto p1 = (Point*)buf1.ptr;
+ auto p2 = (Point*)buf2.ptr;
+ auto diag1 = boost::make_iterator_range(p1, p1+buf1.shape[0]);
+ auto diag2 = boost::make_iterator_range(p2, p2+buf2.shape[0]);
+
+ hera::AuctionParams<double> params;
+ params.wasserstein_power = wasserstein_power;
+ // hera encodes infinity as -1...
+ if(std::isinf(internal_p)) internal_p = hera::get_infinity<double>();
+ params.internal_p = internal_p;
+ params.delta = delta;
+ // The extra parameters are purposedly not exposed for now.
+ return hera::wasserstein_dist(diag1, diag2, params);
+}
+
+PYBIND11_MODULE(hera, m) {
+ m.def("wasserstein_distance", &wasserstein_distance,
+ py::arg("X"), py::arg("Y"),
+ py::arg("order") = 1,
+ py::arg("internal_p") = std::numeric_limits<double>::infinity(),
+ py::arg("delta") = .01,
+ R"pbdoc(
+ Compute the Wasserstein distance between two diagrams.
+ Points at infinity are supported.
+
+ Parameters:
+ X (n x 2 numpy array): First diagram
+ Y (n x 2 numpy array): Second diagram
+ order (float): Wasserstein exponent W_q
+ internal_p (float): Internal Minkowski norm L^p in R^2
+ delta (float): Relative error 1+delta
+
+ Returns:
+ float: Approximate Wasserstein distance W_q(X,Y)
+ )pbdoc");
+}
diff --git a/src/python/gudhi/nerve_gic.pyx b/src/python/gudhi/nerve_gic.pyx
index 382e71c5..45cc8eba 100644
--- a/src/python/gudhi/nerve_gic.pyx
+++ b/src/python/gudhi/nerve_gic.pyx
@@ -187,7 +187,7 @@ cdef class CoverComplex:
def set_automatic_resolution(self):
"""Computes the optimal length of intervals (i.e. the smallest interval
- length avoiding discretization artifacts—see :cite:`Carriere17c`) for a
+ length avoiding discretization artifacts - see :cite:`Carriere17c`) for a
functional cover.
:rtype: double
@@ -288,7 +288,7 @@ cdef class CoverComplex:
def set_graph_from_automatic_rips(self, N=100):
"""Creates a graph G from a Rips complex whose threshold value is
- automatically tuned with subsampling—see.
+ automatically tuned with subsampling - see :cite:`Carriere17c`.
:param N: Number of subsampling iteration (the default reasonable value
is 100, but there is no guarantee on how to choose it).
diff --git a/src/python/gudhi/persistence_graphical_tools.py b/src/python/gudhi/persistence_graphical_tools.py
index 246280de..cc3db467 100644
--- a/src/python/gudhi/persistence_graphical_tools.py
+++ b/src/python/gudhi/persistence_graphical_tools.py
@@ -5,6 +5,7 @@
# Copyright (C) 2016 Inria
#
# Modification(s):
+# - 2020/02 Theo Lacombe: Added more options for improved rendering and more flexibility.
# - YYYY/MM Author: Description of the modification
from os import path
@@ -14,7 +15,7 @@ import numpy as np
from gudhi.reader_utils import read_persistence_intervals_in_dimension
from gudhi.reader_utils import read_persistence_intervals_grouped_by_dimension
-__author__ = "Vincent Rouvreau, Bertrand Michel"
+__author__ = "Vincent Rouvreau, Bertrand Michel, Theo Lacombe"
__copyright__ = "Copyright (C) 2016 Inria"
__license__ = "MIT"
@@ -43,6 +44,19 @@ def __min_birth_max_death(persistence, band=0.0):
max_death += band
return (min_birth, max_death)
+
+def _array_handler(a):
+ '''
+ :param a: if array, assumes it is a (n x 2) np.array and return a
+ persistence-compatible list (padding with 0), so that the
+ plot can be performed seamlessly.
+ '''
+ if isinstance(a[0][1], np.float64) or isinstance(a[0][1], float):
+ return [[0, x] for x in a]
+ else:
+ return a
+
+
def plot_persistence_barcode(
persistence=[],
persistence_file="",
@@ -52,13 +66,16 @@ def plot_persistence_barcode(
inf_delta=0.1,
legend=False,
colormap=None,
- axes=None
+ axes=None,
+ fontsize=16,
):
"""This function plots the persistence bar code from persistence values list
+ , a np.array of shape (N x 2) (representing a diagram
+ in a single homology dimension),
or from a :doc:`persistence file <fileformats>`.
- :param persistence: Persistence intervals values list grouped by dimension.
- :type persistence: list of tuples(dimension, tuple(birth, death)).
+ :param persistence: Persistence intervals values list. Can be grouped by dimension or not.
+ :type persistence: an array of (dimension, array of (birth, death)) or an array of (birth, death).
:param persistence_file: A :doc:`persistence file <fileformats>` style name
(reset persistence if both are set).
:type persistence_file: string
@@ -81,11 +98,19 @@ def plot_persistence_barcode(
:param axes: A matplotlib-like subplot axes. If None, the plot is drawn on
a new set of axes.
:type axes: `matplotlib.axes.Axes`
+ :param fontsize: Fontsize to use in axis.
+ :type fontsize: int
:returns: (`matplotlib.axes.Axes`): The axes on which the plot was drawn.
"""
try:
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
+ from matplotlib import rc
+ plt.rc('text', usetex=True)
+ plt.rc('font', family='serif')
+
+
+ persistence = _array_handler(persistence)
if persistence_file != "":
if path.isfile(persistence_file):
@@ -163,7 +188,7 @@ def plot_persistence_barcode(
loc="lower right",
)
- axes.set_title("Persistence barcode")
+ axes.set_title("Persistence barcode", fontsize=fontsize)
# Ends plot on infinity value and starts a little bit before min_birth
axes.axis([axis_start, infinity, 0, ind])
@@ -183,13 +208,16 @@ def plot_persistence_diagram(
inf_delta=0.1,
legend=False,
colormap=None,
- axes=None
+ axes=None,
+ fontsize=16,
+ greyblock=True
):
"""This function plots the persistence diagram from persistence values
- list or from a :doc:`persistence file <fileformats>`.
+ list, a np.array of shape (N x 2) representing a diagram in a single
+ homology dimension, or from a :doc:`persistence file <fileformats>`.
- :param persistence: Persistence intervals values list grouped by dimension.
- :type persistence: list of tuples(dimension, tuple(birth, death)).
+ :param persistence: Persistence intervals values list. Can be grouped by dimension or not.
+ :type persistence: an array of (dimension, array of (birth, death)) or an array of (birth, death).
:param persistence_file: A :doc:`persistence file <fileformats>` style name
(reset persistence if both are set).
:type persistence_file: string
@@ -214,11 +242,20 @@ def plot_persistence_diagram(
:param axes: A matplotlib-like subplot axes. If None, the plot is drawn on
a new set of axes.
:type axes: `matplotlib.axes.Axes`
+ :param fontsize: Fontsize to use in axis.
+ :type fontsize: int
+ :param greyblock: if we want to plot a grey patch on the lower half plane for nicer rendering. Default True.
+ :type greyblock: boolean
:returns: (`matplotlib.axes.Axes`): The axes on which the plot was drawn.
"""
try:
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
+ from matplotlib import rc
+ plt.rc('text', usetex=True)
+ plt.rc('font', family='serif')
+
+ persistence = _array_handler(persistence)
if persistence_file != "":
if path.isfile(persistence_file):
@@ -256,19 +293,18 @@ def plot_persistence_diagram(
# Replace infinity values with max_death + delta for diagram to be more
# readable
infinity = max_death + delta
+ axis_end = max_death + delta / 2
axis_start = min_birth - delta
- # line display of equation : birth = death
- x = np.linspace(axis_start, infinity, 1000)
- # infinity line and text
- axes.plot(x, x, color="k", linewidth=1.0)
- axes.plot(x, [infinity] * len(x), linewidth=1.0, color="k", alpha=alpha)
- axes.text(axis_start, infinity, r"$\infty$", color="k", alpha=alpha)
# bootstrap band
if band > 0.0:
+ x = np.linspace(axis_start, infinity, 1000)
axes.fill_between(x, x, x + band, alpha=alpha, facecolor="red")
-
+ # lower diag patch
+ if greyblock:
+ axes.add_patch(mpatches.Polygon([[axis_start, axis_start], [axis_end, axis_start], [axis_end, axis_end]], fill=True, color='lightgrey'))
# Draw points in loop
+ pts_at_infty = False # Records presence of pts at infty
for interval in reversed(persistence):
if float(interval[1][1]) != float("inf"):
# Finite death case
@@ -279,10 +315,23 @@ def plot_persistence_diagram(
color=colormap[interval[0]],
)
else:
+ pts_at_infty = True
# Infinite death case for diagram to be nicer
axes.scatter(
interval[1][0], infinity, alpha=alpha, color=colormap[interval[0]]
)
+ if pts_at_infty:
+ # infinity line and text
+ axes.plot([axis_start, axis_end], [axis_start, axis_end], linewidth=1.0, color="k")
+ axes.plot([axis_start, axis_end], [infinity, infinity], linewidth=1.0, color="k", alpha=alpha)
+ # Infinity label
+ yt = axes.get_yticks()
+ yt = yt[np.where(yt < axis_end)] # to avoid ploting ticklabel higher than infinity
+ yt = np.append(yt, infinity)
+ ytl = ["%.3f" % e for e in yt] # to avoid float precision error
+ ytl[-1] = r'$+\infty$'
+ axes.set_yticks(yt)
+ axes.set_yticklabels(ytl)
if legend:
dimensions = list(set(item[0] for item in persistence))
@@ -293,11 +342,11 @@ def plot_persistence_diagram(
]
)
- axes.set_xlabel("Birth")
- axes.set_ylabel("Death")
+ axes.set_xlabel("Birth", fontsize=fontsize)
+ axes.set_ylabel("Death", fontsize=fontsize)
+ axes.set_title("Persistence diagram", fontsize=fontsize)
# Ends plot on infinity value and starts a little bit before min_birth
- axes.axis([axis_start, infinity, axis_start, infinity + delta])
- axes.set_title("Persistence diagram")
+ axes.axis([axis_start, axis_end, axis_start, infinity + delta/2])
return axes
except ImportError:
@@ -313,16 +362,22 @@ def plot_persistence_density(
dimension=None,
cmap=None,
legend=False,
- axes=None
+ axes=None,
+ fontsize=16,
+ greyblock=False
):
"""This function plots the persistence density from persistence
- values list or from a :doc:`persistence file <fileformats>`. Be
+ values list, np.array of shape (N x 2) representing a diagram
+ in a single homology dimension,
+ or from a :doc:`persistence file <fileformats>`. Be
aware that this function does not distinguish the dimension, it is
up to you to select the required one. This function also does not handle
degenerate data set (scipy correlation matrix inversion can fail).
- :param persistence: Persistence intervals values list grouped by dimension.
- :type persistence: list of tuples(dimension, tuple(birth, death)).
+ :param persistence: Persistence intervals values list.
+ Can be grouped by dimension or not.
+ :type persistence: an array of (dimension, array of (birth, death))
+ or an array of (birth, death).
:param persistence_file: A :doc:`persistence file <fileformats>`
style name (reset persistence if both are set).
:type persistence_file: string
@@ -355,11 +410,22 @@ def plot_persistence_density(
:param axes: A matplotlib-like subplot axes. If None, the plot is drawn on
a new set of axes.
:type axes: `matplotlib.axes.Axes`
+ :param fontsize: Fontsize to use in axis.
+ :type fontsize: int
+ :param greyblock: if we want to plot a grey patch on the lower half plane
+ for nicer rendering. Default False.
+ :type greyblock: boolean
:returns: (`matplotlib.axes.Axes`): The axes on which the plot was drawn.
"""
try:
import matplotlib.pyplot as plt
+ import matplotlib.patches as mpatches
from scipy.stats import kde
+ from matplotlib import rc
+ plt.rc('text', usetex=True)
+ plt.rc('font', family='serif')
+
+ persistence = _array_handler(persistence)
if persistence_file != "":
if dimension is None:
@@ -418,12 +484,16 @@ def plot_persistence_density(
# Make the plot
img = axes.pcolormesh(xi, yi, zi.reshape(xi.shape), cmap=cmap)
+ if greyblock:
+ axes.add_patch(mpatches.Polygon([[birth.min(), birth.min()], [death.max(), birth.min()], [death.max(), death.max()]], fill=True, color='lightgrey'))
+
if legend:
plt.colorbar(img, ax=axes)
- axes.set_xlabel("Birth")
- axes.set_ylabel("Death")
- axes.set_title("Persistence density")
+ axes.set_xlabel("Birth", fontsize=fontsize)
+ axes.set_ylabel("Death", fontsize=fontsize)
+ axes.set_title("Persistence density", fontsize=fontsize)
+
return axes
except ImportError:
diff --git a/src/python/gudhi/wasserstein.py b/src/python/gudhi/wasserstein.py
index db5ddff2..13102094 100644
--- a/src/python/gudhi/wasserstein.py
+++ b/src/python/gudhi/wasserstein.py
@@ -27,8 +27,8 @@ def _build_dist_matrix(X, Y, order=2., internal_p=2.):
'''
:param X: (n x 2) numpy.array encoding the (points of the) first diagram.
:param Y: (m x 2) numpy.array encoding the second diagram.
- :param internal_p: Ground metric (i.e. norm l_p).
:param order: exponent for the Wasserstein metric.
+ :param internal_p: Ground metric (i.e. norm L^p).
:returns: (n+1) x (m+1) np.array encoding the cost matrix C.
For 1 <= i <= n, 1 <= j <= m, C[i,j] encodes the distance between X[i] and Y[j], while C[i, m+1] (resp. C[n+1, j]) encodes the distance (to the p) between X[i] (resp Y[j]) and its orthogonal proj onto the diagonal.
note also that C[n+1, m+1] = 0 (it costs nothing to move from the diagonal to the diagonal).
@@ -54,8 +54,8 @@ def _build_dist_matrix(X, Y, order=2., internal_p=2.):
def _perstot(X, order, internal_p):
'''
:param X: (n x 2) numpy.array (points of a given diagram).
- :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (Euclidean norm).
:param order: exponent for Wasserstein. Default value is 2.
+ :param internal_p: Ground metric on the (upper-half) plane (i.e. norm L^p in R^2); Default value is 2 (Euclidean norm).
:returns: float, the total persistence of the diagram (that is, its distance to the empty diagram).
'''
Xdiag = _proj_on_diag(X)
@@ -66,8 +66,8 @@ def wasserstein_distance(X, Y, order=2., internal_p=2.):
'''
:param X: (n x 2) numpy.array encoding the (finite points of the) first diagram. Must not contain essential points (i.e. with infinite coordinate).
:param Y: (m x 2) numpy.array encoding the second diagram.
- :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (euclidean norm).
:param order: exponent for Wasserstein; Default value is 2.
+ :param internal_p: Ground metric on the (upper-half) plane (i.e. norm L^p in R^2); Default value is 2 (Euclidean norm).
:returns: the Wasserstein distance of order q (1 <= q < infinity) between persistence diagrams with respect to the internal_p-norm as ground metric.
:rtype: float
'''
diff --git a/src/python/setup.py.in b/src/python/setup.py.in
index 9c2124f4..f968bd59 100644
--- a/src/python/setup.py.in
+++ b/src/python/setup.py.in
@@ -8,10 +8,11 @@
- YYYY/MM Author: Description of the modification
"""
-from setuptools import setup, Extension
+from setuptools import setup, Extension, find_packages
from Cython.Build import cythonize
from numpy import get_include as numpy_get_include
import sys
+import pybind11
__author__ = "Vincent Rouvreau"
__copyright__ = "Copyright (C) 2016 Inria"
@@ -42,14 +43,26 @@ for module in modules:
runtime_library_dirs=runtime_library_dirs,
cython_directives = {'language_level': str(sys.version_info[0])},))
+ext_modules = cythonize(ext_modules)
+
+ext_modules.append(Extension(
+ 'gudhi.hera',
+ sources = [source_dir + 'hera.cc'],
+ language = 'c++',
+ include_dirs = include_dirs +
+ ['@HERA_WASSERSTEIN_INCLUDE_DIR@',
+ pybind11.get_include(False), pybind11.get_include(True)],
+ extra_compile_args=extra_compile_args + [@GUDHI_PYBIND11_EXTRA_COMPILE_ARGS@],
+ ))
+
setup(
name = 'gudhi',
- packages=["gudhi",],
+ packages=find_packages(), # find_namespace_packages(include=["gudhi*"])
author='GUDHI Editorial Board',
author_email='gudhi-contact@lists.gforge.inria.fr',
version='@GUDHI_VERSION@',
url='http://gudhi.gforge.inria.fr/',
- ext_modules = cythonize(ext_modules),
+ ext_modules = ext_modules,
install_requires = ['cython','numpy >= 1.9',],
- setup_requires = ['numpy >= 1.9',],
+ setup_requires = ['numpy >= 1.9','pybind11',],
)
diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py
index 43dda77e..6a6b217b 100755
--- a/src/python/test/test_wasserstein_distance.py
+++ b/src/python/test/test_wasserstein_distance.py
@@ -1,6 +1,6 @@
""" This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
- Author(s): Theo Lacombe
+ Author(s): Theo Lacombe, Marc Glisse
Copyright (C) 2019 Inria
@@ -8,41 +8,66 @@
- YYYY/MM Author: Description of the modification
"""
-from gudhi.wasserstein import wasserstein_distance
+from gudhi.wasserstein import wasserstein_distance as pot
+from gudhi.hera import wasserstein_distance as hera
import numpy as np
+import pytest
__author__ = "Theo Lacombe"
__copyright__ = "Copyright (C) 2019 Inria"
__license__ = "MIT"
-
-def test_basic_wasserstein():
+def _basic_wasserstein(wasserstein_distance, delta, test_infinity=True):
diag1 = np.array([[2.7, 3.7], [9.6, 14.0], [34.2, 34.974]])
diag2 = np.array([[2.8, 4.45], [9.5, 14.1]])
diag3 = np.array([[0, 2], [4, 6]])
diag4 = np.array([[0, 3], [4, 8]])
- emptydiag = np.array([[]])
+ emptydiag = np.array([])
+
+ # We just need to handle positive numbers here
+ def approx(x):
+ return pytest.approx(x, rel=delta)
assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., order=1.) == 0.
assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, order=1.) == 0.
assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, order=2.) == 0.
assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., order=2.) == 0.
- assert wasserstein_distance(diag3, emptydiag, internal_p=np.inf, order=1.) == 2.
- assert wasserstein_distance(diag3, emptydiag, internal_p=1., order=1.) == 4.
+ assert wasserstein_distance(diag3, emptydiag, internal_p=np.inf, order=1.) == approx(2.)
+ assert wasserstein_distance(diag3, emptydiag, internal_p=1., order=1.) == approx(4.)
+
+ assert wasserstein_distance(diag4, emptydiag, internal_p=1., order=2.) == approx(5.) # thank you Pythagorician triplets
+ assert wasserstein_distance(diag4, emptydiag, internal_p=np.inf, order=2.) == approx(2.5)
+ assert wasserstein_distance(diag4, emptydiag, internal_p=2., order=2.) == approx(3.5355339059327378)
+
+ assert wasserstein_distance(diag1, diag2, internal_p=2., order=1.) == approx(1.4453593023967701)
+ assert wasserstein_distance(diag1, diag2, internal_p=2.35, order=1.74) == approx(0.9772734057168739)
+
+ assert wasserstein_distance(diag1, emptydiag, internal_p=2.35, order=1.7863) == approx(3.141592214572228)
+
+ assert wasserstein_distance(diag3, diag4, internal_p=1., order=1.) == approx(3.)
+ assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=1.) == approx(3.) # no diag matching here
+ assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=2.) == approx(np.sqrt(5))
+ assert wasserstein_distance(diag3, diag4, internal_p=1., order=2.) == approx(np.sqrt(5))
+ assert wasserstein_distance(diag3, diag4, internal_p=4.5, order=2.) == approx(np.sqrt(5))
+
+ if(not test_infinity):
+ return
- assert wasserstein_distance(diag4, emptydiag, internal_p=1., order=2.) == 5. # thank you Pythagorician triplets
- assert wasserstein_distance(diag4, emptydiag, internal_p=np.inf, order=2.) == 2.5
- assert wasserstein_distance(diag4, emptydiag, internal_p=2., order=2.) == 3.5355339059327378
+ diag5 = np.array([[0, 3], [4, np.inf]])
+ diag6 = np.array([[7, 8], [4, 6], [3, np.inf]])
- assert wasserstein_distance(diag1, diag2, internal_p=2., order=1.) == 1.4453593023967701
- assert wasserstein_distance(diag1, diag2, internal_p=2.35, order=1.74) == 0.9772734057168739
+ assert wasserstein_distance(diag4, diag5) == np.inf
+ assert wasserstein_distance(diag5, diag6, order=1, internal_p=np.inf) == approx(4.)
- assert wasserstein_distance(diag1, emptydiag, internal_p=2.35, order=1.7863) == 3.141592214572228
+def hera_wrap(delta):
+ def fun(*kargs,**kwargs):
+ return hera(*kargs,**kwargs,delta=delta)
+ return fun
- assert wasserstein_distance(diag3, diag4, internal_p=1., order=1.) == 3.
- assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=1.) == 3. # no diag matching here
- assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=2.) == np.sqrt(5)
- assert wasserstein_distance(diag3, diag4, internal_p=1., order=2.) == np.sqrt(5)
- assert wasserstein_distance(diag3, diag4, internal_p=4.5, order=2.) == np.sqrt(5)
+def test_wasserstein_distance_pot():
+ _basic_wasserstein(pot, 1e-15, test_infinity=False)
+def test_wasserstein_distance_hera():
+ _basic_wasserstein(hera_wrap(1e-12), 1e-12)
+ _basic_wasserstein(hera_wrap(.1), .1)