summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorskachano <skachano@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2017-02-22 16:49:21 +0000
committerskachano <skachano@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2017-02-22 16:49:21 +0000
commit899838ae83f4a9cea085ba877e91a7ca035fbb4d (patch)
tree76c56df09e6ad006f94aa46b0d355492e4830f4b /src
parent81575612aaa0552307a6c744c327765ff89165e4 (diff)
parent707120336966af3dffb8b54cd0095fc1bcc3836d (diff)
Merged with trunk + minor changes
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/relaxed-witness@2094 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 6b23778cbe43e7697cd325039e843758a263d927
Diffstat (limited to 'src')
-rw-r--r--src/Bottleneck_distance/benchmark/CMakeLists.txt4
-rw-r--r--src/Bottleneck_distance/concept/Persistence_diagram.h13
-rw-r--r--src/Bottleneck_distance/doc/Intro_bottleneck_distance.h6
-rw-r--r--src/Bottleneck_distance/example/CMakeLists.txt17
-rw-r--r--src/Bottleneck_distance/example/alpha_rips_persistence_bottleneck_distance.cpp190
-rw-r--r--src/Bottleneck_distance/example/bottleneck_basic_example.cpp6
-rw-r--r--src/Bottleneck_distance/example/bottleneck_read_file_example.cpp2
-rw-r--r--src/Bottleneck_distance/include/gudhi/Bottleneck.h30
-rw-r--r--src/Bottleneck_distance/include/gudhi/Graph_matching.h3
-rw-r--r--src/Bottleneck_distance/include/gudhi/Neighbors_finder.h1
-rw-r--r--src/Bottleneck_distance/include/gudhi/Persistence_graph.h12
-rw-r--r--src/Bottleneck_distance/test/CMakeLists.txt14
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/Doxyfile10
-rw-r--r--src/GudhUI/CMakeLists.txt67
-rw-r--r--src/GudhUI/gui/MainWindow.h3
-rw-r--r--src/GudhUI/gui/Menu_edge_contraction.h5
-rw-r--r--src/GudhUI/gui/Menu_k_nearest_neighbors.h2
-rw-r--r--src/GudhUI/gui/Menu_persistence.h2
-rw-r--r--src/GudhUI/gui/Menu_uniform_neighbors.h2
-rw-r--r--src/GudhUI/utils/Persistence_compute.h17
-rw-r--r--src/GudhUI/view/Viewer.h3
-rw-r--r--src/GudhUI/view/Viewer_instructor.h3
-rw-r--r--src/Persistent_cohomology/benchmark/CMakeLists.txt14
-rw-r--r--src/Persistent_cohomology/benchmark/performance_rips_persistence.cpp (renamed from src/Persistent_cohomology/example/performance_rips_persistence.cpp)36
-rw-r--r--src/Persistent_cohomology/doc/Intro_persistent_cohomology.h20
-rw-r--r--src/Persistent_cohomology/example/CMakeLists.txt20
-rw-r--r--src/Persistent_cohomology/example/README50
-rw-r--r--src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp5
-rw-r--r--src/Persistent_cohomology/example/alpha_complex_persistence.cpp7
-rw-r--r--src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp19
-rw-r--r--src/Persistent_cohomology/example/persistence_from_simple_simplex_tree.cpp19
-rw-r--r--src/Persistent_cohomology/example/rips_distance_matrix_persistence.cpp144
-rw-r--r--src/Persistent_cohomology/example/rips_multifield_persistence.cpp58
-rw-r--r--src/Persistent_cohomology/example/rips_persistence.cpp60
-rw-r--r--src/Persistent_cohomology/example/rips_persistence_step_by_step.cpp217
-rw-r--r--src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp52
-rw-r--r--src/Persistent_cohomology/test/persistent_cohomology_unit_test_multi_field.cpp4
-rw-r--r--src/Rips_complex/concept/Simplicial_complex_for_rips.h54
-rw-r--r--src/Rips_complex/doc/Intro_rips_complex.h158
-rw-r--r--src/Rips_complex/doc/rips_complex_representation.ipe326
-rw-r--r--src/Rips_complex/doc/rips_complex_representation.pngbin0 -> 15677 bytes
-rw-r--r--src/Rips_complex/doc/rips_one_skeleton.ipe326
-rw-r--r--src/Rips_complex/doc/rips_one_skeleton.pngbin0 -> 47651 bytes
-rw-r--r--src/Rips_complex/example/CMakeLists.txt47
-rw-r--r--src/Rips_complex/example/example_one_skeleton_rips_from_distance_matrix.cpp58
-rw-r--r--src/Rips_complex/example/example_one_skeleton_rips_from_points.cpp52
-rw-r--r--src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp72
-rw-r--r--src/Rips_complex/example/example_rips_complex_from_off_file.cpp71
-rw-r--r--src/Rips_complex/example/full_skeleton_rips_for_doc.txt26
-rw-r--r--src/Rips_complex/example/one_skeleton_rips_for_doc.txt20
-rw-r--r--src/Rips_complex/include/gudhi/Rips_complex.h185
-rw-r--r--src/Rips_complex/test/CMakeLists.txt25
-rw-r--r--src/Rips_complex/test/README12
-rw-r--r--src/Rips_complex/test/test_rips_complex.cpp353
-rw-r--r--src/Simplex_tree/example/simple_simplex_tree.cpp15
-rw-r--r--src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp11
-rw-r--r--src/Simplex_tree/test/simplex_tree_unit_test.cpp69
-rw-r--r--src/Witness_complex/example/example_strong_witness_complex_off.cpp2
-rw-r--r--src/Witness_complex/example/example_witness_complex_off.cpp2
-rw-r--r--src/Witness_complex/test/test_simple_witness_complex.cpp1
-rw-r--r--src/cmake/modules/FindQGLViewer.cmake2
-rw-r--r--src/cmake/modules/GUDHI_user_version_target.txt12
-rw-r--r--src/common/doc/main_page.h48
-rw-r--r--src/common/example/example_CGAL_3D_points_off_reader.cpp2
-rw-r--r--src/common/example/example_CGAL_points_off_reader.cpp2
-rw-r--r--src/common/include/gudhi/distance_functions.h34
-rw-r--r--src/common/include/gudhi/graph_simplicial_complex.h59
-rw-r--r--src/common/include/gudhi/reader_utils.h166
-rw-r--r--src/common/test/CMakeLists.txt9
-rw-r--r--src/common/test/test_distance_matrix_reader.cpp85
-rw-r--r--src/common/test/test_points_off_reader.cpp2
72 files changed, 2999 insertions, 445 deletions
diff --git a/src/Bottleneck_distance/benchmark/CMakeLists.txt b/src/Bottleneck_distance/benchmark/CMakeLists.txt
index f70dd8ff..355e8d31 100644
--- a/src/Bottleneck_distance/benchmark/CMakeLists.txt
+++ b/src/Bottleneck_distance/benchmark/CMakeLists.txt
@@ -6,8 +6,6 @@ project(Bottleneck_distance_benchmark)
# cmake -DCGAL_DIR=~/workspace/CGAL-4.8 ../../..
if(CGAL_FOUND)
if (NOT CGAL_VERSION VERSION_LESS 4.8.0)
- if (EIGEN3_FOUND)
- add_executable ( bottleneck_chrono bottleneck_chrono.cpp )
- endif()
+ add_executable ( bottleneck_chrono bottleneck_chrono.cpp )
endif ()
endif()
diff --git a/src/Bottleneck_distance/concept/Persistence_diagram.h b/src/Bottleneck_distance/concept/Persistence_diagram.h
index 2706716b..b157f22a 100644
--- a/src/Bottleneck_distance/concept/Persistence_diagram.h
+++ b/src/Bottleneck_distance/concept/Persistence_diagram.h
@@ -25,24 +25,25 @@
namespace Gudhi {
-namespace bottleneck_distance {
+namespace persistence_diagram {
-/** \brief Concept of Diagram_point. std::get<0>(point) must return the birth of the corresponding component and std::get<1>(point) its death.
+/** \brief Concept of point in a persistence diagram. std::get<0>(point) must return the birth of the corresponding component and std::get<1>(point) its death.
+ * Both should be convertible to `double`.
* A valid implementation of this concept is std::pair<double,double>.
* Death should be larger than birth, death can be std::numeric_limits<double>::infinity() for components which stay alive.
*
* \ingroup bottleneck_distance
*/
-typename Diagram_point;
+struct DiagramPoint{};
-/** \brief Concept of persistence diagram. It's a range of Diagram_point.
+/** \brief Concept of persistence diagram. It is a range of `DiagramPoint`.
* std::begin(diagram) and std::end(diagram) must return corresponding iterators.
*
* \ingroup bottleneck_distance
*/
-typename Persistence_Diagram;
+struct PersistenceDiagram{};
-} // namespace bottleneck_distance
+} // namespace persistence_diagram
} // namespace Gudhi
diff --git a/src/Bottleneck_distance/doc/Intro_bottleneck_distance.h b/src/Bottleneck_distance/doc/Intro_bottleneck_distance.h
index 21187f9c..5223678d 100644
--- a/src/Bottleneck_distance/doc/Intro_bottleneck_distance.h
+++ b/src/Bottleneck_distance/doc/Intro_bottleneck_distance.h
@@ -26,7 +26,7 @@
// needs namespace for Doxygen to link on classes
namespace Gudhi {
// needs namespace for Doxygen to link on classes
-namespace bottleneck_distance {
+namespace persistence_diagram {
/** \defgroup bottleneck_distance Bottleneck distance
*
@@ -35,7 +35,7 @@ namespace bottleneck_distance {
*
* \section bottleneckdefinition Definition
*
- * The bottleneck distance measures the similarity between two persistence diagrams. It's the shortest distance b for which there exists a perfect matching between
+ * The bottleneck distance measures the similarity between two persistence diagrams. It is the shortest distance b for which there exists a perfect matching between
* the points of the two diagrams (completed with all the points on the diagonal in order to ignore cardinality mismatchs) such that
* any couple of matched points are at distance at most b.
*
@@ -44,7 +44,7 @@ namespace bottleneck_distance {
*/
/** @} */ // end defgroup bottleneck_distance
-} // namespace bottleneck_distance
+} // namespace persistence_diagram
} // namespace Gudhi
diff --git a/src/Bottleneck_distance/example/CMakeLists.txt b/src/Bottleneck_distance/example/CMakeLists.txt
index c66623e9..b36d0f34 100644
--- a/src/Bottleneck_distance/example/CMakeLists.txt
+++ b/src/Bottleneck_distance/example/CMakeLists.txt
@@ -5,11 +5,18 @@ project(Bottleneck_distance_examples)
# cmake -DCGAL_DIR=~/workspace/CGAL-4.8 ../../..
if(CGAL_FOUND)
if (NOT CGAL_VERSION VERSION_LESS 4.8.0)
- if (EIGEN3_FOUND)
- add_executable (bottleneck_read_file_example bottleneck_read_file_example.cpp)
- add_executable (bottleneck_basic_example bottleneck_basic_example.cpp)
+ add_executable (bottleneck_read_file_example bottleneck_read_file_example.cpp)
+ add_executable (bottleneck_basic_example bottleneck_basic_example.cpp)
+
+ add_test(bottleneck_basic_example ${CMAKE_CURRENT_BINARY_DIR}/bottleneck_basic_example)
+
+ add_executable (alpha_rips_persistence_bottleneck_distance alpha_rips_persistence_bottleneck_distance.cpp)
+ target_link_libraries(alpha_rips_persistence_bottleneck_distance ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(alpha_rips_persistence_bottleneck_distance ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
+ add_test(alpha_rips_persistence_bottleneck_distance ${CMAKE_CURRENT_BINARY_DIR}/alpha_rips_persistence_bottleneck_distance
+ ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off -r 0.15 -m 0.12 -d 3 -p 3)
- add_test(bottleneck_basic_example ${CMAKE_CURRENT_BINARY_DIR}/bottleneck_basic_example)
- endif()
endif ()
endif()
diff --git a/src/Bottleneck_distance/example/alpha_rips_persistence_bottleneck_distance.cpp b/src/Bottleneck_distance/example/alpha_rips_persistence_bottleneck_distance.cpp
new file mode 100644
index 00000000..6e9be97b
--- /dev/null
+++ b/src/Bottleneck_distance/example/alpha_rips_persistence_bottleneck_distance.cpp
@@ -0,0 +1,190 @@
+/* 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): Vincent Rouvreau
+ *
+ * Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <gudhi/Alpha_complex.h>
+#include <gudhi/Rips_complex.h>
+#include <gudhi/distance_functions.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/Points_off_io.h>
+#include <gudhi/Bottleneck.h>
+
+#include <CGAL/Epick_d.h>
+
+#include <boost/program_options.hpp>
+
+#include <string>
+#include <vector>
+#include <limits> // infinity
+#include <utility> // for pair
+#include <algorithm> // for transform
+
+
+// Types definition
+using Simplex_tree = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+using Field_Zp = Gudhi::persistent_cohomology::Field_Zp;
+using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Field_Zp >;
+using Kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >;
+using Point_d = Kernel::Point_d;
+using Points_off_reader = Gudhi::Points_off_reader<Point_d>;
+
+void program_options(int argc, char * argv[]
+ , std::string & off_file_points
+ , Filtration_value & threshold
+ , int & dim_max
+ , int & p
+ , Filtration_value & min_persistence);
+
+static inline std::pair<double, double> compute_root_square (std::pair<double, double> input) {
+ return std::make_pair(std::sqrt(input.first), std::sqrt(input.second));
+}
+
+int main(int argc, char * argv[]) {
+ std::string off_file_points;
+ Filtration_value threshold;
+ int dim_max;
+ int p;
+ Filtration_value min_persistence;
+
+ program_options(argc, argv, off_file_points, threshold, dim_max, p, min_persistence);
+
+ Points_off_reader off_reader(off_file_points);
+
+ // --------------------------------------------
+ // Rips persistence
+ // --------------------------------------------
+ Rips_complex rips_complex(off_reader.get_point_cloud(), threshold, Euclidean_distance());
+
+ // Construct the Rips complex in a Simplex Tree
+ Simplex_tree rips_stree;
+
+ rips_complex.create_complex(rips_stree, dim_max);
+ std::cout << "The Rips complex contains " << rips_stree.num_simplices() << " simplices and has dimension "
+ << rips_stree.dimension() << " \n";
+
+ // Sort the simplices in the order of the filtration
+ rips_stree.initialize_filtration();
+
+ // Compute the persistence diagram of the complex
+ Persistent_cohomology rips_pcoh(rips_stree);
+ // initializes the coefficient field for homology
+ rips_pcoh.init_coefficients(p);
+ rips_pcoh.compute_persistent_cohomology(min_persistence);
+
+ // rips_pcoh.output_diagram();
+
+ // --------------------------------------------
+ // Alpha persistence
+ // --------------------------------------------
+ Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex(off_reader.get_point_cloud());
+
+ Simplex_tree alpha_stree;
+ alpha_complex.create_complex(alpha_stree, threshold * threshold);
+ std::cout << "The Alpha complex contains " << alpha_stree.num_simplices() << " simplices and has dimension "
+ << alpha_stree.dimension() << " \n";
+
+ // Sort the simplices in the order of the filtration
+ alpha_stree.initialize_filtration();
+
+ // Compute the persistence diagram of the complex
+ Persistent_cohomology alpha_pcoh(alpha_stree);
+ // initializes the coefficient field for homology
+ alpha_pcoh.init_coefficients(p);
+ alpha_pcoh.compute_persistent_cohomology(min_persistence * min_persistence);
+
+ // alpha_pcoh.output_diagram();
+
+ // --------------------------------------------
+ // Bottleneck distance between both persistence
+ // --------------------------------------------
+ double max_b_distance {};
+ for (int dim = 0; dim < dim_max; dim ++) {
+ std::vector< std::pair< Filtration_value , Filtration_value > > rips_intervals;
+ std::vector< std::pair< Filtration_value , Filtration_value > > alpha_intervals;
+ rips_intervals = rips_pcoh.intervals_in_dimension(dim);
+ alpha_intervals = alpha_pcoh.intervals_in_dimension(dim);
+ std::transform(alpha_intervals.begin(), alpha_intervals.end(), alpha_intervals.begin(), compute_root_square);
+
+ double bottleneck_distance = Gudhi::persistence_diagram::bottleneck_distance(rips_intervals, alpha_intervals);
+ std::cout << "In dimension " << dim << ", bottleneck distance = " << bottleneck_distance << std::endl;
+ if (bottleneck_distance > max_b_distance)
+ max_b_distance = bottleneck_distance;
+ }
+ std::cout << "================================================================================" << std::endl;
+ std::cout << "Bottleneck distance is " << max_b_distance << std::endl;
+
+ return 0;
+}
+
+void program_options(int argc, char * argv[]
+ , std::string & off_file_points
+ , Filtration_value & threshold
+ , 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<std::string>(&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")
+ ("max-edge-length,r",
+ po::value<Filtration_value>(&threshold)->default_value(std::numeric_limits<Filtration_value>::infinity()),
+ "Maximal length of an edge for the Rips complex construction.")
+ ("cpx-dimension,d", po::value<int>(&dim_max)->default_value(1),
+ "Maximal dimension of the Rips complex we want to compute.")
+ ("field-charac,p", po::value<int>(&p)->default_value(11),
+ "Characteristic p of the coefficient field Z/pZ for computing homology.")
+ ("min-persistence,m", po::value<Filtration_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 Rips complex defined 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();
+ }
+}
diff --git a/src/Bottleneck_distance/example/bottleneck_basic_example.cpp b/src/Bottleneck_distance/example/bottleneck_basic_example.cpp
index 91a7302f..d0ca4e20 100644
--- a/src/Bottleneck_distance/example/bottleneck_basic_example.cpp
+++ b/src/Bottleneck_distance/example/bottleneck_basic_example.cpp
@@ -21,10 +21,13 @@
*/
#include <gudhi/Bottleneck.h>
+
#include <iostream>
+#include <vector>
+#include <utility> // for pair
+#include <limits> // for numeric_limits
int main() {
-
std::vector< std::pair<double, double> > v1, v2;
v1.emplace_back(2.7, 3.7);
@@ -44,5 +47,4 @@ int main() {
b = Gudhi::persistence_diagram::bottleneck_distance(v1, v2, 0.1);
std::cout << "Approx bottleneck distance = " << b << std::endl;
-
}
diff --git a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp
index 4c74b66e..bde05825 100644
--- a/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp
+++ b/src/Bottleneck_distance/example/bottleneck_read_file_example.cpp
@@ -24,6 +24,8 @@
#include <gudhi/Bottleneck.h>
#include <iostream>
+#include <vector>
+#include <utility> // for pair
#include <fstream>
#include <sstream>
#include <string>
diff --git a/src/Bottleneck_distance/include/gudhi/Bottleneck.h b/src/Bottleneck_distance/include/gudhi/Bottleneck.h
index 2b7e4767..b90a0ee0 100644
--- a/src/Bottleneck_distance/include/gudhi/Bottleneck.h
+++ b/src/Bottleneck_distance/include/gudhi/Bottleneck.h
@@ -24,6 +24,11 @@
#define BOTTLENECK_H_
#include <gudhi/Graph_matching.h>
+
+#include <vector>
+#include <algorithm> // for max
+#include <limits> // for numeric_limits
+
#include <cmath>
namespace Gudhi {
@@ -41,7 +46,7 @@ double bottleneck_distance_approx(Persistence_graph& g, double e) {
if (step <= b_lower_bound || step >= b_upper_bound) // Avoid precision problem
break;
m.set_r(step);
- while (m.multi_augment()); // compute a maximum matching (in the graph corresponding to the current r)
+ while (m.multi_augment()) {}; // compute a maximum matching (in the graph corresponding to the current r)
if (m.perfect()) {
m = biggest_unperfect;
b_upper_bound = step;
@@ -63,7 +68,7 @@ double bottleneck_distance_exact(Persistence_graph& g) {
while (lower_bound_i != upper_bound_i) {
long step = lower_bound_i + static_cast<long> ((upper_bound_i - lower_bound_i - 1) / alpha);
m.set_r(sd.at(step));
- while (m.multi_augment()); // compute a maximum matching (in the graph corresponding to the current r)
+ while (m.multi_augment()) {}; // compute a maximum matching (in the graph corresponding to the current r)
if (m.perfect()) {
m = biggest_unperfect;
upper_bound_i = step;
@@ -75,11 +80,22 @@ double bottleneck_distance_exact(Persistence_graph& g) {
return sd.at(lower_bound_i);
}
-/** \brief Function to use in order to compute the Bottleneck distance between two persistence diagrams (see concepts).
- * If the last parameter e is not 0, you get an additive e-approximation, which is a lot faster to compute whatever is
- * e.
- * Thus, by default, e is a very small positive double, actually the smallest double possible such that the
- * floating-point inaccuracies don't lead to a failure of the algorithm.
+/** \brief Function to compute the Bottleneck distance between two persistence diagrams.
+ *
+ * \tparam Persistence_diagram1,Persistence_diagram2
+ * models of the concept `PersistenceDiagram`.
+ * \param[in] e
+ * \parblock
+ * If `e` is 0, this uses an expensive algorithm to compute the exact distance.
+ *
+ * If `e` is not 0, it asks for an additive `e`-approximation, and currently
+ * also allows a small multiplicative error (the last 2 or 3 bits of the
+ * mantissa may be wrong). This version of the algorithm takes advantage of the
+ * limited precision of `double` and is usually a lot faster to compute,
+ * whatever the value of `e`.
+ *
+ * Thus, by default, `e` is the smallest positive double.
+ * \endparblock
*
* \ingroup bottleneck_distance
*/
diff --git a/src/Bottleneck_distance/include/gudhi/Graph_matching.h b/src/Bottleneck_distance/include/gudhi/Graph_matching.h
index 253c89b4..e1708c5b 100644
--- a/src/Bottleneck_distance/include/gudhi/Graph_matching.h
+++ b/src/Bottleneck_distance/include/gudhi/Graph_matching.h
@@ -25,6 +25,9 @@
#include <gudhi/Neighbors_finder.h>
+#include <vector>
+#include <list>
+
namespace Gudhi {
namespace persistence_diagram {
diff --git a/src/Bottleneck_distance/include/gudhi/Neighbors_finder.h b/src/Bottleneck_distance/include/gudhi/Neighbors_finder.h
index 96ece360..cd5486f8 100644
--- a/src/Bottleneck_distance/include/gudhi/Neighbors_finder.h
+++ b/src/Bottleneck_distance/include/gudhi/Neighbors_finder.h
@@ -34,6 +34,7 @@
#include <gudhi/Internal_point.h>
#include <unordered_set>
+#include <vector>
namespace Gudhi {
diff --git a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h
index 3a4a5fec..c7695112 100644
--- a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h
+++ b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h
@@ -23,9 +23,11 @@
#ifndef PERSISTENCE_GRAPH_H_
#define PERSISTENCE_GRAPH_H_
+#include <gudhi/Internal_point.h>
+
#include <vector>
#include <algorithm>
-#include <gudhi/Internal_point.h>
+#include <limits> // for numeric_limits
namespace Gudhi {
@@ -38,7 +40,7 @@ namespace persistence_diagram {
*/
class Persistence_graph {
public:
- /** \internal \brief Constructor taking 2 Persistence_Diagrams (concept) as parameters. */
+ /** \internal \brief Constructor taking 2 PersistenceDiagrams (concept) as parameters. */
template<typename Persistence_diagram1, typename Persistence_diagram2>
Persistence_graph(const Persistence_diagram1& diag1, const Persistence_diagram2& diag2, double e);
/** \internal \brief Is the given point from U the projection of a point in V ? */
@@ -92,10 +94,12 @@ Persistence_graph::Persistence_graph(const Persistence_diagram1 &diag1,
swap(u, v);
std::sort(u_alive.begin(), u_alive.end());
std::sort(v_alive.begin(), v_alive.end());
- if (u_alive.size() != v_alive.size())
+ if (u_alive.size() != v_alive.size()) {
b_alive = std::numeric_limits<double>::infinity();
- else for (auto it_u = u_alive.cbegin(), it_v = v_alive.cbegin(); it_u != u_alive.cend(); ++it_u, ++it_v)
+ } else {
+ for (auto it_u = u_alive.cbegin(), it_v = v_alive.cbegin(); it_u != u_alive.cend(); ++it_u, ++it_v)
b_alive = std::max(b_alive, std::fabs(*it_u - *it_v));
+ }
}
inline bool Persistence_graph::on_the_u_diagonal(int u_point_index) const {
diff --git a/src/Bottleneck_distance/test/CMakeLists.txt b/src/Bottleneck_distance/test/CMakeLists.txt
index a6979d3c..6c8f112d 100644
--- a/src/Bottleneck_distance/test/CMakeLists.txt
+++ b/src/Bottleneck_distance/test/CMakeLists.txt
@@ -15,14 +15,12 @@ endif()
# cmake -DCGAL_DIR=~/workspace/CGAL-4.8 ../../..
if(CGAL_FOUND)
if (NOT CGAL_VERSION VERSION_LESS 4.8.0)
- if (EIGEN3_FOUND)
- add_executable ( bottleneckUT bottleneck_unit_test.cpp )
- target_link_libraries(bottleneckUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+ add_executable ( bottleneckUT bottleneck_unit_test.cpp )
+ target_link_libraries(bottleneckUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
- # Unitary tests
- add_test(NAME bottleneckUT COMMAND ${CMAKE_CURRENT_BINARY_DIR}/bottleneckUT
- # XML format for Jenkins xUnit plugin
- --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/bottleneckUT.xml --log_level=test_suite --report_level=no)
- endif()
+ # Unitary tests
+ add_test(NAME bottleneckUT COMMAND ${CMAKE_CURRENT_BINARY_DIR}/bottleneckUT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/bottleneckUT.xml --log_level=test_suite --report_level=no)
endif ()
endif()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1fa62e35..eb349052 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -112,6 +112,7 @@ else()
add_subdirectory(example/Bitmap_cubical_complex)
add_subdirectory(example/Witness_complex)
add_subdirectory(example/Alpha_complex)
+ add_subdirectory(example/Rips_complex)
add_subdirectory(example/Spatial_searching)
add_subdirectory(example/Subsampling)
add_subdirectory(example/Tangential_complex)
diff --git a/src/Doxyfile b/src/Doxyfile
index 71aa038d..a41c6d6f 100644
--- a/src/Doxyfile
+++ b/src/Doxyfile
@@ -500,7 +500,7 @@ HIDE_SCOPE_NAMES = NO
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
-SHOW_INCLUDE_FILES = YES
+SHOW_INCLUDE_FILES = NO
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
@@ -784,7 +784,8 @@ EXCLUDE = data/ \
example/ \
GudhUI/ \
cmake/ \
- debian/
+ debian/ \
+ include/gudhi_patches/
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -846,6 +847,7 @@ IMAGE_PATH = doc/Skeleton_blocker/ \
doc/Persistent_cohomology/ \
doc/Witness_complex/ \
doc/Bitmap_cubical_complex/ \
+ doc/Rips_complex/ \
doc/Subsampling/ \
doc/Spatial_searching/ \
doc/Tangential_complex/ \
@@ -2151,7 +2153,7 @@ TEMPLATE_RELATIONS = YES
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-INCLUDE_GRAPH = YES
+INCLUDE_GRAPH = NO
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
@@ -2160,7 +2162,7 @@ INCLUDE_GRAPH = YES
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-INCLUDED_BY_GRAPH = YES
+INCLUDED_BY_GRAPH = NO
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt
index a43294ea..d3a52b60 100644
--- a/src/GudhUI/CMakeLists.txt
+++ b/src/GudhUI/CMakeLists.txt
@@ -1,46 +1,40 @@
cmake_minimum_required(VERSION 2.8)
project(GudhUI)
-find_package(Qt4)
+find_package(CGAL COMPONENTS Qt5)
+find_package(Qt5 COMPONENTS Widgets Xml OpenGL)
find_package(QGLViewer)
find_package(OpenGL)
-if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND )
- set( QT_USE_QTXML TRUE )
- set( QT_USE_QTMAIN TRUE )
- set( QT_USE_QTSCRIPT TRUE )
- set( QT_USE_QTOPENGL TRUE )
- SET(Boost_USE_STATIC_LIBS ON)
- SET(Boost_USE_MULTITHREAD OFF)
- include(${QT_USE_FILE})
+if (NOT CGAL_FOUND)
+ message(ERROR " GudhUI requires CGAL and will not be compiled.")
+endif()
+
+if (NOT Qt5_FOUND)
+ message(ERROR " GudhUI requires Qt5 and will not be compiled.")
+endif()
+
+if (NOT OPENGL_FOUND)
+ message(ERROR " GudhUI requires OpenGL and will not be compiled.")
+endif()
+
+if (NOT QGLVIEWER_FOUND)
+ message(ERROR " GudhUI requires QGLViewer and will not be compiled.")
+endif()
+
+
+if ( CGAL_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND )
+
+ set(CMAKE_AUTOMOC ON)
+ set(CMAKE_AUTOUIC ON)
+ set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+ SET(Boost_USE_STATIC_LIBS ON)
+ SET(Boost_USE_MULTITHREAD OFF)
include_directories (${QGLVIEWER_INCLUDE_DIR})
- include_directories(.)
- # qt : ui file, created wih Qt Designer ###############
- set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gui")
- qt4_wrap_ui( uis
- gui/main_window.ui
- gui/MenuEdgeContraction.ui
- gui/KNearestNeighborsMenu.ui
- gui/UniformNeighborsMenu.ui
- gui/PersistenceMenu.ui
- )
-
- set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gui")
- qt4_automoc(
- gui/MainWindow.cpp
- gui/Menu_k_nearest_neighbors.cpp
- gui/Menu_uniform_neighbors.cpp
- gui/Menu_edge_contraction.cpp
- gui/Menu_persistence.cpp
- )
-
- set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/view")
- qt4_automoc(view/Viewer_instructor.cpp
- view/Viewer.cpp
- )
#####################################################################
add_executable ( GudhUI
@@ -52,10 +46,9 @@ if ( CGAL_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND )
gui/Menu_persistence.cpp
view/Viewer_instructor.cpp
view/Viewer.cpp
- ${uis}
)
-
- target_link_libraries( GudhUI ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} )
+ target_link_libraries( GudhUI Qt5::Widgets Qt5::Xml Qt5::OpenGL )
+ target_link_libraries( GudhUI ${QGLVIEWER_LIBRARIES} )
target_link_libraries( GudhUI ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} )
if (TBB_FOUND)
target_link_libraries( GudhUI ${TBB_LIBRARIES})
@@ -64,5 +57,5 @@ endif()
###############################################################################
else()
- message(STATUS "NOTICE: GudhUI requires CGAL, the QGLViewer, OpenGL and Qt4, and will not be compiled.")
+ message(STATUS "NOTICE: GudhUI requires CGAL, the QGLViewer, OpenGL and Qt5, and will not be compiled.")
endif()
diff --git a/src/GudhUI/gui/MainWindow.h b/src/GudhUI/gui/MainWindow.h
index 3fe0d720..15664dcb 100644
--- a/src/GudhUI/gui/MainWindow.h
+++ b/src/GudhUI/gui/MainWindow.h
@@ -23,9 +23,6 @@
#ifndef GUI_MAINWINDOW_H_
#define GUI_MAINWINDOW_H_
-// Workaround for moc-qt4 not parsing boost headers
-#include <CGAL/config.h>
-
// Workaround https://svn.boost.org/trac/boost/ticket/12534
#include <boost/container/flat_map.hpp>
diff --git a/src/GudhUI/gui/Menu_edge_contraction.h b/src/GudhUI/gui/Menu_edge_contraction.h
index 08f0bf67..2d5640e8 100644
--- a/src/GudhUI/gui/Menu_edge_contraction.h
+++ b/src/GudhUI/gui/Menu_edge_contraction.h
@@ -23,11 +23,8 @@
#ifndef GUI_MENU_EDGE_CONTRACTION_H_
#define GUI_MENU_EDGE_CONTRACTION_H_
-// Workaround for moc-qt4 not parsing boost headers
-#include <CGAL/config.h>
-
#include "gui/MainWindow.h"
-#include "gui/ui_MenuEdgeContraction.h"
+#include "ui_MenuEdgeContraction.h"
#include "model/Model.h"
diff --git a/src/GudhUI/gui/Menu_k_nearest_neighbors.h b/src/GudhUI/gui/Menu_k_nearest_neighbors.h
index 8088b768..77303b67 100644
--- a/src/GudhUI/gui/Menu_k_nearest_neighbors.h
+++ b/src/GudhUI/gui/Menu_k_nearest_neighbors.h
@@ -24,7 +24,7 @@
#define GUI_MENU_K_NEAREST_NEIGHBORS_H_
#include <QMainWindow>
-#include "gui/ui_KNearestNeighborsMenu.h"
+#include "ui_KNearestNeighborsMenu.h"
class QWidget;
diff --git a/src/GudhUI/gui/Menu_persistence.h b/src/GudhUI/gui/Menu_persistence.h
index 8c4df158..1a2a2408 100644
--- a/src/GudhUI/gui/Menu_persistence.h
+++ b/src/GudhUI/gui/Menu_persistence.h
@@ -25,7 +25,7 @@
#define GUI_MENU_PERSISTENCE_H_
#include <QMainWindow>
-#include "gui/ui_PersistenceMenu.h"
+#include "ui_PersistenceMenu.h"
class QWidget;
diff --git a/src/GudhUI/gui/Menu_uniform_neighbors.h b/src/GudhUI/gui/Menu_uniform_neighbors.h
index 0b6f65fe..61316966 100644
--- a/src/GudhUI/gui/Menu_uniform_neighbors.h
+++ b/src/GudhUI/gui/Menu_uniform_neighbors.h
@@ -25,7 +25,7 @@
#define GUI_MENU_UNIFORM_NEIGHBORS_H_
#include <QMainWindow>
-#include "gui/ui_UniformNeighborsMenu.h"
+#include "ui_UniformNeighborsMenu.h"
class Menu_uniform_neighbors : public QDialog, public Ui::UniformMenu {
Q_OBJECT
diff --git a/src/GudhUI/utils/Persistence_compute.h b/src/GudhUI/utils/Persistence_compute.h
index 97165490..2dc03c8e 100644
--- a/src/GudhUI/utils/Persistence_compute.h
+++ b/src/GudhUI/utils/Persistence_compute.h
@@ -29,6 +29,7 @@
#include <gudhi/Simplex_tree.h>
#include <gudhi/distance_functions.h>
#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/Rips_complex.h>
#include <vector>
@@ -69,21 +70,23 @@ template<typename SkBlComplex> class Persistence_compute {
points.emplace_back(std::move(pt_to_add));
}
+ using Simplex_tree = Gudhi::Simplex_tree<>;
+ using Filtration_value = Simplex_tree::Filtration_value;
+ using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+ using Field_Zp = Gudhi::persistent_cohomology::Field_Zp;
+ using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Field_Zp>;
- Graph_t prox_graph = compute_proximity_graph(points, params.threshold, euclidean_distance<Point_t>);
- Gudhi::Simplex_tree<> st;
- st.insert_graph(prox_graph);
- st.expansion(params.max_dim);
+ Rips_complex rips_complex(points, params.threshold, Euclidean_distance());
- Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::Simplex_tree<>,
- Gudhi::persistent_cohomology::Field_Zp > pcoh(st);
+ Simplex_tree st;
+ rips_complex.create_complex(st, params.max_dim);
+ Persistent_cohomology pcoh(st);
// initializes the coefficient field for homology
pcoh.init_coefficients(params.p);
// put params.min_pers
pcoh.compute_persistent_cohomology(params.min_pers);
stream << "persistence: \n";
stream << "p dimension birth death: \n";
-
pcoh.output_diagram(stream);
}
};
diff --git a/src/GudhUI/view/Viewer.h b/src/GudhUI/view/Viewer.h
index 319c8e04..797ddc53 100644
--- a/src/GudhUI/view/Viewer.h
+++ b/src/GudhUI/view/Viewer.h
@@ -24,9 +24,6 @@
#ifndef VIEW_VIEWER_H_
#define VIEW_VIEWER_H_
-// Workaround for moc-qt4 not parsing boost headers
-#include <CGAL/config.h>
-
#include <QGLViewer/qglviewer.h>
#include <vector>
diff --git a/src/GudhUI/view/Viewer_instructor.h b/src/GudhUI/view/Viewer_instructor.h
index 1da28009..05c5c1fc 100644
--- a/src/GudhUI/view/Viewer_instructor.h
+++ b/src/GudhUI/view/Viewer_instructor.h
@@ -26,9 +26,6 @@
// todo do a viewer instructor that have directely a pointer to a QGLviewer and buffer ot not triangles
-// Workaround for moc-qt4 not parsing boost headers
-#include <CGAL/config.h>
-
#include <QFileDialog>
#include <QKeyEvent>
#include <QGLViewer/camera.h>
diff --git a/src/Persistent_cohomology/benchmark/CMakeLists.txt b/src/Persistent_cohomology/benchmark/CMakeLists.txt
new file mode 100644
index 00000000..ea792c89
--- /dev/null
+++ b/src/Persistent_cohomology/benchmark/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.6)
+project(Persistent_cohomology_benchmark)
+
+
+if(GMP_FOUND)
+ if(GMPXX_FOUND)
+ add_executable ( performance_rips_persistence EXCLUDE_FROM_ALL performance_rips_persistence.cpp )
+ target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
+ if (TBB_FOUND)
+ target_link_libraries(performance_rips_persistence ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
+ file(COPY "${CMAKE_SOURCE_DIR}/data/points/Kl.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+ endif(GMPXX_FOUND)
+endif(GMP_FOUND)
diff --git a/src/Persistent_cohomology/example/performance_rips_persistence.cpp b/src/Persistent_cohomology/benchmark/performance_rips_persistence.cpp
index b4d282ac..ba752999 100644
--- a/src/Persistent_cohomology/example/performance_rips_persistence.cpp
+++ b/src/Persistent_cohomology/benchmark/performance_rips_persistence.cpp
@@ -20,20 +20,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gudhi/reader_utils.h>
-#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Rips_complex.h>
#include <gudhi/distance_functions.h>
#include <gudhi/Simplex_tree.h>
#include <gudhi/Persistent_cohomology.h>
#include <gudhi/Persistent_cohomology/Multi_field.h>
#include <gudhi/Hasse_complex.h>
+#include <gudhi/Points_off_io.h>
#include <chrono>
#include <string>
#include <vector>
-using namespace Gudhi;
-using namespace Gudhi::persistent_cohomology;
+// Types definition
+using Simplex_tree = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+using Field_Zp = Gudhi::persistent_cohomology::Field_Zp;
+using Multi_field = Gudhi::persistent_cohomology::Multi_field;
+using Point = std::vector<double>;
+using Points_off_reader = Gudhi::Points_off_reader<Point>;
/* Compute the persistent homology of the complex cpx with coefficients in Z/pZ. */
template< typename FilteredComplex>
@@ -66,33 +72,29 @@ int main(int argc, char * argv[]) {
int elapsed_sec;
{
- std::string filepoints = "../../../data/points/Kl.txt";
+ std::string off_file_points = "Kl.off";
Filtration_value threshold = 0.27;
int dim_max = 3;
int p = 2;
int q = 1223;
- // Extract the points from the file filepoints
- typedef std::vector<double> Point_t;
- std::vector< Point_t > points;
- read_points(filepoints, points);
+ // Extract the points from the file off_file_points
+ Points_off_reader off_reader(off_file_points);
// Compute the proximity graph of the points
start = std::chrono::system_clock::now();
- Graph_t prox_graph = compute_proximity_graph(points, threshold
- , euclidean_distance<Point_t>);
+ Rips_complex rips_complex_from_file(off_reader.get_point_cloud(), threshold, Euclidean_distance());
end = std::chrono::system_clock::now();
elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "Compute Rips graph in " << elapsed_sec << " ms.\n";
// Construct the Rips complex in a Simplex Tree
- Simplex_tree<Simplex_tree_options_fast_persistence> st;
+ Simplex_tree st;
start = std::chrono::system_clock::now();
// insert the proximity graph in the simplex tree
- st.insert_graph(prox_graph);
// expand the graph until dimension dim_max
- st.expansion(dim_max);
+ rips_complex_from_file.create_complex(st, dim_max);
end = std::chrono::system_clock::now();
elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
@@ -120,7 +122,7 @@ int main(int argc, char * argv[]) {
// Convert the simplex tree into a hasse diagram
start = std::chrono::system_clock::now();
- Hasse_complex<> hcpx(st);
+ Gudhi::Hasse_complex<> hcpx(st);
end = std::chrono::system_clock::now();
elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "Convert the simplex tree into a Hasse diagram in " << elapsed_sec << " ms.\n";
@@ -152,7 +154,7 @@ timing_persistence(FilteredComplex & cpx
int elapsed_sec;
{
start = std::chrono::system_clock::now();
- Persistent_cohomology< FilteredComplex, Field_Zp > pcoh(cpx);
+ Gudhi::persistent_cohomology::Persistent_cohomology< FilteredComplex, Field_Zp > pcoh(cpx);
end = std::chrono::system_clock::now();
elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << " Initialize pcoh in " << elapsed_sec << " ms.\n";
@@ -186,7 +188,7 @@ timing_persistence(FilteredComplex & cpx
int elapsed_sec;
{
start = std::chrono::system_clock::now();
- Persistent_cohomology< FilteredComplex, Multi_field > pcoh(cpx);
+ Gudhi::persistent_cohomology::Persistent_cohomology< FilteredComplex, Multi_field > pcoh(cpx);
end = std::chrono::system_clock::now();
elapsed_sec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << " Initialize pcoh in " << elapsed_sec << " ms.\n";
diff --git a/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h b/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h
index 433cfd3e..40dd3f93 100644
--- a/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h
+++ b/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h
@@ -144,17 +144,23 @@ namespace persistent_cohomology {
We provide several example files: run these examples with -h for details on their use, and read the README file.
\li <a href="_persistent_cohomology_2rips_persistence_8cpp-example.html">
-Persistent_cohomology/rips_persistence.cpp</a> computes the Rips complex of a point cloud and its persistence diagram.
+Persistent_cohomology/rips_persistence.cpp</a> computes the Rips complex of a point cloud and outputs its persistence
+diagram.
+\code $> ./rips_persistence ../../data/points/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 3 \endcode
+\code The complex contains 177838 simplices
+ and has dimension 3
+3 0 0 inf
+3 1 0.0983494 inf
+3 1 0.104347 inf
+3 2 0.138335 inf \endcode
\li <a href="_persistent_cohomology_2rips_multifield_persistence_8cpp-example.html">
-Persistent_cohomology/rips_multifield_persistence.cpp</a> computes the Rips complex of a point cloud and its
+Persistent_cohomology/rips_multifield_persistence.cpp</a> computes the Rips complex of a point cloud and outputs its
persistence diagram with a family of field coefficients.
-\li <a href="_persistent_cohomology_2performance_rips_persistence_8cpp-example.html">
-Persistent_cohomology/performance_rips_persistence.cpp</a> provides timings for the construction of the Rips complex
-on a set of points sampling a Klein bottle in \f$\mathbb{R}^5\f$ with a simplex tree, its conversion to a
-Hasse diagram and the computation of persistent homology and multi-field persistent homology for the
-different representations.
+\li <a href="_persistent_cohomology_2rips_distance_matrix_persistence_8cpp-example.html">
+Persistent_cohomology/rips_distance_matrix_persistence.cpp</a> computes the Rips complex of a distance matrix and
+outputs its persistence diagram.
\li <a href="_persistent_cohomology_2alpha_complex_3d_persistence_8cpp-example.html">
Persistent_cohomology/alpha_complex_3d_persistence.cpp</a> computes the persistent homology with
diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt
index 758bd6b1..38d7e9a9 100644
--- a/src/Persistent_cohomology/example/CMakeLists.txt
+++ b/src/Persistent_cohomology/example/CMakeLists.txt
@@ -11,9 +11,15 @@ target_link_libraries(plain_homology ${Boost_SYSTEM_LIBRARY})
add_executable(persistence_from_simple_simplex_tree persistence_from_simple_simplex_tree.cpp)
target_link_libraries(persistence_from_simple_simplex_tree ${Boost_SYSTEM_LIBRARY})
+add_executable(rips_distance_matrix_persistence rips_distance_matrix_persistence.cpp)
+target_link_libraries(rips_distance_matrix_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+
add_executable(rips_persistence rips_persistence.cpp)
target_link_libraries(rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+add_executable(rips_persistence_step_by_step rips_persistence_step_by_step.cpp)
+target_link_libraries(rips_persistence_step_by_step ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
+
add_executable(rips_persistence_via_boundary_matrix rips_persistence_via_boundary_matrix.cpp)
target_link_libraries(rips_persistence_via_boundary_matrix ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY})
@@ -23,15 +29,19 @@ target_link_libraries(persistence_from_file ${Boost_SYSTEM_LIBRARY} ${Boost_PROG
if (TBB_FOUND)
target_link_libraries(plain_homology ${TBB_LIBRARIES})
target_link_libraries(persistence_from_simple_simplex_tree ${TBB_LIBRARIES})
+ target_link_libraries(rips_distance_matrix_persistence ${TBB_LIBRARIES})
target_link_libraries(rips_persistence ${TBB_LIBRARIES})
+ target_link_libraries(rips_persistence_step_by_step ${TBB_LIBRARIES})
target_link_libraries(rips_persistence_via_boundary_matrix ${TBB_LIBRARIES})
target_link_libraries(persistence_from_file ${TBB_LIBRARIES})
endif()
add_test(plain_homology ${CMAKE_CURRENT_BINARY_DIR}/plain_homology)
add_test(persistence_from_simple_simplex_tree ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_simple_simplex_tree 1 0)
-add_test(rips_persistence_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.16 -d 3 -p 3 -m 100)
-add_test(rips_persistence_via_boundary_matrix_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence_via_boundary_matrix ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.16 -d 3 -p 3 -m 100)
+add_test(rips_distance_matrix ${CMAKE_CURRENT_BINARY_DIR}/rips_distance_matrix_persistence ${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv -r 1.0 -d 3 -p 3 -m 0)
+add_test(rips_persistence_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 3)
+add_test(rips_persistence_step_by_step_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence_step_by_step ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 3)
+add_test(rips_persistence_via_boundary_matrix_3 ${CMAKE_CURRENT_BINARY_DIR}/rips_persistence_via_boundary_matrix ${CMAKE_SOURCE_DIR}/data/points/Kl.off -r 0.16 -d 3 -p 3 -m 100)
add_test(persistence_from_file_3_2_0 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc -p 2 -m 0)
add_test(persistence_from_file_3_3_100 ${CMAKE_CURRENT_BINARY_DIR}/persistence_from_file ${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/bunny_5000_complex.fsc -p 3 -m 100)
@@ -39,14 +49,10 @@ if(GMP_FOUND)
if(GMPXX_FOUND)
add_executable(rips_multifield_persistence rips_multifield_persistence.cpp )
target_link_libraries(rips_multifield_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
- add_executable ( performance_rips_persistence performance_rips_persistence.cpp )
- target_link_libraries(performance_rips_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES})
if (TBB_FOUND)
target_link_libraries(rips_multifield_persistence ${TBB_LIBRARIES})
- target_link_libraries(performance_rips_persistence ${TBB_LIBRARIES})
endif(TBB_FOUND)
-
- add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/Kl.txt -r 0.2 -d 3 -p 2 -q 71 -m 100)
+ add_test(rips_multifield_persistence_2_71 ${CMAKE_CURRENT_BINARY_DIR}/rips_multifield_persistence ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 2 -q 71)
endif(GMPXX_FOUND)
endif(GMP_FOUND)
diff --git a/src/Persistent_cohomology/example/README b/src/Persistent_cohomology/example/README
index 7803e5ab..2ac79398 100644
--- a/src/Persistent_cohomology/example/README
+++ b/src/Persistent_cohomology/example/README
@@ -10,13 +10,13 @@ Example of use of RIPS:
Computation of the persistent homology with Z/2Z coefficients of the Rips complex on points
sampling a Klein bottle:
-./rips_persistence ../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -m 100
+./rips_persistence ../../data/points/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 2
output:
-210 0 0 inf
-210 1 0.0702103 inf
-2 1 0.0702103 inf
-2 2 0.159992 inf
+2 0 0 inf
+2 1 0.0983494 inf
+2 1 0.104347 inf
+2 2 0.138335 inf
Every line is of this format: p1*...*pr dim b d
@@ -29,31 +29,45 @@ where
with Z/3Z coefficients:
-./rips_persistence ../../data/points/Kl.txt -r 0.25 -d 3 -p 3 -m 100
+./rips_persistence ../../data/points/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 3
output:
-3 0 0 inf
-3 1 0.0702103 inf
+3 0 0 inf
+3 1 0.0983494 inf
+3 1 0.104347 inf
+3 2 0.138335 inf
and the computation with Z/2Z and Z/3Z coefficients simultaneously:
-./rips_multifield_persistence ../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 3 -m 100
+./rips_multifield_persistence ../../data/points/tore3D_1307.off -r 0.25 -m 0.12 -d 3 -p 2 -q 3
output:
-6 0 0 inf
-6 1 0.0702103 inf
-2 1 0.0702103 inf
-2 2 0.159992 inf
+6 0 0 inf
+6 1 0.0983494 inf
+6 1 0.104347 inf
+6 2 0.138335 inf
+6 0 0 0.122545
+6 0 0 0.121171
+6 0 0 0.120964
+6 0 0 0.12057
+6 0 0 0.12047
+6 0 0 0.120414
and finally the computation with all Z/pZ for 2 <= p <= 71 (20 first prime numbers):
- ./rips_multifield_persistence ../../data/points/Kl.txt -r 0.25 -d 3 -p 2 -q 71 -m 100
+ ./rips_multifield_persistence ../../data/points/Kl.off -r 0.25 -m 0.5 -d 3 -p 2 -q 71
output:
-557940830126698960967415390 0 0 inf
-557940830126698960967415390 1 0.0702103 inf
-2 1 0.0702103 inf
-2 2 0.159992 inf
+557940830126698960967415390 0 0 inf
+557940830126698960967415390 1 0.0983494 inf
+557940830126698960967415390 1 0.104347 inf
+557940830126698960967415390 2 0.138335 inf
+557940830126698960967415390 0 0 0.122545
+557940830126698960967415390 0 0 0.121171
+557940830126698960967415390 0 0 0.120964
+557940830126698960967415390 0 0 0.12057
+557940830126698960967415390 0 0 0.12047
+557940830126698960967415390 0 0 0.120414
***********************************************************************************************************************
Example of use of ALPHA:
diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp
index 48fbb91a..978dc942 100644
--- a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp
+++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp
@@ -4,7 +4,7 @@
*
* Author(s): Vincent Rouvreau
*
- * Copyright (C) 2014 INRIA Saclay (France)
+ * 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
@@ -64,6 +64,7 @@ typedef std::list<Alpha_shape_3::Vertex_handle> Vertex_list;
// gudhi type definition
typedef Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence> ST;
+typedef ST::Filtration_value Filtration_value;
typedef ST::Vertex_handle Simplex_tree_vertex;
typedef std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex > Alpha_shape_simplex_tree_map;
typedef std::pair<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex> Alpha_shape_simplex_tree_pair;
@@ -132,7 +133,7 @@ int main(int argc, char * const argv[]) {
int coeff_field_characteristic = atoi(argv[2]);
Filtration_value min_persistence = 0.0;
- int returnedScanValue = sscanf(argv[3], "%lf", &min_persistence);
+ int returnedScanValue = sscanf(argv[3], "%f", &min_persistence);
if ((returnedScanValue == EOF) || (min_persistence < -1.0)) {
std::cerr << "Error: " << argv[3] << " is not correct\n";
usage(argv[0]);
diff --git a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp
index 2412569a..9e84e91f 100644
--- a/src/Persistent_cohomology/example/alpha_complex_persistence.cpp
+++ b/src/Persistent_cohomology/example/alpha_complex_persistence.cpp
@@ -11,6 +11,9 @@
#include <string>
#include <limits> // for numeric_limits
+using Simplex_tree = Gudhi::Simplex_tree<>;
+using Filtration_value = Simplex_tree::Filtration_value;
+
void program_options(int argc, char * argv[]
, std::string & off_file_points
, std::string & output_file_diag
@@ -34,7 +37,7 @@ int main(int argc, char **argv) {
using Kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >;
Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex_from_file(off_file_points);
- Gudhi::Simplex_tree<> simplex;
+ Simplex_tree simplex;
if (alpha_complex_from_file.create_complex(simplex, alpha_square_max_value)) {
// ----------------------------------------------------------------------------
// Display information about the alpha complex
@@ -48,7 +51,7 @@ int main(int argc, char **argv) {
std::cout << "Simplex_tree dim: " << simplex.dimension() << std::endl;
// Compute the persistence diagram of the complex
- Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::Simplex_tree<>,
+ Gudhi::persistent_cohomology::Persistent_cohomology< Simplex_tree,
Gudhi::persistent_cohomology::Field_Zp > pcoh(simplex);
// initializes the coefficient field for homology
pcoh.init_coefficients(coeff_field_characteristic);
diff --git a/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp
index a199fea1..dbc42706 100644
--- a/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp
+++ b/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp
@@ -4,7 +4,7 @@
*
* Author(s): Vincent Rouvreau
*
- * Copyright (C) 2014 INRIA Saclay (France)
+ * 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
@@ -39,6 +39,7 @@
#include <utility>
#include <list>
#include <vector>
+#include <cstdlib>
// Traits
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
@@ -70,6 +71,7 @@ using Vertex_list = std::list<Alpha_shape_3::Vertex_handle>;
// gudhi type definition
using ST = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Filtration_value = ST::Filtration_value;
using Simplex_tree_vertex = ST::Vertex_handle;
using Alpha_shape_simplex_tree_map = std::map<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex >;
using Alpha_shape_simplex_tree_pair = std::pair<Alpha_shape_3::Vertex_handle, Simplex_tree_vertex>;
@@ -136,19 +138,8 @@ int main(int argc, char * const argv[]) {
usage(argv[0]);
}
- int coeff_field_characteristic = 0;
- int returnedScanValue = sscanf(argv[3], "%d", &coeff_field_characteristic);
- if ((returnedScanValue == EOF) || (coeff_field_characteristic <= 0)) {
- std::cerr << "Error: " << argv[3] << " is not correct\n";
- usage(argv[0]);
- }
-
- Filtration_value min_persistence = 0.0;
- returnedScanValue = sscanf(argv[4], "%lf", &min_persistence);
- if ((returnedScanValue == EOF) || (min_persistence < -1.0)) {
- std::cerr << "Error: " << argv[4] << " is not correct\n";
- usage(argv[0]);
- }
+ int coeff_field_characteristic = atoi(argv[3]);
+ Filtration_value min_persistence = strtof(argv[4], nullptr);
// Read points from file
std::string offInputFile(argv[1]);
diff --git a/src/Persistent_cohomology/example/persistence_from_simple_simplex_tree.cpp b/src/Persistent_cohomology/example/persistence_from_simple_simplex_tree.cpp
index ba772f04..7ca9410a 100644
--- a/src/Persistent_cohomology/example/persistence_from_simple_simplex_tree.cpp
+++ b/src/Persistent_cohomology/example/persistence_from_simple_simplex_tree.cpp
@@ -4,7 +4,7 @@
*
* Author(s): Vincent Rouvreau
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * 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
@@ -29,13 +29,12 @@
#include <utility>
#include <vector>
-using namespace Gudhi;
-using namespace Gudhi::persistent_cohomology;
-
-typedef std::vector< Vertex_handle > typeVectorVertex;
-typedef std::pair<typeVectorVertex, Filtration_value> typeSimplex;
-typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool;
-typedef Simplex_tree<> typeST;
+// Types definition
+using Simplex_tree = Gudhi::Simplex_tree<>;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Field_Zp = Gudhi::persistent_cohomology::Field_Zp;
+using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Field_Zp >;
+using typeVectorVertex = std::vector< Simplex_tree::Vertex_handle >;
void usage(char * const progName) {
std::cerr << "Usage: " << progName << " coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n";
@@ -66,7 +65,7 @@ int main(int argc, char * const argv[]) {
// TEST OF INSERTION
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST OF INSERTION" << std::endl;
- typeST st;
+ Simplex_tree st;
// ++ FIRST
std::cout << " - INSERT (0,1,2)" << std::endl;
@@ -166,7 +165,7 @@ int main(int argc, char * const argv[]) {
std::cout << "**************************************************************" << std::endl;
// Compute the persistence diagram of the complex
- persistent_cohomology::Persistent_cohomology< Simplex_tree<>, Field_Zp > pcoh(st);
+ Persistent_cohomology pcoh(st);
// initializes the coefficient field for homology
pcoh.init_coefficients(coeff_field_characteristic);
diff --git a/src/Persistent_cohomology/example/rips_distance_matrix_persistence.cpp b/src/Persistent_cohomology/example/rips_distance_matrix_persistence.cpp
new file mode 100644
index 00000000..8517e7f6
--- /dev/null
+++ b/src/Persistent_cohomology/example/rips_distance_matrix_persistence.cpp
@@ -0,0 +1,144 @@
+/* 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): Pawel Dlotko, Vincent Rouvreau
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <gudhi/Rips_complex.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/reader_utils.h>
+
+#include <boost/program_options.hpp>
+
+#include <string>
+#include <vector>
+#include <limits> // infinity
+
+// Types definition
+using Simplex_tree = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+using Field_Zp = Gudhi::persistent_cohomology::Field_Zp;
+using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Field_Zp >;
+using Distance_matrix = std::vector<std::vector<Filtration_value>>;
+
+void program_options(int argc, char * argv[]
+ , std::string & csv_matrix_file
+ , std::string & filediag
+ , Filtration_value & threshold
+ , int & dim_max
+ , int & p
+ , Filtration_value & min_persistence);
+
+int main(int argc, char * argv[]) {
+ std::string csv_matrix_file;
+ std::string filediag;
+ Filtration_value threshold;
+ int dim_max;
+ int p;
+ Filtration_value min_persistence;
+
+ program_options(argc, argv, csv_matrix_file, filediag, threshold, dim_max, p, min_persistence);
+
+ Distance_matrix distances = read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_matrix_file);
+ Rips_complex rips_complex_from_file(distances, threshold);
+
+ // Construct the Rips complex in a Simplex Tree
+ Simplex_tree simplex_tree;
+
+ rips_complex_from_file.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 & csv_matrix_file
+ , std::string & filediag
+ , Filtration_value & threshold
+ , 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<std::string>(&csv_matrix_file),
+ "Name of file containing a distance matrix. Can be square or lower triangular matrix. Separator is ';'.");
+
+ po::options_description visible("Allowed options", 100);
+ visible.add_options()
+ ("help,h", "produce help message")
+ ("output-file,o", po::value<std::string>(&filediag)->default_value(std::string()),
+ "Name of file in which the persistence diagram is written. Default print in std::cout")
+ ("max-edge-length,r",
+ po::value<Filtration_value>(&threshold)->default_value(std::numeric_limits<Filtration_value>::infinity()),
+ "Maximal length of an edge for the Rips complex construction.")
+ ("cpx-dimension,d", po::value<int>(&dim_max)->default_value(1),
+ "Maximal dimension of the Rips complex we want to compute.")
+ ("field-charac,p", po::value<int>(&p)->default_value(11),
+ "Characteristic p of the coefficient field Z/pZ for computing homology.")
+ ("min-persistence,m", po::value<Filtration_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 Rips complex defined on a set of distance matrix.\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();
+ }
+}
diff --git a/src/Persistent_cohomology/example/rips_multifield_persistence.cpp b/src/Persistent_cohomology/example/rips_multifield_persistence.cpp
index c5cd775d..7674b5a5 100644
--- a/src/Persistent_cohomology/example/rips_multifield_persistence.cpp
+++ b/src/Persistent_cohomology/example/rips_multifield_persistence.cpp
@@ -4,7 +4,7 @@
*
* Author(s): Clément Maria
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * 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
@@ -20,26 +20,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gudhi/reader_utils.h>
-#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Rips_complex.h>
#include <gudhi/distance_functions.h>
#include <gudhi/Simplex_tree.h>
#include <gudhi/Persistent_cohomology.h>
#include <gudhi/Persistent_cohomology/Multi_field.h>
+#include <gudhi/Points_off_io.h>
#include <boost/program_options.hpp>
#include <string>
#include <vector>
-using namespace Gudhi;
-using namespace Gudhi::persistent_cohomology;
-
-typedef int Vertex_handle;
-typedef double Filtration_value;
+// Types definition
+using Simplex_tree = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+using Multi_field = Gudhi::persistent_cohomology::Multi_field;
+using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Multi_field >;
+using Point = std::vector<double>;
+using Points_off_reader = Gudhi::Points_off_reader<Point>;
void program_options(int argc, char * argv[]
- , std::string & filepoints
+ , std::string & off_file_points
, std::string & filediag
, Filtration_value & threshold
, int & dim_max
@@ -48,7 +51,7 @@ void program_options(int argc, char * argv[]
, Filtration_value & min_persistence);
int main(int argc, char * argv[]) {
- std::string filepoints;
+ std::string off_file_points;
std::string filediag;
Filtration_value threshold;
int dim_max;
@@ -56,33 +59,26 @@ int main(int argc, char * argv[]) {
int max_p;
Filtration_value min_persistence;
- program_options(argc, argv, filepoints, filediag, threshold, dim_max, min_p, max_p, min_persistence);
-
- // Extract the points from the file filepoints
- typedef std::vector<double> Point_t;
- std::vector< Point_t > points;
- read_points(filepoints, points);
+ program_options(argc, argv, off_file_points, filediag, threshold, dim_max, min_p, max_p, min_persistence);
- // Compute the proximity graph of the points
- Graph_t prox_graph = compute_proximity_graph(points, threshold
- , euclidean_distance<Point_t>);
+ Points_off_reader off_reader(off_file_points);
+ Rips_complex rips_complex_from_file(off_reader.get_point_cloud(), threshold, Euclidean_distance());
// Construct the Rips complex in a Simplex Tree
- typedef Simplex_tree<Simplex_tree_options_fast_persistence> ST;
- ST st;
- // insert the proximity graph in the simplex tree
- st.insert_graph(prox_graph);
- // expand the graph until dimension dim_max
- st.expansion(dim_max);
+ Simplex_tree simplex_tree;
+
+ rips_complex_from_file.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
- st.initialize_filtration();
+ simplex_tree.initialize_filtration();
// Compute the persistence diagram of the complex
- Persistent_cohomology<ST, Multi_field > pcoh(st);
+ Persistent_cohomology pcoh(simplex_tree);
// initializes the coefficient field for homology
pcoh.init_coefficients(min_p, max_p);
- // compute persistent homology, disgarding persistent features of life shorter than min_persistence
+
pcoh.compute_persistent_cohomology(min_persistence);
// Output the diagram in filediag
@@ -98,7 +94,7 @@ int main(int argc, char * argv[]) {
}
void program_options(int argc, char * argv[]
- , std::string & filepoints
+ , std::string & off_file_points
, std::string & filediag
, Filtration_value & threshold
, int & dim_max
@@ -108,8 +104,8 @@ void program_options(int argc, char * argv[]
namespace po = boost::program_options;
po::options_description hidden("Hidden options");
hidden.add_options()
- ("input-file", po::value<std::string>(&filepoints),
- "Name of file containing a point set. Format is one point per line: X1 ... Xd \n");
+ ("input-file", po::value<std::string>(&off_file_points),
+ "Name of an OFF file containing a point set.\n");
po::options_description visible("Allowed options");
visible.add_options()
diff --git a/src/Persistent_cohomology/example/rips_persistence.cpp b/src/Persistent_cohomology/example/rips_persistence.cpp
index cab49395..c6378de7 100644
--- a/src/Persistent_cohomology/example/rips_persistence.cpp
+++ b/src/Persistent_cohomology/example/rips_persistence.cpp
@@ -4,7 +4,7 @@
*
* Author(s): Clément Maria
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * 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
@@ -20,11 +20,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gudhi/reader_utils.h>
-#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/Rips_complex.h>
#include <gudhi/distance_functions.h>
#include <gudhi/Simplex_tree.h>
#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/Points_off_io.h>
#include <boost/program_options.hpp>
@@ -32,14 +32,17 @@
#include <vector>
#include <limits> // infinity
-using namespace Gudhi;
-using namespace Gudhi::persistent_cohomology;
-
-typedef int Vertex_handle;
-typedef double Filtration_value;
+// Types definition
+using Simplex_tree = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+using Field_Zp = Gudhi::persistent_cohomology::Field_Zp;
+using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Field_Zp >;
+using Point = std::vector<double>;
+using Points_off_reader = Gudhi::Points_off_reader<Point>;
void program_options(int argc, char * argv[]
- , std::string & filepoints
+ , std::string & off_file_points
, std::string & filediag
, Filtration_value & threshold
, int & dim_max
@@ -47,40 +50,30 @@ void program_options(int argc, char * argv[]
, Filtration_value & min_persistence);
int main(int argc, char * argv[]) {
- std::string filepoints;
+ std::string off_file_points;
std::string filediag;
Filtration_value threshold;
int dim_max;
int p;
Filtration_value min_persistence;
- program_options(argc, argv, filepoints, filediag, threshold, dim_max, p, min_persistence);
-
- // Extract the points from the file filepoints
- typedef std::vector<double> Point_t;
- std::vector< Point_t > points;
- read_points(filepoints, points);
+ program_options(argc, argv, off_file_points, filediag, threshold, dim_max, p, min_persistence);
- // Compute the proximity graph of the points
- Graph_t prox_graph = compute_proximity_graph(points, threshold
- , euclidean_distance<Point_t>);
+ Points_off_reader off_reader(off_file_points);
+ Rips_complex rips_complex_from_file(off_reader.get_point_cloud(), threshold, Euclidean_distance());
// Construct the Rips complex in a Simplex Tree
- typedef Simplex_tree<Simplex_tree_options_fast_persistence> ST;
- ST st;
- // insert the proximity graph in the simplex tree
- st.insert_graph(prox_graph);
- // expand the graph until dimension dim_max
- st.expansion(dim_max);
+ Simplex_tree simplex_tree;
- std::cout << "The complex contains " << st.num_simplices() << " simplices \n";
- std::cout << " and has dimension " << st.dimension() << " \n";
+ rips_complex_from_file.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
- st.initialize_filtration();
+ simplex_tree.initialize_filtration();
// Compute the persistence diagram of the complex
- persistent_cohomology::Persistent_cohomology<ST, Field_Zp > pcoh(st);
+ Persistent_cohomology pcoh(simplex_tree);
// initializes the coefficient field for homology
pcoh.init_coefficients(p);
@@ -99,7 +92,7 @@ int main(int argc, char * argv[]) {
}
void program_options(int argc, char * argv[]
- , std::string & filepoints
+ , std::string & off_file_points
, std::string & filediag
, Filtration_value & threshold
, int & dim_max
@@ -108,15 +101,16 @@ void program_options(int argc, char * argv[]
namespace po = boost::program_options;
po::options_description hidden("Hidden options");
hidden.add_options()
- ("input-file", po::value<std::string>(&filepoints),
- "Name of file containing a point set. Format is one point per line: X1 ... Xd ");
+ ("input-file", po::value<std::string>(&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<std::string>(&filediag)->default_value(std::string()),
"Name of file in which the persistence diagram is written. Default print in std::cout")
- ("max-edge-length,r", po::value<Filtration_value>(&threshold)->default_value(std::numeric_limits<Filtration_value>::infinity()),
+ ("max-edge-length,r",
+ po::value<Filtration_value>(&threshold)->default_value(std::numeric_limits<Filtration_value>::infinity()),
"Maximal length of an edge for the Rips complex construction.")
("cpx-dimension,d", po::value<int>(&dim_max)->default_value(1),
"Maximal dimension of the Rips complex we want to compute.")
diff --git a/src/Persistent_cohomology/example/rips_persistence_step_by_step.cpp b/src/Persistent_cohomology/example/rips_persistence_step_by_step.cpp
new file mode 100644
index 00000000..b159c62e
--- /dev/null
+++ b/src/Persistent_cohomology/example/rips_persistence_step_by_step.cpp
@@ -0,0 +1,217 @@
+/* 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): Clément Maria
+ *
+ * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <gudhi/graph_simplicial_complex.h>
+#include <gudhi/distance_functions.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/Points_off_io.h>
+
+#include <boost/program_options.hpp>
+
+#include <string>
+#include <vector>
+#include <limits> // infinity
+#include <utility> // for pair
+#include <map>
+
+// ----------------------------------------------------------------------------
+// rips_persistence_step_by_step is an example of each step that is required to
+// build a Rips over a Simplex_tree. Please refer to rips_persistence to see
+// how to do the same thing with the Rips_complex wrapper for less detailed
+// steps.
+// ----------------------------------------------------------------------------
+
+// Types definition
+using Simplex_tree = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+using Vertex_handle = Simplex_tree::Vertex_handle;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Graph_t = boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS
+, boost::property < vertex_filtration_t, Filtration_value >
+, boost::property < edge_filtration_t, Filtration_value >
+>;
+using Edge_t = std::pair< Vertex_handle, Vertex_handle >;
+
+template< typename InputPointRange, typename Distance >
+Graph_t compute_proximity_graph(InputPointRange &points, Filtration_value threshold, Distance distance);
+
+using Field_Zp = Gudhi::persistent_cohomology::Field_Zp;
+using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Field_Zp >;
+using Point = std::vector<double>;
+using Points_off_reader = Gudhi::Points_off_reader<Point>;
+
+void program_options(int argc, char * argv[]
+ , std::string & off_file_points
+ , std::string & filediag
+ , Filtration_value & threshold
+ , int & dim_max
+ , int & p
+ , Filtration_value & min_persistence);
+
+int main(int argc, char * argv[]) {
+ std::string off_file_points;
+ std::string filediag;
+ Filtration_value threshold;
+ int dim_max;
+ int p;
+ Filtration_value min_persistence;
+
+ program_options(argc, argv, off_file_points, filediag, threshold, dim_max, p, min_persistence);
+
+ // Extract the points from the file filepoints
+ Points_off_reader off_reader(off_file_points);
+
+ // Compute the proximity graph of the points
+ Graph_t prox_graph = compute_proximity_graph(off_reader.get_point_cloud(), threshold
+ , Euclidean_distance());
+
+ // Construct the Rips complex in a Simplex Tree
+ Simplex_tree st;
+ // insert the proximity graph in the simplex tree
+ st.insert_graph(prox_graph);
+ // expand the graph until dimension dim_max
+ st.expansion(dim_max);
+
+ std::cout << "The complex contains " << st.num_simplices() << " simplices \n";
+ std::cout << " and has dimension " << st.dimension() << " \n";
+
+ // Sort the simplices in the order of the filtration
+ st.initialize_filtration();
+
+ // Compute the persistence diagram of the complex
+ Persistent_cohomology pcoh(st);
+ // 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
+ , Filtration_value & threshold
+ , 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<std::string>(&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<std::string>(&filediag)->default_value(std::string()),
+ "Name of file in which the persistence diagram is written. Default print in std::cout")
+ ("max-edge-length,r",
+ po::value<Filtration_value>(&threshold)->default_value(std::numeric_limits<Filtration_value>::infinity()),
+ "Maximal length of an edge for the Rips complex construction.")
+ ("cpx-dimension,d", po::value<int>(&dim_max)->default_value(1),
+ "Maximal dimension of the Rips complex we want to compute.")
+ ("field-charac,p", po::value<int>(&p)->default_value(11),
+ "Characteristic p of the coefficient field Z/pZ for computing homology.")
+ ("min-persistence,m", po::value<Filtration_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 Rips complex defined 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();
+ }
+}
+
+/** Output the proximity graph of the points.
+ *
+ * If points contains n elements, the proximity graph is the graph
+ * with n vertices, and an edge [u,v] iff the distance function between
+ * points u and v is smaller than threshold.
+ *
+ * The type PointCloud furnishes .begin() and .end() methods, that return
+ * iterators with value_type Point.
+ */
+template< typename InputPointRange, typename Distance >
+Graph_t compute_proximity_graph(InputPointRange &points, Filtration_value threshold, Distance distance) {
+ std::vector< Edge_t > edges;
+ std::vector< Filtration_value > edges_fil;
+
+ Vertex_handle idx_u, idx_v;
+ Filtration_value fil;
+ idx_u = 0;
+ for (auto it_u = points.begin(); it_u != points.end(); ++it_u) {
+ idx_v = idx_u + 1;
+ for (auto it_v = it_u + 1; it_v != points.end(); ++it_v, ++idx_v) {
+ fil = distance(*it_u, *it_v);
+ if (fil <= threshold) {
+ edges.emplace_back(idx_u, idx_v);
+ edges_fil.push_back(fil);
+ }
+ }
+ ++idx_u;
+ }
+
+ Graph_t skel_graph(edges.begin()
+ , edges.end()
+ , edges_fil.begin()
+ , idx_u); // number of points labeled from 0 to idx_u-1
+
+ auto vertex_prop = boost::get(vertex_filtration_t(), skel_graph);
+
+ boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
+ for (std::tie(vi, vi_end) = boost::vertices(skel_graph);
+ vi != vi_end; ++vi) {
+ boost::put(vertex_prop, *vi, 0.);
+ }
+
+ return skel_graph;
+}
diff --git a/src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp b/src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp
index 4c6656f5..63da9847 100644
--- a/src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp
+++ b/src/Persistent_cohomology/example/rips_persistence_via_boundary_matrix.cpp
@@ -4,8 +4,7 @@
*
* Author(s): Clément Maria, Marc Glisse
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France),
- * 2015 INRIA Saclay Île de France)
+ * 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
@@ -21,12 +20,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gudhi/reader_utils.h>
-#include <gudhi/graph_simplicial_complex.h>
-#include <gudhi/distance_functions.h>
#include <gudhi/Simplex_tree.h>
#include <gudhi/Persistent_cohomology.h>
+#include <gudhi/Rips_complex.h>
#include <gudhi/Hasse_complex.h>
+#include <gudhi/Points_off_io.h>
+#include <gudhi/distance_functions.h>
#include <boost/program_options.hpp>
@@ -44,14 +43,16 @@
// //
////////////////////////////////////////////////////////////////
-using namespace Gudhi;
-using namespace Gudhi::persistent_cohomology;
-
-typedef int Vertex_handle;
-typedef double Filtration_value;
+// Types definition
+using Simplex_tree = Gudhi::Simplex_tree<>;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+using Field_Zp = Gudhi::persistent_cohomology::Field_Zp;
+using Point = std::vector<double>;
+using Points_off_reader = Gudhi::Points_off_reader<Point>;
void program_options(int argc, char * argv[]
- , std::string & filepoints
+ , std::string & off_file_points
, std::string & filediag
, Filtration_value & threshold
, int & dim_max
@@ -59,30 +60,21 @@ void program_options(int argc, char * argv[]
, Filtration_value & min_persistence);
int main(int argc, char * argv[]) {
- std::string filepoints;
+ std::string off_file_points;
std::string filediag;
Filtration_value threshold;
int dim_max;
int p;
Filtration_value min_persistence;
- program_options(argc, argv, filepoints, filediag, threshold, dim_max, p, min_persistence);
-
- // Extract the points from the file filepoints
- typedef std::vector<double> Point_t;
- std::vector< Point_t > points;
- read_points(filepoints, points);
+ program_options(argc, argv, off_file_points, filediag, threshold, dim_max, p, min_persistence);
- // Compute the proximity graph of the points
- Graph_t prox_graph = compute_proximity_graph(points, threshold
- , euclidean_distance<Point_t>);
+ Points_off_reader off_reader(off_file_points);
+ Rips_complex rips_complex_from_file(off_reader.get_point_cloud(), threshold, Euclidean_distance());
// Construct the Rips complex in a Simplex Tree
- Simplex_tree<>& st = *new Simplex_tree<>;
- // insert the proximity graph in the simplex tree
- st.insert_graph(prox_graph);
- // expand the graph until dimension dim_max
- st.expansion(dim_max);
+ Simplex_tree& st = *new Simplex_tree;
+ rips_complex_from_file.create_complex(st, dim_max);
std::cout << "The complex contains " << st.num_simplices() << " simplices \n";
std::cout << " and has dimension " << st.dimension() << " \n";
@@ -99,7 +91,7 @@ int main(int argc, char * argv[]) {
st.assign_key(sh, count++);
// Convert to a more convenient representation.
- Hasse_complex<> hcpx(st);
+ Gudhi::Hasse_complex<> hcpx(st);
#ifdef GUDHI_USE_TBB
ts.terminate();
@@ -109,7 +101,7 @@ int main(int argc, char * argv[]) {
delete &st;
// Compute the persistence diagram of the complex
- persistent_cohomology::Persistent_cohomology< Hasse_complex<>, Field_Zp > pcoh(hcpx);
+ Gudhi::persistent_cohomology::Persistent_cohomology< Gudhi::Hasse_complex<>, Field_Zp > pcoh(hcpx);
// initializes the coefficient field for homology
pcoh.init_coefficients(p);
@@ -126,7 +118,7 @@ int main(int argc, char * argv[]) {
}
void program_options(int argc, char * argv[]
- , std::string & filepoints
+ , std::string & off_file_points
, std::string & filediag
, Filtration_value & threshold
, int & dim_max
@@ -135,7 +127,7 @@ void program_options(int argc, char * argv[]
namespace po = boost::program_options;
po::options_description hidden("Hidden options");
hidden.add_options()
- ("input-file", po::value<std::string>(&filepoints),
+ ("input-file", po::value<std::string>(&off_file_points),
"Name of file containing a point set. Format is one point per line: X1 ... Xd ");
po::options_description visible("Allowed options", 100);
diff --git a/src/Persistent_cohomology/test/persistent_cohomology_unit_test_multi_field.cpp b/src/Persistent_cohomology/test/persistent_cohomology_unit_test_multi_field.cpp
index 703682e1..1a6e3296 100644
--- a/src/Persistent_cohomology/test/persistent_cohomology_unit_test_multi_field.cpp
+++ b/src/Persistent_cohomology/test/persistent_cohomology_unit_test_multi_field.cpp
@@ -21,7 +21,7 @@ using namespace boost::unit_test;
typedef Simplex_tree<> typeST;
-std::string test_rips_persistence(int min_coefficient, int max_coefficient, int min_persistence) {
+std::string test_rips_persistence(int min_coefficient, int max_coefficient, double min_persistence) {
// file name is given as parameter from CMakeLists.txt
const std::string inputFile(framework::master_test_suite().argv[1]);
@@ -74,7 +74,7 @@ void test_rips_persistence_in_dimension(int min_dimension, int max_dimension) {
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST OF RIPS_PERSISTENT_COHOMOLOGY_MULTI_FIELD MIN_DIM=" << min_dimension << " MAX_DIM=" << max_dimension << " MIN_PERS=0" << std::endl;
- std::string str_rips_persistence = test_rips_persistence(min_dimension, max_dimension, static_cast<Filtration_value> (0.0));
+ std::string str_rips_persistence = test_rips_persistence(min_dimension, max_dimension, 0.0);
std::cout << "str_rips_persistence=" << str_rips_persistence << std::endl;
BOOST_CHECK(str_rips_persistence.find(value0) != std::string::npos); // Check found
diff --git a/src/Rips_complex/concept/Simplicial_complex_for_rips.h b/src/Rips_complex/concept/Simplicial_complex_for_rips.h
new file mode 100644
index 00000000..7dab0615
--- /dev/null
+++ b/src/Rips_complex/concept/Simplicial_complex_for_rips.h
@@ -0,0 +1,54 @@
+/* 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): Vincent Rouvreau
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONCEPT_RIPS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_RIPS_H_
+#define CONCEPT_RIPS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_RIPS_H_
+
+namespace Gudhi {
+
+namespace rips_complex {
+
+/** \brief The concept SimplicialComplexForRips describes the requirements for a type to implement a simplicial
+ * complex, that can be created from a `Rips_complex`. The only available model for the moment is the `Simplex_tree`.
+ */
+struct SimplicialComplexForRips {
+ /** \brief Type used to store the filtration values of the simplicial complex. */
+ typedef unspecified Filtration_value;
+
+ /** \brief Inserts a given `Gudhi::rips_complex::Rips_complex::OneSkeletonGraph` in the simplicial complex. */
+ template<class OneSkeletonGraph>
+ void insert_graph(const OneSkeletonGraph& skel_graph);
+
+ /** \brief Expands the simplicial complex containing only its one skeleton until a given maximal dimension as
+ * explained in \ref ripsdefinition. */
+ void expansion(int max_dim);
+
+ /** \brief Returns the number of vertices in the simplicial complex. */
+ std::size_t num_vertices();
+
+};
+
+} // namespace rips_complex
+
+} // namespace Gudhi
+
+#endif // CONCEPT_RIPS_COMPLEX_SIMPLICIAL_COMPLEX_FOR_RIPS_H_
diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h
new file mode 100644
index 00000000..8e374c09
--- /dev/null
+++ b/src/Rips_complex/doc/Intro_rips_complex.h
@@ -0,0 +1,158 @@
+/* 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): Clément Maria, Pawel Dlotko, Vincent Rouvreau
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DOC_RIPS_COMPLEX_INTRO_RIPS_COMPLEX_H_
+#define DOC_RIPS_COMPLEX_INTRO_RIPS_COMPLEX_H_
+
+namespace Gudhi {
+
+namespace rips_complex {
+
+/** \defgroup rips_complex Rips complex
+ *
+ * \author Clément Maria, Pawel Dlotko, Vincent Rouvreau
+ *
+ * @{
+ *
+ * \section ripsdefinition Rips complex definition
+ *
+ * Rips_complex
+ * <a target="_blank" href="https://en.wikipedia.org/wiki/Vietoris%E2%80%93Rips_complex">(Wikipedia)</a> is a
+ * one skeleton graph that allows to construct a
+ * <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a>
+ * 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.
+ *
+ * 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 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"
+ *
+ * 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 \f$max(filtration(4,5), filtration(4,6), filtration(5,6))\f$.
+ * And so on for simplex (0,1,2,3).
+ *
+ * If the Rips_complex interfaces are not detailed enough for your need, please refer to
+ * <a href="_persistent_cohomology_2rips_persistence_step_by_step_8cpp-example.html">
+ * rips_persistence_step_by_step.cpp</a> example, where the graph construction over the Simplex_tree is more detailed.
+ *
+ * \section ripspointsdistance Point cloud and distance function
+ *
+ * \subsection ripspointscloudexample Example from a point cloud and a distance function
+ *
+ * This example builds the one skeleton graph from the given points, threshold value, and distance function.
+ * Then it creates a `Simplex_tree` with it.
+ *
+ * Then, it is asked to display information about the simplicial complex.
+ *
+ * \include Rips_complex/example_one_skeleton_rips_from_points.cpp
+ *
+ * When launching (Rips maximal distance between 2 points is 12.0, is expanded until dimension 1 - one skeleton graph
+ * in other words):
+ *
+ * \code $> ./oneskeletonripspoints
+ * \endcode
+ *
+ * the program output is:
+ *
+ * \include Rips_complex/one_skeleton_rips_for_doc.txt
+ *
+ * \subsection ripsoffexample Example from OFF file
+ *
+ * This example builds the Rips_complex from the given points in an OFF file, threshold value, and distance
+ * function.
+ * Then it creates a `Simplex_tree` with it.
+ *
+ *
+ * Then, it is asked to display information about the Rips complex.
+ *
+ * \include Rips_complex/example_rips_complex_from_off_file.cpp
+ *
+ * When launching:
+ *
+ * \code $> ./ripsoffreader ../../data/points/alphacomplexdoc.off 12.0 3
+ * \endcode
+ *
+ * the program output is:
+ *
+ * \include Rips_complex/full_skeleton_rips_for_doc.txt
+ *
+ *
+ *
+ * \section ripsdistancematrix Distance matrix
+ *
+ * \subsection ripsdistancematrixexample Example from a distance matrix
+ *
+ * This example builds the one skeleton graph from the given distance matrix and threshold value.
+ * Then it creates a `Simplex_tree` with it.
+ *
+ * Then, it is asked to display information about the simplicial complex.
+ *
+ * \include Rips_complex/example_one_skeleton_rips_from_distance_matrix.cpp
+ *
+ * When launching (Rips maximal distance between 2 points is 1.0, is expanded until dimension 1 - one skeleton graph
+ * with other words):
+ *
+ * \code $> ./oneskeletonripsdistance
+ * \endcode
+ *
+ * the program output is:
+ *
+ * \include Rips_complex/one_skeleton_rips_for_doc.txt
+ *
+ * \subsection ripscsvdistanceexample Example from a distance matrix read in a csv file
+ *
+ * This example builds the one skeleton graph from the given distance matrix read in a csv file and threshold value.
+ * Then it creates a `Simplex_tree` with it.
+ *
+ *
+ * Then, it is asked to display information about the Rips complex.
+ *
+ * \include Rips_complex/example_rips_complex_from_csv_distance_matrix_file.cpp
+ *
+ * When launching:
+ *
+ * \code $> ./ripscsvdistancereader ../../data/distance_matrix/full_square_distance_matrix.csv 1.0 3
+ * \endcode
+ *
+ * the program output is:
+ *
+ * \include Rips_complex/full_skeleton_rips_for_doc.txt
+ *
+ * \copyright GNU General Public License v3.
+ * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim
+ */
+/** @} */ // end defgroup rips_complex
+
+} // namespace rips_complex
+
+} // namespace Gudhi
+
+#endif // DOC_RIPS_COMPLEX_INTRO_RIPS_COMPLEX_H_
diff --git a/src/Rips_complex/doc/rips_complex_representation.ipe b/src/Rips_complex/doc/rips_complex_representation.ipe
new file mode 100644
index 00000000..7f6028f4
--- /dev/null
+++ b/src/Rips_complex/doc/rips_complex_representation.ipe
@@ -0,0 +1,326 @@
+<?xml version="1.0"?>
+<!DOCTYPE ipe SYSTEM "ipe.dtd">
+<ipe version="70107" creator="Ipe 7.1.10">
+<info created="D:20150603143945" modified="D:20160928121844"/>
+<ipestyle name="basic">
+<symbol name="arrow/arc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/farc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="mark/circle(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</symbol>
+<symbol name="mark/disk(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+</path>
+</symbol>
+<symbol name="mark/fdisk(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+0.5 0 0 0.5 0 0 e
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</group>
+</symbol>
+<symbol name="mark/box(sx)" transformations="translations">
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</symbol>
+<symbol name="mark/square(sx)" transformations="translations">
+<path fill="sym-stroke">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+</path>
+</symbol>
+<symbol name="mark/fsquare(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+-0.5 -0.5 m
+0.5 -0.5 l
+0.5 0.5 l
+-0.5 0.5 l
+h
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="mark/cross(sx)" transformations="translations">
+<group>
+<path fill="sym-stroke">
+-0.43 -0.57 m
+0.57 0.43 l
+0.43 0.57 l
+-0.57 -0.43 l
+h
+</path>
+<path fill="sym-stroke">
+-0.43 0.57 m
+0.57 -0.43 l
+0.43 -0.57 l
+-0.57 0.43 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="arrow/fnormal(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/pointed(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fpointed(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/linear(spx)">
+<path stroke="sym-stroke" pen="sym-pen">
+-1 0.333 m
+0 0 l
+-1 -0.333 l
+</path>
+</symbol>
+<symbol name="arrow/fdouble(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/double(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<pen name="heavier" value="0.8"/>
+<pen name="fat" value="1.2"/>
+<pen name="ultrafat" value="2"/>
+<symbolsize name="large" value="5"/>
+<symbolsize name="small" value="2"/>
+<symbolsize name="tiny" value="1.1"/>
+<arrowsize name="large" value="10"/>
+<arrowsize name="small" value="5"/>
+<arrowsize name="tiny" value="3"/>
+<color name="red" value="1 0 0"/>
+<color name="green" value="0 1 0"/>
+<color name="blue" value="0 0 1"/>
+<color name="yellow" value="1 1 0"/>
+<color name="orange" value="1 0.647 0"/>
+<color name="gold" value="1 0.843 0"/>
+<color name="purple" value="0.627 0.125 0.941"/>
+<color name="gray" value="0.745"/>
+<color name="brown" value="0.647 0.165 0.165"/>
+<color name="navy" value="0 0 0.502"/>
+<color name="pink" value="1 0.753 0.796"/>
+<color name="seagreen" value="0.18 0.545 0.341"/>
+<color name="turquoise" value="0.251 0.878 0.816"/>
+<color name="violet" value="0.933 0.51 0.933"/>
+<color name="darkblue" value="0 0 0.545"/>
+<color name="darkcyan" value="0 0.545 0.545"/>
+<color name="darkgray" value="0.663"/>
+<color name="darkgreen" value="0 0.392 0"/>
+<color name="darkmagenta" value="0.545 0 0.545"/>
+<color name="darkorange" value="1 0.549 0"/>
+<color name="darkred" value="0.545 0 0"/>
+<color name="lightblue" value="0.678 0.847 0.902"/>
+<color name="lightcyan" value="0.878 1 1"/>
+<color name="lightgray" value="0.827"/>
+<color name="lightgreen" value="0.565 0.933 0.565"/>
+<color name="lightyellow" value="1 1 0.878"/>
+<dashstyle name="dashed" value="[4] 0"/>
+<dashstyle name="dotted" value="[1 3] 0"/>
+<dashstyle name="dash dotted" value="[4 2 1 2] 0"/>
+<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/>
+<textsize name="large" value="\large"/>
+<textsize name="small" value="\small"/>
+<textsize name="tiny" value="\tiny"/>
+<textsize name="Large" value="\Large"/>
+<textsize name="LARGE" value="\LARGE"/>
+<textsize name="huge" value="\huge"/>
+<textsize name="Huge" value="\Huge"/>
+<textsize name="footnote" value="\footnotesize"/>
+<textstyle name="center" begin="\begin{center}" end="\end{center}"/>
+<textstyle name="itemize" begin="\begin{itemize}" end="\end{itemize}"/>
+<textstyle name="item" begin="\begin{itemize}\item{}" end="\end{itemize}"/>
+<gridsize name="4 pts" value="4"/>
+<gridsize name="8 pts (~3 mm)" value="8"/>
+<gridsize name="16 pts (~6 mm)" value="16"/>
+<gridsize name="32 pts (~12 mm)" value="32"/>
+<gridsize name="10 pts (~3.5 mm)" value="10"/>
+<gridsize name="20 pts (~7 mm)" value="20"/>
+<gridsize name="14 pts (~5 mm)" value="14"/>
+<gridsize name="28 pts (~10 mm)" value="28"/>
+<gridsize name="56 pts (~20 mm)" value="56"/>
+<anglesize name="90 deg" value="90"/>
+<anglesize name="60 deg" value="60"/>
+<anglesize name="45 deg" value="45"/>
+<anglesize name="30 deg" value="30"/>
+<anglesize name="22.5 deg" value="22.5"/>
+<tiling name="falling" angle="-60" step="4" width="1"/>
+<tiling name="rising" angle="30" step="4" width="1"/>
+</ipestyle>
+<page>
+<layer name="alpha"/>
+<view layers="alpha" active="alpha"/>
+<path layer="alpha" matrix="1 0 0 1 0 -8" fill="darkblue">
+109.771 601.912 m
+159.595 601.797 l
+140.058 541.915 l
+h
+</path>
+<path matrix="1 0 0 1 0 -8" fill="darkblue">
+79.8776 552.169 m
+109.756 601.699 l
+139.812 542.209 l
+h
+</path>
+<path matrix="1 0 0 1 0 -8" fill="lightblue">
+69.8453 682.419 m
+159.925 712.208 l
+90.12 732.039 l
+h
+</path>
+<text matrix="1 0 0 1 -230.178 14.1775" transformations="translations" pos="380 530" stroke="seagreen" type="label" width="68.836" height="8.307" depth="2.32" valign="baseline" size="large">Rips complex</text>
+<text matrix="1 0 0 1 -212.333 10.6762" transformations="translations" pos="282.952 524.893" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="352.708 510.349" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="310.693 578.759" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="375.332 578.49" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="272.179 660.635" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<text matrix="1 0 0 1 -209.478 4.0238" transformations="translations" pos="296.419 724.197" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="375.332 689.453" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+60 710 m
+40 660 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+40 660 m
+130 690 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+130 690 m
+60 710 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+40 660 m
+80 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+80 580 m
+130 580 l
+130 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+130 580 m
+110 520 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+110 520 m
+50 530 l
+50 530 l
+50 530 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+50 530 m
+80 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+130 580 m
+130 690 l
+</path>
+<use matrix="1 0 0 1 -209.478 4.0238" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="280 660" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="370 690" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="370 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="290 530" size="normal" stroke="black" fill="white"/>
+<path matrix="1 0 0 1 -40 -16" stroke="black" pen="heavier">
+150.038 609.9 m
+179.929 549.727 l
+</path>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="320 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="350 520" size="normal" stroke="black" fill="white"/>
+<path stroke="black" pen="heavier">
+158.7 593.269 m
+81.4925 544.805 l
+</path>
+<path matrix="1 0 0 1 -17.9662 -17.9662" stroke="gray">
+256.324 639.958 m
+370.055 639.958 l
+</path>
+<path matrix="1 0 0 1 -17.9662 -17.9662" stroke="gray">
+56.8567 0 0 56.8567 313.217 639.756 e
+</path>
+<use matrix="1 0 0 1 52.1387 -98.0941" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="gray" fill="white"/>
+<use matrix="1 0 0 1 -61.4926 -98.0942" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="gray" fill="white"/>
+<text matrix="1 0 0 1 -26.6167 -33.2708" transformations="translations" pos="295.735 657.944" stroke="gray" type="label" width="63.374" height="6.926" depth="1.93" valign="baseline">Rips threshold</text>
+</page>
+</ipe>
diff --git a/src/Rips_complex/doc/rips_complex_representation.png b/src/Rips_complex/doc/rips_complex_representation.png
new file mode 100644
index 00000000..e901d92e
--- /dev/null
+++ b/src/Rips_complex/doc/rips_complex_representation.png
Binary files differ
diff --git a/src/Rips_complex/doc/rips_one_skeleton.ipe b/src/Rips_complex/doc/rips_one_skeleton.ipe
new file mode 100644
index 00000000..3a35970c
--- /dev/null
+++ b/src/Rips_complex/doc/rips_one_skeleton.ipe
@@ -0,0 +1,326 @@
+<?xml version="1.0"?>
+<!DOCTYPE ipe SYSTEM "ipe.dtd">
+<ipe version="70107" creator="Ipe 7.1.10">
+<info created="D:20150603143945" modified="D:20160928130224"/>
+<ipestyle name="basic">
+<symbol name="arrow/arc(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/farc(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="mark/circle(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</symbol>
+<symbol name="mark/disk(sx)" transformations="translations">
+<path fill="sym-stroke">
+0.6 0 0 0.6 0 0 e
+</path>
+</symbol>
+<symbol name="mark/fdisk(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+0.5 0 0 0.5 0 0 e
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+0.6 0 0 0.6 0 0 e
+0.4 0 0 0.4 0 0 e
+</path>
+</group>
+</symbol>
+<symbol name="mark/box(sx)" transformations="translations">
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</symbol>
+<symbol name="mark/square(sx)" transformations="translations">
+<path fill="sym-stroke">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+</path>
+</symbol>
+<symbol name="mark/fsquare(sfx)" transformations="translations">
+<group>
+<path fill="sym-fill">
+-0.5 -0.5 m
+0.5 -0.5 l
+0.5 0.5 l
+-0.5 0.5 l
+h
+</path>
+<path fill="sym-stroke" fillrule="eofill">
+-0.6 -0.6 m
+0.6 -0.6 l
+0.6 0.6 l
+-0.6 0.6 l
+h
+-0.4 -0.4 m
+0.4 -0.4 l
+0.4 0.4 l
+-0.4 0.4 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="mark/cross(sx)" transformations="translations">
+<group>
+<path fill="sym-stroke">
+-0.43 -0.57 m
+0.57 0.43 l
+0.43 0.57 l
+-0.57 -0.43 l
+h
+</path>
+<path fill="sym-stroke">
+-0.43 0.57 m
+0.57 -0.43 l
+0.43 -0.57 l
+-0.57 0.43 l
+h
+</path>
+</group>
+</symbol>
+<symbol name="arrow/fnormal(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/pointed(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/fpointed(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-0.8 0 l
+-1 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/linear(spx)">
+<path stroke="sym-stroke" pen="sym-pen">
+-1 0.333 m
+0 0 l
+-1 -0.333 l
+</path>
+</symbol>
+<symbol name="arrow/fdouble(spx)">
+<path stroke="sym-stroke" fill="white" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<symbol name="arrow/double(spx)">
+<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen">
+0 0 m
+-1 0.333 l
+-1 -0.333 l
+h
+-1 0 m
+-2 0.333 l
+-2 -0.333 l
+h
+</path>
+</symbol>
+<pen name="heavier" value="0.8"/>
+<pen name="fat" value="1.2"/>
+<pen name="ultrafat" value="2"/>
+<symbolsize name="large" value="5"/>
+<symbolsize name="small" value="2"/>
+<symbolsize name="tiny" value="1.1"/>
+<arrowsize name="large" value="10"/>
+<arrowsize name="small" value="5"/>
+<arrowsize name="tiny" value="3"/>
+<color name="red" value="1 0 0"/>
+<color name="green" value="0 1 0"/>
+<color name="blue" value="0 0 1"/>
+<color name="yellow" value="1 1 0"/>
+<color name="orange" value="1 0.647 0"/>
+<color name="gold" value="1 0.843 0"/>
+<color name="purple" value="0.627 0.125 0.941"/>
+<color name="gray" value="0.745"/>
+<color name="brown" value="0.647 0.165 0.165"/>
+<color name="navy" value="0 0 0.502"/>
+<color name="pink" value="1 0.753 0.796"/>
+<color name="seagreen" value="0.18 0.545 0.341"/>
+<color name="turquoise" value="0.251 0.878 0.816"/>
+<color name="violet" value="0.933 0.51 0.933"/>
+<color name="darkblue" value="0 0 0.545"/>
+<color name="darkcyan" value="0 0.545 0.545"/>
+<color name="darkgray" value="0.663"/>
+<color name="darkgreen" value="0 0.392 0"/>
+<color name="darkmagenta" value="0.545 0 0.545"/>
+<color name="darkorange" value="1 0.549 0"/>
+<color name="darkred" value="0.545 0 0"/>
+<color name="lightblue" value="0.678 0.847 0.902"/>
+<color name="lightcyan" value="0.878 1 1"/>
+<color name="lightgray" value="0.827"/>
+<color name="lightgreen" value="0.565 0.933 0.565"/>
+<color name="lightyellow" value="1 1 0.878"/>
+<dashstyle name="dashed" value="[4] 0"/>
+<dashstyle name="dotted" value="[1 3] 0"/>
+<dashstyle name="dash dotted" value="[4 2 1 2] 0"/>
+<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/>
+<textsize name="large" value="\large"/>
+<textsize name="small" value="\small"/>
+<textsize name="tiny" value="\tiny"/>
+<textsize name="Large" value="\Large"/>
+<textsize name="LARGE" value="\LARGE"/>
+<textsize name="huge" value="\huge"/>
+<textsize name="Huge" value="\Huge"/>
+<textsize name="footnote" value="\footnotesize"/>
+<textstyle name="center" begin="\begin{center}" end="\end{center}"/>
+<textstyle name="itemize" begin="\begin{itemize}" end="\end{itemize}"/>
+<textstyle name="item" begin="\begin{itemize}\item{}" end="\end{itemize}"/>
+<gridsize name="4 pts" value="4"/>
+<gridsize name="8 pts (~3 mm)" value="8"/>
+<gridsize name="16 pts (~6 mm)" value="16"/>
+<gridsize name="32 pts (~12 mm)" value="32"/>
+<gridsize name="10 pts (~3.5 mm)" value="10"/>
+<gridsize name="20 pts (~7 mm)" value="20"/>
+<gridsize name="14 pts (~5 mm)" value="14"/>
+<gridsize name="28 pts (~10 mm)" value="28"/>
+<gridsize name="56 pts (~20 mm)" value="56"/>
+<anglesize name="90 deg" value="90"/>
+<anglesize name="60 deg" value="60"/>
+<anglesize name="45 deg" value="45"/>
+<anglesize name="30 deg" value="30"/>
+<anglesize name="22.5 deg" value="22.5"/>
+<tiling name="falling" angle="-60" step="4" width="1"/>
+<tiling name="rising" angle="30" step="4" width="1"/>
+</ipestyle>
+<page>
+<layer name="alpha"/>
+<view layers="alpha" active="alpha"/>
+<path layer="alpha" matrix="1 0 0 1 0 -8" stroke="0">
+109.771 601.912 m
+159.595 601.797 l
+140.058 541.915 l
+h
+</path>
+<path matrix="1 0 0 1 0 -8" stroke="0">
+79.8776 552.169 m
+109.756 601.699 l
+139.812 542.209 l
+h
+</path>
+<path matrix="1 0 0 1 0.665417 -8.66542" stroke="0">
+69.8453 682.419 m
+159.925 712.208 l
+90.12 732.039 l
+h
+</path>
+<text matrix="1 0 0 1 -230.178 14.1775" transformations="translations" pos="380 530" stroke="seagreen" type="label" width="98.916" height="8.307" depth="2.32" valign="baseline" size="large">One skeleton graph</text>
+<text matrix="1 0 0 1 -212.333 10.6762" transformations="translations" pos="282.952 524.893" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">0</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="352.708 510.349" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">1</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="310.693 578.759" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">2</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="375.332 578.49" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">3</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="272.179 660.635" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">4</text>
+<text matrix="1 0 0 1 -209.478 4.0238" transformations="translations" pos="296.419 724.197" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">5</text>
+<text matrix="1 0 0 1 -210.178 14.1775" transformations="translations" pos="375.332 689.453" stroke="black" type="label" width="4.981" height="6.42" depth="0" valign="baseline">6</text>
+<path matrix="1 0 0 1 30.6497 14.0396" stroke="black" pen="heavier">
+60 710 m
+40 660 l
+</path>
+<path matrix="1 0 0 1 30.3739 13.9018" stroke="black" pen="heavier">
+40 660 m
+130 690 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+130 690 m
+60 710 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+40 660 m
+80 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+80 580 m
+130 580 l
+130 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+130 580 m
+110 520 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+110 520 m
+50 530 l
+50 530 l
+50 530 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+50 530 m
+80 580 l
+</path>
+<path matrix="1 0 0 1 29.8225 14.1775" stroke="black" pen="heavier">
+130 580 m
+130 690 l
+</path>
+<use matrix="1 0 0 1 -209.478 4.0238" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="280 660" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="370 690" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="370 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="290 530" size="normal" stroke="black" fill="white"/>
+<path matrix="1 0 0 1 -40 -16" stroke="black" pen="heavier">
+150.038 609.9 m
+179.929 549.727 l
+</path>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="320 580" size="normal" stroke="black" fill="white"/>
+<use matrix="1 0 0 1 -210.178 14.1775" name="mark/fdisk(sfx)" pos="350 520" size="normal" stroke="black" fill="white"/>
+<path stroke="black" pen="heavier">
+158.7 593.269 m
+81.4925 544.805 l
+</path>
+<path matrix="1 0 0 1 -17.9662 -17.9662" stroke="gray">
+256.324 639.958 m
+370.055 639.958 l
+</path>
+<path matrix="1 0 0 1 -17.9662 -17.9662" stroke="gray">
+56.8567 0 0 56.8567 313.217 639.756 e
+</path>
+<use matrix="1 0 0 1 52.1387 -98.0941" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="gray" fill="white"/>
+<use matrix="1 0 0 1 -61.4926 -98.0942" name="mark/fdisk(sfx)" pos="300 720" size="normal" stroke="gray" fill="white"/>
+<text matrix="1 0 0 1 -26.6167 -33.2708" transformations="translations" pos="295.735 657.944" stroke="gray" type="label" width="63.374" height="6.926" depth="1.93" valign="baseline">Rips threshold</text>
+</page>
+</ipe>
diff --git a/src/Rips_complex/doc/rips_one_skeleton.png b/src/Rips_complex/doc/rips_one_skeleton.png
new file mode 100644
index 00000000..1028770e
--- /dev/null
+++ b/src/Rips_complex/doc/rips_one_skeleton.png
Binary files differ
diff --git a/src/Rips_complex/example/CMakeLists.txt b/src/Rips_complex/example/CMakeLists.txt
new file mode 100644
index 00000000..070ac710
--- /dev/null
+++ b/src/Rips_complex/example/CMakeLists.txt
@@ -0,0 +1,47 @@
+cmake_minimum_required(VERSION 2.6)
+project(Rips_complex_examples)
+
+# Point cloud
+add_executable ( ripsoffreader example_rips_complex_from_off_file.cpp )
+target_link_libraries(ripsoffreader ${Boost_SYSTEM_LIBRARY})
+
+add_executable ( oneskeletonripspoints example_one_skeleton_rips_from_points.cpp )
+target_link_libraries(oneskeletonripspoints ${Boost_SYSTEM_LIBRARY})
+
+# Distance matrix
+add_executable ( oneskeletonripsdistance example_one_skeleton_rips_from_distance_matrix.cpp )
+target_link_libraries(oneskeletonripsdistance ${Boost_SYSTEM_LIBRARY})
+
+add_executable ( ripscsvdistancereader example_rips_complex_from_csv_distance_matrix_file.cpp )
+target_link_libraries(ripscsvdistancereader ${Boost_SYSTEM_LIBRARY})
+
+if (TBB_FOUND)
+ target_link_libraries(ripsoffreader ${TBB_LIBRARIES})
+ target_link_libraries(oneskeletonripspoints ${TBB_LIBRARIES})
+ target_link_libraries(oneskeletonripsdistance ${TBB_LIBRARIES})
+ target_link_libraries(ripscsvdistancereader ${TBB_LIBRARIES})
+endif()
+
+add_test(oneskeletonripspoints ${CMAKE_CURRENT_BINARY_DIR}/oneskeletonripspoints)
+add_test(oneskeletonripsdistance ${CMAKE_CURRENT_BINARY_DIR}/oneskeletonripsdistance)
+
+# Do not forget to copy test files in current binary dir
+file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+add_test(ripsoffreader_doc_12_1 ${CMAKE_CURRENT_BINARY_DIR}/ripsoffreader alphacomplexdoc.off 12.0 1 ${CMAKE_CURRENT_BINARY_DIR}/ripsoffreader_result_12_1.txt)
+add_test(ripsoffreader_doc_12_3 ${CMAKE_CURRENT_BINARY_DIR}/ripsoffreader alphacomplexdoc.off 12.0 3 ${CMAKE_CURRENT_BINARY_DIR}/ripsoffreader_result_12_3.txt)
+
+file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+add_test(ripscsvdistancereader_doc_12_1 ${CMAKE_CURRENT_BINARY_DIR}/ripscsvdistancereader full_square_distance_matrix.csv 12.0 1 ${CMAKE_CURRENT_BINARY_DIR}/ripscsvreader_result_12_1.txt)
+add_test(ripscsvdistancereader_doc_12_3 ${CMAKE_CURRENT_BINARY_DIR}/ripscsvdistancereader full_square_distance_matrix.csv 12.0 3 ${CMAKE_CURRENT_BINARY_DIR}/ripscsvreader_result_12_3.txt)
+
+
+if (DIFF_PATH)
+ # Do not forget to copy test results files in current binary dir
+ file(COPY "one_skeleton_rips_for_doc.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+ file(COPY "full_skeleton_rips_for_doc.txt" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+
+ add_test(ripsoffreader_doc_12_1_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/ripsoffreader_result_12_1.txt ${CMAKE_CURRENT_BINARY_DIR}/one_skeleton_rips_for_doc.txt)
+ add_test(ripsoffreader_doc_12_3_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/ripsoffreader_result_12_3.txt ${CMAKE_CURRENT_BINARY_DIR}/full_skeleton_rips_for_doc.txt)
+ add_test(ripscsvreader_doc_12_1_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/ripscsvreader_result_12_1.txt ${CMAKE_CURRENT_BINARY_DIR}/one_skeleton_rips_for_doc.txt)
+ add_test(ripscsvreader_doc_12_3_diff_files ${DIFF_PATH} ${CMAKE_CURRENT_BINARY_DIR}/ripscsvreader_result_12_3.txt ${CMAKE_CURRENT_BINARY_DIR}/full_skeleton_rips_for_doc.txt)
+endif()
diff --git a/src/Rips_complex/example/example_one_skeleton_rips_from_distance_matrix.cpp b/src/Rips_complex/example/example_one_skeleton_rips_from_distance_matrix.cpp
new file mode 100644
index 00000000..bbc3c755
--- /dev/null
+++ b/src/Rips_complex/example/example_one_skeleton_rips_from_distance_matrix.cpp
@@ -0,0 +1,58 @@
+#include <gudhi/Rips_complex.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/distance_functions.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <limits> // for std::numeric_limits
+
+int main() {
+ // Type definitions
+ using Simplex_tree = Gudhi::Simplex_tree<>;
+ using Filtration_value = Simplex_tree::Filtration_value;
+ using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+ using Distance_matrix = std::vector<std::vector<Filtration_value>>;
+
+ // User defined distance matrix is:
+ // | 0 0.94 0.77 0.99 0.11 |
+ // | 0.94 0 0.26 0.99 0.39 |
+ // | 0.77 0.26 0 0.28 0.97 |
+ // | 0.99 0.99 0.28 0 0.30 |
+ // | 0.11 0.39 0.97 0.30 0 |
+
+ Distance_matrix distances;
+ distances.push_back({});
+ distances.push_back({0.94});
+ distances.push_back({0.77, 0.26});
+ distances.push_back({0.99, 0.99, 0.28});
+ distances.push_back({0.11, 0.39, 0.97, 0.30});
+
+ // ----------------------------------------------------------------------------
+ // Init of a Rips complex from points
+ // ----------------------------------------------------------------------------
+ double threshold = 1.0;
+ Rips_complex rips_complex_from_points(distances, threshold);
+
+ Simplex_tree stree;
+ rips_complex_from_points.create_complex(stree, 1);
+ // ----------------------------------------------------------------------------
+ // Display information about the one skeleton Rips complex
+ // ----------------------------------------------------------------------------
+ std::cout << "Rips complex is of dimension " << stree.dimension() <<
+ " - " << stree.num_simplices() << " simplices - " <<
+ stree.num_vertices() << " vertices." << std::endl;
+
+ std::cout << "Iterator on Rips complex simplices in the filtration order, with [filtration value]:" <<
+ std::endl;
+ for (auto f_simplex : stree.filtration_simplex_range()) {
+ std::cout << " ( ";
+ for (auto vertex : stree.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> " << "[" << stree.filtration(f_simplex) << "] ";
+ std::cout << std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/Rips_complex/example/example_one_skeleton_rips_from_points.cpp b/src/Rips_complex/example/example_one_skeleton_rips_from_points.cpp
new file mode 100644
index 00000000..3fd69ebc
--- /dev/null
+++ b/src/Rips_complex/example/example_one_skeleton_rips_from_points.cpp
@@ -0,0 +1,52 @@
+#include <gudhi/Rips_complex.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/distance_functions.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <limits> // for std::numeric_limits
+
+int main() {
+ // Type definitions
+ using Point = std::vector<double>;
+ using Simplex_tree = Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_fast_persistence>;
+ using Filtration_value = Simplex_tree::Filtration_value;
+ using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+
+ std::vector<Point> points;
+ points.push_back({1.0, 1.0});
+ points.push_back({7.0, 0.0});
+ points.push_back({4.0, 6.0});
+ points.push_back({9.0, 6.0});
+ points.push_back({0.0, 14.0});
+ points.push_back({2.0, 19.0});
+ points.push_back({9.0, 17.0});
+
+ // ----------------------------------------------------------------------------
+ // Init of a Rips complex from points
+ // ----------------------------------------------------------------------------
+ double threshold = 12.0;
+ Rips_complex rips_complex_from_points(points, threshold, Euclidean_distance());
+
+ Simplex_tree stree;
+ rips_complex_from_points.create_complex(stree, 1);
+ // ----------------------------------------------------------------------------
+ // Display information about the one skeleton Rips complex
+ // ----------------------------------------------------------------------------
+ std::cout << "Rips complex is of dimension " << stree.dimension() <<
+ " - " << stree.num_simplices() << " simplices - " <<
+ stree.num_vertices() << " vertices." << std::endl;
+
+ std::cout << "Iterator on Rips complex simplices in the filtration order, with [filtration value]:" <<
+ std::endl;
+ for (auto f_simplex : stree.filtration_simplex_range()) {
+ std::cout << " ( ";
+ for (auto vertex : stree.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << " ";
+ }
+ std::cout << ") -> " << "[" << stree.filtration(f_simplex) << "] ";
+ std::cout << std::endl;
+ }
+ return 0;
+}
diff --git a/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp b/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp
new file mode 100644
index 00000000..ef3a9d13
--- /dev/null
+++ b/src/Rips_complex/example/example_rips_complex_from_csv_distance_matrix_file.cpp
@@ -0,0 +1,72 @@
+#include <gudhi/Rips_complex.h>
+// to construct Rips_complex from a OFF file of points
+#include <gudhi/reader_utils.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/distance_functions.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+void usage(int nbArgs, char * const progName) {
+ std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n";
+ std::cerr << "Usage: " << progName << " filename.csv threshold dim_max [ouput_file.txt]\n";
+ std::cerr << " i.e.: " << progName << " ../../data/distance_matrix/full_square_distance_matrix.csv 1.0 3\n";
+ exit(-1); // ----- >>
+}
+
+int main(int argc, char **argv) {
+ if ((argc != 4) && (argc != 5)) usage(argc, (argv[0] - 1));
+
+ std::string csv_file_name(argv[1]);
+ double threshold = atof(argv[2]);
+ int dim_max = atoi(argv[3]);
+
+ // Type definitions
+ using Simplex_tree = Gudhi::Simplex_tree<>;
+ using Filtration_value = Simplex_tree::Filtration_value;
+ using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+ using Distance_matrix = std::vector<std::vector<Filtration_value>>;
+
+ // ----------------------------------------------------------------------------
+ // Init of a Rips complex from a distance matrix in a csv file
+ // Default separator is ';'
+ // ----------------------------------------------------------------------------
+ Distance_matrix distances = read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_file_name);
+ Rips_complex rips_complex_from_file(distances, threshold);
+
+ std::streambuf* streambufffer;
+ std::ofstream ouput_file_stream;
+
+ if (argc == 5) {
+ ouput_file_stream.open(std::string(argv[4]));
+ streambufffer = ouput_file_stream.rdbuf();
+ } else {
+ streambufffer = std::cout.rdbuf();
+ }
+
+ Simplex_tree stree;
+ rips_complex_from_file.create_complex(stree, dim_max);
+ std::ostream output_stream(streambufffer);
+
+ // ----------------------------------------------------------------------------
+ // Display information about the Rips complex
+ // ----------------------------------------------------------------------------
+ output_stream << "Rips complex is of dimension " << stree.dimension() <<
+ " - " << stree.num_simplices() << " simplices - " <<
+ stree.num_vertices() << " vertices." << std::endl;
+
+ output_stream << "Iterator on Rips complex simplices in the filtration order, with [filtration value]:" <<
+ std::endl;
+ for (auto f_simplex : stree.filtration_simplex_range()) {
+ output_stream << " ( ";
+ for (auto vertex : stree.simplex_vertex_range(f_simplex)) {
+ output_stream << vertex << " ";
+ }
+ output_stream << ") -> " << "[" << stree.filtration(f_simplex) << "] ";
+ output_stream << std::endl;
+ }
+
+ ouput_file_stream.close();
+ return 0;
+}
diff --git a/src/Rips_complex/example/example_rips_complex_from_off_file.cpp b/src/Rips_complex/example/example_rips_complex_from_off_file.cpp
new file mode 100644
index 00000000..a1e4e255
--- /dev/null
+++ b/src/Rips_complex/example/example_rips_complex_from_off_file.cpp
@@ -0,0 +1,71 @@
+#include <gudhi/Rips_complex.h>
+// to construct Rips_complex from a OFF file of points
+#include <gudhi/Points_off_io.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/distance_functions.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+void usage(int nbArgs, char * const progName) {
+ std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n";
+ std::cerr << "Usage: " << progName << " filename.off threshold dim_max [ouput_file.txt]\n";
+ std::cerr << " i.e.: " << progName << " ../../data/points/alphacomplexdoc.off 60.0\n";
+ exit(-1); // ----- >>
+}
+
+int main(int argc, char **argv) {
+ if ((argc != 4) && (argc != 5)) usage(argc, (argv[0] - 1));
+
+ std::string off_file_name(argv[1]);
+ double threshold = atof(argv[2]);
+ int dim_max = atoi(argv[3]);
+
+ // Type definitions
+ using Point = std::vector<float>;
+ using Simplex_tree = Gudhi::Simplex_tree<>;
+ using Filtration_value = Simplex_tree::Filtration_value;
+ using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>;
+
+ // ----------------------------------------------------------------------------
+ // Init of a Rips complex from an OFF file
+ // ----------------------------------------------------------------------------
+ Gudhi::Points_off_reader<Point> off_reader(off_file_name);
+ Rips_complex rips_complex_from_file(off_reader.get_point_cloud(), threshold, Euclidean_distance());
+
+ std::streambuf* streambufffer;
+ std::ofstream ouput_file_stream;
+
+ if (argc == 5) {
+ ouput_file_stream.open(std::string(argv[4]));
+ streambufffer = ouput_file_stream.rdbuf();
+ } else {
+ streambufffer = std::cout.rdbuf();
+ }
+
+ Simplex_tree stree;
+ rips_complex_from_file.create_complex(stree, dim_max);
+ std::ostream output_stream(streambufffer);
+
+ // ----------------------------------------------------------------------------
+ // Display information about the Rips complex
+ // ----------------------------------------------------------------------------
+ output_stream << "Rips complex is of dimension " << stree.dimension() <<
+ " - " << stree.num_simplices() << " simplices - " <<
+ stree.num_vertices() << " vertices." << std::endl;
+
+ output_stream << "Iterator on Rips complex simplices in the filtration order, with [filtration value]:" <<
+ std::endl;
+ for (auto f_simplex : stree.filtration_simplex_range()) {
+ output_stream << " ( ";
+ for (auto vertex : stree.simplex_vertex_range(f_simplex)) {
+ output_stream << vertex << " ";
+ }
+ output_stream << ") -> " << "[" << stree.filtration(f_simplex) << "] ";
+ output_stream << std::endl;
+ }
+
+ ouput_file_stream.close();
+ return 0;
+}
diff --git a/src/Rips_complex/example/full_skeleton_rips_for_doc.txt b/src/Rips_complex/example/full_skeleton_rips_for_doc.txt
new file mode 100644
index 00000000..55de4ab8
--- /dev/null
+++ b/src/Rips_complex/example/full_skeleton_rips_for_doc.txt
@@ -0,0 +1,26 @@
+Rips complex is of dimension 3 - 24 simplices - 7 vertices.
+Iterator on Rips complex simplices in the filtration order, with [filtration value]:
+ ( 0 ) -> [0]
+ ( 1 ) -> [0]
+ ( 2 ) -> [0]
+ ( 3 ) -> [0]
+ ( 4 ) -> [0]
+ ( 5 ) -> [0]
+ ( 6 ) -> [0]
+ ( 3 2 ) -> [5]
+ ( 5 4 ) -> [5.38516]
+ ( 2 0 ) -> [5.83095]
+ ( 1 0 ) -> [6.08276]
+ ( 3 1 ) -> [6.32456]
+ ( 2 1 ) -> [6.7082]
+ ( 2 1 0 ) -> [6.7082]
+ ( 3 2 1 ) -> [6.7082]
+ ( 6 5 ) -> [7.28011]
+ ( 4 2 ) -> [8.94427]
+ ( 3 0 ) -> [9.43398]
+ ( 3 1 0 ) -> [9.43398]
+ ( 3 2 0 ) -> [9.43398]
+ ( 3 2 1 0 ) -> [9.43398]
+ ( 6 4 ) -> [9.48683]
+ ( 6 5 4 ) -> [9.48683]
+ ( 6 3 ) -> [11]
diff --git a/src/Rips_complex/example/one_skeleton_rips_for_doc.txt b/src/Rips_complex/example/one_skeleton_rips_for_doc.txt
new file mode 100644
index 00000000..706512a5
--- /dev/null
+++ b/src/Rips_complex/example/one_skeleton_rips_for_doc.txt
@@ -0,0 +1,20 @@
+Rips complex is of dimension 1 - 18 simplices - 7 vertices.
+Iterator on Rips complex simplices in the filtration order, with [filtration value]:
+ ( 0 ) -> [0]
+ ( 1 ) -> [0]
+ ( 2 ) -> [0]
+ ( 3 ) -> [0]
+ ( 4 ) -> [0]
+ ( 5 ) -> [0]
+ ( 6 ) -> [0]
+ ( 3 2 ) -> [5]
+ ( 5 4 ) -> [5.38516]
+ ( 2 0 ) -> [5.83095]
+ ( 1 0 ) -> [6.08276]
+ ( 3 1 ) -> [6.32456]
+ ( 2 1 ) -> [6.7082]
+ ( 6 5 ) -> [7.28011]
+ ( 4 2 ) -> [8.94427]
+ ( 3 0 ) -> [9.43398]
+ ( 6 4 ) -> [9.48683]
+ ( 6 3 ) -> [11]
diff --git a/src/Rips_complex/include/gudhi/Rips_complex.h b/src/Rips_complex/include/gudhi/Rips_complex.h
new file mode 100644
index 00000000..1e4b76a7
--- /dev/null
+++ b/src/Rips_complex/include/gudhi/Rips_complex.h
@@ -0,0 +1,185 @@
+/* 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): Clément Maria, Pawel Dlotko, Vincent Rouvreau
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RIPS_COMPLEX_H_
+#define RIPS_COMPLEX_H_
+
+#include <gudhi/Debug_utils.h>
+#include <gudhi/graph_simplicial_complex.h>
+
+#include <boost/graph/adjacency_list.hpp>
+
+#include <iostream>
+#include <vector>
+#include <map>
+#include <string>
+#include <limits> // for numeric_limits
+#include <utility> // for pair<>
+
+
+namespace Gudhi {
+
+namespace rips_complex {
+
+/**
+ * \class Rips_complex
+ * \brief Rips complex data structure.
+ *
+ * \ingroup rips_complex
+ *
+ * \details
+ * The data structure is a one skeleton graph, or Rips graph, containing edges when the edge length is less or equal
+ * to a given threshold. Edge length is computed from a user given point cloud with a given distance function, or a
+ * distance matrix.
+ *
+ * \tparam Filtration_value is the type used to store the filtration values of the simplicial complex.
+ */
+template<typename Filtration_value>
+class Rips_complex {
+ public:
+ /**
+ * \brief Type of the one skeleton graph stored inside the Rips complex structure.
+ */
+ typedef typename boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS
+ , boost::property < vertex_filtration_t, Filtration_value >
+ , boost::property < edge_filtration_t, Filtration_value >> OneSkeletonGraph;
+
+ private:
+ typedef int Vertex_handle;
+
+ public:
+ /** \brief Rips_complex constructor from a list of points.
+ *
+ * @param[in] points Range of points.
+ * @param[in] threshold Rips value.
+ * @param[in] distance distance function that returns a `Filtration_value` from 2 given points.
+ *
+ * \tparam ForwardPointRange must be a range for which `std::begin` and `std::end` return input iterators on a
+ * point.
+ *
+ * \tparam Distance furnishes `operator()(const Point& p1, const Point& p2)`, where
+ * `Point` is a point from the `ForwardPointRange`, and that returns a `Filtration_value`.
+ */
+ template<typename ForwardPointRange, typename Distance >
+ Rips_complex(const ForwardPointRange& points, Filtration_value threshold, Distance distance) {
+ compute_proximity_graph(points, threshold, distance);
+ }
+
+ /** \brief Rips_complex constructor from a distance matrix.
+ *
+ * @param[in] distance_matrix Range of distances.
+ * @param[in] threshold Rips value.
+ *
+ * \tparam DistanceMatrix must have a `size()` method and on which `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<typename DistanceMatrix>
+ Rips_complex(const DistanceMatrix& distance_matrix, Filtration_value threshold) {
+ compute_proximity_graph(boost::irange((size_t)0, distance_matrix.size()), threshold,
+ [&](size_t i, size_t j){return distance_matrix[j][i];});
+ }
+
+ /** \brief Initializes the simplicial complex from the Rips graph and expands it until a given maximal
+ * dimension.
+ *
+ * \tparam SimplicialComplexForRips must meet `SimplicialComplexForRips` concept.
+ *
+ * @param[in] complex SimplicialComplexForRips to be created.
+ * @param[in] dim_max graph expansion for Rips until this given maximal dimension.
+ * @exception std::invalid_argument In debug mode, if `complex.num_vertices()` does not return 0.
+ *
+ */
+ template <typename SimplicialComplexForRips>
+ void create_complex(SimplicialComplexForRips& complex, int dim_max) {
+ GUDHI_CHECK(complex.num_vertices() == 0,
+ std::invalid_argument("Rips_complex::create_complex - simplicial complex is not empty"));
+
+ // insert the proximity graph in the simplicial complex
+ complex.insert_graph(rips_skeleton_graph_);
+ // expand the graph until dimension dim_max
+ complex.expansion(dim_max);
+ }
+
+ private:
+ /** \brief Computes the proximity graph of the points.
+ *
+ * If points contains n elements, the proximity graph is the graph with n vertices, and an edge [u,v] iff the
+ * distance function between points u and v is smaller than threshold.
+ *
+ * \tparam ForwardPointRange furnishes `.begin()` and `.end()`
+ * methods.
+ *
+ * \tparam Distance furnishes `operator()(const Point& p1, const Point& p2)`, where
+ * `Point` is a point from the `ForwardPointRange`, and that returns a `Filtration_value`.
+ */
+ template< typename ForwardPointRange, typename Distance >
+ void compute_proximity_graph(const ForwardPointRange& points, Filtration_value threshold,
+ Distance distance) {
+ std::vector< std::pair< Vertex_handle, Vertex_handle > > edges;
+ std::vector< Filtration_value > edges_fil;
+
+ // Compute the proximity graph of the points.
+ // If points contains n elements, the proximity graph is the graph with n vertices, and an edge [u,v] iff the
+ // distance function between points u and v is smaller than threshold.
+ // --------------------------------------------------------------------------------------------
+ // Creates the vector of edges and its filtration values (returned by distance function)
+ Vertex_handle idx_u = 0;
+ for (auto it_u = std::begin(points); it_u != std::end(points); ++it_u, ++idx_u) {
+ Vertex_handle idx_v = idx_u + 1;
+ for (auto it_v = it_u + 1; it_v != std::end(points); ++it_v, ++idx_v) {
+ Filtration_value fil = distance(*it_u, *it_v);
+ if (fil <= threshold) {
+ edges.emplace_back(idx_u, idx_v);
+ edges_fil.push_back(fil);
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------
+ // Creates the proximity graph from edges and sets the property with the filtration value.
+ // Number of points is labeled from 0 to idx_u-1
+ // --------------------------------------------------------------------------------------------
+ // Do not use : rips_skeleton_graph_ = OneSkeletonGraph(...) -> deep copy of the graph (boost graph is not
+ // move-enabled)
+ rips_skeleton_graph_.~OneSkeletonGraph();
+ new(&rips_skeleton_graph_)OneSkeletonGraph(edges.begin(), edges.end(), edges_fil.begin(), idx_u);
+
+ auto vertex_prop = boost::get(vertex_filtration_t(), rips_skeleton_graph_);
+
+ using vertex_iterator = typename boost::graph_traits<OneSkeletonGraph>::vertex_iterator;
+ vertex_iterator vi, vi_end;
+ for (std::tie(vi, vi_end) = boost::vertices(rips_skeleton_graph_);
+ vi != vi_end; ++vi) {
+ boost::put(vertex_prop, *vi, 0.);
+ }
+ }
+
+ private:
+ OneSkeletonGraph rips_skeleton_graph_;
+};
+
+} // namespace rips_complex
+
+} // namespace Gudhi
+
+#endif // RIPS_COMPLEX_H_
diff --git a/src/Rips_complex/test/CMakeLists.txt b/src/Rips_complex/test/CMakeLists.txt
new file mode 100644
index 00000000..87bad2ed
--- /dev/null
+++ b/src/Rips_complex/test/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 2.6)
+project(Rips_complex_tests)
+
+if (GCOVR_PATH)
+ # for gcovr to make coverage reports - Corbera Jenkins plugin
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+if (GPROF_PATH)
+ # for gprof to make coverage reports - Jenkins
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+endif()
+
+add_executable ( rips_complex_UT test_rips_complex.cpp )
+target_link_libraries(rips_complex_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+if (TBB_FOUND)
+ target_link_libraries(rips_complex_UT ${TBB_LIBRARIES})
+endif()
+
+# Do not forget to copy test files in current binary dir
+file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+
+add_test(rips_complex_UT ${CMAKE_CURRENT_BINARY_DIR}/rips_complex_UT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/rips_complex_UT.xml --log_level=test_suite --report_level=no)
diff --git a/src/Rips_complex/test/README b/src/Rips_complex/test/README
new file mode 100644
index 00000000..28236b52
--- /dev/null
+++ b/src/Rips_complex/test/README
@@ -0,0 +1,12 @@
+To compile:
+***********
+
+cmake .
+make
+
+To launch with details:
+***********************
+
+./rips_complex_UT --report_level=detailed --log_level=all
+
+ ==> echo $? returns 0 in case of success (non-zero otherwise)
diff --git a/src/Rips_complex/test/test_rips_complex.cpp b/src/Rips_complex/test/test_rips_complex.cpp
new file mode 100644
index 00000000..ae68ba0d
--- /dev/null
+++ b/src/Rips_complex/test/test_rips_complex.cpp
@@ -0,0 +1,353 @@
+/* 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): Vincent Rouvreau
+ *
+ * Copyright (C) 2016 INRIA Saclay (France)
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "rips_complex"
+#include <boost/test/unit_test.hpp>
+
+#include <cmath> // float comparison
+#include <limits>
+#include <string>
+#include <vector>
+#include <algorithm> // std::max
+
+#include <gudhi/Rips_complex.h>
+// to construct Rips_complex from a OFF file of points
+#include <gudhi/Points_off_io.h>
+#include <gudhi/Simplex_tree.h>
+#include <gudhi/distance_functions.h>
+#include <gudhi/reader_utils.h>
+
+// Type definitions
+using Point = std::vector<double>;
+using Simplex_tree = Gudhi::Simplex_tree<>;
+using Filtration_value = Simplex_tree::Filtration_value;
+using Rips_complex = Gudhi::rips_complex::Rips_complex<Simplex_tree::Filtration_value>;
+using Distance_matrix = std::vector<std::vector<Filtration_value>>;
+
+bool are_almost_the_same(float a, float b) {
+ return std::fabs(a - b) < std::numeric_limits<float>::epsilon();
+}
+
+BOOST_AUTO_TEST_CASE(RIPS_DOC_OFF_file) {
+ // ----------------------------------------------------------------------------
+ //
+ // Init of a Rips complex from a OFF file
+ //
+ // ----------------------------------------------------------------------------
+ std::string off_file_name("alphacomplexdoc.off");
+ double rips_threshold = 12.0;
+ std::cout << "========== OFF FILE NAME = " << off_file_name << " - Rips threshold=" <<
+ rips_threshold << "==========" << std::endl;
+
+ Gudhi::Points_off_reader<Point> off_reader(off_file_name);
+ Rips_complex rips_complex_from_file(off_reader.get_point_cloud(), rips_threshold, Euclidean_distance());
+
+ const int DIMENSION_1 = 1;
+ Simplex_tree st;
+ rips_complex_from_file.create_complex(st, DIMENSION_1);
+ std::cout << "st.dimension()=" << st.dimension() << std::endl;
+ BOOST_CHECK(st.dimension() == DIMENSION_1);
+
+ const int NUMBER_OF_VERTICES = 7;
+ std::cout << "st.num_vertices()=" << st.num_vertices() << std::endl;
+ BOOST_CHECK(st.num_vertices() == NUMBER_OF_VERTICES);
+
+ std::cout << "st.num_simplices()=" << st.num_simplices() << std::endl;
+ BOOST_CHECK(st.num_simplices() == 18);
+
+ // Check filtration values of vertices is 0.0
+ for (auto f_simplex : st.skeleton_simplex_range(0)) {
+ BOOST_CHECK(st.filtration(f_simplex) == 0.0);
+ }
+
+ // Check filtration values of edges
+ for (auto f_simplex : st.skeleton_simplex_range(DIMENSION_1)) {
+ if (DIMENSION_1 == st.dimension(f_simplex)) {
+ std::vector<Point> vp;
+ std::cout << "vertex = (";
+ for (auto vertex : st.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << ",";
+ vp.push_back(off_reader.get_point_cloud().at(vertex));
+ }
+ std::cout << ") - distance =" << Euclidean_distance()(vp.at(0), vp.at(1)) <<
+ " - filtration =" << st.filtration(f_simplex) << std::endl;
+ BOOST_CHECK(vp.size() == 2);
+ BOOST_CHECK(are_almost_the_same(st.filtration(f_simplex), Euclidean_distance()(vp.at(0), vp.at(1))));
+ }
+ }
+
+ const int DIMENSION_2 = 2;
+ Simplex_tree st2;
+ rips_complex_from_file.create_complex(st2, DIMENSION_2);
+ std::cout << "st2.dimension()=" << st2.dimension() << std::endl;
+ BOOST_CHECK(st2.dimension() == DIMENSION_2);
+
+ std::cout << "st2.num_vertices()=" << st2.num_vertices() << std::endl;
+ BOOST_CHECK(st2.num_vertices() == NUMBER_OF_VERTICES);
+
+ std::cout << "st2.num_simplices()=" << st2.num_simplices() << std::endl;
+ BOOST_CHECK(st2.num_simplices() == 23);
+
+ Simplex_tree::Filtration_value f01 = st2.filtration(st2.find({0, 1}));
+ Simplex_tree::Filtration_value f02 = st2.filtration(st2.find({0, 2}));
+ Simplex_tree::Filtration_value f12 = st2.filtration(st2.find({1, 2}));
+ Simplex_tree::Filtration_value f012 = st2.filtration(st2.find({0, 1, 2}));
+ std::cout << "f012= " << f012 << " | f01= " << f01 << " - f02= " << f02 << " - f12= " << f12 << std::endl;
+ BOOST_CHECK(are_almost_the_same(f012, std::max(f01, std::max(f02,f12))));
+
+ Simplex_tree::Filtration_value f45 = st2.filtration(st2.find({4, 5}));
+ Simplex_tree::Filtration_value f56 = st2.filtration(st2.find({5, 6}));
+ Simplex_tree::Filtration_value f46 = st2.filtration(st2.find({4, 6}));
+ Simplex_tree::Filtration_value f456 = st2.filtration(st2.find({4, 5, 6}));
+ std::cout << "f456= " << f456 << " | f45= " << f45 << " - f56= " << f56 << " - f46= " << f46 << std::endl;
+ BOOST_CHECK(are_almost_the_same(f456, std::max(f45, std::max(f56,f46))));
+
+ const int DIMENSION_3 = 3;
+ Simplex_tree st3;
+ rips_complex_from_file.create_complex(st3, DIMENSION_3);
+ std::cout << "st3.dimension()=" << st3.dimension() << std::endl;
+ BOOST_CHECK(st3.dimension() == DIMENSION_3);
+
+ std::cout << "st3.num_vertices()=" << st3.num_vertices() << std::endl;
+ BOOST_CHECK(st3.num_vertices() == NUMBER_OF_VERTICES);
+
+ std::cout << "st3.num_simplices()=" << st3.num_simplices() << std::endl;
+ BOOST_CHECK(st3.num_simplices() == 24);
+
+ Simplex_tree::Filtration_value f123 = st3.filtration(st3.find({1, 2, 3}));
+ Simplex_tree::Filtration_value f013 = st3.filtration(st3.find({0, 1, 3}));
+ Simplex_tree::Filtration_value f023 = st3.filtration(st3.find({0, 2, 3}));
+ Simplex_tree::Filtration_value f0123 = st3.filtration(st3.find({0, 1, 2, 3}));
+ std::cout << "f0123= " << f0123 << " | f012= " << f012 << " - f123= " << f123 << " - f013= " << f013 <<
+ " - f023= " << f023 << std::endl;
+ BOOST_CHECK(are_almost_the_same(f0123, std::max(f012, std::max(f123, std::max(f013, f023)))));
+
+}
+
+using Vector_of_points = std::vector<Point>;
+
+bool is_point_in_list(Vector_of_points points_list, Point point) {
+ for (auto& point_in_list : points_list) {
+ if (point_in_list == point) {
+ return true; // point found
+ }
+ }
+ return false; // point not found
+}
+
+class Custom_square_euclidean_distance {
+ public:
+ template< typename Point >
+ auto operator()(const Point& p1, const Point& p2) -> typename Point::value_type {
+ auto it1 = p1.begin();
+ auto it2 = p2.begin();
+ typename Point::value_type dist = 0.;
+ for (; it1 != p1.end(); ++it1, ++it2) {
+ typename Point::value_type tmp = (*it1) - (*it2);
+ dist += tmp*tmp;
+ }
+ return dist;
+ }
+};
+
+BOOST_AUTO_TEST_CASE(Rips_complex_from_points) {
+ // ----------------------------------------------------------------------------
+ // Init of a list of points
+ // ----------------------------------------------------------------------------
+ Vector_of_points points;
+ std::vector<double> 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
+ // ----------------------------------------------------------------------------
+ Rips_complex rips_complex_from_points(points, 2.0, Custom_square_euclidean_distance());
+
+ std::cout << "========== Rips_complex_from_points ==========" << std::endl;
+ Simplex_tree st;
+ const int DIMENSION = 3;
+ rips_complex_from_points.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:
+ BOOST_CHECK(are_almost_the_same(st.filtration(f_simplex), 0.0));
+ break;
+ case 1:
+ case 2:
+ case 3:
+ BOOST_CHECK(are_almost_the_same(st.filtration(f_simplex), 2.0));
+ break;
+ default:
+ BOOST_CHECK(false); // Shall not happen
+ break;
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(Rips_doc_csv_file) {
+ // ----------------------------------------------------------------------------
+ //
+ // Init of a Rips complex from a OFF file
+ //
+ // ----------------------------------------------------------------------------
+ std::string csv_file_name("full_square_distance_matrix.csv");
+ double rips_threshold = 12.0;
+ std::cout << "========== CSV FILE NAME = " << csv_file_name << " - Rips threshold=" <<
+ rips_threshold << "==========" << std::endl;
+
+ Distance_matrix distances = read_lower_triangular_matrix_from_csv_file<Filtration_value>(csv_file_name);
+ Rips_complex rips_complex_from_file(distances, rips_threshold);
+
+ const int DIMENSION_1 = 1;
+ Simplex_tree st;
+ rips_complex_from_file.create_complex(st, DIMENSION_1);
+ std::cout << "st.dimension()=" << st.dimension() << std::endl;
+ BOOST_CHECK(st.dimension() == DIMENSION_1);
+
+ const int NUMBER_OF_VERTICES = 7;
+ std::cout << "st.num_vertices()=" << st.num_vertices() << std::endl;
+ BOOST_CHECK(st.num_vertices() == NUMBER_OF_VERTICES);
+
+ std::cout << "st.num_simplices()=" << st.num_simplices() << std::endl;
+ BOOST_CHECK(st.num_simplices() == 18);
+
+ // Check filtration values of vertices is 0.0
+ for (auto f_simplex : st.skeleton_simplex_range(0)) {
+ BOOST_CHECK(st.filtration(f_simplex) == 0.0);
+ }
+
+ // Check filtration values of edges
+ for (auto f_simplex : st.skeleton_simplex_range(DIMENSION_1)) {
+ if (DIMENSION_1 == st.dimension(f_simplex)) {
+ std::vector<Simplex_tree::Vertex_handle> vvh;
+ std::cout << "vertex = (";
+ for (auto vertex : st.simplex_vertex_range(f_simplex)) {
+ std::cout << vertex << ",";
+ vvh.push_back(vertex);
+ }
+ std::cout << ") - filtration =" << st.filtration(f_simplex) << std::endl;
+ BOOST_CHECK(vvh.size() == 2);
+ BOOST_CHECK(are_almost_the_same(st.filtration(f_simplex), distances[vvh.at(0)][vvh.at(1)]));
+ }
+ }
+
+ const int DIMENSION_2 = 2;
+ Simplex_tree st2;
+ rips_complex_from_file.create_complex(st2, DIMENSION_2);
+ std::cout << "st2.dimension()=" << st2.dimension() << std::endl;
+ BOOST_CHECK(st2.dimension() == DIMENSION_2);
+
+ std::cout << "st2.num_vertices()=" << st2.num_vertices() << std::endl;
+ BOOST_CHECK(st2.num_vertices() == NUMBER_OF_VERTICES);
+
+ std::cout << "st2.num_simplices()=" << st2.num_simplices() << std::endl;
+ BOOST_CHECK(st2.num_simplices() == 23);
+
+ Simplex_tree::Filtration_value f01 = st2.filtration(st2.find({0, 1}));
+ Simplex_tree::Filtration_value f02 = st2.filtration(st2.find({0, 2}));
+ Simplex_tree::Filtration_value f12 = st2.filtration(st2.find({1, 2}));
+ Simplex_tree::Filtration_value f012 = st2.filtration(st2.find({0, 1, 2}));
+ std::cout << "f012= " << f012 << " | f01= " << f01 << " - f02= " << f02 << " - f12= " << f12 << std::endl;
+ BOOST_CHECK(are_almost_the_same(f012, std::max(f01, std::max(f02,f12))));
+
+ Simplex_tree::Filtration_value f45 = st2.filtration(st2.find({4, 5}));
+ Simplex_tree::Filtration_value f56 = st2.filtration(st2.find({5, 6}));
+ Simplex_tree::Filtration_value f46 = st2.filtration(st2.find({4, 6}));
+ Simplex_tree::Filtration_value f456 = st2.filtration(st2.find({4, 5, 6}));
+ std::cout << "f456= " << f456 << " | f45= " << f45 << " - f56= " << f56 << " - f46= " << f46 << std::endl;
+ BOOST_CHECK(are_almost_the_same(f456, std::max(f45, std::max(f56,f46))));
+
+ const int DIMENSION_3 = 3;
+ Simplex_tree st3;
+ rips_complex_from_file.create_complex(st3, DIMENSION_3);
+ std::cout << "st3.dimension()=" << st3.dimension() << std::endl;
+ BOOST_CHECK(st3.dimension() == DIMENSION_3);
+
+ std::cout << "st3.num_vertices()=" << st3.num_vertices() << std::endl;
+ BOOST_CHECK(st3.num_vertices() == NUMBER_OF_VERTICES);
+
+ std::cout << "st3.num_simplices()=" << st3.num_simplices() << std::endl;
+ BOOST_CHECK(st3.num_simplices() == 24);
+
+ Simplex_tree::Filtration_value f123 = st3.filtration(st3.find({1, 2, 3}));
+ Simplex_tree::Filtration_value f013 = st3.filtration(st3.find({0, 1, 3}));
+ Simplex_tree::Filtration_value f023 = st3.filtration(st3.find({0, 2, 3}));
+ Simplex_tree::Filtration_value f0123 = st3.filtration(st3.find({0, 1, 2, 3}));
+ std::cout << "f0123= " << f0123 << " | f012= " << f012 << " - f123= " << f123 << " - f013= " << f013 <<
+ " - f023= " << f023 << std::endl;
+ BOOST_CHECK(are_almost_the_same(f0123, std::max(f012, std::max(f123, std::max(f013, f023)))));
+
+}
+
+#ifdef GUDHI_DEBUG
+BOOST_AUTO_TEST_CASE(Rips_create_complex_throw) {
+ // ----------------------------------------------------------------------------
+ //
+ // Init of a Rips complex from a OFF file
+ //
+ // ----------------------------------------------------------------------------
+ std::string off_file_name("alphacomplexdoc.off");
+ double rips_threshold = 12.0;
+ std::cout << "========== OFF FILE NAME = " << off_file_name << " - Rips threshold=" <<
+ rips_threshold << "==========" << std::endl;
+
+ Gudhi::Points_off_reader<Point> off_reader(off_file_name);
+ Rips_complex rips_complex_from_file(off_reader.get_point_cloud(), rips_threshold, Euclidean_distance());
+
+ Simplex_tree stree;
+ std::vector<int> simplex = {0, 1, 2};
+ stree.insert_simplex_and_subfaces(simplex);
+ std::cout << "Check exception throw in debug mode" << std::endl;
+ // throw excpt because stree is not empty
+ BOOST_CHECK_THROW (rips_complex_from_file.create_complex(stree, 1), std::invalid_argument);
+}
+#endif
diff --git a/src/Simplex_tree/example/simple_simplex_tree.cpp b/src/Simplex_tree/example/simple_simplex_tree.cpp
index 5146b906..60f9a35e 100644
--- a/src/Simplex_tree/example/simple_simplex_tree.cpp
+++ b/src/Simplex_tree/example/simple_simplex_tree.cpp
@@ -4,7 +4,7 @@
*
* Author(s): Vincent Rouvreau
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * Copyright (C) 2014
*
* 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
@@ -27,10 +27,11 @@
#include <utility> // for pair
#include <vector>
-using namespace Gudhi;
-
-typedef std::vector< Vertex_handle > typeVectorVertex;
-typedef std::pair< Simplex_tree<>::Simplex_handle, bool > typePairSimplexBool;
+using Simplex_tree = Gudhi::Simplex_tree<>;
+using Vertex_handle = Simplex_tree::Vertex_handle;
+using Filtration_value = Simplex_tree::Filtration_value;
+using typeVectorVertex = std::vector< Vertex_handle >;
+using typePairSimplexBool = std::pair< Simplex_tree::Simplex_handle, bool >;
int main(int argc, char * const argv[]) {
const Filtration_value FIRST_FILTRATION_VALUE = 0.1;
@@ -42,7 +43,7 @@ int main(int argc, char * const argv[]) {
std::cout << "********************************************************************" << std::endl;
std::cout << "EXAMPLE OF SIMPLE INSERTION" << std::endl;
// Construct the Simplex Tree
- Simplex_tree<> simplexTree;
+ Simplex_tree simplexTree;
/* Simplex to be inserted: */
/* 1 */
@@ -212,7 +213,7 @@ int main(int argc, char * const argv[]) {
// ------------------------------------------------------------------------------------------------------------------
// Find in the simplex_tree
// ------------------------------------------------------------------------------------------------------------------
- Simplex_tree<>::Simplex_handle simplexFound = simplexTree.find(secondSimplexVector);
+ Simplex_tree::Simplex_handle simplexFound = simplexTree.find(secondSimplexVector);
std::cout << "**************IS THE SIMPLEX {1} IN THE SIMPLEX TREE ?\n";
if (simplexFound != simplexTree.null_simplex())
std::cout << "***+ YES IT IS!\n";
diff --git a/src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp b/src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp
index 58085014..d1b8b2de 100644
--- a/src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp
+++ b/src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp
@@ -4,7 +4,7 @@
*
* Author(s): Clément Maria
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * 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
@@ -26,9 +26,16 @@
#include <iostream>
#include <ctime>
#include <string>
+#include <utility> // for std::pair
using namespace Gudhi;
+typedef int Vertex_handle;
+typedef double Filtration_value;
+typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS,
+ boost::property < vertex_filtration_t, Filtration_value >,
+ boost::property < edge_filtration_t, Filtration_value > > Graph_t;
+
int main(int argc, char * const argv[]) {
if (argc != 3) {
std::cerr << "Usage: " << argv[0]
@@ -43,7 +50,7 @@ int main(int argc, char * const argv[]) {
Simplex_tree<> st;
start = clock();
- auto g = read_graph(filegraph);
+ auto g = read_graph<Graph_t, Filtration_value, Vertex_handle>(filegraph);
// insert the graph in the simplex tree as 1-skeleton
st.insert_graph(g);
end = clock();
diff --git a/src/Simplex_tree/test/simplex_tree_unit_test.cpp b/src/Simplex_tree/test/simplex_tree_unit_test.cpp
index 28bf202b..b06d7ec9 100644
--- a/src/Simplex_tree/test/simplex_tree_unit_test.cpp
+++ b/src/Simplex_tree/test/simplex_tree_unit_test.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <fstream>
#include <string>
#include <algorithm>
#include <utility> // std::pair, std::make_pair
@@ -19,19 +20,19 @@ using namespace Gudhi;
typedef boost::mpl::list<Simplex_tree<>, Simplex_tree<Simplex_tree_options_fast_persistence>> list_of_tested_variants;
-const Vertex_handle DEFAULT_VERTEX_HANDLE = (const Vertex_handle) - 1;
-const Filtration_value DEFAULT_FILTRATION_VALUE = (const Filtration_value) 0.0;
template<class typeST>
void test_empty_simplex_tree(typeST& tst) {
- BOOST_CHECK(tst.null_vertex() == DEFAULT_VERTEX_HANDLE);
- BOOST_CHECK(tst.filtration() == DEFAULT_FILTRATION_VALUE);
+ typedef typename typeST::Vertex_handle Vertex_handle;
+ const Vertex_handle DEFAULT_VERTEX_VALUE = Vertex_handle(- 1);
+ BOOST_CHECK(tst.null_vertex() == DEFAULT_VERTEX_VALUE);
+ BOOST_CHECK(tst.filtration() == 0.0);
BOOST_CHECK(tst.num_vertices() == (size_t) 0);
BOOST_CHECK(tst.num_simplices() == (size_t) 0);
typename typeST::Siblings* STRoot = tst.root();
BOOST_CHECK(STRoot != nullptr);
BOOST_CHECK(STRoot->oncles() == nullptr);
- BOOST_CHECK(STRoot->parent() == DEFAULT_VERTEX_HANDLE);
+ BOOST_CHECK(STRoot->parent() == DEFAULT_VERTEX_VALUE);
BOOST_CHECK(tst.dimension() == -1);
}
@@ -59,7 +60,7 @@ void test_iterators_on_empty_simplex_tree(typeST& tst) {
BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_when_empty, typeST, list_of_tested_variants) {
typedef std::pair<typename typeST::Simplex_handle, bool> typePairSimplexBool;
- typedef std::vector<Vertex_handle> typeVectorVertex;
+ typedef std::vector<typename typeST::Vertex_handle> typeVectorVertex;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST OF DEFAULT CONSTRUCTOR" << std::endl;
@@ -72,8 +73,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_when_empty, typeST, list_of_tested_va
std::cout << "TEST OF EMPTY INSERTION" << std::endl;
typeVectorVertex simplexVectorEmpty;
BOOST_CHECK(simplexVectorEmpty.empty() == true);
- typePairSimplexBool returnEmptyValue = st.insert_simplex(simplexVectorEmpty,
- DEFAULT_FILTRATION_VALUE);
+ typePairSimplexBool returnEmptyValue = st.insert_simplex(simplexVectorEmpty, 0.0);
BOOST_CHECK(returnEmptyValue.first == typename typeST::Simplex_handle(nullptr));
BOOST_CHECK(returnEmptyValue.second == true);
@@ -141,12 +141,13 @@ void test_simplex_tree_contains(typeST& simplexTree, typeSimplex& simplex, int p
template<class typeST, class typePairSimplexBool>
void test_simplex_tree_insert_returns_true(const typePairSimplexBool& returnValue) {
BOOST_CHECK(returnValue.second == true);
- typename typeST::Simplex_handle shReturned = returnValue.first; // Simplex_handle = boost::container::flat_map< Vertex_handle, Node >::iterator
+ // Simplex_handle = boost::container::flat_map< typeST::Vertex_handle, Node >::iterator
+ typename typeST::Simplex_handle shReturned = returnValue.first;
BOOST_CHECK(shReturned != typename typeST::Simplex_handle(nullptr));
}
// Global variables
-Filtration_value max_fil = DEFAULT_FILTRATION_VALUE;
+double max_fil = 0.0;
int dim_max = -1;
template<class typeST, class Filtration_value>
@@ -179,8 +180,9 @@ void set_and_test_simplex_tree_dim_fil(typeST& simplexTree, int vectorSize, cons
}
BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_insertion, typeST, list_of_tested_variants) {
+ typedef typename typeST::Filtration_value Filtration_value;
typedef std::pair<typename typeST::Simplex_handle, bool> typePairSimplexBool;
- typedef std::vector<Vertex_handle> typeVectorVertex;
+ typedef std::vector<typename typeST::Vertex_handle> typeVectorVertex;
typedef std::pair<typeVectorVertex, Filtration_value> typeSimplex;
const Filtration_value FIRST_FILTRATION_VALUE = 0.1;
const Filtration_value SECOND_FILTRATION_VALUE = 0.2;
@@ -188,7 +190,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_insertion, typeST, list_of_tested_var
const Filtration_value FOURTH_FILTRATION_VALUE = 0.4;
// reset since we run the test several times
dim_max = -1;
- max_fil = DEFAULT_FILTRATION_VALUE;
+ max_fil = 0.0;
// TEST OF INSERTION
std::cout << "********************************************************************" << std::endl;
@@ -303,7 +305,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_insertion, typeST, list_of_tested_var
returnValue = st.insert_simplex(tenthSimplex.first, tenthSimplex.second);
BOOST_CHECK(returnValue.second == false);
- typename typeST::Simplex_handle shReturned = returnValue.first; // Simplex_handle = boost::container::flat_map< Vertex_handle, Node >::iterator
+ // Simplex_handle = boost::container::flat_map< typeST::Vertex_handle, Node >::iterator
+ typename typeST::Simplex_handle shReturned = returnValue.first;
BOOST_CHECK(shReturned == typename typeST::Simplex_handle(nullptr));
BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented !!
BOOST_CHECK(st.dimension() == dim_max);
@@ -317,7 +320,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_insertion, typeST, list_of_tested_var
returnValue = st.insert_simplex(eleventhSimplex.first, eleventhSimplex.second);
BOOST_CHECK(returnValue.second == false);
- shReturned = returnValue.first; // Simplex_handle = boost::container::flat_map< Vertex_handle, Node >::iterator
+ // Simplex_handle = boost::container::flat_map< typeST::Vertex_handle, Node >::iterator
+ shReturned = returnValue.first;
BOOST_CHECK(shReturned == typename typeST::Simplex_handle(nullptr));
BOOST_CHECK(st.num_vertices() == (size_t) 4); // Not incremented !!
BOOST_CHECK(st.dimension() == dim_max);
@@ -375,8 +379,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(simplex_tree_insertion, typeST, list_of_tested_var
BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_of_tested_variants) {
typedef std::pair<typename typeST::Simplex_handle, bool> typePairSimplexBool;
- typedef std::vector<Vertex_handle> typeVectorVertex;
- typedef std::pair<typeVectorVertex, Filtration_value> typeSimplex;
+ typedef std::vector<typename typeST::Vertex_handle> typeVectorVertex;
+ typedef std::pair<typeVectorVertex, typename typeST::Filtration_value> typeSimplex;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST OF RECURSIVE INSERTION" << std::endl;
typeST st;
@@ -394,7 +398,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_o
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector1.begin(), SimplexVector1.end(), std::greater<Vertex_handle>());
+ std::sort(SimplexVector1.begin(), SimplexVector1.end(), std::greater<typename typeST::Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector1[position] << std::endl;
@@ -413,7 +417,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_o
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector2.begin(), SimplexVector2.end(), std::greater<Vertex_handle>());
+ std::sort(SimplexVector2.begin(), SimplexVector2.end(), std::greater<typename typeST::Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector2[position] << std::endl;
@@ -432,7 +436,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_o
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector3.begin(), SimplexVector3.end(), std::greater<Vertex_handle>());
+ std::sort(SimplexVector3.begin(), SimplexVector3.end(), std::greater<typename typeST::Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector3[position] << std::endl;
@@ -462,7 +466,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_o
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector5.begin(), SimplexVector5.end(), std::greater<Vertex_handle>());
+ std::sort(SimplexVector5.begin(), SimplexVector5.end(), std::greater<typename typeST::Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector5[position] << std::endl;
@@ -481,7 +485,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_o
// Check it is well inserted
BOOST_CHECK(true == returnValue.second);
position = 0;
- std::sort(SimplexVector6.begin(), SimplexVector6.end(), std::greater<Vertex_handle>());
+ std::sort(SimplexVector6.begin(), SimplexVector6.end(), std::greater<typename typeST::Vertex_handle>());
for (auto vertex : st.simplex_vertex_range(returnValue.first)) {
// Check returned Simplex_handle
std::cout << "vertex = " << vertex << " | vector[" << position << "] = " << SimplexVector6[position] << std::endl;
@@ -504,12 +508,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(NSimplexAndSubfaces_tree_insertion, typeST, list_o
/* A facet [3,4,5] */
/* A cell [0,1,6,7] */
- typeSimplex simplexPair1 = std::make_pair(SimplexVector1, DEFAULT_FILTRATION_VALUE);
- typeSimplex simplexPair2 = std::make_pair(SimplexVector2, DEFAULT_FILTRATION_VALUE);
- typeSimplex simplexPair3 = std::make_pair(SimplexVector3, DEFAULT_FILTRATION_VALUE);
- typeSimplex simplexPair4 = std::make_pair(SimplexVector4, DEFAULT_FILTRATION_VALUE);
- typeSimplex simplexPair5 = std::make_pair(SimplexVector5, DEFAULT_FILTRATION_VALUE);
- typeSimplex simplexPair6 = std::make_pair(SimplexVector6, DEFAULT_FILTRATION_VALUE);
+ typeSimplex simplexPair1 = std::make_pair(SimplexVector1, 0.0);
+ typeSimplex simplexPair2 = std::make_pair(SimplexVector2, 0.0);
+ typeSimplex simplexPair3 = std::make_pair(SimplexVector3, 0.0);
+ typeSimplex simplexPair4 = std::make_pair(SimplexVector4, 0.0);
+ typeSimplex simplexPair5 = std::make_pair(SimplexVector5, 0.0);
+ typeSimplex simplexPair6 = std::make_pair(SimplexVector6, 0.0);
test_simplex_tree_contains(st, simplexPair1, 6); // (2,1,0) is in position 6
test_simplex_tree_contains(st, simplexPair2, 7); // (3) is in position 7
test_simplex_tree_contains(st, simplexPair3, 8); // (3,0) is in position 8
@@ -600,7 +604,7 @@ void test_cofaces(typeST& st, const std::vector<Vertex_handle>& expected, int di
}
BOOST_AUTO_TEST_CASE_TEMPLATE(coface_on_simplex_tree, typeST, list_of_tested_variants) {
- typedef std::vector<Vertex_handle> typeVectorVertex;
+ typedef std::vector<typename typeST::Vertex_handle> typeVectorVertex;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST COFACE ALGORITHM" << std::endl;
typeST st;
@@ -629,7 +633,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(coface_on_simplex_tree, typeST, list_of_tested_var
// FIXME
st.set_dimension(3);
- std::vector<Vertex_handle> simplex_result;
+ std::vector<typename typeST::Vertex_handle> simplex_result;
std::vector<typename typeST::Simplex_handle> result;
std::cout << "First test - Star of (3):" << std::endl;
@@ -649,7 +653,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(coface_on_simplex_tree, typeST, list_of_tested_var
result.push_back(st.find(simplex_result));
simplex_result.clear();
- std::vector<Vertex_handle> vertex = {3};
+ std::vector<typename typeST::Vertex_handle> vertex = {3};
test_cofaces(st, vertex, 0, result);
vertex.clear();
result.clear();
@@ -699,7 +703,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(coface_on_simplex_tree, typeST, list_of_tested_var
}
BOOST_AUTO_TEST_CASE_TEMPLATE(copy_move_on_simplex_tree, typeST, list_of_tested_variants) {
- typedef std::vector<Vertex_handle> typeVectorVertex;
+ typedef std::vector<typename typeST::Vertex_handle> typeVectorVertex;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST COPY MOVE CONSTRUCTORS" << std::endl;
typeST st;
@@ -771,12 +775,11 @@ void test_simplex_is_vertex(typeST& st, typename typeST::Simplex_handle sh, type
BOOST_AUTO_TEST_CASE(non_contiguous) {
typedef Simplex_tree<> typeST;
- typedef typeST::Vertex_handle Vertex_handle;
typedef typeST::Simplex_handle Simplex_handle;
std::cout << "********************************************************************" << std::endl;
std::cout << "TEST NON-CONTIGUOUS VERTICES" << std::endl;
typeST st;
- Vertex_handle e[] = {3,-7};
+ typeST::Vertex_handle e[] = {3,-7};
std::cout << "Insert" << std::endl;
st.insert_simplex_and_subfaces(e);
BOOST_CHECK(st.num_vertices() == 2);
diff --git a/src/Witness_complex/example/example_strong_witness_complex_off.cpp b/src/Witness_complex/example/example_strong_witness_complex_off.cpp
index 61b8bc4a..c9a3b543 100644
--- a/src/Witness_complex/example/example_strong_witness_complex_off.cpp
+++ b/src/Witness_complex/example/example_strong_witness_complex_off.cpp
@@ -17,7 +17,7 @@
typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K;
typedef typename K::Point_d Point_d;
typedef typename Gudhi::witness_complex::Euclidean_strong_witness_complex<K> Witness_complex;
-typedef std::vector< Vertex_handle > typeVectorVertex;
+typedef std::vector< typename Gudhi::Simplex_tree<>::Vertex_handle > typeVectorVertex;
typedef std::vector< Point_d > Point_vector;
int main(int argc, char * const argv[]) {
diff --git a/src/Witness_complex/example/example_witness_complex_off.cpp b/src/Witness_complex/example/example_witness_complex_off.cpp
index 751d2d4c..38c6bedc 100644
--- a/src/Witness_complex/example/example_witness_complex_off.cpp
+++ b/src/Witness_complex/example/example_witness_complex_off.cpp
@@ -17,7 +17,7 @@
typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K;
typedef typename K::Point_d Point_d;
typedef typename Gudhi::witness_complex::Euclidean_witness_complex<K> Witness_complex;
-typedef std::vector< Vertex_handle > typeVectorVertex;
+typedef std::vector< typename Gudhi::Simplex_tree<>::Vertex_handle > typeVectorVertex;
typedef std::vector< Point_d > Point_vector;
int main(int argc, char * const argv[]) {
diff --git a/src/Witness_complex/test/test_simple_witness_complex.cpp b/src/Witness_complex/test/test_simple_witness_complex.cpp
index b47ebe4d..bb1df72d 100644
--- a/src/Witness_complex/test/test_simple_witness_complex.cpp
+++ b/src/Witness_complex/test/test_simple_witness_complex.cpp
@@ -19,6 +19,7 @@
#include <vector>
typedef Gudhi::Simplex_tree<> Simplex_tree;
+typedef typename Simplex_tree::Vertex_handle Vertex_handle;
typedef std::vector< Vertex_handle > typeVectorVertex;
typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> Kernel;
typedef typename Kernel::FT FT;
diff --git a/src/cmake/modules/FindQGLViewer.cmake b/src/cmake/modules/FindQGLViewer.cmake
index 1f3dbc1f..56c1b3cf 100644
--- a/src/cmake/modules/FindQGLViewer.cmake
+++ b/src/cmake/modules/FindQGLViewer.cmake
@@ -15,7 +15,7 @@ find_path(QGLVIEWER_INCLUDE_DIR
)
find_library(QGLVIEWER_LIBRARY_RELEASE
- NAMES qglviewer-qt4 QGLViewer-qt4 qglviewer QGLViewer QGLViewer2
+ NAMES qglviewer-qt5 QGLViewer-qt5 qglviewer QGLViewer QGLViewer2
PATHS /usr/lib
/usr/local/lib
ENV QGLVIEWERROOT
diff --git a/src/cmake/modules/GUDHI_user_version_target.txt b/src/cmake/modules/GUDHI_user_version_target.txt
index c91d5659..6332b065 100644
--- a/src/cmake/modules/GUDHI_user_version_target.txt
+++ b/src/cmake/modules/GUDHI_user_version_target.txt
@@ -48,7 +48,7 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.11)
add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
copy_directory ${CMAKE_SOURCE_DIR}/src/GudhUI ${GUDHI_USER_VERSION_DIR}/GudhUI)
- set(GUDHI_MODULES "common;Alpha_complex;Bitmap_cubical_complex;Bottleneck_distance;Contraction;Hasse_complex;Persistent_cohomology;Simplex_tree;Skeleton_blocker;Spatial_searching;Subsampling;Tangential_complex;Witness_complex")
+ set(GUDHI_MODULES "common;Alpha_complex;Bitmap_cubical_complex;Bottleneck_distance;Contraction;Hasse_complex;Persistent_cohomology;Rips_complex;Simplex_tree;Skeleton_blocker;Spatial_searching;Subsampling;Tangential_complex;Witness_complex")
foreach(GUDHI_MODULE ${GUDHI_MODULES})
# doc files
@@ -81,21 +81,21 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.11)
endif()
endforeach()
- # include files and patches
- file(GLOB GUDHI_INCLUDE_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/include/*)
+ # include files
+ file(GLOB GUDHI_INCLUDE_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/include/gudhi/*)
foreach(GUDHI_INCLUDE_FILE ${GUDHI_INCLUDE_FILES})
get_filename_component(GUDHI_INCLUDE_FILE_NAME ${GUDHI_INCLUDE_FILE} NAME)
# GUDHI_INCLUDE_FILE can be a file or a directory
if(IS_DIRECTORY ${GUDHI_INCLUDE_FILE})
add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
- copy_directory ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/include/${GUDHI_INCLUDE_FILE_NAME})
+ copy_directory ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/include/gudhi/${GUDHI_INCLUDE_FILE_NAME})
else()
add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E
- copy ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/include/${GUDHI_INCLUDE_FILE_NAME})
+ copy ${GUDHI_INCLUDE_FILE} ${GUDHI_USER_VERSION_DIR}/include/gudhi/${GUDHI_INCLUDE_FILE_NAME})
endif()
endforeach()
-
+
# concept files
file(GLOB GUDHI_CONCEPT_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/concept/*.h)
diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h
index 5fb75002..116aba09 100644
--- a/src/common/doc/main_page.h
+++ b/src/common/doc/main_page.h
@@ -56,6 +56,24 @@
<b>User manual:</b> \ref cubical_complex - <b>Reference manual:</b> Gudhi::cubical_complex::Bitmap_cubical_complex
</td>
</tr>
+ \subsection RipsComplexDataStructure Rips complex
+ \image html "rips_complex_representation.png" "Rips complex representation"
+<table border="0">
+ <tr>
+ <td width="25%">
+ <b>Author:</b> Cl&eacute;ment Maria, Pawel Dlotko, Vincent Rouvreau<br>
+ <b>Introduced in:</b> GUDHI 1.4.0<br>
+ <b>Copyright:</b> GPL v3<br>
+ </td>
+ <td width="75%">
+ Rips_complex is a simplicial complex constructed from a one skeleton graph.<br>
+ The filtration value of each edge is computed from a user-given distance function and is inserted until a
+ user-given threshold value.<br>
+ This complex can be built from a point cloud and a distance function, or from a distance matrix.<br>
+ <b>User manual:</b> \ref rips_complex - <b>Reference manual:</b> Gudhi::rips_complex::Rips_complex
+ </td>
+ </tr>
+</table>
</table>
\subsection SimplexTreeDataStructure Simplex tree
\image html "Simplex_tree_representation.png" "Simplex tree representation"
@@ -223,8 +241,6 @@ make \endverbatim
*
* The following example requires the <a target="_blank" href="http://gmplib.org/">GNU Multiple Precision Arithmetic
* Library</a> (GMP) and will not be built if GMP is not installed:
- * \li <a href="_persistent_cohomology_2performance_rips_persistence_8cpp-example.html">
- * Persistent_cohomology/performance_rips_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2rips_multifield_persistence_8cpp-example.html">
* Persistent_cohomology/rips_multifield_persistence.cpp</a>
*
@@ -261,9 +277,11 @@ make \endverbatim
* Persistent_cohomology/custom_persistence_sort.cpp</a>
*
* The following example requires CGAL version &ge; 4.8.0:
- * \li <a href="_bottleneck_distance_2_bottleneck_example_8cpp-example.html">
- *
- * Bottleneck_distance/bottleneck_example.cpp</a>
+ * \li <a href="_bottleneck_distance_2_bottleneck_basic_example_8cpp-example.html">
+ * Bottleneck_distance/bottleneck_basic_example.cpp</a>
+ * \li <a href="_bottleneck_distance_2_bottleneck_read_file_example_8cpp-example.html">
+ * Bottleneck_distance/bottleneck_read_file_example.cpp</a>
+ *
* \subsection eigen3 Eigen3
* The \ref alpha_complex data structure and few examples requires
* <a target="_blank" href="http://eigen.tuxfamily.org/">Eigen3</a> is a C++ template library for linear algebra:
@@ -275,8 +293,6 @@ make \endverbatim
* Alpha_complex/Alpha_complex_from_off.cpp</a>
* \li <a href="_alpha_complex_2_alpha_complex_from_points_8cpp-example.html">
* Alpha_complex/Alpha_complex_from_points.cpp</a>
- * \li <a href="_bottleneck_distance_2_bottleneck_example_8cpp-example.html">
- * Bottleneck_distance/bottleneck_example.cpp</a>
* \li <a href="_persistent_cohomology_2alpha_complex_persistence_8cpp-example.html">
* Persistent_cohomology/alpha_complex_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
@@ -318,22 +334,28 @@ make \endverbatim
* Persistent_cohomology/alpha_complex_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2rips_persistence_via_boundary_matrix_8cpp-example.html">
* Persistent_cohomology/rips_persistence_via_boundary_matrix.cpp</a>
- * \li <a href="_persistent_cohomology_2performance_rips_persistence_8cpp-example.html">
- * Persistent_cohomology/performance_rips_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2persistence_from_file_8cpp-example.html">
* Persistent_cohomology/persistence_from_file.cpp</a>
* \li <a href="_persistent_cohomology_2persistence_from_simple_simplex_tree_8cpp-example.html">
* Persistent_cohomology/persistence_from_simple_simplex_tree.cpp</a>
* \li <a href="_persistent_cohomology_2plain_homology_8cpp-example.html">
* Persistent_cohomology/plain_homology.cpp</a>
+ * \li <a href="_persistent_cohomology_2rips_distance_matrix_persistence_8cpp-example.html">
+ * Persistent_cohomology/rips_distance_matrix_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2rips_multifield_persistence_8cpp-example.html">
* Persistent_cohomology/rips_multifield_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2rips_persistence_8cpp-example.html">
* Persistent_cohomology/rips_persistence.cpp</a>
+ * \li <a href="_persistent_cohomology_2rips_persistence_step_by_step_8cpp-example.html">
+ * Persistent_cohomology/rips_persistence_step_by_step.cpp</a>
* \li <a href="_persistent_cohomology_2periodic_alpha_complex_3d_persistence_8cpp-example.html">
* Persistent_cohomology/periodic_alpha_complex_3d_persistence.cpp</a>
* \li <a href="_persistent_cohomology_2custom_persistence_sort_8cpp-example.html">
* Persistent_cohomology/custom_persistence_sort.cpp</a>
+ * \li <a href="_rips_complex_2example_one_skeleton_rips_from_points_8cpp-example.html">
+ * Rips_complex/example_one_skeleton_rips_from_points.cpp</a>
+ * \li <a href="_rips_complex_2example_rips_complex_from_off_file_8cpp-example.html">
+ * Rips_complex/example_rips_complex_from_off_file.cpp</a>
*
* \section Contributions Bug reports and contributions
* Please help us improving the quality of the GUDHI library. You may report bugs or suggestions to:
@@ -358,7 +380,8 @@ make \endverbatim
/*! @file Examples
* @example Alpha_complex/Alpha_complex_from_off.cpp
* @example Alpha_complex/Alpha_complex_from_points.cpp
- * @example Bottleneck_distance/bottleneck_example.cpp
+ * @example Bottleneck_distance/bottleneck_basic_example.cpp
+ * @example Bottleneck_distance/bottleneck_read_file_example.cpp
* @example Bitmap_cubical_complex/Bitmap_cubical_complex.cpp
* @example Bitmap_cubical_complex/Bitmap_cubical_complex_periodic_boundary_conditions.cpp
* @example Bitmap_cubical_complex/Random_bitmap_cubical_complex.cpp
@@ -369,14 +392,17 @@ make \endverbatim
* @example Persistent_cohomology/alpha_complex_3d_persistence.cpp
* @example Persistent_cohomology/alpha_complex_persistence.cpp
* @example Persistent_cohomology/rips_persistence_via_boundary_matrix.cpp
- * @example Persistent_cohomology/performance_rips_persistence.cpp
* @example Persistent_cohomology/periodic_alpha_complex_3d_persistence.cpp
* @example Persistent_cohomology/persistence_from_file.cpp
* @example Persistent_cohomology/persistence_from_simple_simplex_tree.cpp
* @example Persistent_cohomology/plain_homology.cpp
* @example Persistent_cohomology/rips_multifield_persistence.cpp
+ * @example Persistent_cohomology/rips_distance_matrix_persistence.cpp
* @example Persistent_cohomology/rips_persistence.cpp
* @example Persistent_cohomology/custom_persistence_sort.cpp
+ * @example Persistent_cohomology/rips_persistence_step_by_step.cpp
+ * @example Rips_complex/example_one_skeleton_rips_from_points.cpp
+ * @example Rips_complex/example_rips_complex_from_off_file.cpp
* @example Simplex_tree/mini_simplex_tree.cpp
* @example Simplex_tree/simple_simplex_tree.cpp
* @example Simplex_tree/example_alpha_shapes_3_simplex_tree_from_off_file.cpp
diff --git a/src/common/example/example_CGAL_3D_points_off_reader.cpp b/src/common/example/example_CGAL_3D_points_off_reader.cpp
index d48bb17d..665b7a29 100644
--- a/src/common/example/example_CGAL_3D_points_off_reader.cpp
+++ b/src/common/example/example_CGAL_3D_points_off_reader.cpp
@@ -32,7 +32,7 @@ int main(int argc, char **argv) {
// Retrieve the triangulation
std::vector<Point_3> point_cloud = off_reader.get_point_cloud();
- int n {0};
+ int n {};
for (auto point : point_cloud) {
++n;
std::cout << "Point[" << n << "] = (" << point[0] << ", " << point[1] << ", " << point[2] << ")\n";
diff --git a/src/common/example/example_CGAL_points_off_reader.cpp b/src/common/example/example_CGAL_points_off_reader.cpp
index 4522174a..8c6a6b54 100644
--- a/src/common/example/example_CGAL_points_off_reader.cpp
+++ b/src/common/example/example_CGAL_points_off_reader.cpp
@@ -34,7 +34,7 @@ int main(int argc, char **argv) {
// Retrieve the triangulation
std::vector<Point_d> point_cloud = off_reader.get_point_cloud();
- int n {0};
+ int n {};
for (auto point : point_cloud) {
std::cout << "Point[" << n << "] = ";
for (std::size_t i {0}; i < point.size(); i++)
diff --git a/src/common/include/gudhi/distance_functions.h b/src/common/include/gudhi/distance_functions.h
index cd518581..5891ef0e 100644
--- a/src/common/include/gudhi/distance_functions.h
+++ b/src/common/include/gudhi/distance_functions.h
@@ -4,7 +4,7 @@
*
* Author(s): Clément Maria
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * 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
@@ -25,19 +25,25 @@
#include <cmath> // for std::sqrt
-/* Compute the Euclidean distance between two Points given
- * by a range of coordinates. The points are assumed to have
- * the same dimension. */
-template< typename Point >
-double euclidean_distance(Point &p1, Point &p2) {
- double dist = 0.;
- auto it1 = p1.begin();
- auto it2 = p2.begin();
- for (; it1 != p1.end(); ++it1, ++it2) {
- double tmp = *it1 - *it2;
- dist += tmp*tmp;
+/** @file
+ * @brief Global distance functions
+ */
+
+/** @brief Compute the Euclidean distance between two Points given by a range of coordinates. The points are assumed to
+ * have the same dimension. */
+class Euclidean_distance {
+ public:
+ template< typename Point >
+ auto operator()(const Point& p1, const Point& p2) -> typename std::decay<decltype(*std::begin(p1))>::type {
+ auto it1 = p1.begin();
+ auto it2 = p2.begin();
+ typename Point::value_type dist = 0.;
+ for (; it1 != p1.end(); ++it1, ++it2) {
+ typename Point::value_type tmp = (*it1) - (*it2);
+ dist += tmp*tmp;
+ }
+ return std::sqrt(dist);
}
- return std::sqrt(dist);
-}
+};
#endif // DISTANCE_FUNCTIONS_H_
diff --git a/src/common/include/gudhi/graph_simplicial_complex.h b/src/common/include/gudhi/graph_simplicial_complex.h
index 042ef516..5fe7c826 100644
--- a/src/common/include/gudhi/graph_simplicial_complex.h
+++ b/src/common/include/gudhi/graph_simplicial_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): Clément Maria
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * 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
@@ -39,61 +39,4 @@ struct vertex_filtration_t {
typedef boost::vertex_property_tag kind;
};
-typedef int Vertex_handle;
-typedef double Filtration_value;
-typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS
-, boost::property < vertex_filtration_t, Filtration_value >
-, boost::property < edge_filtration_t, Filtration_value >
-> Graph_t;
-typedef std::pair< Vertex_handle, Vertex_handle > Edge_t;
-
-/** \brief Output the proximity graph of the points.
- *
- * If points contains n elements, the proximity graph is the graph
- * with n vertices, and an edge [u,v] iff the distance function between
- * points u and v is smaller than threshold.
- *
- * The type PointCloud furnishes .begin() and .end() methods, that return
- * iterators with value_type Point.
- */
-template< typename PointCloud
-, typename Point >
-Graph_t compute_proximity_graph(PointCloud &points
- , Filtration_value threshold
- , Filtration_value distance(Point p1, Point p2)) {
- std::vector< Edge_t > edges;
- std::vector< Filtration_value > edges_fil;
- std::map< Vertex_handle, Filtration_value > vertices;
-
- Vertex_handle idx_u, idx_v;
- Filtration_value fil;
- idx_u = 0;
- for (auto it_u = points.begin(); it_u != points.end(); ++it_u) {
- idx_v = idx_u + 1;
- for (auto it_v = it_u + 1; it_v != points.end(); ++it_v, ++idx_v) {
- fil = distance(*it_u, *it_v);
- if (fil <= threshold) {
- edges.emplace_back(idx_u, idx_v);
- edges_fil.push_back(fil);
- }
- }
- ++idx_u;
- }
-
- Graph_t skel_graph(edges.begin()
- , edges.end()
- , edges_fil.begin()
- , idx_u); // number of points labeled from 0 to idx_u-1
-
- auto vertex_prop = boost::get(vertex_filtration_t(), skel_graph);
-
- boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
- for (std::tie(vi, vi_end) = boost::vertices(skel_graph);
- vi != vi_end; ++vi) {
- boost::put(vertex_prop, *vi, 0.);
- }
-
- return skel_graph;
-}
-
#endif // GRAPH_SIMPLICIAL_COMPLEX_H_
diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h
index 899f9df6..97a87edd 100644
--- a/src/common/include/gudhi/reader_utils.h
+++ b/src/common/include/gudhi/reader_utils.h
@@ -2,9 +2,9 @@
* (Geometric Understanding in Higher Dimensions) is a generic C++
* library for computational topology.
*
- * Author(s): Clément Maria
+ * Author(s): Clement Maria, Pawel Dlotko
*
- * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ * 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
@@ -30,18 +30,25 @@
#include <iostream>
#include <fstream>
#include <map>
-#include <limits> // for numeric_limits<>
+#include <limits> // for numeric_limits
#include <string>
#include <vector>
+#include <utility> // for pair
+
+// Keep this file tag for Doxygen to parse the code, otherwise, functions are not documented.
+// It is required for global functions and variables.
+
+/** @file
+ * @brief This file includes common file reader for GUDHI
+ */
/**
- * \brief Read a set of points to turn it
- * into a vector< vector<double> > by filling points
+ * @brief Read a set of points to turn it into a vector< vector<double> > by filling points.
*
- * File format: 1 point per line
- * X11 X12 ... X1d
- * X21 X22 ... X2d
- * etc
+ * File format: 1 point per line<br>
+ * X11 X12 ... X1d<br>
+ * X21 X22 ... X2d<br>
+ * etc<br>
*/
inline void read_points(std::string file_name, std::vector< std::vector< double > > & points) {
std::ifstream in_file(file_name.c_str(), std::ios::in);
@@ -66,23 +73,29 @@ inline void read_points(std::string file_name, std::vector< std::vector< double
}
/**
- * \brief Read a graph from a file.
+ * @brief Read a graph from a file.
+ *
+ * \tparam Graph_t Type for the return graph. Must be constructible from iterators on pairs of Vertex_handle
+ * \tparam Filtration_value Type for the value of the read filtration
+ * \tparam Vertex_handle Type for the value of the read vertices
*
- * File format: 1 simplex per line
- * Dim1 X11 X12 ... X1d Fil1
- * Dim2 X21 X22 ... X2d Fil2
- * etc
+ * File format: 1 simplex per line<br>
+ * Dim1 X11 X12 ... X1d Fil1<br>
+ * Dim2 X21 X22 ... X2d Fil2<br>
+ * etc<br>
*
* The vertices must be labeled from 0 to n-1.
* Every simplex must appear exactly once.
* Simplices of dimension more than 1 are ignored.
*/
-inline Graph_t read_graph(std::string file_name) {
+template< typename Graph_t, typename Filtration_value, typename Vertex_handle >
+Graph_t read_graph(std::string file_name) {
std::ifstream in_(file_name.c_str(), std::ios::in);
if (!in_.is_open()) {
std::cerr << "Unable to open file " << file_name << std::endl;
}
+ typedef std::pair< Vertex_handle, Vertex_handle > Edge_t;
std::vector< Edge_t > edges;
std::vector< Filtration_value > edges_fil;
std::map< Vertex_handle, Filtration_value > vertices;
@@ -130,7 +143,7 @@ inline Graph_t read_graph(std::string file_name) {
Graph_t skel_graph(edges.begin(), edges.end(), edges_fil.begin(), vertices.size());
auto vertex_prop = boost::get(vertex_filtration_t(), skel_graph);
- boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
+ typename boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
auto v_it = vertices.begin();
for (std::tie(vi, vi_end) = boost::vertices(skel_graph); vi != vi_end; ++vi, ++v_it) {
boost::put(vertex_prop, *vi, v_it->second);
@@ -140,12 +153,12 @@ inline Graph_t read_graph(std::string file_name) {
}
/**
- * \brief Read a face from a file.
+ * @brief Read a face from a file.
*
- * File format: 1 simplex per line
- * Dim1 X11 X12 ... X1d Fil1
- * Dim2 X21 X22 ... X2d Fil2
- * etc
+ * File format: 1 simplex per line<br>
+ * Dim1 X11 X12 ... X1d Fil1<br>
+ * Dim2 X21 X22 ... X2d Fil2<br>
+ * etc<br>
*
* The vertices must be labeled from 0 to n-1.
* Every simplex must appear exactly once.
@@ -166,18 +179,16 @@ bool read_simplex(std::istream & in_, std::vector< Vertex_handle > & simplex, Fi
}
/**
- * \brief Read a hasse simplex from a file.
- *
- * File format: 1 simplex per line
- * Dim1 k11 k12 ... k1Dim1 Fil1
- * Dim2 k21 k22 ... k2Dim2 Fil2
- * etc
- *
- * The key of a simplex is its position in the filtration order
- * and also the number of its row in the file.
- * Dimi ki1 ki2 ... kiDimi Fili means that the ith simplex in the
- * filtration has dimension Dimi, filtration value fil1 and simplices with
- * key ki1 ... kiDimi in its boundary.*/
+ * @brief Read a hasse simplex from a file.
+ *
+ * File format: 1 simplex per line<br>
+ * Dim1 k11 k12 ... k1Dim1 Fil1<br>
+ * Dim2 k21 k22 ... k2Dim2 Fil2<br>
+ * etc<br>
+ *
+ * The key of a simplex is its position in the filtration order and also the number of its row in the file.
+ * Dimi ki1 ki2 ... kiDimi Fili means that the ith simplex in the filtration has dimension Dimi, filtration value
+ * fil1 and simplices with key ki1 ... kiDimi in its boundary.*/
template< typename Simplex_key, typename Filtration_value >
bool read_hasse_simplex(std::istream & in_, std::vector< Simplex_key > & boundary, Filtration_value & fil) {
int dim;
@@ -195,4 +206,93 @@ bool read_hasse_simplex(std::istream & in_, std::vector< Simplex_key > & boundar
return true;
}
+/**
+ * @brief Read a lower triangular distance matrix from a csv file. We assume that the .csv store the whole
+ * (square) matrix.
+ *
+ * @author Pawel Dlotko
+ *
+ * Square matrix file format:<br>
+ * 0;D12;...;D1j<br>
+ * D21;0;...;D2j<br>
+ * ...<br>
+ * Dj1;Dj2;...;0<br>
+ *
+ * lower matrix file format:<br>
+ * 0<br>
+ * D21;<br>
+ * D31;D32;<br>
+ * ...<br>
+ * Dj1;Dj2;...;Dj(j-1);<br>
+ *
+ **/
+template< typename Filtration_value >
+std::vector< std::vector< Filtration_value > > read_lower_triangular_matrix_from_csv_file(const std::string& filename,
+ const char separator = ';') {
+#ifdef DEBUG_TRACES
+ std::cout << "Using procedure read_lower_triangular_matrix_from_csv_file \n";
+#endif // DEBUG_TRACES
+ std::vector< std::vector< Filtration_value > > result;
+ std::ifstream in;
+ in.open(filename.c_str());
+ if (!in.is_open()) {
+ return result;
+ }
+
+ std::string line;
+
+ // the first line is emtpy, so we ignore it:
+ std::getline(in, line);
+ std::vector< Filtration_value > values_in_this_line;
+ result.push_back(values_in_this_line);
+
+ int number_of_line = 0;
+
+ // first, read the file line by line to a string:
+ while (std::getline(in, line)) {
+ // if line is empty, break
+ if (line.size() == 0)
+ break;
+
+ // if the last element of a string is comma:
+ if (line[ line.size() - 1 ] == separator) {
+ // then shrink the string by one
+ line.pop_back();
+ }
+
+ // replace all commas with spaces
+ std::replace(line.begin(), line.end(), separator, ' ');
+
+ // put the new line to a stream
+ std::istringstream iss(line);
+ // and now read the doubles.
+
+ int number_of_entry = 0;
+ std::vector< Filtration_value > values_in_this_line;
+ while (iss.good()) {
+ double entry;
+ iss >> entry;
+ if (number_of_entry <= number_of_line) {
+ values_in_this_line.push_back(entry);
+ }
+ ++number_of_entry;
+ }
+ if (!values_in_this_line.empty())result.push_back(values_in_this_line);
+ ++number_of_line;
+ }
+ in.close();
+
+#ifdef DEBUG_TRACES
+ std::cerr << "Here is the matrix we read : \n";
+ for (size_t i = 0; i != result.size(); ++i) {
+ for (size_t j = 0; j != result[i].size(); ++j) {
+ std::cerr << result[i][j] << " ";
+ }
+ std::cerr << std::endl;
+ }
+#endif // DEBUG_TRACES
+
+ return result;
+} // read_lower_triangular_matrix_from_csv_file
+
#endif // READER_UTILS_H_
diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt
index 7ccdb752..baa24539 100644
--- a/src/common/test/CMakeLists.txt
+++ b/src/common/test/CMakeLists.txt
@@ -13,12 +13,21 @@ endif()
add_executable ( poffreader_UT test_points_off_reader.cpp )
target_link_libraries(poffreader_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+add_executable ( distancematrixreader_UT test_distance_matrix_reader.cpp )
+target_link_libraries(distancematrixreader_UT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+
# Do not forget to copy test files in current binary dir
file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
+file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
# Unitary tests
add_test(poffreader_UT ${CMAKE_CURRENT_BINARY_DIR}/poffreader_UT
# XML format for Jenkins xUnit plugin
--log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/poffreader_UT.xml --log_level=test_suite --report_level=no)
+add_test(distancematrixreader_UT ${CMAKE_CURRENT_BINARY_DIR}/distancematrixreader_UT
+ # XML format for Jenkins xUnit plugin
+ --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/distancematrixreader_UT.xml --log_level=test_suite --report_level=no)
+
diff --git a/src/common/test/test_distance_matrix_reader.cpp b/src/common/test/test_distance_matrix_reader.cpp
new file mode 100644
index 00000000..95a73bd9
--- /dev/null
+++ b/src/common/test/test_distance_matrix_reader.cpp
@@ -0,0 +1,85 @@
+/* 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): Vincent Rouvreau
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <gudhi/reader_utils.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "distance_matrix_reader"
+#include <boost/test/unit_test.hpp>
+
+using Distance_matrix = std::vector<std::vector<double>>;
+
+BOOST_AUTO_TEST_CASE( lower_triangular_distance_matrix )
+{
+ Distance_matrix from_lower_triangular;
+ // Read lower_triangular_distance_matrix.csv file where the separator is a ','
+ from_lower_triangular = read_lower_triangular_matrix_from_csv_file<double>("lower_triangular_distance_matrix.csv",
+ ',');
+ for (auto& i : from_lower_triangular) {
+ for (auto j : i) {
+ std::cout << j << " ";
+ }
+ std::cout << std::endl;
+ }
+ std::cout << "from_lower_triangular size = " << from_lower_triangular.size() << std::endl;
+ BOOST_CHECK(from_lower_triangular.size() == 5);
+
+ for (std::size_t i = 0; i < from_lower_triangular.size(); i++) {
+ std::cout << "from_lower_triangular[" << i << "] size = " << from_lower_triangular[i].size() << std::endl;
+ BOOST_CHECK(from_lower_triangular[i].size() == i);
+ }
+ std::vector<double> expected = {1};
+ BOOST_CHECK(from_lower_triangular[1] == expected);
+
+ expected = {2,3};
+ BOOST_CHECK(from_lower_triangular[2] == expected);
+
+ expected = {4,5,6};
+ BOOST_CHECK(from_lower_triangular[3] == expected);
+
+ expected = {7,8,9,10};
+ BOOST_CHECK(from_lower_triangular[4] == expected);
+
+}
+
+BOOST_AUTO_TEST_CASE( full_square_distance_matrix )
+{
+ Distance_matrix from_full_square;
+ // Read full_square_distance_matrix.csv file where the separator is the default one ';'
+ from_full_square = read_lower_triangular_matrix_from_csv_file<double>("full_square_distance_matrix.csv");
+ for (auto& i : from_full_square) {
+ for (auto j : i) {
+ std::cout << j << " ";
+ }
+ std::cout << std::endl;
+ }
+ std::cout << "from_full_square size = " << from_full_square.size() << std::endl;
+ BOOST_CHECK(from_full_square.size() == 7);
+ for (std::size_t i = 0; i < from_full_square.size(); i++) {
+ std::cout << "from_full_square[" << i << "] size = " << from_full_square[i].size() << std::endl;
+ BOOST_CHECK(from_full_square[i].size() == i);
+ }
+}
diff --git a/src/common/test/test_points_off_reader.cpp b/src/common/test/test_points_off_reader.cpp
index b4f71182..0a78d190 100644
--- a/src/common/test/test_points_off_reader.cpp
+++ b/src/common/test/test_points_off_reader.cpp
@@ -4,7 +4,7 @@
*
* Author(s): Vincent Rouvreau
*
- * Copyright (C) 2015 INRIA Saclay (France)
+ * Copyright (C) 2015
*
* 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