From f5c97bc9fd1c247045d35ddf261f9afe4d024406 Mon Sep 17 00:00:00 2001 From: glisse Date: Fri, 20 Jul 2018 15:03:46 +0000 Subject: First try at interfacing the sparse rips in python. Needs at least documentation and tests. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3697 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 75bef59e90355853ee24807ca7453c4bb0a38f43 --- src/cython/cython/rips_complex.pyx | 50 +++++++++++++++++------------ src/cython/include/Rips_complex_interface.h | 39 ++++++++++++++-------- src/cython/test/test_rips_complex.py | 1 - 3 files changed, 55 insertions(+), 35 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx index 59c16bff..620130ca 100644 --- a/src/cython/cython/rips_complex.pyx +++ b/src/cython/cython/rips_complex.pyx @@ -33,7 +33,11 @@ __license__ = "GPL v3" cdef extern from "Rips_complex_interface.h" namespace "Gudhi": cdef cppclass Rips_complex_interface "Gudhi::rips_complex::Rips_complex_interface": - Rips_complex_interface(vector[vector[double]] values, double threshold, bool euclidean) + Rips_complex_interface() + void init_points(vector[vector[double]] values, double threshold) + void init_matrix(vector[vector[double]] values, double threshold) + void init_points_sparse(vector[vector[double]] values, double threshold, double sparse) + void init_matrix_sparse(vector[vector[double]] values, double threshold, double sparse) void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, int dim_max) # RipsComplex python interface @@ -44,14 +48,14 @@ cdef class RipsComplex: function, or a distance matrix. """ - cdef Rips_complex_interface * thisptr + cdef Rips_complex_interface thisref # Fake constructor that does nothing but documenting the constructor - def __init__(self, points=None, distance_matrix=None, max_edge_length=float('inf')): + def __init__(self, points=None, distance_matrix=None, max_edge_length=float('inf'), sparse=None): """RipsComplex constructor. :param max_edge_length: Rips value. - :type max_edge_length: int + :type max_edge_length: float :param points: A list of points in d-Dimension. :type points: list of list of double @@ -61,27 +65,31 @@ cdef class RipsComplex: :param distance_matrix: A distance matrix (full square or lower triangular). :type points: list of list of double + + And in both cases + :param sparse: If this is not None, it switches to building a sparse Rips and represents the approximation parameter epsilon. + :type sparse: float """ # The real cython constructor - def __cinit__(self, points=None, distance_matrix=None, max_edge_length=float('inf')): - if distance_matrix is not None: - self.thisptr = new Rips_complex_interface(distance_matrix, max_edge_length, False) + def __cinit__(self, points=None, distance_matrix=None, max_edge_length=float('inf'), sparse=None): + if sparse is not None: + if distance_matrix is not None: + self.thisref.init_matrix_sparse(distance_matrix, max_edge_length, sparse) + else: + if points is None: + # Empty Rips construction + points=[] + self.thisref.init_points_sparse(points, max_edge_length, sparse) else: - if points is None: - # Empty Rips construction - points=[] - self.thisptr = new Rips_complex_interface(points, max_edge_length, True) - - - def __dealloc__(self): - if self.thisptr != NULL: - del self.thisptr + if distance_matrix is not None: + self.thisref.init_matrix(distance_matrix, max_edge_length) + else: + if points is None: + # Empty Rips construction + points=[] + self.thisref.init_points(points, max_edge_length) - def __is_defined(self): - """Returns true if RipsComplex pointer is not NULL. - """ - return self.thisptr != NULL def create_simplex_tree(self, max_dimension=1): """ @@ -92,5 +100,5 @@ cdef class RipsComplex: :rtype: SimplexTree """ simplex_tree = SimplexTree() - self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_dimension) + self.thisref.create_simplex_tree(simplex_tree.thisptr, max_dimension) return simplex_tree diff --git a/src/cython/include/Rips_complex_interface.h b/src/cython/include/Rips_complex_interface.h index 8b6c9c35..f6fc79a1 100644 --- a/src/cython/include/Rips_complex_interface.h +++ b/src/cython/include/Rips_complex_interface.h @@ -25,8 +25,11 @@ #include #include +#include #include +#include + #include "Simplex_tree_interface.h" #include @@ -43,28 +46,38 @@ class Rips_complex_interface { using Distance_matrix = std::vector::Filtration_value>>; public: - Rips_complex_interface(const std::vector>& values, double threshold, bool euclidean) { - if (euclidean) { - // Rips construction where values is a vector of points - rips_complex_ = new Rips_complex::Filtration_value>(values, threshold, - Gudhi::Euclidean_distance()); - } else { - // Rips construction where values is a distance matrix - rips_complex_ = new Rips_complex::Filtration_value>(values, threshold); - } + void init_points(const std::vector>& points, double threshold) { + rips_complex_.emplace(points, threshold, Gudhi::Euclidean_distance()); + } + void init_matrix(const std::vector>& matrix, double threshold) { + rips_complex_.emplace(matrix, threshold); } - ~Rips_complex_interface() { - delete rips_complex_; + void init_points_sparse(const std::vector>& points, double threshold, double epsilon) { + sparse_rips_complex_.emplace(points, Gudhi::Euclidean_distance(), epsilon); + threshold_ = threshold; + } + void init_matrix_sparse(const std::vector>& matrix, double threshold, double epsilon) { + sparse_rips_complex_.emplace(matrix, epsilon); + threshold_ = threshold; } void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, int dim_max) { - rips_complex_->create_complex(*simplex_tree, dim_max); + if (rips_complex_) + rips_complex_->create_complex(*simplex_tree, dim_max); + else { + sparse_rips_complex_->create_complex(*simplex_tree, dim_max); + // This pruning should be done much earlier! It isn't that useful for sparse Rips, but it would be inconsistent not to do it. + simplex_tree->prune_above_filtration(threshold_); + } simplex_tree->initialize_filtration(); } private: - Rips_complex::Filtration_value>* rips_complex_; + // std::variant would work, but we don't require C++17 yet, and boost::variant is not super convenient. Anyway, storing a graph would make more sense. Or changing the interface completely so there is no such storage. + boost::optional::Filtration_value>> rips_complex_; + boost::optional::Filtration_value>> sparse_rips_complex_; + double threshold_; }; } // namespace rips_complex diff --git a/src/cython/test/test_rips_complex.py b/src/cython/test/test_rips_complex.py index c37b5400..2eb1c61c 100755 --- a/src/cython/test/test_rips_complex.py +++ b/src/cython/test/test_rips_complex.py @@ -30,7 +30,6 @@ __license__ = "GPL v3" def test_empty_rips(): rips_complex = RipsComplex() - assert rips_complex.__is_defined() == True def test_rips_from_points(): point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] -- cgit v1.2.3 From 629a456684e9bbf4c2ef5dbfefebe85e9c04a39d Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 10 Sep 2018 09:23:07 +0000 Subject: Add minimal testing for sparse rips in python git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3879 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 14cde17f1ef634539937b215e82bcfe3c8c784f0 --- src/cython/test/test_rips_complex.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/cython') diff --git a/src/cython/test/test_rips_complex.py b/src/cython/test/test_rips_complex.py index 2eb1c61c..73cdac17 100755 --- a/src/cython/test/test_rips_complex.py +++ b/src/cython/test/test_rips_complex.py @@ -67,6 +67,18 @@ def test_filtered_rips_from_points(): assert simplex_tree.num_simplices() == 8 assert simplex_tree.num_vertices() == 4 +def test_sparse_filtered_rips_from_points(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + filtered_rips = RipsComplex(points=point_list, max_edge_length=1.0, sparse=.001) + + simplex_tree = filtered_rips.create_simplex_tree(max_dimension=1) + + assert simplex_tree.__is_defined() == True + assert simplex_tree.__is_persistence_defined() == False + + assert simplex_tree.num_simplices() == 8 + assert simplex_tree.num_vertices() == 4 + def test_rips_from_distance_matrix(): distance_matrix = [[0], [1, 0], -- cgit v1.2.3 From 4bf56301ea1aa0c43855bea88344c80db237adbb Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 10 Sep 2018 09:29:57 +0000 Subject: sparse rips example git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3880 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8dfc1b3218d3ac3e97a04bf25e59e2d48fc8db1d --- .../example/sparse_rips_persistence_diagram.py | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100755 src/cython/example/sparse_rips_persistence_diagram.py (limited to 'src/cython') diff --git a/src/cython/example/sparse_rips_persistence_diagram.py b/src/cython/example/sparse_rips_persistence_diagram.py new file mode 100755 index 00000000..3bed87c1 --- /dev/null +++ b/src/cython/example/sparse_rips_persistence_diagram.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): Marc Glisse + + Copyright (C) 2016 Inria + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +""" + +__author__ = "Marc Glisse" +__copyright__ = "Copyright (C) 2016 Inria" +__license__ = "GPL v3" + +print("#####################################################################") +print("RipsComplex creation from points") +rips = gudhi.RipsComplex(points=[[0, 0], [0, 0.1], [1, 0], [0, 1], [1, 1]], + max_edge_length=42, sparse=.5) + +simplex_tree = rips.create_simplex_tree(max_dimension=2) + + +diag = simplex_tree.persistence(homology_coeff_field=2, min_persistence=0) +print("diag=", diag) + +pplot = gudhi.plot_persistence_diagram(diag) +pplot.show() -- cgit v1.2.3 From 42e599ebd89231c276a3c6e1b9121ea13f25d118 Mon Sep 17 00:00:00 2001 From: glisse Date: Tue, 2 Oct 2018 09:21:13 +0000 Subject: More doc changes for python sparse rips git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3921 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f9a33e3c4a6fc6d68a81b753a88ff9d39bdcfb9f --- biblio/bibliography.bib | 3 +- src/Rips_complex/doc/Intro_rips_complex.h | 2 +- src/cython/cython/rips_complex.pyx | 3 +- src/cython/doc/rips_complex_user.rst | 52 ++++++++++++++++++++----------- 4 files changed, 38 insertions(+), 22 deletions(-) (limited to 'src/cython') diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index 16f43d6f..e85876d3 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -1073,9 +1073,10 @@ language={English} @article{buchet16efficient, title = {Efficient and Robust Persistent Homology for Measures}, author = {Micka\"{e}l Buchet and Fr\'{e}d\'{e}ric Chazal and Steve Y. Oudot and Donald Sheehy}, - booktitle = {Computational Geometry: Theory and Applications}, + journal = {Computational Geometry: Theory and Applications}, volume = {58}, pages = {70--96}, + doi = "https://doi.org/10.1016/j.comgeo.2016.07.001", year = {2016} } diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 3db5287e..e54ae57c 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -39,7 +39,7 @@ namespace rips_complex { * (Wikipedia) * is an abstract simplicial complex * defined on a finite metric space, where each simplex corresponds to a subset - * of point whose diameter is smaller that some given threshold. + * of points whose diameter is smaller that some given threshold. * Varying the threshold, we can also see the Rips complex as a filtration of * the \f$(n-1)-\f$dimensional simplex, where the filtration value of each * simplex is the diameter of the corresponding subset of points. diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx index 620130ca..ecf039b6 100644 --- a/src/cython/cython/rips_complex.pyx +++ b/src/cython/cython/rips_complex.pyx @@ -62,8 +62,7 @@ cdef class RipsComplex: Or - :param distance_matrix: A distance matrix (full square or lower - triangular). + :param distance_matrix: A distance matrix (full square or lower triangular). :type points: list of list of double And in both cases diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index a8c06cf9..9fa3a677 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -7,27 +7,22 @@ Rips complex user manual Definition ---------- -======================================================= ===================================== ===================================== -:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 -======================================================= ===================================== ===================================== +==================================================================== ================================ ====================== +:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +==================================================================== ================================ ====================== +-------------------------------------------+----------------------------------------------------------------------+ | :doc:`rips_complex_user` | :doc:`rips_complex_ref` | +-------------------------------------------+----------------------------------------------------------------------+ -`Rips complex `_ is a one skeleton graph that allows to -construct a simplicial complex from it. The input can be a point cloud with a given distance function, or a distance -matrix. +The `Rips complex `_ is a simplicial complex defined as the clique complex of a graph. The graph is defined on a set of points with one vertex for each point and an edge between any 2 points, of weight (aka filtration value) the distance between the 2 points. This graph (and thus the complex) can be restricted to edges shorter than some threshold, to reduce its size. -The filtration value of each edge is computed from a user-given distance function, or directly from the distance -matrix. +The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix. -All edges that have a filtration value strictly greater than a given threshold value are not inserted into the complex. +When creating a simplicial complex from the graph, `RipsComplex` inserts the graph into the data +structure, and then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. -When creating a simplicial complex from this one skeleton graph, Rips inserts the one skeleton graph into the data -structure, and then expands the simplicial complex when required. - -Vertex name correspond to the index of the point in the given range (aka. the point cloud). +A vertex name corresponds to the index of the point in the given range (aka. the point cloud). .. figure:: ../../doc/Rips_complex/rips_complex_representation.png @@ -38,8 +33,27 @@ Vertex name correspond to the index of the point in the given range (aka. the po On this example, as edges (4,5), (4,6) and (5,6) are in the complex, simplex (4,5,6) is added with the filtration value set with :math:`max(filtration(4,5), filtration(4,6), filtration(5,6))`. And so on for simplex (0,1,2,3). -If the Rips_complex interfaces are not detailed enough for your need, please refer to rips_persistence_step_by_step.cpp -example, where the graph construction over the Simplex_tree is more detailed. +If the `RipsComplex` interfaces are not detailed enough for your need, please refer to rips_persistence_step_by_step.cpp +C++ example, where the graph construction over the Simplex_tree is more detailed. + +A Rips complex can easily become huge, even if we limit the length of the edges +and the dimension of the simplices. One easy trick, before building a Rips +complex on a point cloud, is to call `sparsify_point_set` which removes points +that are too close to each other. This does not change its persistence diagram +by more than the length used to define "too close". + +A more general technique is to use a sparse approximation of the Rips +introduced by Don Sheehy :cite:`sheehy13linear`. We are using the version +described in :cite:`buchet16efficient` (except that we multiply all filtration +values by 2, to match the usual Rips complex), which proves a +:math:`\frac{1+\epsilon}{1-\epsilon}`-interleaving, although in practice the +error is usually smaller. A more intuitive presentation of the idea is +available in :cite:`cavanna15geometric`, and in a video +:cite:`cavanna15visualizing`. Passing an extra argument `sparse=0.3` at the +construction of a `RipsComplex` object asks it to build a sparse Rips with +parameter `ε=0.3`, while the default `sparse=None` builds the +regular Rips complex. + Point cloud ----------- @@ -47,7 +61,7 @@ Point cloud Example from a point cloud ^^^^^^^^^^^^^^^^^^^^^^^^^^ -This example builds the one skeleton graph from the given points, and max_edge_length value. +This example builds the neighborhood graph from the given points, up to max_edge_length. Then it creates a :doc:`Simplex_tree ` with it. Finally, it is asked to display information about the simplicial complex. @@ -92,10 +106,12 @@ until dimension 1 - one skeleton graph in other words), the output is: [4, 6] -> 9.49 [3, 6] -> 11.00 +Notice that if we use `rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], max_edge_length=12.0, sparse=2)`, asking for very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), 2 to 5 edges disappear, depending on the random vertex used to start the sparsification. + Example from OFF file ^^^^^^^^^^^^^^^^^^^^^ -This example builds the :doc:`Rips_complex ` from the given +This example builds the :doc:`RipsComplex ` from the given points in an OFF file, and max_edge_length value. Then it creates a :doc:`Simplex_tree ` with it. @@ -200,7 +216,7 @@ until dimension 1 - one skeleton graph in other words), the output is: Example from csv file ^^^^^^^^^^^^^^^^^^^^^ -This example builds the :doc:`Rips_complex ` from the given +This example builds the :doc:`RipsComplex ` from the given distance matrix in a csv file, and max_edge_length value. Then it creates a :doc:`Simplex_tree ` with it. -- cgit v1.2.3 From 0567f550258966a12911cd3ffe490852c022c358 Mon Sep 17 00:00:00 2001 From: glisse Date: Sat, 6 Oct 2018 14:01:16 +0000 Subject: Doc tweaks. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3936 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 3c75c674876bcb38d0a87de41d406832baf61b55 --- biblio/bibliography.bib | 2 ++ src/cython/cython/rips_complex.pyx | 1 + src/cython/doc/rips_complex_user.rst | 5 ++--- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index e85876d3..a8c040ed 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -1084,6 +1084,7 @@ language={English} author = {Nicholas J. Cavanna and Mahmoodreza Jahanseir and Donald R. Sheehy}, booktitle = {Proceedings of the Canadian Conference on Computational Geometry}, title = {A Geometric Perspective on Sparse Filtrations}, + url = {http://research.cs.queensu.ca/cccg2015/CCCG15-papers/01.pdf}, year = {2015} } @@ -1102,5 +1103,6 @@ language={English} volume = {49}, number = {4}, pages = {778--796}, + doi = "10.1007/s00454-013-9513-1", year = {2013} } diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx index ecf039b6..cb9aad2e 100644 --- a/src/cython/cython/rips_complex.pyx +++ b/src/cython/cython/rips_complex.pyx @@ -66,6 +66,7 @@ cdef class RipsComplex: :type points: list of list of double And in both cases + :param sparse: If this is not None, it switches to building a sparse Rips and represents the approximation parameter epsilon. :type sparse: float """ diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index 9fa3a677..95bb40b6 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -15,12 +15,11 @@ Definition | :doc:`rips_complex_user` | :doc:`rips_complex_ref` | +-------------------------------------------+----------------------------------------------------------------------+ -The `Rips complex `_ is a simplicial complex defined as the clique complex of a graph. The graph is defined on a set of points with one vertex for each point and an edge between any 2 points, of weight (aka filtration value) the distance between the 2 points. This graph (and thus the complex) can be restricted to edges shorter than some threshold, to reduce its size. +The `Rips complex `_ is a simplicial complex that generalizes proximity (ε-ball) graphs to higher dimensions. The vertices correspond to the input points, and a simplex is present if and only if its diameter is smaller than some parameter α. Considering all parameters α defines a filtered simplicial complex, where the filtration value of a simplex is its diameter. The filtration can be restricted to values α smaller than some threshold, to reduce its size. The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix. -When creating a simplicial complex from the graph, `RipsComplex` inserts the graph into the data -structure, and then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. +When creating a simplicial complex from the graph, `RipsComplex` first builds the graph and inserts it into the data structure. It then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. A vertex name corresponds to the index of the point in the given range (aka. the point cloud). -- cgit v1.2.3 From c537a466ffdd812d92098bcea04cdf6f0bfc64ec Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 21:17:19 +0000 Subject: Example text and copyright year git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3937 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6d5bf6a2c55f7c4fd4f3f5159651b3ffa057ffdd --- src/cython/example/sparse_rips_persistence_diagram.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/example/sparse_rips_persistence_diagram.py b/src/cython/example/sparse_rips_persistence_diagram.py index 3bed87c1..d58c244c 100755 --- a/src/cython/example/sparse_rips_persistence_diagram.py +++ b/src/cython/example/sparse_rips_persistence_diagram.py @@ -8,7 +8,7 @@ import gudhi Author(s): Marc Glisse - Copyright (C) 2016 Inria + Copyright (C) 2018 Inria This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,11 +25,11 @@ import gudhi """ __author__ = "Marc Glisse" -__copyright__ = "Copyright (C) 2016 Inria" +__copyright__ = "Copyright (C) 2018 Inria" __license__ = "GPL v3" print("#####################################################################") -print("RipsComplex creation from points") +print("Sparse RipsComplex creation from points") rips = gudhi.RipsComplex(points=[[0, 0], [0, 0.1], [1, 0], [0, 1], [1, 1]], max_edge_length=42, sparse=.5) -- cgit v1.2.3 From d16910a5c74552b3b1feffc3e793ec5b6d52f952 Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 21:43:35 +0000 Subject: Use math instead of unicode for epsilon git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3938 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8cccce774b7406d90a55d0e2827fad6dc3855b39 --- src/cython/doc/rips_complex_user.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index 95bb40b6..cddf4f16 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -45,7 +45,7 @@ A more general technique is to use a sparse approximation of the Rips introduced by Don Sheehy :cite:`sheehy13linear`. We are using the version described in :cite:`buchet16efficient` (except that we multiply all filtration values by 2, to match the usual Rips complex), which proves a -:math:`\frac{1+\epsilon}{1-\epsilon}`-interleaving, although in practice the +:math:`\frac{1+\varepsilon}{1-\varepsilon}`-interleaving, although in practice the error is usually smaller. A more intuitive presentation of the idea is available in :cite:`cavanna15geometric`, and in a video :cite:`cavanna15visualizing`. Passing an extra argument `sparse=0.3` at the -- cgit v1.2.3 From b6f3903f0ce07fe243ea7a3c18098043114f7f6a Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 21:52:27 +0000 Subject: epsilon + code block git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3939 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6a88d96a67d9d02f95e63fd627c295abebb49ce8 --- src/cython/doc/rips_complex_user.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index cddf4f16..933643e2 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -15,7 +15,7 @@ Definition | :doc:`rips_complex_user` | :doc:`rips_complex_ref` | +-------------------------------------------+----------------------------------------------------------------------+ -The `Rips complex `_ is a simplicial complex that generalizes proximity (ε-ball) graphs to higher dimensions. The vertices correspond to the input points, and a simplex is present if and only if its diameter is smaller than some parameter α. Considering all parameters α defines a filtered simplicial complex, where the filtration value of a simplex is its diameter. The filtration can be restricted to values α smaller than some threshold, to reduce its size. +The `Rips complex `_ is a simplicial complex that generalizes proximity (:math:`\varepsilon`-ball) graphs to higher dimensions. The vertices correspond to the input points, and a simplex is present if and only if its diameter is smaller than some parameter α. Considering all parameters α defines a filtered simplicial complex, where the filtration value of a simplex is its diameter. The filtration can be restricted to values α smaller than some threshold, to reduce its size. The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix. @@ -50,7 +50,7 @@ error is usually smaller. A more intuitive presentation of the idea is available in :cite:`cavanna15geometric`, and in a video :cite:`cavanna15visualizing`. Passing an extra argument `sparse=0.3` at the construction of a `RipsComplex` object asks it to build a sparse Rips with -parameter `ε=0.3`, while the default `sparse=None` builds the +parameter :math:`\varepsilon=0.3`, while the default `sparse=None` builds the regular Rips complex. @@ -105,7 +105,13 @@ until dimension 1 - one skeleton graph in other words), the output is: [4, 6] -> 9.49 [3, 6] -> 11.00 -Notice that if we use `rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], max_edge_length=12.0, sparse=2)`, asking for very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), 2 to 5 edges disappear, depending on the random vertex used to start the sparsification. +Notice that if we use + +.. code-block:: python + + rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], max_edge_length=12.0, sparse=2) + +asking for a very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), 2 to 5 edges disappear, depending on the random vertex used to start the sparsification. Example from OFF file ^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From e9d843d0a5c48315c45e8639e8bf9b79ccf904af Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 21:55:26 +0000 Subject: add example to the list of examples git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3940 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fe3c41785e3bb72766f7a817851583f82b9f7d15 --- src/cython/doc/examples.rst | 1 + 1 file changed, 1 insertion(+) (limited to 'src/cython') diff --git a/src/cython/doc/examples.rst b/src/cython/doc/examples.rst index 1f02f8a2..edbc2f72 100644 --- a/src/cython/doc/examples.rst +++ b/src/cython/doc/examples.rst @@ -22,6 +22,7 @@ Examples * :download:`rips_complex_diagram_persistence_from_off_file_example.py <../example/rips_complex_diagram_persistence_from_off_file_example.py>` * :download:`rips_complex_diagram_persistence_from_distance_matrix_file_example.py <../example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py>` * :download:`rips_persistence_diagram.py <../example/rips_persistence_diagram.py>` + * :download:`sparse_rips_persistence_diagram.py <../example/sparse_rips_persistence_diagram.py>` * :download:`random_cubical_complex_persistence_example.py <../example/random_cubical_complex_persistence_example.py>` * :download:`coordinate_graph_induced_complex.py <../example/coordinate_graph_induced_complex.py>` * :download:`functional_graph_induced_complex.py <../example/functional_graph_induced_complex.py>` -- cgit v1.2.3 From 665ba1dfe82b663ed755267b74c62706ec6eb88a Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 22:04:13 +0000 Subject: add myself as coauthor git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3941 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 61cf8acdce3bc5cb0c8261166e195eccc3f8bb54 --- src/cython/doc/rips_complex_sum.inc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_sum.inc b/src/cython/doc/rips_complex_sum.inc index 5616bfa9..ea26769a 100644 --- a/src/cython/doc/rips_complex_sum.inc +++ b/src/cython/doc/rips_complex_sum.inc @@ -1,6 +1,6 @@ -================================================================= =================================== =================================== -:Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 -================================================================= =================================== =================================== +===================================================================== =========================== =================================== +:Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +===================================================================== =========================== =================================== +----------------------------------------------------------------+------------------------------------------------------------------------+ | .. figure:: | Rips complex is a simplicial complex constructed from a one skeleton | -- cgit v1.2.3 From 354da3ae06ffa2479d56e9ea45cefbe218da2c76 Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 10 Oct 2018 22:11:23 +0000 Subject: Make RipsComplex a clickable link git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3942 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 642ae449f85cf8516fc632716ea14b22f74ec517 --- src/cython/doc/rips_complex_user.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index 933643e2..e0c71cd1 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -19,7 +19,7 @@ The `Rips complex ` The input discrete metric space can be provided as a point cloud plus a distance function, or as a distance matrix. -When creating a simplicial complex from the graph, `RipsComplex` first builds the graph and inserts it into the data structure. It then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. +When creating a simplicial complex from the graph, :doc:`RipsComplex ` first builds the graph and inserts it into the data structure. It then expands the simplicial complex (adds the simplices corresponding to cliques) when required. The expansion can be stopped at dimension `max_dimension`, by default 1. A vertex name corresponds to the index of the point in the given range (aka. the point cloud). -- cgit v1.2.3 From 07c214f675595b75a2a9d1f8dc2888487aa6086a Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 17 Oct 2018 08:11:14 +0000 Subject: Some indentation fix git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-python@3960 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6dce53b98bc0b299a3621602f385b3b44e16d489 --- src/cython/doc/rips_complex_user.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst index e0c71cd1..0aeffe55 100644 --- a/src/cython/doc/rips_complex_user.rst +++ b/src/cython/doc/rips_complex_user.rst @@ -69,7 +69,7 @@ Finally, it is asked to display information about the simplicial complex. import gudhi rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], - max_edge_length=12.0) + max_edge_length=12.0) simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) result_str = 'Rips complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ @@ -109,9 +109,11 @@ Notice that if we use .. code-block:: python - rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], max_edge_length=12.0, sparse=2) + rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], + max_edge_length=12.0, sparse=2) -asking for a very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), 2 to 5 edges disappear, depending on the random vertex used to start the sparsification. +asking for a very sparse version (theory only gives some guarantee on the meaning of the output if `sparse<1`), +2 to 5 edges disappear, depending on the random vertex used to start the sparsification. Example from OFF file ^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From 4f07edab3e86ffe9f0bcd8c055592dff22fab2ce Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 18 Oct 2018 19:30:14 +0000 Subject: Add persistence_dim_max argument in simplex tree persistence documentation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@3963 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ef8f3b0c2b0e3cdbda73687f1e65877213918830 --- src/cython/cython/simplex_tree.pyx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/cython') diff --git a/src/cython/cython/simplex_tree.pyx b/src/cython/cython/simplex_tree.pyx index 8397d9d9..0ab97f80 100644 --- a/src/cython/cython/simplex_tree.pyx +++ b/src/cython/cython/simplex_tree.pyx @@ -44,8 +44,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": void set_dimension(int dimension) int dimension() int upper_bound_dimension() - bint find_simplex(vector[int] simplex) - bint insert_simplex_and_subfaces(vector[int] simplex, + bool find_simplex(vector[int] simplex) + bool insert_simplex_and_subfaces(vector[int] simplex, double filtration) vector[pair[vector[int], double]] get_filtration() vector[pair[vector[int], double]] get_skeleton(int dimension) @@ -355,7 +355,7 @@ cdef class SimplexTree: :param filtration: Maximum threshold value. :type filtration: float. :returns: The filtration modification information. - :rtype: bint + :rtype: bool .. note:: @@ -406,7 +406,7 @@ cdef class SimplexTree: value than its faces by increasing the filtration values. :returns: The filtration modification information. - :rtype: bint + :rtype: bool .. note:: @@ -432,6 +432,10 @@ cdef class SimplexTree: 0.0. Sets min_persistence to -1.0 to see all values. :type min_persistence: float. + :param persistence_dim_max: If true, the persistent homology for the + maximal dimension in the complex is computed. If false, it is + ignored. Default is false. + :type persistence_dim_max: bool :returns: The persistence of the simplicial complex. :rtype: list of pairs(dimension, pair(birth, death)) """ -- cgit v1.2.3 From e8401b6fd2f9ff533824a6773f592b448d0863ed Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Wed, 31 Oct 2018 11:48:04 +0000 Subject: Make dependency with boost 1.56 instead of 1.48 git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/boost_1.56_vincent@3967 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: a5941b8c4f65ec8e6f62117aceb5f22e0142f255 --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 +- src/common/doc/installation.h | 2 +- src/cython/doc/installation.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/cython') diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index b020ebfc..cde3725c 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -1,6 +1,6 @@ # This files manage third party libraries required by GUDHI -find_package(Boost 1.48.0 REQUIRED COMPONENTS system filesystem unit_test_framework program_options thread) +find_package(Boost 1.56.0 REQUIRED COMPONENTS system filesystem unit_test_framework program_options thread) if(NOT Boost_FOUND) message(FATAL_ERROR "NOTICE: This program requires Boost and will not be compiled.") diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index df7eed37..bf2d0a87 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -5,7 +5,7 @@ * Examples of GUDHI headers inclusion can be found in \ref utilities. * * \section compiling Compiling - * The library uses c++11 and requires Boost ≥ 1.48.0 + * The library uses c++11 and requires Boost ≥ 1.56.0 * and CMake ≥ 3.1. * It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015. * diff --git a/src/cython/doc/installation.rst b/src/cython/doc/installation.rst index ef2f7af2..040f6b4a 100644 --- a/src/cython/doc/installation.rst +++ b/src/cython/doc/installation.rst @@ -7,7 +7,7 @@ Installation Compiling ********* -The library uses c++11 and requires `Boost `_ ≥ 1.48.0 +The library uses c++11 and requires `Boost `_ ≥ 1.56.0 and `CMake `_ ≥ 3.1. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015. -- cgit v1.2.3 From e105da964b96218459c8822816de36273f6cdf17 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 17 Dec 2018 20:57:42 +0000 Subject: Merge tangential-miro branch Add reference to cubical in persistence module git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@4038 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 832343cd6e2357c9e229d5b34f6de03e50d2da67 --- .../include/gudhi/Tangential_complex.h | 57 ++++++++++++++-------- src/cython/doc/persistent_cohomology_user.rst | 14 +++--- 2 files changed, 46 insertions(+), 25 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h index d1c846cf..37cdf1b4 100644 --- a/src/Tangential_complex/include/gudhi/Tangential_complex.h +++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -356,7 +357,7 @@ class Tangential_complex { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), Compute_tangent_triangulation(*this)); } else { #endif // GUDHI_USE_TBB - // Sequential + // Sequential for (std::size_t i = 0; i < m_points.size(); ++i) compute_tangent_triangulation(i); #ifdef GUDHI_USE_TBB } @@ -629,12 +630,12 @@ class Tangential_complex { // Don't export infinite cells if (!export_infinite_simplices && is_infinite(c)) continue; - if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue; - if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); // Add the missing center vertex c.insert(idx); + if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue; + // Try to insert the simplex bool inserted = tree.insert_simplex_and_subfaces(c).second; @@ -689,6 +690,10 @@ class Tangential_complex { // Don't export infinite cells if (!export_infinite_simplices && is_infinite(c)) continue; + if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); + // Add the missing center vertex + c.insert(idx); + if (!export_inconsistent_simplices && !is_simplex_consistent(c)) continue; // Unusual simplex dim? @@ -701,10 +706,6 @@ class Tangential_complex { check_lower_and_higher_dim_simplices = 1; } - if (static_cast(c.size()) > max_dim) max_dim = static_cast(c.size()); - // Add the missing center vertex - c.insert(idx); - // Try to insert the simplex bool added = complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1); @@ -800,7 +801,7 @@ class Tangential_complex { tbb::parallel_for(tbb::blocked_range(0, m_points.size()), Compute_tangent_triangulation(*this)); } else { #endif // GUDHI_USE_TBB - // Sequential + // Sequential for (std::size_t i = 0; i < m_points.size(); ++i) compute_tangent_triangulation(i); #ifdef GUDHI_USE_TBB } @@ -835,7 +836,7 @@ class Tangential_complex { Refresh_tangent_triangulation(*this, updated_pts_ds)); } else { #endif // GUDHI_USE_TBB - // Sequential + // Sequential for (std::size_t i = 0; i < m_points.size(); ++i) refresh_tangent_triangulation(i, updated_pts_ds); #ifdef GUDHI_USE_TBB } @@ -983,10 +984,9 @@ class Tangential_complex { // of the sphere "star sphere" centered at "center_vertex" // and which contains all the // circumspheres of the star of "center_vertex" - boost::optional squared_star_sphere_radius_plus_margin = boost::make_optional(false, FT()); - // This is the strange way boost is recommending to get rid of "may be used uninitialized in this function". - // Former code was : - // boost::optional squared_star_sphere_radius_plus_margin; + // If th the m_max_squared_edge_length is set the maximal radius of the "star sphere" + // is at most square root of m_max_squared_edge_length + boost::optional squared_star_sphere_radius_plus_margin = m_max_squared_edge_length; // Insert points until we find a point which is outside "star sphere" for (auto nn_it = ins_range.begin(); nn_it != ins_range.end(); ++nn_it) { @@ -999,10 +999,16 @@ class Tangential_complex { Point neighbor_pt; FT neighbor_weight; compute_perturbed_weighted_point(neighbor_point_idx, neighbor_pt, neighbor_weight); - + GUDHI_CHECK(!m_max_squared_edge_length || + squared_star_sphere_radius_plus_margin.value() <= m_max_squared_edge_length.value(), + std::invalid_argument("Tangential_complex::compute_star - set a bigger value with set_max_squared_edge_length.")); if (squared_star_sphere_radius_plus_margin && - k_sqdist(center_pt, neighbor_pt) > *squared_star_sphere_radius_plus_margin) + k_sqdist(center_pt, neighbor_pt) > squared_star_sphere_radius_plus_margin.value()) { + GUDHI_CHECK(triangulation.current_dimension() >= tangent_space_dim, + std::invalid_argument("Tangential_complex::compute_star - Dimension of the star is only " + \ + std::to_string(triangulation.current_dimension()))); break; + } Tr_point proj_pt = project_point_and_compute_weight(neighbor_pt, neighbor_weight, tsb, local_tr_traits); @@ -1044,7 +1050,7 @@ class Tangential_complex { FT sq_power_sphere_diam = 4 * point_weight(c); if (!squared_star_sphere_radius_plus_margin || - sq_power_sphere_diam > *squared_star_sphere_radius_plus_margin) { + sq_power_sphere_diam > squared_star_sphere_radius_plus_margin.value()) { squared_star_sphere_radius_plus_margin = sq_power_sphere_diam; } } @@ -1055,12 +1061,22 @@ class Tangential_complex { if (squared_star_sphere_radius_plus_margin) { // "2*m_last_max_perturb" because both points can be perturbed squared_star_sphere_radius_plus_margin = - CGAL::square(std::sqrt(*squared_star_sphere_radius_plus_margin) + 2 * m_last_max_perturb); + CGAL::square(std::sqrt(squared_star_sphere_radius_plus_margin.value()) + 2 * m_last_max_perturb); + + // Reduce the square radius to m_max_squared_edge_length if necessary + if (m_max_squared_edge_length && squared_star_sphere_radius_plus_margin.value() > m_max_squared_edge_length.value()) { + squared_star_sphere_radius_plus_margin = m_max_squared_edge_length.value(); + } // Save it in `m_squared_star_spheres_radii_incl_margin` - m_squared_star_spheres_radii_incl_margin[i] = *squared_star_sphere_radius_plus_margin; + m_squared_star_spheres_radii_incl_margin[i] = squared_star_sphere_radius_plus_margin.value(); } else { - m_squared_star_spheres_radii_incl_margin[i] = FT(-1); + if (m_max_squared_edge_length) { + squared_star_sphere_radius_plus_margin = m_max_squared_edge_length.value(); + m_squared_star_spheres_radii_incl_margin[i] = m_max_squared_edge_length.value(); + } else { + m_squared_star_spheres_radii_incl_margin[i] = FT(-1); + } } } } @@ -1968,6 +1984,8 @@ class Tangential_complex { return os; } + void set_max_squared_edge_length(FT max_squared_edge_length) { m_max_squared_edge_length = max_squared_edge_length; } + private: const K m_k; const int m_intrinsic_dim; @@ -1993,6 +2011,7 @@ class Tangential_complex { // and their center vertex Stars_container m_stars; std::vector m_squared_star_spheres_radii_incl_margin; + boost::optional m_max_squared_edge_length; #ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM Points m_points_for_tse; diff --git a/src/cython/doc/persistent_cohomology_user.rst b/src/cython/doc/persistent_cohomology_user.rst index ce7fc685..de83cda1 100644 --- a/src/cython/doc/persistent_cohomology_user.rst +++ b/src/cython/doc/persistent_cohomology_user.rst @@ -10,12 +10,14 @@ Definition :Author: Clément Maria :Introduced in: GUDHI PYTHON 2.0.0 :Copyright: GPL v3 ===================================== ===================================== ===================================== -+---------------------------------------------+----------------------------------------------------------------------+ -| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | -| | feature for reference: | -| | | -| | * :doc:`simplex_tree_ref` | -+---------------------------------------------+----------------------------------------------------------------------+ ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ +| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | +| | feature for reference: | +| | | +| | * :doc:`simplex_tree_ref` | +| | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ Computation of persistent cohomology using the algorithm of :cite:`DBLP:journals/dcg/SilvaMV11` and -- cgit v1.2.3 From f29a6e9a03dca95dc0a070b604fb11e18897a6f6 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 12 Feb 2019 14:08:56 +0000 Subject: Fix doc for C++ and Python. Fix some warnings on Nerve GIC sphinx doc generation git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/cubical_complex_small_fix@4101 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 57eacb8c4108be212e61796c65e3b45bb9c13644 --- src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h | 13 +++++++------ src/common/doc/file_formats.h | 8 ++++---- src/cython/doc/cubical_complex_user.rst | 10 ++++++++-- src/cython/doc/fileformats.rst | 10 +++++++++- src/cython/doc/nerve_gic_complex_ref.rst | 4 ++++ src/cython/doc/nerve_gic_complex_user.rst | 4 ++++ 6 files changed, 36 insertions(+), 13 deletions(-) (limited to 'src/cython') diff --git a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h index e1e5885e..5fa02a5e 100644 --- a/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h +++ b/src/Bitmap_cubical_complex/doc/Gudhi_Cubical_Complex_doc.h @@ -87,15 +87,16 @@ namespace cubical_complex { * * \section inputformat Input Format * - * In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star + * In the current implementation, filtration is given at the maximal cubes, and it is then extended by the lower star * filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users * who want to use the code directly. They can be found in the \a Bitmap_cubical_complex class. * Currently one input from a text file is used. It uses a format inspired from the Perseus software - * (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. Note however an important difference: while Perseus - * assume the filtration of all maximal cubes to be non-negative, over here we do not enforce this and we allow any - * filtration values. - * As a consequence one cannot use -1's to indicate missing cubes. If you have missing cubes in your complex, please - * set their filtration to +Inf. The file format is described in details in here: \ref FileFormatsPerseus. + * (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. + * \note While Perseus assume the filtration of all maximal cubes to be non-negative, over here we do not enforce this + * and we allow any filtration values. As a consequence one cannot use `-1`'s to indicate missing cubes. If you have + * missing cubes in your complex, please set their filtration to \f$+\infty\f$ (aka. `inf` in the file). + * + * The file format is described in details in \ref FileFormatsPerseus file format section. * * \section PeriodicBoundaryConditions Periodic boundary conditions * Often one would like to impose periodic boundary conditions to the cubical complex. Let \f$ I_1\times ... \times diff --git a/src/common/doc/file_formats.h b/src/common/doc/file_formats.h index d38d90e0..23214e25 100644 --- a/src/common/doc/file_formats.h +++ b/src/common/doc/file_formats.h @@ -72,7 +72,7 @@ namespace Gudhi { \section FileFormatsPerseus Perseus - This file format is the format used by the Perseus software + This file format is a format inspired from the Perseus software (http://www.sas.upenn.edu/~vnanda/perseus/) by Vidit Nanda. The first line contains a number d begin the dimension of the bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3 @@ -119,9 +119,9 @@ namespace Gudhi { Other sample files can be found in the `data/bitmap` folder. - Please note that unlike in Perseus format the filtration on the maximal cubes can be any double precision number. - Consequently one cannot mark the cubes that are not present with -1's. To do that please set their filtration value to - +Inf. + \note Unlike in Perseus format the filtration on the maximal cubes can be any double precision number. + Consequently one cannot mark the cubes that are not present with `-1`'s. To do that please set their filtration value + to \f$+\infty\f$ (aka. `inf` in the file). */ } // namespace Gudhi diff --git a/src/cython/doc/cubical_complex_user.rst b/src/cython/doc/cubical_complex_user.rst index 320bd79b..19120360 100644 --- a/src/cython/doc/cubical_complex_user.rst +++ b/src/cython/doc/cubical_complex_user.rst @@ -83,9 +83,15 @@ Input Format. In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users who want to use the code directly. They can be found in the :doc:`cubical_complex_ref`. -Currently one input from a text file is used. It uses a format used already in +Currently one input from a text file is used. It uses a format inspired from the Perseus software `Perseus software `_ by Vidit Nanda. -The file format is described here: :doc:`Perseus `. + +.. note:: + While Perseus assume the filtration of all maximal cubes to be non-negative, over here we do not enforce this and + we allow any filtration values. As a consequence one cannot use ``-1``'s to indicate missing cubes. If you have + missing cubes in your complex, please set their filtration to :math:`+\infty` (aka. ``inf`` in the file). + +The file format is described in details in :ref:`Perseus file format` file format section. .. testcode:: diff --git a/src/cython/doc/fileformats.rst b/src/cython/doc/fileformats.rst index ff20f26e..e205cc8b 100644 --- a/src/cython/doc/fileformats.rst +++ b/src/cython/doc/fileformats.rst @@ -51,10 +51,12 @@ Here is a simple sample file in the 3D case:: 1. 1. 1. +.. _Perseus file format: + Perseus ******* -This file format is the format used by the +This file format is a format inspired from the `Perseus software `_ by Vidit Nanda. The first line contains a number d begin the dimension of the bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each @@ -88,3 +90,9 @@ Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. Other sample files can be found in the `data/bitmap` folder. + +.. note:: + Unlike in Perseus format the filtration on the maximal cubes can be any + double precision number. Consequently one cannot mark the cubes that are + not present with ``-1``'s. To do that please set their filtration value to + :math:`+\infty` (aka. ``inf`` in the file). \ No newline at end of file diff --git a/src/cython/doc/nerve_gic_complex_ref.rst b/src/cython/doc/nerve_gic_complex_ref.rst index e24e01fc..abde2e8c 100644 --- a/src/cython/doc/nerve_gic_complex_ref.rst +++ b/src/cython/doc/nerve_gic_complex_ref.rst @@ -1,3 +1,7 @@ +:orphan: + +.. To get rid of WARNING: document isn't included in any toctree + ================================ Cover complexes reference manual ================================ diff --git a/src/cython/doc/nerve_gic_complex_user.rst b/src/cython/doc/nerve_gic_complex_user.rst index d774827e..44f30e1a 100644 --- a/src/cython/doc/nerve_gic_complex_user.rst +++ b/src/cython/doc/nerve_gic_complex_user.rst @@ -1,3 +1,7 @@ +:orphan: + +.. To get rid of WARNING: document isn't included in any toctree + Cover complexes user manual =========================== Definition -- cgit v1.2.3 From 68c4ffe856b8de030bb4c7c75bccce7082d5478c Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 14 Feb 2019 10:21:41 +0000 Subject: Fix https://gitlab.inria.fr/GUDHI/gudhi-devel/issues/25 [python] A Cmake option to set/unset runtime_library_dirs cmake -DWITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS=OFF .. # to disable runtime_library_dirs set in setup.py cf. Debian disallows setting rpath, so I'm currently unsetting runtime_library_dirs for the Python extensions. Could this perhaps be made into a CMake option? https://git.nonempty.org/debian-gudhi/tree/debian/patches/0005-Don-t-set-runtime-library-dirs-for-Python-extensions.patch?h=debian/sid&id=fed62e52ab396f0d6ba9029f12d5ef35d7761989 git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@4105 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 75f19373b2f01c2757bf1b11c81beff64021ddd8 --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 ++ src/cython/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/cython') diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index cde3725c..7b0d350d 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -154,6 +154,8 @@ if(NOT GUDHI_CYTHON_PATH) message(FATAL_ERROR "ERROR: GUDHI_CYTHON_PATH is not valid.") endif(NOT GUDHI_CYTHON_PATH) +option(WITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "Build with setting runtime_library_dirs. Usefull when setting rpath is not allowed" ON) + if(PYTHONINTERP_FOUND AND CYTHON_FOUND) # Default found version 2 if(PYTHON_VERSION_MAJOR EQUAL 2) diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index dc2e9278..97859c98 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -198,9 +198,9 @@ if(PYTHONINTERP_FOUND) set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") endif() - if(UNIX) + if(UNIX AND WITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS) set( GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}") - endif(UNIX) + endif(UNIX AND WITH_GUDHI_CYTHON_RUNTIME_LIBRARY_DIRS) # Generate setup.py file to cythonize Gudhi - This file must be named setup.py by convention configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY) -- cgit v1.2.3 From d7216fffe2a7fb3b15dcb84a4d5464968ae4a436 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Thu, 14 Feb 2019 16:57:30 +0000 Subject: Fix https://gitlab.inria.fr/GUDHI/gudhi-devel/issues/28 [python - install] make install does not install properly Use 'python setup.py install' command instead of copying files git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@4108 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 652d3597897aa3e7d1df97083cc3e2e4ae14f090 --- src/cython/CMakeLists.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt index 97859c98..480332d7 100644 --- a/src/cython/CMakeLists.txt +++ b/src/cython/CMakeLists.txt @@ -215,12 +215,7 @@ if(PYTHONINTERP_FOUND) add_custom_target(cython ALL DEPENDS gudhi.so COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests") - # For installation purpose - # TODO(VR) : files matching pattern mechanism is copying all cython directory - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DESTINATION "${PYTHON_SITE_PACKAGES}/" FILES_MATCHING - PATTERN "*.so" - PATTERN "*.dylib" - PATTERN "*.pyd") + install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py install)") # Test examples if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.8.1) -- cgit v1.2.3 From 6112bd15d73b00a07edd54eeaf9c94cdff93aa9e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 12 Mar 2019 23:12:51 +0100 Subject: Add some documentation for Fix #31 Cythonization of Fix #31 Add some tests --- .../include/gudhi/Tangential_complex.h | 13 +++++++++- .../test/test_tangential_complex.cpp | 30 ++++++++++++++++++++++ src/cython/cython/tangential_complex.pyx | 26 +++++++++++++++++++ src/cython/doc/tangential_complex_user.rst | 2 ++ ...complex_plain_homology_from_off_file_example.py | 1 + src/cython/include/Tangential_complex_interface.h | 15 +++++++---- src/cython/test/test_tangential_complex.py | 9 +++++++ 7 files changed, 90 insertions(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h index 37cdf1b4..4a78127c 100644 --- a/src/Tangential_complex/include/gudhi/Tangential_complex.h +++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h @@ -322,7 +322,11 @@ class Tangential_complex { for (std::size_t i = 0; i < m_points.size(); ++i) m_are_tangent_spaces_computed[i] = true; } - /// Computes the tangential complex. + /** \brief Computes the tangential complex. + * \exception std::invalid_argument In debug mode, if the computed star dimension is too low. Try to set a bigger + * maximal edge length value with `Tangential_complex::set_max_squared_edge_length` if + * this happens. + */ void compute_tangential_complex() { #ifdef GUDHI_TC_PERFORM_EXTRA_CHECKS std::cerr << red << "WARNING: GUDHI_TC_PERFORM_EXTRA_CHECKS is defined. " @@ -1984,6 +1988,13 @@ class Tangential_complex { return os; } + /** \brief Sets the maximal possible squared edge length for the edges in the triangulations. + * + * @param[in] max_squared_edge_length Maximal possible squared edge length. + * + * If the maximal edge length value is too low `Tangential_complex::compute_tangential_complex` will throw an + * exception in debug mode. + */ void set_max_squared_edge_length(FT max_squared_edge_length) { m_max_squared_edge_length = max_squared_edge_length; } private: diff --git a/src/Tangential_complex/test/test_tangential_complex.cpp b/src/Tangential_complex/test/test_tangential_complex.cpp index 4e2d4f65..103b8b30 100644 --- a/src/Tangential_complex/test/test_tangential_complex.cpp +++ b/src/Tangential_complex/test/test_tangential_complex.cpp @@ -126,3 +126,33 @@ BOOST_AUTO_TEST_CASE(test_mini_tangential) { BOOST_CHECK(stree.num_vertices() == 4); BOOST_CHECK(stree.num_simplices() == 6); } + +#ifdef GUDHI_DEBUG +BOOST_AUTO_TEST_CASE(test_basic_example_throw) { + typedef CGAL::Epick_d Kernel; + typedef Kernel::FT FT; + typedef Kernel::Point_d Point; + typedef Kernel::Vector_d Vector; + typedef tc::Tangential_complex TC; + + const int INTRINSIC_DIM = 2; + const int AMBIENT_DIM = 3; + const int NUM_POINTS = 1000; + + Kernel k; + + // Generate points on a 2-sphere + CGAL::Random_points_on_sphere_d generator(AMBIENT_DIM, 3.); + std::vector points; + points.reserve(NUM_POINTS); + for (int i = 0; i < NUM_POINTS; ++i) + points.push_back(*generator++); + + // Compute the TC + TC tc(points, INTRINSIC_DIM, k); + tc.set_max_squared_edge_length(0.01); + std::cout << "test_basic_example_throw - set_max_squared_edge_length(0.01) to make GUDHI_CHECK fail" << std::endl; + BOOST_CHECK_THROW(tc.compute_tangential_complex(), std::invalid_argument); + +} +#endif diff --git a/src/cython/cython/tangential_complex.pyx b/src/cython/cython/tangential_complex.pyx index 4bb07076..293ef8cb 100644 --- a/src/cython/cython/tangential_complex.pyx +++ b/src/cython/cython/tangential_complex.pyx @@ -36,6 +36,7 @@ cdef extern from "Tangential_complex_interface.h" namespace "Gudhi": Tangential_complex_interface(int intrisic_dim, vector[vector[double]] points) # bool from_file is a workaround for cython to find the correct signature Tangential_complex_interface(int intrisic_dim, string off_file, bool from_file) + void compute_tangential_complex() except + vector[double] get_point(unsigned vertex) unsigned number_of_vertices() unsigned number_of_simplices() @@ -43,6 +44,7 @@ cdef extern from "Tangential_complex_interface.h" namespace "Gudhi": unsigned number_of_inconsistent_stars() void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree) void fix_inconsistencies_using_perturbation(double max_perturb, double time_limit) + void set_max_squared_edge_length(double max_squared_edge_length) # TangentialComplex python interface cdef class TangentialComplex: @@ -92,6 +94,17 @@ cdef class TangentialComplex: """ return self.thisptr != NULL + def compute_tangential_complex(self): + """This function computes the tangential complex. + + Raises: + ValueError: In debug mode, if the computed star dimension is too + low. Try to set a bigger maximal edge length value with + :func:`~gudhi.Tangential_complex.set_max_squared_edge_length` + if this happens. + """ + self.thisptr.compute_tangential_complex() + def get_point(self, vertex): """This function returns the point corresponding to a given vertex. @@ -152,3 +165,16 @@ cdef class TangentialComplex: """ self.thisptr.fix_inconsistencies_using_perturbation(max_perturb, time_limit) + + def set_max_squared_edge_length(self, max_squared_edge_length): + """Sets the maximal possible squared edge length for the edges in the + triangulations. + + :param max_squared_edge_length: Maximal possible squared edge length. + :type max_squared_edge_length: double + + If the maximal edge length value is too low + :func:`~gudhi.Tangential_complex.compute_tangential_complex` + will throw an exception in debug mode. + """ + self.thisptr.set_max_squared_edge_length(max_squared_edge_length) diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst index 5ce69e86..97471baf 100644 --- a/src/cython/doc/tangential_complex_user.rst +++ b/src/cython/doc/tangential_complex_user.rst @@ -128,6 +128,7 @@ This example builds the Tangential complex of point set read in an OFF file. import gudhi tc = gudhi.TangentialComplex(intrisic_dim = 1, off_file=gudhi.__root_source_dir__ + '/data/points/alphacomplexdoc.off') + tc.compute_tangential_complex() result_str = 'Tangential contains ' + repr(tc.num_simplices()) + \ ' simplices - ' + repr(tc.num_vertices()) + ' vertices.' print(result_str) @@ -175,6 +176,7 @@ simplices. import gudhi tc = gudhi.TangentialComplex(intrisic_dim = 1, points=[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]) + tc.compute_tangential_complex() result_str = 'Tangential contains ' + repr(tc.num_vertices()) + ' vertices.' print(result_str) diff --git a/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py index 0f8f5e80..536517d1 100755 --- a/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py +++ b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py @@ -50,6 +50,7 @@ with open(args.file, 'r') as f: print("TangentialComplex creation from points read in a OFF file") tc = gudhi.TangentialComplex(intrisic_dim = args.intrisic_dim, off_file=args.file) + tc.compute_tangential_complex() st = tc.create_simplex_tree() message = "Number of simplices=" + repr(st.num_simplices()) diff --git a/src/cython/include/Tangential_complex_interface.h b/src/cython/include/Tangential_complex_interface.h index 71418886..c4ddbdbe 100644 --- a/src/cython/include/Tangential_complex_interface.h +++ b/src/cython/include/Tangential_complex_interface.h @@ -49,8 +49,6 @@ class Tangential_complex_interface { Dynamic_kernel k; tangential_complex_ = new TC(points, intrisic_dim, k); - tangential_complex_->compute_tangential_complex(); - num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); } Tangential_complex_interface(int intrisic_dim, const std::string& off_file_name, bool from_file = true) { @@ -60,14 +58,17 @@ class Tangential_complex_interface { std::vector points = off_reader.get_point_cloud(); tangential_complex_ = new TC(points, intrisic_dim, k); - tangential_complex_->compute_tangential_complex(); - num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); } ~Tangential_complex_interface() { delete tangential_complex_; } + void compute_tangential_complex() { + tangential_complex_->compute_tangential_complex(); + num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); + } + std::vector get_point(unsigned vh) { std::vector vd; if (vh < tangential_complex_->number_of_vertices()) { @@ -104,7 +105,11 @@ class Tangential_complex_interface { simplex_tree->initialize_filtration(); } - private: + void set_max_squared_edge_length(double max_squared_edge_length) { + tangential_complex_->set_max_squared_edge_length(max_squared_edge_length); + } + +private: TC* tangential_complex_; TC::Num_inconsistencies num_inconsistencies_; }; diff --git a/src/cython/test/test_tangential_complex.py b/src/cython/test/test_tangential_complex.py index 5385a0d3..5c62f278 100755 --- a/src/cython/test/test_tangential_complex.py +++ b/src/cython/test/test_tangential_complex.py @@ -32,6 +32,15 @@ def test_tangential(): tc = TangentialComplex(intrisic_dim = 1, points=point_list) assert tc.__is_defined() == True assert tc.num_vertices() == 4 + assert tc.num_simplices() == 0 + assert tc.num_inconsistent_simplices() == 0 + assert tc.num_inconsistent_stars() == 0 + + tc.compute_tangential_complex() + assert tc.num_vertices() == 4 + assert tc.num_simplices() == 4 + assert tc.num_inconsistent_simplices() == 0 + assert tc.num_inconsistent_stars() == 0 st = tc.create_simplex_tree() assert st.__is_defined() == True -- cgit v1.2.3 From 481718886577973385f657484c124456890ffa76 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 13 Mar 2019 07:37:33 +0100 Subject: Improve documentation for Tangential complex (Fix #16) --- src/Tangential_complex/doc/Intro_tangential_complex.h | 5 +++-- src/cython/doc/tangential_complex_user.rst | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/doc/Intro_tangential_complex.h b/src/Tangential_complex/doc/Intro_tangential_complex.h index f4fc8ac7..649ec389 100644 --- a/src/Tangential_complex/doc/Intro_tangential_complex.h +++ b/src/Tangential_complex/doc/Intro_tangential_complex.h @@ -46,9 +46,10 @@ An extensive description of the Tangential complex can be found in \cite tangent \subsection whatisthetc What is a Tangential Complex? Let us start with the description of the Tangential complex of a simple example, with \f$ k=1 \f$ and \f$ d=2 \f$. -The input data is 4 points \f$ P \f$ located on a curve embedded in 2D. +Only 4 points will be displayed (more are required for PCA) to simplify the figures. \f$ P \f$ located on a closed +curve embedded in 2D. \image html "tc_example_01.png" "The input" -For each point \f$ p \f$, estimate its tangent subspace \f$ T_p \f$ (e.g. using PCA). +For each point \f$ p \f$, estimate its tangent subspace \f$ T_p \f$ using PCA. \image html "tc_example_02.png" "The estimated normals" Let us add the Voronoi diagram of the points in orange. For each point \f$ p \f$, construct its star in the Delaunay triangulation of \f$ P \f$ restricted to \f$ T_p \f$. \image html "tc_example_03.png" "The Voronoi diagram" diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst index 97471baf..5147797c 100644 --- a/src/cython/doc/tangential_complex_user.rst +++ b/src/cython/doc/tangential_complex_user.rst @@ -23,8 +23,9 @@ What is a Tangential Complex? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Let us start with the description of the Tangential complex of a simple -example, with :math:`k = 1` and :math:`d = 2`. The input data is 4 points -:math:`P` located on a curve embedded in 2D. +example, with :math:`k = 1` and :math:`d = 2`. Only 4 points will be displayed +(more are required for PCA) to simplify the figures. :math:`P` located +on a closed curve embedded in 2D. .. figure:: ../../doc/Tangential_complex/tc_example_01.png :alt: The input @@ -32,8 +33,7 @@ example, with :math:`k = 1` and :math:`d = 2`. The input data is 4 points The input -For each point :math:`p`, estimate its tangent subspace :math:`T_p` (e.g. -using PCA). +For each point :math:`p`, estimate its tangent subspace :math:`T_p` using PCA. .. figure:: ../../doc/Tangential_complex/tc_example_02.png :alt: The estimated normals -- cgit v1.2.3 From 3ec4014f39c514aa456a652bc0d876fba70ad6f9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 14 Mar 2019 18:05:11 +0100 Subject: Fix code review --- src/Tangential_complex/doc/Intro_tangential_complex.h | 19 +++++++++++-------- src/cython/doc/tangential_complex_user.rst | 13 +++++++------ 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/doc/Intro_tangential_complex.h b/src/Tangential_complex/doc/Intro_tangential_complex.h index 649ec389..2b019021 100644 --- a/src/Tangential_complex/doc/Intro_tangential_complex.h +++ b/src/Tangential_complex/doc/Intro_tangential_complex.h @@ -35,9 +35,11 @@ namespace tangential_complex { \section tangentialdefinition Definition -A Tangential Delaunay complex is a simplicial complex +A Tangential Delaunay complex is a +simplicial complex designed to reconstruct a \f$k\f$-dimensional smooth manifold embedded in \f$d\f$-dimensional Euclidean space. -The input is a point sample coming from an unknown manifold, which means that the points lie close to a structure of "small" intrinsic dimension. +The input is a point sample coming from an unknown manifold, which means that the points lie close to a structure of +"small" intrinsic dimension. The running time depends only linearly on the extrinsic dimension \f$ d \f$ and exponentially on the intrinsic dimension \f$ k \f$. @@ -46,18 +48,19 @@ An extensive description of the Tangential complex can be found in \cite tangent \subsection whatisthetc What is a Tangential Complex? Let us start with the description of the Tangential complex of a simple example, with \f$ k=1 \f$ and \f$ d=2 \f$. -Only 4 points will be displayed (more are required for PCA) to simplify the figures. \f$ P \f$ located on a closed -curve embedded in 2D. +The point set \f$ \mathscr P \f$ is located on a closed curve embedded in 2D. +Only 4 points will be displayed (more are required for PCA) to simplify the figures. \image html "tc_example_01.png" "The input" -For each point \f$ p \f$, estimate its tangent subspace \f$ T_p \f$ using PCA. +For each point \f$ P \f$, estimate its tangent subspace \f$ T_p \f$ using PCA. \image html "tc_example_02.png" "The estimated normals" -Let us add the Voronoi diagram of the points in orange. For each point \f$ p \f$, construct its star in the Delaunay triangulation of \f$ P \f$ restricted to \f$ T_p \f$. +Let us add the Voronoi diagram of the points in orange. For each point \f$ P \f$, construct its star in the Delaunay +triangulation of \f$ \mathscr P \f$ restricted to \f$ T_p \f$. \image html "tc_example_03.png" "The Voronoi diagram" The Tangential Delaunay complex is the union of those stars. In practice, neither the ambient Voronoi diagram nor the ambient Delaunay triangulation is computed. -Instead, local \f$ k \f$-dimensional regular triangulations are computed with a limited number of points as we only need the star of each point. -More details can be found in \cite tangentialcomplex2014. +Instead, local \f$ k \f$-dimensional regular triangulations are computed with a limited number of points as we only +need the star of each point. More details can be found in \cite tangentialcomplex2014. \subsection inconsistencies Inconsistencies diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst index 5147797c..11b37009 100644 --- a/src/cython/doc/tangential_complex_user.rst +++ b/src/cython/doc/tangential_complex_user.rst @@ -23,9 +23,10 @@ What is a Tangential Complex? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Let us start with the description of the Tangential complex of a simple -example, with :math:`k = 1` and :math:`d = 2`. Only 4 points will be displayed -(more are required for PCA) to simplify the figures. :math:`P` located -on a closed curve embedded in 2D. +example, with :math:`k = 1` and :math:`d = 2`. The point set +:math:`\mathscr P` is located on a closed curve embedded in 2D. +Only 4 points will be displayed (more are required for PCA) to simplify the +figures. .. figure:: ../../doc/Tangential_complex/tc_example_01.png :alt: The input @@ -33,7 +34,7 @@ on a closed curve embedded in 2D. The input -For each point :math:`p`, estimate its tangent subspace :math:`T_p` using PCA. +For each point :math:`P`, estimate its tangent subspace :math:`T_p` using PCA. .. figure:: ../../doc/Tangential_complex/tc_example_02.png :alt: The estimated normals @@ -43,8 +44,8 @@ For each point :math:`p`, estimate its tangent subspace :math:`T_p` using PCA. Let us add the Voronoi diagram of the points in orange. For each point -:math:`p`, construct its star in the Delaunay triangulation of :math:`P` -restricted to :math:`T_p`. +:math:`P`, construct its star in the Delaunay triangulation of +:math:`\mathscr P` restricted to :math:`T_p`. .. figure:: ../../doc/Tangential_complex/tc_example_03.png :alt: The Voronoi diagram -- cgit v1.2.3 From fe79987e03b5bce4515638f8d0549ae8db64f3e6 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 15 Mar 2019 08:32:37 +0100 Subject: Fix code review --- src/Tangential_complex/doc/Intro_tangential_complex.h | 6 +++--- src/cython/doc/tangential_complex_user.rst | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/cython') diff --git a/src/Tangential_complex/doc/Intro_tangential_complex.h b/src/Tangential_complex/doc/Intro_tangential_complex.h index 2b019021..501f4a8b 100644 --- a/src/Tangential_complex/doc/Intro_tangential_complex.h +++ b/src/Tangential_complex/doc/Intro_tangential_complex.h @@ -51,10 +51,10 @@ Let us start with the description of the Tangential complex of a simple example, The point set \f$ \mathscr P \f$ is located on a closed curve embedded in 2D. Only 4 points will be displayed (more are required for PCA) to simplify the figures. \image html "tc_example_01.png" "The input" -For each point \f$ P \f$, estimate its tangent subspace \f$ T_p \f$ using PCA. +For each point \f$ P \f$, estimate its tangent subspace \f$ T_P \f$ using PCA. \image html "tc_example_02.png" "The estimated normals" Let us add the Voronoi diagram of the points in orange. For each point \f$ P \f$, construct its star in the Delaunay -triangulation of \f$ \mathscr P \f$ restricted to \f$ T_p \f$. +triangulation of \f$ \mathscr P \f$ restricted to \f$ T_P \f$. \image html "tc_example_03.png" "The Voronoi diagram" The Tangential Delaunay complex is the union of those stars. @@ -69,7 +69,7 @@ An inconsistency occurs when a simplex is not in the star of all its vertices. Let us take the same example. \image html "tc_example_07_before.png" "Before" -Let us slightly move the tangent subspace \f$ T_q \f$ +Let us slightly move the tangent subspace \f$ T_Q \f$ \image html "tc_example_07_after.png" "After" Now, the star of \f$ Q \f$ contains \f$ QP \f$, but the star of \f$ P \f$ does not contain \f$ QP \f$. We have an inconsistency. \image html "tc_example_08.png" "After" diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst index 11b37009..ebfe1e29 100644 --- a/src/cython/doc/tangential_complex_user.rst +++ b/src/cython/doc/tangential_complex_user.rst @@ -34,7 +34,7 @@ figures. The input -For each point :math:`P`, estimate its tangent subspace :math:`T_p` using PCA. +For each point :math:`P`, estimate its tangent subspace :math:`T_P` using PCA. .. figure:: ../../doc/Tangential_complex/tc_example_02.png :alt: The estimated normals @@ -45,7 +45,7 @@ For each point :math:`P`, estimate its tangent subspace :math:`T_p` using PCA. Let us add the Voronoi diagram of the points in orange. For each point :math:`P`, construct its star in the Delaunay triangulation of -:math:`\mathscr P` restricted to :math:`T_p`. +:math:`\mathscr P` restricted to :math:`T_P`. .. figure:: ../../doc/Tangential_complex/tc_example_03.png :alt: The Voronoi diagram @@ -73,7 +73,7 @@ Let us take the same example. Before -Let us slightly move the tangent subspace :math:`T_q` +Let us slightly move the tangent subspace :math:`T_Q` .. figure:: ../../doc/Tangential_complex/tc_example_07_after.png :alt: After -- cgit v1.2.3 From b2675aa4e27dd19ecf8bcef18a53f380d8a21421 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 15 Mar 2019 16:36:53 +0100 Subject: Improve python installation documentation --- src/cython/doc/installation.rst | 56 +++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 16 deletions(-) (limited to 'src/cython') diff --git a/src/cython/doc/installation.rst b/src/cython/doc/installation.rst index 040f6b4a..855dea44 100644 --- a/src/cython/doc/installation.rst +++ b/src/cython/doc/installation.rst @@ -7,24 +7,23 @@ Installation Compiling ********* -The library uses c++11 and requires `Boost `_ ≥ 1.56.0 -and `CMake `_ ≥ 3.1. +The library uses c++11 and requires `Boost `_ ≥ 1.56.0, +`CMake `_ ≥ 3.1 to generate makefiles, and +`Cython `_ to compile the GUDHI Python module. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2015. -It also requires cmake to generate makefiles, and cython to compile the -library. On `Windows `_ , only Python 3.5 and 3.6 are available because of the required Visual Studio version. -On other systems, if you have several Python/cython installed, the version 2.X +On other systems, if you have several Python/Cython installed, the version 2.X will be used by default, but you can force it by adding :code:`-DPython_ADDITIONAL_VERSIONS=3` to the cmake command. -GUDHI Cythonization -=================== +GUDHI Python module compilation +=============================== -To build the GUDHI cython module, run the following commands in a terminal: +To build the GUDHI Python module, run the following commands in a terminal: .. code-block:: bash @@ -32,7 +31,28 @@ To build the GUDHI cython module, run the following commands in a terminal: mkdir build cd build/ cmake .. - make cython + cd cython + make + +GUDHI Python module installation +================================ + +Once the compilation succeeds, one can add the GUDHI Python module path to the +PYTHONPATH: + +.. code-block:: bash + + # For windows, you have to set PYTHONPATH environment variable + export PYTHONPATH='$PYTHONPATH:/path-to-gudhi/build/cython' + +Or install it definitely in your Python packages folder: + +.. code-block:: bash + + cd /path-to-gudhi/build/cython + # May require sudo or administrator privileges + make install + Test suites =========== @@ -45,7 +65,7 @@ following command in a terminal: cd /path-to-gudhi/build/cython # For windows, you have to set PYTHONPATH environment variable export PYTHONPATH='$PYTHONPATH:/path-to-gudhi/build/cython' - ctest -R py_test + make test Debugging issues ================ @@ -54,7 +74,7 @@ If tests fail, please check your PYTHONPATH and try to :code:`import gudhi` and check the errors. The problem can come from a third-party library bad link or installation. -If :code:`import gudhi` succeeds, please have a look to debug informations: +If :code:`import gudhi` succeeds, please have a look to debug information: .. code-block:: python @@ -105,13 +125,17 @@ A complete configuration would be : Documentation ============= -To build the documentation, `sphinx-doc `_ is -required. Please refer to *conf.py* file to see which -`sphinx-doc `_ modules are required to -generate the documentation. Run the following commands in a terminal: +To build the documentation, `sphinx-doc `_ and +`sphinxcontrib-bibtex `_ are +required. As the documentation is auto-tested, `CGAL`_, `Eigen3`_, +`Matplotlib`_, `NumPy`_ and `SciPy`_ are also mandatory to build the +documentation. + +Run the following commands in a terminal: .. code-block:: bash + cd /path-to-gudhi/build/cython make sphinx Optional third-party library @@ -127,7 +151,7 @@ The :doc:`Alpha complex `, C++ library which provides easy access to efficient and reliable geometric algorithms. -Having CGAL, the Computational Geometry Algorithms Library, version 4.7.0 or +Having CGAL, the Computational Geometry Algorithms Library, version 4.7.0 or higher installed is recommended. The procedure to install this library according to your operating system is detailed `here `_. -- cgit v1.2.3