-- cgit v1.2.3 From fe318b14148c20541d76649a1de76bdf6f7eaeab Mon Sep 17 00:00:00 2001 From: glisse Date: Tue, 16 Jan 2018 16:03:29 +0000 Subject: Initial commit of sparse Rips, based on Rips_complex. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3137 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f0550a0a24a25e8d9ab16535eb4364e8dc4228e6 --- .../include/gudhi/Sparse_rips_complex.h | 169 +++++++++++++++++++++ .../utilities/sparse_rips_persistence.cpp | 145 ++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 src/Rips_complex/include/gudhi/Sparse_rips_complex.h create mode 100644 src/Rips_complex/utilities/sparse_rips_persistence.cpp diff --git a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h new file mode 100644 index 00000000..c5378b6e --- /dev/null +++ b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h @@ -0,0 +1,169 @@ +/* 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) 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 + * 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 . + */ + +#ifndef SPARSE_RIPS_COMPLEX_H_ +#define SPARSE_RIPS_COMPLEX_H_ + +#include +#include +#include + +#include +#include + +#include + + +namespace Gudhi { + +namespace rips_complex { + +// The whole interface is copied on Rips_complex. A redesign should be discussed with all complex creation classes in mind. + +/** + * \class Sparse_rips_complex + * \brief Sparse Rips complex data structure. + * + * \ingroup rips_complex + * + * \details + * This class is used to construct a sparse \f$(1+\epsilon)\f$-approximation of `Rips_complex`. + * + * \tparam Filtration_value is the type used to store the filtration values of the simplicial complex. + */ +template +class Sparse_rips_complex { + private: + // TODO: use a different graph where we know we can safely insert in parallel. + typedef typename boost::adjacency_list + , boost::property> Graph; + + typedef int Vertex_handle; + + public: + /** \brief Sparse_rips_complex constructor from a list of points. + * + * @param[in] points Range of points. + * @param[in] distance distance function that returns a `Filtration_value` from 2 given points. + * + */ + template + Sparse_rips_complex(const RandomAccessPointRange& points, Distance distance, double epsilon) { + std::vector sorted_points; + std::vector params; + auto dist_fun = [&](Vertex_handle i, Vertex_handle j){return distance(points[i], points[j]);}; + Ker kernel(dist_fun); + subsampling::choose_n_farthest_points(kernel, boost::irange(0, boost::size(points)), -1, -1, std::back_inserter(sorted_points), std::back_inserter(params)); + compute_sparse_graph(sorted_points, params, dist_fun, epsilon); + } + + /** \brief Rips_complex constructor from a distance matrix. + * + * @param[in] distance_matrix Range of range of distances. + * `distance_matrix[i][j]` returns the distance between points \f$i\f$ and + * \f$j\f$ as long as \f$ 0 \leqslant i < j \leqslant + * distance\_matrix.size().\f$ + */ + template + Sparse_rips_complex(const DistanceMatrix& distance_matrix, double epsilon) + : Sparse_rips_complex( + boost::irange(0, boost::size(distance_matrix)), + [&](Vertex_handle i, Vertex_handle j){return distance_matrix[j][i];}, + epsilon) {} + + /** \brief Fills the simplicial complex with the sparse Rips graph and + * expands it with all the cliques, stopping at a given maximal dimension. + * + * \tparam SimplicialComplexForRips must meet `SimplicialComplexForRips` concept. + * + * @param[in] complex the complex to fill + * @param[in] dim_max maximal dimension of the simplicial complex. + * @exception std::invalid_argument In debug mode, if `complex.num_vertices()` does not return 0. + * + */ + template + void create_complex(SimplicialComplexForRips& complex, int dim_max) { + GUDHI_CHECK(complex.num_vertices() == 0, + std::invalid_argument("Sparse_rips_complex::create_complex - simplicial complex is not empty")); + + complex.insert_graph(graph_); + complex.expansion(dim_max); + } + + private: + // choose_n_farthest_points wants the distance function in this form... + template + struct Ker { + typedef std::size_t Point_d; // index into point range + Ker(Distance& d) : dist (d) {} + // Despite the name, this is not squared... + typedef Distance Squared_distance_d; + Squared_distance_d& squared_distance_d_object() const { return dist; } + Distance& dist; + }; + + // PointRange must be random access. + template + void compute_sparse_graph(const PointRange& points, const ParamRange& params, Distance& dist, double epsilon) { + const int n = boost::size(points); + graph_.~Graph(); + new(&graph_) Graph(n); + //for(auto v : vertices(g)) // doesn't work :-( + typename boost::graph_traits::vertex_iterator v_i, v_e; + for(std::tie(v_i, v_e) = vertices(graph_); v_i != v_e; ++v_i) { + auto v = *v_i; + // This whole loop might not be necessary, leave it until someone investigates if it is safe to remove. + put(vertex_filtration_t(), graph_, v, 0); + } + + // TODO: + // - make it parallel + // - only test near-enough neighbors + for(int i = 0; i < n; ++i) + for(int j = i + 1; j < n; ++j){ + auto&& pi = points[i]; + auto&& pj = points[j]; + auto d = dist(pi, pj); + auto li = params[i]; + auto lj = params[j]; + GUDHI_CHECK(lj <= li, "Bad furthest point sorting"); + Filtration_value alpha; + + if(d * epsilon <= 2 * lj) + alpha = d / 2; + else if(d * epsilon <= li + lj && (epsilon >= 1 || d * epsilon <= lj * (1 + 1 / (1 - epsilon)))) + alpha = d - lj / epsilon; + else continue; + + add_edge(pi, pj, alpha, graph_); + } + } + + Graph graph_; +}; + +} // namespace rips_complex + +} // namespace Gudhi + +#endif // SPARSE_RIPS_COMPLEX_H_ diff --git a/src/Rips_complex/utilities/sparse_rips_persistence.cpp b/src/Rips_complex/utilities/sparse_rips_persistence.cpp new file mode 100644 index 00000000..12b3b099 --- /dev/null +++ b/src/Rips_complex/utilities/sparse_rips_persistence.cpp @@ -0,0 +1,145 @@ +/* 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, Clément Maria + * + * Copyright (C) 2014 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 . + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +// Types definition +using Simplex_tree = Gudhi::Simplex_tree; +using Filtration_value = Simplex_tree::Filtration_value; +using Sparse_rips = Gudhi::rips_complex::Sparse_rips_complex; +using Field_Zp = Gudhi::persistent_cohomology::Field_Zp; +using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology; +using Point = std::vector; +using Points_off_reader = Gudhi::Points_off_reader; + +void program_options(int argc, char * argv[] + , std::string & off_file_points + , std::string & filediag + , double & epsilon + , int & dim_max + , int & p + , Filtration_value & min_persistence); + +int main(int argc, char * argv[]) { + std::string off_file_points; + std::string filediag; + double epsilon; + int dim_max; + int p; + Filtration_value min_persistence; + + program_options(argc, argv, off_file_points, filediag, epsilon, dim_max, p, min_persistence); + + Points_off_reader off_reader(off_file_points); + Sparse_rips sparse_rips(off_reader.get_point_cloud(), Gudhi::Euclidean_distance(), epsilon); + + // Construct the Rips complex in a Simplex Tree + Simplex_tree simplex_tree; + + sparse_rips.create_complex(simplex_tree, dim_max); + std::cout << "The complex contains " << simplex_tree.num_simplices() << " simplices \n"; + std::cout << " and has dimension " << simplex_tree.dimension() << " \n"; + + // Sort the simplices in the order of the filtration + simplex_tree.initialize_filtration(); + + // Compute the persistence diagram of the complex + Persistent_cohomology pcoh(simplex_tree); + // initializes the coefficient field for homology + pcoh.init_coefficients(p); + + pcoh.compute_persistent_cohomology(min_persistence); + + // Output the diagram in filediag + if (filediag.empty()) { + pcoh.output_diagram(); + } else { + std::ofstream out(filediag); + pcoh.output_diagram(out); + out.close(); + } + + return 0; +} + +void program_options(int argc, char * argv[] + , std::string & off_file_points + , std::string & filediag + , double & epsilon + , int & dim_max + , int & p + , Filtration_value & min_persistence) { + namespace po = boost::program_options; + po::options_description hidden("Hidden options"); + hidden.add_options() + ("input-file", po::value(&off_file_points), + "Name of an OFF file containing a point set.\n"); + + po::options_description visible("Allowed options", 100); + visible.add_options() + ("help,h", "produce help message") + ("output-file,o", po::value(&filediag)->default_value(std::string()), + "Name of file in which the persistence diagram is written. Default print in std::cout") + ("approximation,e", po::value(&epsilon)->default_value(.5), + "Epsilon, where the sparse Rips complex is a (1+epsilon)-approximation of the Rips complex.") + ("cpx-dimension,d", po::value(&dim_max)->default_value(1), + "Maximal dimension of the Rips complex we want to compute.") + ("field-charac,p", po::value(&p)->default_value(11), + "Characteristic p of the coefficient field Z/pZ for computing homology.") + ("min-persistence,m", po::value(&min_persistence), + "Minimal lifetime of homology feature to be recorded. Default is 0. Enter a negative value to see zero length intervals"); + + po::positional_options_description pos; + pos.add("input-file", 1); + + po::options_description all; + all.add(visible).add(hidden); + + po::variables_map vm; + po::store(po::command_line_parser(argc, argv). + options(all).positional(pos).run(), vm); + po::notify(vm); + + if (vm.count("help") || !vm.count("input-file")) { + std::cout << std::endl; + std::cout << "Compute the persistent homology with coefficient field Z/pZ \n"; + std::cout << "of a sparse (1+epsilon)-approximation of the Rips complex \ndefined on a set of input points.\n \n"; + std::cout << "The output diagram contains one bar per line, written with the convention: \n"; + std::cout << " p dim b d \n"; + std::cout << "where dim is the dimension of the homological feature,\n"; + std::cout << "b and d are respectively the birth and death of the feature and \n"; + std::cout << "p is the characteristic of the field Z/pZ used for homology coefficients." << std::endl << std::endl; + + std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl << std::endl; + std::cout << visible << std::endl; + std::abort(); + } +} -- cgit v1.2.3 From 0402766ea6b40be945c7f1454386137ee88749c7 Mon Sep 17 00:00:00 2001 From: glisse Date: Tue, 16 Jan 2018 16:13:12 +0000 Subject: Some references for sparse Rips. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3138 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 56151faea78697afd3da72084f186d25b9252552 --- biblio/bibliography.bib | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index b101cb76..f2ff368d 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -1070,5 +1070,36 @@ language={English} year = {2015} } - - +@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}, + Volume = {58} + Pages = {70--96} + Year = {2016} +} + +@inproceedings{cavanna15geometric, + 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}, + Year = {2015} +} + +@inproceedings{cavanna15visualizing, + Author = {Nicholas J. Cavanna and Mahmoodreza Jahanseir and Donald R. Sheehy}, + Booktitle = {Proceedings of the 31st International Symposium on Computational Geometry}, + Title = {Visualizing Sparse Filtrations}, + Year = {2015}, + doi = {10.4230/LIPIcs.SOCG.2015.23} +} + +@article{sheehy13linear, + Title = {Linear-Size Approximations to the {V}ietoris-{R}ips Filtration}, + Author = {Donald R. Sheehy}, + Journal = {Discrete \& Computational Geometry}, + Volume = {49}, + Number = {4}, + Pages = {778--796}, + Year = {2013} +} -- cgit v1.2.3 From 1c28771ee5fd6acbbc3110adef8ae3c7b52d95e4 Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 22 Jan 2018 11:24:44 +0000 Subject: Some general doc. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3146 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8105c997b5541d0f3c8640e985de5d6810ab6be9 --- src/Rips_complex/doc/Intro_rips_complex.h | 66 +++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 124dfec9..54afad66 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -29,28 +29,38 @@ namespace rips_complex { /** \defgroup rips_complex Rips complex * - * \author Clément Maria, Pawel Dlotko, Vincent Rouvreau + * \author Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse * * @{ * * \section ripsdefinition Rips complex definition * - * Rips_complex - * (Wikipedia) 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 filtration value of each edge is computed from a user-given distance function, or directly from the distance - * matrix. + * The Vietoris-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. + * 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. + * + * This filtered complex is most often used as an approximation of the + * Čech complex (they share the same 1-skeleton and are multiplicatively + * 2-interleaved or better), which is slightly bigger but easier to compute. + * + * The number of simplices in the full Rips complex is exponential in the + * number of vertices, it is thus usually restricted, by excluding all the + * simplices with filtration value larger than some threshold, and keeping only + * the dim_max-skeleton. + * + * In order to build this complex, the algorithm first builds the graph. + * The filtration value of each edge is computed from a user-given distance + * function, or directly read from the distance matrix. + * In a second step, this graph is inserted in a simplicial complex, which then + * gets expanded to a flag complex. * - * All edges that have a filtration value strictly greater than a given threshold value are not inserted into - * the complex. + * The input can be given as a range of points and a distance function, or as a + * distance matrix. * - * 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). * * \image html "rips_complex_representation.png" "Rips-complex one skeleton graph representation" @@ -61,7 +71,31 @@ namespace rips_complex { * * 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. + * rips_persistence_step_by_step.cpp example, where the constructions of the graph and the Simplex_tree are more detailed. + * + * \section sparserips Sparse Rips complex + * + * Even truncated in filtration value and dimension, the Rips complex remains + * quite large. However, it is possible to approximate it by a much smaller + * filtered simplicial complex (linear size, with constants that depend on + * ε and the doubling dimension of the space) that is + * \f$(1+O(\epsilon))-\f$interleaved with it (in particular, their persistence + * diagrams are at log-bottleneck distance at most ε). + * + * The sparse Rips filtration was introduced by Don Sheehy \cite + * sheehy13linear. We are using the version from \cite buchet16efficient. + * A more intuitive presentation of the idea is available in \cite + * cavanna15geometric, and in a video \cite cavanna15visualizing. + * + * The interface of `Sparse_rips_complex` is similar to the one for the usual + * `Rips_complex`, except that one has to specify the approximation factor, and + * there is no option to limit the maximum filtration value (the way the + * approximation is done means that larger filtration values are much cheaper + * to handle than low filtration values, so the gain would be too small). + * + * Theoretical guarantees are only available for \f$\epsilon<1\f$. The + * construction accepts larger values of ε, and the size of the complex + * keeps decreasing, but there is no guarantee on the quality of the result. * * \section ripspointsdistance Point cloud and distance function * -- cgit v1.2.3 From 342a72ccb89f42109e709ae087d01fa6dcf98e39 Mon Sep 17 00:00:00 2001 From: glisse Date: Fri, 26 Jan 2018 10:22:30 +0000 Subject: doc for epsilon git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3162 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 02ec0665d288e7e68959aa188cd291924a7d1c8f --- src/Rips_complex/include/gudhi/Sparse_rips_complex.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h index c5378b6e..e1e3a951 100644 --- a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h +++ b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h @@ -46,7 +46,7 @@ namespace rips_complex { * \ingroup rips_complex * * \details - * This class is used to construct a sparse \f$(1+\epsilon)\f$-approximation of `Rips_complex`. + * This class is used to construct a sparse \f$(1+\epsilon)\f$-approximation of `Rips_complex`, i.e. a filtered simplicial complex that is multiplicatively \f$(1+\epsilon)\f$-interleaved with the Rips filtration. * * \tparam Filtration_value is the type used to store the filtration values of the simplicial complex. */ @@ -65,10 +65,12 @@ class Sparse_rips_complex { * * @param[in] points Range of points. * @param[in] distance distance function that returns a `Filtration_value` from 2 given points. + * @param[in] epsilon (1+epsilon) is the desired approximation factor. epsilon must be positive. * */ template Sparse_rips_complex(const RandomAccessPointRange& points, Distance distance, double epsilon) { + GUDHI_CHECK(epsilon > 0, "epsilon must be positive"); std::vector sorted_points; std::vector params; auto dist_fun = [&](Vertex_handle i, Vertex_handle j){return distance(points[i], points[j]);}; @@ -83,6 +85,7 @@ class Sparse_rips_complex { * `distance_matrix[i][j]` returns the distance between points \f$i\f$ and * \f$j\f$ as long as \f$ 0 \leqslant i < j \leqslant * distance\_matrix.size().\f$ + * @param[in] epsilon (1+epsilon) is the desired approximation factor. epsilon must be positive. */ template Sparse_rips_complex(const DistanceMatrix& distance_matrix, double epsilon) -- cgit v1.2.3 From 841ffc23f9e9b757bf4ab0813bdf86fb10908bd6 Mon Sep 17 00:00:00 2001 From: glisse Date: Fri, 26 Jan 2018 10:24:29 +0000 Subject: Bug in Persistent_cohomology: it computes H_1 for a 1-complex, while it does not compute H_2 for a 2-complex. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3163 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 0c027aa0c8f14e563ba1e707419b9dee1b84a610 --- src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index e0a147b3..a8c9afa3 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -285,7 +285,7 @@ class Persistent_cohomology { } } cpx_->assign_key(sigma, cpx_->null_key()); - } else { // If ku == kv, same connected component: create a 1-cocycle class. + } else if (dim_max_ > 1) { // If ku == kv, same connected component: create a 1-cocycle class. create_cocycle(sigma, coeff_field_.multiplicative_identity(), coeff_field_.characteristic()); } } -- cgit v1.2.3 From c4a3e9ad811034c21d7664f5e47457d2b7ffb888 Mon Sep 17 00:00:00 2001 From: glisse Date: Tue, 30 Jan 2018 16:22:07 +0000 Subject: Compile and doc utility git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3187 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b9d1ff7172a9012dcca747c97b9367dc5a78800f --- src/Rips_complex/utilities/CMakeLists.txt | 5 +++++ src/Rips_complex/utilities/README | 36 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/Rips_complex/utilities/CMakeLists.txt b/src/Rips_complex/utilities/CMakeLists.txt index baa571fa..55cf5a6a 100644 --- a/src/Rips_complex/utilities/CMakeLists.txt +++ b/src/Rips_complex/utilities/CMakeLists.txt @@ -7,9 +7,13 @@ target_link_libraries(rips_distance_matrix_persistence ${Boost_PROGRAM_OPTIONS_L add_executable(rips_persistence rips_persistence.cpp) target_link_libraries(rips_persistence ${Boost_PROGRAM_OPTIONS_LIBRARY}) +add_executable(sparse_rips_persistence sparse_rips_persistence.cpp) +target_link_libraries(sparse_rips_persistence ${Boost_PROGRAM_OPTIONS_LIBRARY}) + if (TBB_FOUND) target_link_libraries(rips_distance_matrix_persistence ${TBB_LIBRARIES}) target_link_libraries(rips_persistence ${TBB_LIBRARIES}) + target_link_libraries(sparse_rips_persistence ${TBB_LIBRARIES}) endif() add_test(NAME Rips_complex_utility_from_rips_distance_matrix COMMAND $ @@ -19,3 +23,4 @@ add_test(NAME Rips_complex_utility_from_rips_on_tore_3D COMMAND $` + +**Allowed options** + +* `-h [ --help ]` Produce help message +* `-o [ --output-file ]` Name of file in which the persistence diagram is written. Default print in standard output. +* `-e [ --approximation ]` (default = .5) Epsilon, where the sparse Rips complex is a (1+epsilon)-approximation of the Rips complex. +* `-d [ --cpx-dimension ]` (default = 1) Maximal dimension of the Rips complex we want to compute. +* `-p [ --field-charac ]` (default = 11) Characteristic p of the coefficient field Z/pZ for computing homology. +* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals. + +**Example with Z/2Z coefficients** +`rips_persistence ../../data/points/tore3D_1307.off -e .5 -m .1 -d 3 -p 2` + +outputs: +``` +The complex contains 16742034 simplices + and has dimension 3 +2 0 0 inf +2 1 0.0521735 0.645093 +2 2 0.0691677 0.289148 +2 1 0.0491747 0.265232 +``` -- cgit v1.2.3 From 258439dfbe0d109b1ab26e9b60370cafdc78ac3e Mon Sep 17 00:00:00 2001 From: glisse Date: Tue, 30 Jan 2018 16:31:13 +0000 Subject: Double all filtration values. It was using the Cech convention, not the Rips, so the Rips approximation was not close to the Rips, which is likely to confuse users. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3188 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7b948c956f39dc75931cb00a64516d08ff42e435 --- src/Rips_complex/doc/Intro_rips_complex.h | 4 +++- src/Rips_complex/include/gudhi/Sparse_rips_complex.h | 5 +++-- src/Rips_complex/utilities/README | 12 ++++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 54afad66..a9cfc0ab 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -83,7 +83,9 @@ namespace rips_complex { * diagrams are at log-bottleneck distance at most ε). * * The sparse Rips filtration was introduced by Don Sheehy \cite - * sheehy13linear. We are using the version from \cite buchet16efficient. + * sheehy13linear. We are using the version from \cite buchet16efficient + * (except that we multiply all filtration values by 2, to match the usual + * Rips complex). * A more intuitive presentation of the idea is available in \cite * cavanna15geometric, and in a video \cite cavanna15visualizing. * diff --git a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h index e1e3a951..b8850d00 100644 --- a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h +++ b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h @@ -152,10 +152,11 @@ class Sparse_rips_complex { GUDHI_CHECK(lj <= li, "Bad furthest point sorting"); Filtration_value alpha; + // The paper has d/2 and d-lj/e to match the Cech, but we use doubles to match the Rips if(d * epsilon <= 2 * lj) - alpha = d / 2; + alpha = d; else if(d * epsilon <= li + lj && (epsilon >= 1 || d * epsilon <= lj * (1 + 1 / (1 - epsilon)))) - alpha = d - lj / epsilon; + alpha = (d - lj / epsilon) * 2; else continue; add_edge(pi, pj, alpha, graph_); diff --git a/src/Rips_complex/utilities/README b/src/Rips_complex/utilities/README index 40fc58ba..390e31f8 100644 --- a/src/Rips_complex/utilities/README +++ b/src/Rips_complex/utilities/README @@ -97,14 +97,14 @@ where `dim` is the dimension of the homological feature, `birth` and `death` are * `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals. **Example with Z/2Z coefficients** -`rips_persistence ../../data/points/tore3D_1307.off -e .5 -m .1 -d 3 -p 2` +`rips_persistence ../../data/points/tore3D_1307.off -e .5 -m .2 -d 3 -p 2` -outputs: +may output (there is randomness involved): ``` -The complex contains 16742034 simplices +The complex contains 17002096 simplices and has dimension 3 2 0 0 inf -2 1 0.0521735 0.645093 -2 2 0.0691677 0.289148 -2 1 0.0491747 0.265232 +2 1 0.104347 1.29343 +2 2 0.138335 0.577743 +2 1 0.0983494 0.529708 ``` -- cgit v1.2.3 From c68ef729971d88818ceae9f1aa8e33f62a4dea7a Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 31 Jan 2018 13:41:06 +0000 Subject: Add example. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3195 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b8ded704563c6794c098f9b80b1a5e0200e84694 --- src/Rips_complex/doc/Intro_rips_complex.h | 16 ++++++++++ src/Rips_complex/example/CMakeLists.txt | 4 +++ src/Rips_complex/example/example_sparse_rips.cpp | 38 ++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 src/Rips_complex/example/example_sparse_rips.cpp diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index a9cfc0ab..96d90d98 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -182,6 +182,22 @@ namespace rips_complex { * * \include Rips_complex/full_skeleton_rips_for_doc.txt * + * \subsection sparseripspointscloudexample Example of a sparse Rips from a point cloud + * + * This example builds the full sparse Rips of a set of 2D Euclidean points, then prints some minimal information about the complex. + * + * \include Rips_complex/example_sparse_rips.cpp + * + * When launching: + * + * \code $> ./Rips_complex_example_sparse + * \endcode + * + * the program output may be (the exact output varies from one run to the next): + * + * \code Sparse Rips complex is of dimension 2 - 19 simplices - 7 vertices. + * \endcode + * * \copyright GNU General Public License v3. * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim */ diff --git a/src/Rips_complex/example/CMakeLists.txt b/src/Rips_complex/example/CMakeLists.txt index 2940f164..8a22a6d8 100644 --- a/src/Rips_complex/example/CMakeLists.txt +++ b/src/Rips_complex/example/CMakeLists.txt @@ -11,11 +11,15 @@ add_executable ( Rips_complex_example_one_skeleton_from_distance_matrix example_ add_executable ( Rips_complex_example_from_csv_distance_matrix example_rips_complex_from_csv_distance_matrix_file.cpp ) +# Point cloud +add_executable ( Rips_complex_example_sparse example_sparse_rips_complex.cpp ) + if (TBB_FOUND) target_link_libraries(Rips_complex_example_from_off ${TBB_LIBRARIES}) target_link_libraries(Rips_complex_example_one_skeleton_from_points ${TBB_LIBRARIES}) target_link_libraries(Rips_complex_example_one_skeleton_from_distance_matrix ${TBB_LIBRARIES}) target_link_libraries(Rips_complex_example_from_csv_distance_matrix ${TBB_LIBRARIES}) + target_link_libraries(Rips_complex_example_sparse ${TBB_LIBRARIES}) endif() add_test(NAME Rips_complex_example_one_skeleton_from_points diff --git a/src/Rips_complex/example/example_sparse_rips.cpp b/src/Rips_complex/example/example_sparse_rips.cpp new file mode 100644 index 00000000..49725f0a --- /dev/null +++ b/src/Rips_complex/example/example_sparse_rips.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +#include +#include + +int main() { + using Point = std::vector; + using Simplex_tree = Gudhi::Simplex_tree; + using Filtration_value = Simplex_tree::Filtration_value; + using Complex = Gudhi::rips_complex::Sparse_rips_complex; + + Point points[] = { + {1.0, 1.0}, + {7.0, 0.0}, + {4.0, 6.0}, + {9.0, 6.0}, + {0.0, 14.0}, + {2.0, 19.0}, + {9.0, 17.0}}; + + // ---------------------------------------------------------------------------- + // Init from Euclidean points + // ---------------------------------------------------------------------------- + double epsilon = 2; // very rough, no guarantees + Complex cpx(points, Gudhi::Euclidean_distance(), epsilon); + + Simplex_tree stree; + cpx.create_complex(stree, 10); + + // ---------------------------------------------------------------------------- + // Display information about the complex + // ---------------------------------------------------------------------------- + std::cout << "Sparse Rips complex is of dimension " << stree.dimension() << + " - " << stree.num_simplices() << " simplices - " << + stree.num_vertices() << " vertices." << std::endl; +} -- cgit v1.2.3 From 7b9b9dcdf26e283232195c9fb3b17f1cc23f0057 Mon Sep 17 00:00:00 2001 From: glisse Date: Wed, 31 Jan 2018 14:48:07 +0000 Subject: test git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3196 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 4fbf12d3a2adc56ee85a13fc35571de3963fee70 --- src/Rips_complex/example/example_sparse_rips.cpp | 6 +-- src/Rips_complex/test/test_rips_complex.cpp | 67 ++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/Rips_complex/example/example_sparse_rips.cpp b/src/Rips_complex/example/example_sparse_rips.cpp index 49725f0a..94e345ea 100644 --- a/src/Rips_complex/example/example_sparse_rips.cpp +++ b/src/Rips_complex/example/example_sparse_rips.cpp @@ -9,7 +9,7 @@ int main() { using Point = std::vector; using Simplex_tree = Gudhi::Simplex_tree; using Filtration_value = Simplex_tree::Filtration_value; - using Complex = Gudhi::rips_complex::Sparse_rips_complex; + using Sparse_rips = Gudhi::rips_complex::Sparse_rips_complex; Point points[] = { {1.0, 1.0}, @@ -24,10 +24,10 @@ int main() { // Init from Euclidean points // ---------------------------------------------------------------------------- double epsilon = 2; // very rough, no guarantees - Complex cpx(points, Gudhi::Euclidean_distance(), epsilon); + Sparse_rips sparse_rips(points, Gudhi::Euclidean_distance(), epsilon); Simplex_tree stree; - cpx.create_complex(stree, 10); + sparse_rips.create_complex(stree, 10); // ---------------------------------------------------------------------------- // Display information about the complex diff --git a/src/Rips_complex/test/test_rips_complex.cpp b/src/Rips_complex/test/test_rips_complex.cpp index 89afbc25..4e7b79d2 100644 --- a/src/Rips_complex/test/test_rips_complex.cpp +++ b/src/Rips_complex/test/test_rips_complex.cpp @@ -31,6 +31,7 @@ #include // std::max #include +#include // to construct Rips_complex from a OFF file of points #include #include @@ -43,6 +44,7 @@ using Point = std::vector; using Simplex_tree = Gudhi::Simplex_tree<>; using Filtration_value = Simplex_tree::Filtration_value; using Rips_complex = Gudhi::rips_complex::Rips_complex; +using Sparse_rips_complex = Gudhi::rips_complex::Sparse_rips_complex; using Distance_matrix = std::vector>; BOOST_AUTO_TEST_CASE(RIPS_DOC_OFF_file) { @@ -230,6 +232,71 @@ BOOST_AUTO_TEST_CASE(Rips_complex_from_points) { } } +BOOST_AUTO_TEST_CASE(Sparse_rips_complex_from_points) { + // This is a clone of the test above + // ---------------------------------------------------------------------------- + // Init of a list of points + // ---------------------------------------------------------------------------- + Vector_of_points points; + std::vector coords = { 0.0, 0.0, 0.0, 1.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 0.0, 0.0, 1.0, 0.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 0.0, 1.0, 0.0, 0.0 }; + points.push_back(Point(coords.begin(), coords.end())); + coords = { 1.0, 0.0, 0.0, 0.0 }; + points.push_back(Point(coords.begin(), coords.end())); + + // ---------------------------------------------------------------------------- + // Init of a Rips complex from the list of points + // ---------------------------------------------------------------------------- + // .001 is small enough that we get a deterministic result matching the exact Rips + Sparse_rips_complex sparse_rips(points, Custom_square_euclidean_distance(), .001); + + std::cout << "========== Sparse_rips_complex_from_points ==========" << std::endl; + Simplex_tree st; + const int DIMENSION = 3; + sparse_rips.create_complex(st, DIMENSION); + + // Another way to check num_simplices + std::cout << "Iterator on Rips complex simplices in the filtration order, with [filtration value]:" << std::endl; + int num_simplices = 0; + for (auto f_simplex : st.filtration_simplex_range()) { + num_simplices++; + std::cout << " ( "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << ") -> " << "[" << st.filtration(f_simplex) << "] "; + std::cout << std::endl; + } + BOOST_CHECK(num_simplices == 15); + std::cout << "st.num_simplices()=" << st.num_simplices() << std::endl; + BOOST_CHECK(st.num_simplices() == 15); + + std::cout << "st.dimension()=" << st.dimension() << std::endl; + BOOST_CHECK(st.dimension() == DIMENSION); + std::cout << "st.num_vertices()=" << st.num_vertices() << std::endl; + BOOST_CHECK(st.num_vertices() == 4); + + for (auto f_simplex : st.filtration_simplex_range()) { + std::cout << "dimension(" << st.dimension(f_simplex) << ") - f = " << st.filtration(f_simplex) << std::endl; + switch (st.dimension(f_simplex)) { + case 0: + GUDHI_TEST_FLOAT_EQUALITY_CHECK(st.filtration(f_simplex), 0.0); + break; + case 1: + case 2: + case 3: + GUDHI_TEST_FLOAT_EQUALITY_CHECK(st.filtration(f_simplex), 2.0); + break; + default: + BOOST_CHECK(false); // Shall not happen + break; + } + } +} + BOOST_AUTO_TEST_CASE(Rips_doc_csv_file) { // ---------------------------------------------------------------------------- // -- cgit v1.2.3 From d3ff96460cbcd7de4d1f2d03c61e4227dd4c4767 Mon Sep 17 00:00:00 2001 From: glisse Date: Thu, 1 Feb 2018 17:52:06 +0000 Subject: typo in CMakeLists.txt + minor reformulation in doc. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3200 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: de115e83e56358fd3d283b802f16a2cc4f6db4f2 --- src/Rips_complex/doc/Intro_rips_complex.h | 6 ++++-- src/Rips_complex/example/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 96d90d98..81f24c71 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -44,8 +44,10 @@ namespace rips_complex { * simplex is the diameter of the corresponding subset of points. * * This filtered complex is most often used as an approximation of the - * Čech complex (they share the same 1-skeleton and are multiplicatively - * 2-interleaved or better), which is slightly bigger but easier to compute. + * Čech complex. After rescaling (Rips using the length of the edges and Čech + * the half-length), they share the same 1-skeleton and are multiplicatively + * 2-interleaved or better. While it is slightly bigger, it is also much + * easier to compute. * * The number of simplices in the full Rips complex is exponential in the * number of vertices, it is thus usually restricted, by excluding all the diff --git a/src/Rips_complex/example/CMakeLists.txt b/src/Rips_complex/example/CMakeLists.txt index 8a22a6d8..d05d3e57 100644 --- a/src/Rips_complex/example/CMakeLists.txt +++ b/src/Rips_complex/example/CMakeLists.txt @@ -12,7 +12,7 @@ add_executable ( Rips_complex_example_one_skeleton_from_distance_matrix example_ add_executable ( Rips_complex_example_from_csv_distance_matrix example_rips_complex_from_csv_distance_matrix_file.cpp ) # Point cloud -add_executable ( Rips_complex_example_sparse example_sparse_rips_complex.cpp ) +add_executable ( Rips_complex_example_sparse example_sparse_rips.cpp ) if (TBB_FOUND) target_link_libraries(Rips_complex_example_from_off ${TBB_LIBRARIES}) -- cgit v1.2.3 From 7100f2e782d21bfbbb3947ba66fe235b424e2902 Mon Sep 17 00:00:00 2001 From: glisse Date: Thu, 1 Feb 2018 18:21:07 +0000 Subject: Really remove README, merge didn't dare. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3202 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 7b05c5e75821d6a1b0759db13d326a6e142cc01b --- src/Rips_complex/utilities/README | 110 -------------------------------------- 1 file changed, 110 deletions(-) delete mode 100644 src/Rips_complex/utilities/README diff --git a/src/Rips_complex/utilities/README b/src/Rips_complex/utilities/README deleted file mode 100644 index 390e31f8..00000000 --- a/src/Rips_complex/utilities/README +++ /dev/null @@ -1,110 +0,0 @@ -# Rips_complex # - -## `rips_persistence` ## -This program computes the persistent homology with coefficient field *Z/pZ* of a Rips complex defined on a set of input points. The output diagram contains one bar per line, written with the convention: - -`p dim birth death` - -where `dim` is the dimension of the homological feature, `birth` and `death` are respectively the birth and death of the feature, and `p` is the characteristic of the field *Z/pZ* used for homology coefficients (`p` must be a prime number). - -**Usage** -`rips_persistence [options] ` - -**Allowed options** - -* `-h [ --help ]` Produce help message -* `-o [ --output-file ]` Name of file in which the persistence diagram is written. Default print in standard output. -* `-r [ --max-edge-length ]` (default = inf) Maximal length of an edge for the Rips complex construction. -* `-d [ --cpx-dimension ]` (default = 1) Maximal dimension of the Rips complex we want to compute. -* `-p [ --field-charac ]` (default = 11) Characteristic p of the coefficient field Z/pZ for computing homology. -* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals. - -Beware: this program may use a lot of RAM and take a lot of time if `max-edge-length` is set to a large value. - -**Example 1 with Z/2Z coefficients** -`rips_persistence ../../data/points/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 2` - -outputs: -``` -2 0 0 inf -2 1 0.0983494 inf -2 1 0.104347 inf -2 2 0.138335 inf -``` - -**Example 2 with Z/3Z coefficients** - -rips_persistence ../../data/points/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 3 - -outputs: -``` -3 0 0 inf -3 1 0.0983494 inf -3 1 0.104347 inf -3 2 0.138335 inf -``` - - - - -## `rips_distance_matrix_persistence` ## -Same as `rips_persistence` but taking a distance matrix as input. - -**Usage** -`rips_persistence [options] ` -where -`` is the path to the file containing a distance matrix. Can be square or lower triangular matrix. Separator is ';'. - -**Example** -`rips_distance_matrix_persistence data/distance_matrix/full_square_distance_matrix.csv -r 15 -d 3 -p 3 -m 0` - -outputs: -``` -The complex contains 46 simplices - and has dimension 3 -3 0 0 inf -3 0 0 8.94427 -3 0 0 7.28011 -3 0 0 6.08276 -3 0 0 5.83095 -3 0 0 5.38516 -3 0 0 5 -3 1 11 12.0416 -3 1 6.32456 6.7082 -``` - - - - -## `rips_persistence` ## -This program computes the persistent homology with coefficient field *Z/pZ* -of a sparse (1+epsilon)-approximation of the Rips complex defined on a set of input points. The output diagram contains one bar per line, written with the convention: - -`p dim birth death` - -where `dim` is the dimension of the homological feature, `birth` and `death` are respectively the birth and death of the feature, and `p` is the characteristic of the field *Z/pZ* used for homology coefficients (`p` must be a prime number). - -**Usage** -`sparse_rips_persistence [options] ` - -**Allowed options** - -* `-h [ --help ]` Produce help message -* `-o [ --output-file ]` Name of file in which the persistence diagram is written. Default print in standard output. -* `-e [ --approximation ]` (default = .5) Epsilon, where the sparse Rips complex is a (1+epsilon)-approximation of the Rips complex. -* `-d [ --cpx-dimension ]` (default = 1) Maximal dimension of the Rips complex we want to compute. -* `-p [ --field-charac ]` (default = 11) Characteristic p of the coefficient field Z/pZ for computing homology. -* `-m [ --min-persistence ]` (default = 0) Minimal lifetime of homology feature to be recorded. Enter a negative value to see zero length intervals. - -**Example with Z/2Z coefficients** -`rips_persistence ../../data/points/tore3D_1307.off -e .5 -m .2 -d 3 -p 2` - -may output (there is randomness involved): -``` -The complex contains 17002096 simplices - and has dimension 3 -2 0 0 inf -2 1 0.104347 1.29343 -2 2 0.138335 0.577743 -2 1 0.0983494 0.529708 -``` -- cgit v1.2.3 From 5784ad59e5a23ba06dae59e14e7281dd6164aa30 Mon Sep 17 00:00:00 2001 From: glisse Date: Thu, 1 Feb 2018 20:35:01 +0000 Subject: Avoid line breaks between \cite and key. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3204 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 292a7f7d5cbbe6c4c79fa2a16416fa6e3983b9fd --- src/Rips_complex/doc/Intro_rips_complex.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index d09c92a4..382ceef2 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -84,12 +84,12 @@ namespace rips_complex { * \f$(1+O(\epsilon))-\f$interleaved with it (in particular, their persistence * diagrams are at log-bottleneck distance at most ε). * - * The sparse Rips filtration was introduced by Don Sheehy \cite - * sheehy13linear. We are using the version from \cite buchet16efficient + * The sparse Rips filtration was introduced by Don Sheehy + * \cite sheehy13linear. We are using the version from \cite buchet16efficient * (except that we multiply all filtration values by 2, to match the usual * Rips complex). - * A more intuitive presentation of the idea is available in \cite - * cavanna15geometric, and in a video \cite cavanna15visualizing. + * A more intuitive presentation of the idea is available in + * \cite cavanna15geometric, and in a video \cite cavanna15visualizing. * * The interface of `Sparse_rips_complex` is similar to the one for the usual * `Rips_complex`, except that one has to specify the approximation factor, and -- cgit v1.2.3 From 531536c7c68dda2d605ee3ed001d7d020545cefd Mon Sep 17 00:00:00 2001 From: glisse Date: Thu, 1 Feb 2018 21:05:14 +0000 Subject: Add myself to how-to-cite. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3205 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 160430d4cc3e910870e8b727c8b54c930fa0363f --- biblio/how_to_cite_gudhi.bib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biblio/how_to_cite_gudhi.bib b/biblio/how_to_cite_gudhi.bib index 5994124a..942f8d7e 100644 --- a/biblio/how_to_cite_gudhi.bib +++ b/biblio/how_to_cite_gudhi.bib @@ -97,7 +97,7 @@ } @incollection{gudhi:RipsComplex -, author = "Cl\'ement Maria, Pawel Dlotko, Vincent Rouvreau" +, author = "Cl\'ement Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse" , title = "Rips complex" , publisher = "{GUDHI Editorial Board}" , booktitle = "{GUDHI} User and Reference Manual" -- cgit v1.2.3 From da0a70444fdfb6f43894ff8bda32e1767cc4eaba Mon Sep 17 00:00:00 2001 From: glisse Date: Thu, 1 Feb 2018 21:15:58 +0000 Subject: git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3206 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 8b4c9b0d6054aa75bd39113d246e43ee051d0658 --- src/Rips_complex/utilities/ripscomplex.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rips_complex/utilities/ripscomplex.md b/src/Rips_complex/utilities/ripscomplex.md index 3bf10aee..82163dae 100644 --- a/src/Rips_complex/utilities/ripscomplex.md +++ b/src/Rips_complex/utilities/ripscomplex.md @@ -51,7 +51,7 @@ where ## sparse_rips_persistence ## This program computes the persistent homology with coefficient field *Z/pZ* -of a sparse (1+epsilon)-approximation of the Rips complex defined on a set of input points. The output diagram contains one bar per line, written with the convention: +of a sparse (1+epsilon)-approximation of the Rips complex defined on a set of input Euclidean points. The output diagram contains one bar per line, written with the convention: `p dim birth death` -- cgit v1.2.3 From 5b111da29bbdc9c0db8bd0d776379d8dd153c4b2 Mon Sep 17 00:00:00 2001 From: glisse Date: Thu, 1 Feb 2018 21:57:27 +0000 Subject: Move sparse example outside of the "distance" section. git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3207 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: cca8dee4bf43082286fc9ce1eae5d366c17a333f --- src/Rips_complex/doc/Intro_rips_complex.h | 33 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 382ceef2..f9663315 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -142,6 +142,23 @@ namespace rips_complex { * * \include Rips_complex/full_skeleton_rips_for_doc.txt * + * + * \subsection sparseripspointscloudexample Example of a sparse Rips from a point cloud + * + * This example builds the full sparse Rips of a set of 2D Euclidean points, then prints some minimal information about the complex. + * + * \include Rips_complex/example_sparse_rips.cpp + * + * When launching: + * + * \code $> ./Rips_complex_example_sparse + * \endcode + * + * the program output may be (the exact output varies from one run to the next): + * + * \code Sparse Rips complex is of dimension 2 - 19 simplices - 7 vertices. + * \endcode + * * * * \section ripsdistancematrix Distance matrix @@ -184,22 +201,6 @@ namespace rips_complex { * * \include Rips_complex/full_skeleton_rips_for_doc.txt * - * \subsection sparseripspointscloudexample Example of a sparse Rips from a point cloud - * - * This example builds the full sparse Rips of a set of 2D Euclidean points, then prints some minimal information about the complex. - * - * \include Rips_complex/example_sparse_rips.cpp - * - * When launching: - * - * \code $> ./Rips_complex_example_sparse - * \endcode - * - * the program output may be (the exact output varies from one run to the next): - * - * \code Sparse Rips complex is of dimension 2 - 19 simplices - 7 vertices. - * \endcode - * */ /** @} */ // end defgroup rips_complex -- cgit v1.2.3 From c6957d5b3d8e410b6104a848c793d633fba8990a Mon Sep 17 00:00:00 2001 From: glisse Date: Thu, 1 Feb 2018 22:00:19 +0000 Subject: git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3208 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 2e0fd8691e04dd1088673910258017802370d265 --- src/Rips_complex/include/gudhi/Sparse_rips_complex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h index b8850d00..44b73930 100644 --- a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h +++ b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h @@ -79,7 +79,7 @@ class Sparse_rips_complex { compute_sparse_graph(sorted_points, params, dist_fun, epsilon); } - /** \brief Rips_complex constructor from a distance matrix. + /** \brief Sparse_rips_complex constructor from a distance matrix. * * @param[in] distance_matrix Range of range of distances. * `distance_matrix[i][j]` returns the distance between points \f$i\f$ and -- cgit v1.2.3 From bae3210f6fb5ef1c498ef669c067b21cd6ddf953 Mon Sep 17 00:00:00 2001 From: glisse Date: Fri, 2 Feb 2018 13:31:23 +0000 Subject: epsilon git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3209 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: c7cac815867c94821d13d8dd972e6505c43b04ba --- src/Rips_complex/doc/Intro_rips_complex.h | 6 ++++-- src/Rips_complex/include/gudhi/Sparse_rips_complex.h | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index f9663315..909735cd 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -82,12 +82,14 @@ namespace rips_complex { * filtered simplicial complex (linear size, with constants that depend on * ε and the doubling dimension of the space) that is * \f$(1+O(\epsilon))-\f$interleaved with it (in particular, their persistence - * diagrams are at log-bottleneck distance at most ε). + * diagrams are at log-bottleneck distance at most \f$O(\epsilon)\f$). * * The sparse Rips filtration was introduced by Don Sheehy * \cite sheehy13linear. We are using the version from \cite buchet16efficient * (except that we multiply all filtration values by 2, to match the usual - * Rips complex). + * Rips complex), which proves a + * \f$\frac{1+\epsilon}{1-\epsilon}\f$-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. * diff --git a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h index 44b73930..503a783a 100644 --- a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h +++ b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h @@ -46,7 +46,7 @@ namespace rips_complex { * \ingroup rips_complex * * \details - * This class is used to construct a sparse \f$(1+\epsilon)\f$-approximation of `Rips_complex`, i.e. a filtered simplicial complex that is multiplicatively \f$(1+\epsilon)\f$-interleaved with the Rips filtration. + * This class is used to construct a sparse \f$(1+O(\epsilon))\f$-approximation of `Rips_complex`, i.e. a filtered simplicial complex that is multiplicatively \f$(1+O(\epsilon))\f$-interleaved with the Rips filtration. * * \tparam Filtration_value is the type used to store the filtration values of the simplicial complex. */ @@ -64,8 +64,8 @@ class Sparse_rips_complex { /** \brief Sparse_rips_complex constructor from a list of points. * * @param[in] points Range of points. - * @param[in] distance distance function that returns a `Filtration_value` from 2 given points. - * @param[in] epsilon (1+epsilon) is the desired approximation factor. epsilon must be positive. + * @param[in] distance Distance function that returns a `Filtration_value` from 2 given points. + * @param[in] epsilon Approximation parameter. epsilon must be positive. * */ template @@ -85,7 +85,7 @@ class Sparse_rips_complex { * `distance_matrix[i][j]` returns the distance between points \f$i\f$ and * \f$j\f$ as long as \f$ 0 \leqslant i < j \leqslant * distance\_matrix.size().\f$ - * @param[in] epsilon (1+epsilon) is the desired approximation factor. epsilon must be positive. + * @param[in] epsilon Approximation parameter. epsilon must be positive. */ template Sparse_rips_complex(const DistanceMatrix& distance_matrix, double epsilon) -- cgit v1.2.3 From ffaf89887efb301c8989284e34574f25b26d20d0 Mon Sep 17 00:00:00 2001 From: glisse Date: Fri, 2 Feb 2018 13:42:26 +0000 Subject: year git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3210 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: f962c12e4016ddcd498265c57add0c432212b4dc --- src/Rips_complex/utilities/sparse_rips_persistence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rips_complex/utilities/sparse_rips_persistence.cpp b/src/Rips_complex/utilities/sparse_rips_persistence.cpp index 12b3b099..dd0b2592 100644 --- a/src/Rips_complex/utilities/sparse_rips_persistence.cpp +++ b/src/Rips_complex/utilities/sparse_rips_persistence.cpp @@ -4,7 +4,7 @@ * * Author(s): Marc Glisse, Clément Maria * - * Copyright (C) 2014 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 -- cgit v1.2.3 From c1ddf3c7d276e946064c09c77b6969a71afaf41b Mon Sep 17 00:00:00 2001 From: glisse Date: Thu, 8 Feb 2018 08:43:40 +0000 Subject: pasto git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3230 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: b6d3b0a18215b9541b72f2c7097717d5bfb65574 --- src/Rips_complex/utilities/ripscomplex.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rips_complex/utilities/ripscomplex.md b/src/Rips_complex/utilities/ripscomplex.md index 82163dae..421caa7d 100644 --- a/src/Rips_complex/utilities/ripscomplex.md +++ b/src/Rips_complex/utilities/ripscomplex.md @@ -72,4 +72,4 @@ where `dim` is the dimension of the homological feature, `birth` and `death` are **Example with Z/2Z coefficients** -`rips_persistence ../../data/points/tore3D_1307.off -e .5 -m .2 -d 3 -p 2` +`sparse_rips_persistence ../../data/points/tore3D_1307.off -e .5 -m .2 -d 3 -p 2` -- cgit v1.2.3 From 11c9005fb1c9be03e208323a6933af66e87813a6 Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 12 Mar 2018 15:55:23 +0000 Subject: git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3278 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 68262663f0fbeceef2a81929e42799479e7038f8 --- src/Rips_complex/doc/Intro_rips_complex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 909735cd..9cc58412 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -85,9 +85,9 @@ namespace rips_complex { * diagrams are at log-bottleneck distance at most \f$O(\epsilon)\f$). * * The sparse Rips filtration was introduced by Don Sheehy - * \cite sheehy13linear. We are using the version from \cite buchet16efficient - * (except that we multiply all filtration values by 2, to match the usual - * Rips complex), which proves a + * \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 * \f$\frac{1+\epsilon}{1-\epsilon}\f$-interleaving, although in practice the * error is usually smaller. * A more intuitive presentation of the idea is available in -- cgit v1.2.3 From 9a60bbaf5b0895ccc24a545aafe5190b2d108126 Mon Sep 17 00:00:00 2001 From: glisse Date: Mon, 12 Mar 2018 16:00:24 +0000 Subject: untested git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/sparserips-glisse@3279 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 327de60f56f1c0baa9dfdcbd4ca86afa43fcc053 --- src/Rips_complex/utilities/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Rips_complex/utilities/CMakeLists.txt b/src/Rips_complex/utilities/CMakeLists.txt index 55cf5a6a..b245eb08 100644 --- a/src/Rips_complex/utilities/CMakeLists.txt +++ b/src/Rips_complex/utilities/CMakeLists.txt @@ -20,6 +20,8 @@ add_test(NAME Rips_complex_utility_from_rips_distance_matrix COMMAND $ "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-r" "0.25" "-m" "0.5" "-d" "3" "-p" "3") +add_test(NAME Sparse_rips_complex_utility_on_tore_3D COMMAND $ + "${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off" "-e" "0.5" "-m" "0.2" "-d" "3" "-p" "2") install(TARGETS rips_distance_matrix_persistence DESTINATION bin) install(TARGETS rips_persistence DESTINATION bin) -- cgit v1.2.3