diff options
author | mcarrier <mcarrier@636b058d-ea47-450e-bf9e-a15bfbe3eedb> | 2017-03-24 07:39:45 +0000 |
---|---|---|
committer | mcarrier <mcarrier@636b058d-ea47-450e-bf9e-a15bfbe3eedb> | 2017-03-24 07:39:45 +0000 |
commit | 6a1d7a51c3ac46b51d2613d58e63d948b4ca7789 (patch) | |
tree | 80950ffe9e1e06ba4cbe5366bdb747ca49e4ae0c /src | |
parent | 57a4ff3594b485a65fef206e03245a995f2feaf7 (diff) | |
parent | f48eae4cd7dc50dbbe0c8ec4f63bb98dda51a5d8 (diff) |
Merged latest trunk changes to Nerve_GIC
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Nerve_GIC@2230 636b058d-ea47-450e-bf9e-a15bfbe3eedb
Former-commit-id: bccc1dde37a431fd2b2808549c308482480e8778
Diffstat (limited to 'src')
180 files changed, 12396 insertions, 926 deletions
diff --git a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h b/src/Alpha_complex/concept/SimplicialComplexForAlpha.h index 2b8bff94..2b8bff94 100644 --- a/src/Alpha_complex/concept/Simplicial_complex_for_alpha.h +++ b/src/Alpha_complex/concept/SimplicialComplexForAlpha.h diff --git a/src/Alpha_complex/doc/COPYRIGHT b/src/Alpha_complex/doc/COPYRIGHT new file mode 100644 index 00000000..dbad2380 --- /dev/null +++ b/src/Alpha_complex/doc/COPYRIGHT @@ -0,0 +1,19 @@ +The files of this directory are 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) 2015 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/>. diff --git a/src/Alpha_complex/example/Alpha_complex_from_off.cpp b/src/Alpha_complex/example/Alpha_complex_from_off.cpp index 32bef1cd..d411e90a 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_off.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_off.cpp @@ -17,13 +17,13 @@ void usage(int nbArgs, char * const progName) { int main(int argc, char **argv) { if ((argc != 3) && (argc != 4)) usage(argc, (argv[0] - 1)); - std::string off_file_name(argv[1]); - double alpha_square_max_value = atof(argv[2]); + std::string off_file_name {argv[1]}; + double alpha_square_max_value {atof(argv[2])}; // ---------------------------------------------------------------------------- // Init of an alpha complex from an OFF file // ---------------------------------------------------------------------------- - typedef CGAL::Epick_d< CGAL::Dynamic_dimension_tag > Kernel; + using Kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex_from_file(off_file_name); std::streambuf* streambufffer; diff --git a/src/Alpha_complex/example/Alpha_complex_from_points.cpp b/src/Alpha_complex/example/Alpha_complex_from_points.cpp index 491b7e6d..c19f7cc8 100644 --- a/src/Alpha_complex/example/Alpha_complex_from_points.cpp +++ b/src/Alpha_complex/example/Alpha_complex_from_points.cpp @@ -9,9 +9,9 @@ #include <vector> #include <limits> // for numeric limits -typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel; -typedef Kernel::Point_d Point; -typedef std::vector<Point> Vector_of_points; +using Kernel = CGAL::Epick_d< CGAL::Dimension_tag<2> >; +using Point = Kernel::Point_d; +using Vector_of_points = std::vector<Point>; void usage(int nbArgs, char * const progName) { std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n"; @@ -24,7 +24,7 @@ int main(int argc, char **argv) { if ((argc != 1) && (argc != 2)) usage(argc, (argv[0] - 1)); // Delaunay complex if alpha_square_max_value is not given by the user. - double alpha_square_max_value = std::numeric_limits<double>::infinity(); + double alpha_square_max_value {std::numeric_limits<double>::infinity()}; if (argc == 2) alpha_square_max_value = atof(argv[1]); diff --git a/src/Bitmap_cubical_complex/doc/COPYRIGHT b/src/Bitmap_cubical_complex/doc/COPYRIGHT new file mode 100644 index 00000000..bcd46b23 --- /dev/null +++ b/src/Bitmap_cubical_complex/doc/COPYRIGHT @@ -0,0 +1,19 @@ +The files of this directory are 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 + +Copyright (C) 2015 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/>. diff --git a/src/Bottleneck_distance/benchmark/CMakeLists.txt b/src/Bottleneck_distance/benchmark/CMakeLists.txt index 355e8d31..c99e0373 100644 --- a/src/Bottleneck_distance/benchmark/CMakeLists.txt +++ b/src/Bottleneck_distance/benchmark/CMakeLists.txt @@ -7,5 +7,8 @@ project(Bottleneck_distance_benchmark) if(CGAL_FOUND) if (NOT CGAL_VERSION VERSION_LESS 4.8.0) add_executable ( bottleneck_chrono bottleneck_chrono.cpp ) + if (TBB_FOUND) + target_link_libraries(bottleneck_chrono ${TBB_LIBRARIES}) + endif(TBB_FOUND) 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/COPYRIGHT b/src/Bottleneck_distance/doc/COPYRIGHT new file mode 100644 index 00000000..179740a6 --- /dev/null +++ b/src/Bottleneck_distance/doc/COPYRIGHT @@ -0,0 +1,19 @@ +The files of this directory are part of the Gudhi Library. The Gudhi library +(Geometric Understanding in Higher Dimensions) is a generic C++ library for +computational topology. + +Author(s): François Godi + +Copyright (C) 2015 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/>. diff --git a/src/Bottleneck_distance/doc/Intro_bottleneck_distance.h b/src/Bottleneck_distance/doc/Intro_bottleneck_distance.h index 21187f9c..3998fe8d 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,16 +35,16 @@ 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 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. + * 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. * * \image html perturb_pd.png On this picture, the red edges represent the matching. The bottleneck distance is the length of the longest edge. * */ /** @} */ // 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 b36d0f34..55f22c01 100644 --- a/src/Bottleneck_distance/example/CMakeLists.txt +++ b/src/Bottleneck_distance/example/CMakeLists.txt @@ -13,6 +13,8 @@ if(CGAL_FOUND) 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(bottleneck_read_file_example ${TBB_LIBRARIES}) + target_link_libraries(bottleneck_basic_example ${TBB_LIBRARIES}) 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 diff --git a/src/Bottleneck_distance/include/gudhi/Bottleneck.h b/src/Bottleneck_distance/include/gudhi/Bottleneck.h index b5641e29..b90a0ee0 100644 --- a/src/Bottleneck_distance/include/gudhi/Bottleneck.h +++ b/src/Bottleneck_distance/include/gudhi/Bottleneck.h @@ -80,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/Persistence_graph.h b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h index 39efc082..44f4b827 100644 --- a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h +++ b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h @@ -25,6 +25,10 @@ #include <gudhi/Internal_point.h> +#ifdef GUDHI_USE_TBB +#include <tbb/parallel_sort.h> +#endif + #include <vector> #include <algorithm> #include <limits> // for numeric_limits @@ -40,7 +44,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 ? */ @@ -144,7 +148,11 @@ inline std::vector<double> Persistence_graph::sorted_distances() const { for (int v_point_index = 0; v_point_index < size(); ++v_point_index) distances.push_back(distance(u_point_index, v_point_index)); } +#ifdef GUDHI_USE_TBB + tbb::parallel_sort(distances.begin(), distances.end()); +#else std::sort(distances.begin(), distances.end()); +#endif return distances; } diff --git a/src/Bottleneck_distance/test/CMakeLists.txt b/src/Bottleneck_distance/test/CMakeLists.txt index 6c8f112d..3e61f4cf 100644 --- a/src/Bottleneck_distance/test/CMakeLists.txt +++ b/src/Bottleneck_distance/test/CMakeLists.txt @@ -17,6 +17,9 @@ if(CGAL_FOUND) if (NOT CGAL_VERSION VERSION_LESS 4.8.0) add_executable ( bottleneckUT bottleneck_unit_test.cpp ) target_link_libraries(bottleneckUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(bottleneckUT ${TBB_LIBRARIES}) + endif(TBB_FOUND) # Unitary tests add_test(NAME bottleneckUT COMMAND ${CMAKE_CURRENT_BINARY_DIR}/bottleneckUT diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ebdcdcea..7ab2a883 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -90,6 +90,8 @@ else() add_definitions(-DBOOST_RESULT_OF_USE_DECLTYPE) # BOOST ISSUE with Libraries name resolution under Windows add_definitions(-DBOOST_ALL_NO_LIB) + # problem with Visual Studio link on Boost program_options + add_definitions( -DBOOST_ALL_DYN_LINK ) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) @@ -125,6 +127,10 @@ else() # Please let GudhUI in last compilation position as QT is known to modify CMAKE_CXX_FLAGS # GudhUI add_subdirectory(GudhUI) + + # This variable is used by Cython CMakeLists.txt to know its path + set(GUDHI_CYTHON_PATH "cython") + add_subdirectory(${GUDHI_CYTHON_PATH}) #--------------------------------------------------------------------------------------- #--------------------------------------------------------------------------------------- diff --git a/src/Contraction/doc/COPYRIGHT b/src/Contraction/doc/COPYRIGHT new file mode 100644 index 00000000..1de850d7 --- /dev/null +++ b/src/Contraction/doc/COPYRIGHT @@ -0,0 +1,18 @@ +The files of this directory are part of the Gudhi Library. The Gudhi library +(Geometric Understanding in Higher Dimensions) is a generic C++ library for +computational topology. + +Author(s): David Salinas +Copyright (C) 2015 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/>. diff --git a/src/Doxyfile b/src/Doxyfile index f06fbd23..60959235 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "GUDHI" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "1.3.1" +PROJECT_NUMBER = "2.0.0" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -781,10 +781,10 @@ RECURSIVE = YES # run. EXCLUDE = data/ \ - example/ \ - GudhUI/ \ - cmake/ \ - debian/ \ + example/ \ + GudhUI/ \ + cmake/ \ + src/cython/ \ include/gudhi_patches/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or diff --git a/src/GudhUI/CMakeLists.txt b/src/GudhUI/CMakeLists.txt index d3a52b60..64429baa 100644 --- a/src/GudhUI/CMakeLists.txt +++ b/src/GudhUI/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 2.8) project(GudhUI) -find_package(CGAL COMPONENTS Qt5) find_package(Qt5 COMPONENTS Widgets Xml OpenGL) find_package(QGLViewer) find_package(OpenGL) - if (NOT CGAL_FOUND) message(ERROR " GudhUI requires CGAL and will not be compiled.") endif() diff --git a/src/Persistent_cohomology/doc/COPYRIGHT b/src/Persistent_cohomology/doc/COPYRIGHT new file mode 100644 index 00000000..34345bef --- /dev/null +++ b/src/Persistent_cohomology/doc/COPYRIGHT @@ -0,0 +1,19 @@ +The files of this directory are 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) 2015 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/>. diff --git a/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h b/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h index 40dd3f93..e17e5926 100644 --- a/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h +++ b/src/Persistent_cohomology/doc/Intro_persistent_cohomology.h @@ -172,6 +172,28 @@ Persistent_cohomology/alpha_complex_3d_persistence.cpp</a> computes the persiste 2 1 0.0934117 1.00003 2 2 0.56444 1.03938 \endcode +\li <a href="_persistent_cohomology_2exact_alpha_complex_3d_persistence_8cpp-example.html"> +Persistent_cohomology/exact_alpha_complex_3d_persistence.cpp</a> computes the persistent homology with +\f$\mathbb{Z}/2\mathbb{Z}\f$ coefficients of the alpha complex on points sampling from an OFF file. +Here, as CGAL computes the exact values, it is slower, but it is necessary when points are on a grid +for instance. +\code $> ./exact_alpha_complex_3d_persistence ../../data/points/sphere3D_pts_on_grid.off 2 0.1 \endcode +\code Simplex_tree dim: 3 +2 0 0 inf +2 2 0.0002 0.2028 \endcode + +\li <a href="_persistent_cohomology_2weighted_alpha_complex_3d_persistence_8cpp-example.html"> +Persistent_cohomology/weighted_alpha_complex_3d_persistence.cpp</a> computes the persistent homology with +\f$\mathbb{Z}/2\mathbb{Z}\f$ coefficients of the weighted alpha complex on points sampling from an OFF file +and a weights file. +\code $> ./weighted_alpha_complex_3d_persistence ../../data/points/tore3D_300.off +../../data/points/tore3D_300.weights 2 0.45 \endcode +\code Simplex_tree dim: 3 +2 -0 0 inf +2 1 0.0682162 1.0001 +2 1 0.0934117 1.00003 +2 2 0.56444 1.03938 \endcode + \li <a href="_persistent_cohomology_2alpha_complex_persistence_8cpp-example.html"> Persistent_cohomology/alpha_complex_persistence.cpp</a> computes the persistent homology with \f$\mathbb{Z}/p\mathbb{Z}\f$ coefficients of the alpha complex on points sampling from an OFF file. diff --git a/src/Persistent_cohomology/example/CMakeLists.txt b/src/Persistent_cohomology/example/CMakeLists.txt index 38d7e9a9..20700d86 100644 --- a/src/Persistent_cohomology/example/CMakeLists.txt +++ b/src/Persistent_cohomology/example/CMakeLists.txt @@ -1,10 +1,6 @@ cmake_minimum_required(VERSION 2.6) project(Persistent_cohomology_examples) -# problem with Visual Studio link on Boost program_options -add_definitions( -DBOOST_ALL_NO_LIB ) -add_definitions( -DBOOST_ALL_DYN_LINK ) - add_executable(plain_homology plain_homology.cpp) target_link_libraries(plain_homology ${Boost_SYSTEM_LIBRARY}) @@ -38,38 +34,58 @@ 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_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) +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) 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}) + target_link_libraries(rips_multifield_persistence + ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${GMPXX_LIBRARIES} ${GMP_LIBRARIES}) if (TBB_FOUND) target_link_libraries(rips_multifield_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/tore3D_1307.off -r 0.25 -m 0.5 -d 3 -p 2 -q 71) + 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) if(CGAL_FOUND) add_executable(alpha_complex_3d_persistence alpha_complex_3d_persistence.cpp) target_link_libraries(alpha_complex_3d_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_executable(exact_alpha_complex_3d_persistence exact_alpha_complex_3d_persistence.cpp) + target_link_libraries(exact_alpha_complex_3d_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) + add_executable(weighted_alpha_complex_3d_persistence weighted_alpha_complex_3d_persistence.cpp) + target_link_libraries(weighted_alpha_complex_3d_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) if (TBB_FOUND) target_link_libraries(alpha_complex_3d_persistence ${TBB_LIBRARIES}) + target_link_libraries(exact_alpha_complex_3d_persistence ${TBB_LIBRARIES}) + target_link_libraries(weighted_alpha_complex_3d_persistence ${TBB_LIBRARIES}) endif(TBB_FOUND) - add_test(alpha_complex_3d_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_complex_3d_persistence ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off 2 0.45) + add_test(alpha_complex_3d_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/alpha_complex_3d_persistence + ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off 2 0.45) + add_test(exact_alpha_complex_3d_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/exact_alpha_complex_3d_persistence + ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off 2 0.45) + add_test(weighted_alpha_complex_3d_persistence_2_0_5 ${CMAKE_CURRENT_BINARY_DIR}/weighted_alpha_complex_3d_persistence + ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.weights 2 0.45) if (NOT CGAL_VERSION VERSION_LESS 4.7.0) if (EIGEN3_FOUND) add_executable (alpha_complex_persistence alpha_complex_persistence.cpp) - target_link_libraries(alpha_complex_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) + target_link_libraries(alpha_complex_persistence + ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) add_executable(periodic_alpha_complex_3d_persistence periodic_alpha_complex_3d_persistence.cpp) target_link_libraries(periodic_alpha_complex_3d_persistence ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) @@ -82,8 +98,10 @@ if(CGAL_FOUND) target_link_libraries(periodic_alpha_complex_3d_persistence ${TBB_LIBRARIES}) target_link_libraries(custom_persistence_sort ${TBB_LIBRARIES}) endif(TBB_FOUND) - add_test(alpha_complex_persistence_2_0_45 ${CMAKE_CURRENT_BINARY_DIR}/alpha_complex_persistence ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -m 0.45 -p 2) - add_test(periodic_alpha_complex_3d_persistence_2_0 ${CMAKE_CURRENT_BINARY_DIR}/periodic_alpha_complex_3d_persistence ${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off ${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt 2 0) + add_test(alpha_complex_persistence_2_0_45 ${CMAKE_CURRENT_BINARY_DIR}/alpha_complex_persistence + ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -m 0.45 -p 2) + add_test(periodic_alpha_complex_3d_persistence_2_0 ${CMAKE_CURRENT_BINARY_DIR}/periodic_alpha_complex_3d_persistence + ${CMAKE_SOURCE_DIR}/data/points/grid_10_10_10_in_0_1.off ${CMAKE_SOURCE_DIR}/data/points/iso_cuboid_3_in_0_1.txt 2 0) add_test(custom_persistence_sort ${CMAKE_CURRENT_BINARY_DIR}/custom_persistence_sort) endif(EIGEN3_FOUND) endif (NOT CGAL_VERSION VERSION_LESS 4.7.0) diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_helper.h b/src/Persistent_cohomology/example/alpha_complex_3d_helper.h new file mode 100644 index 00000000..ceefd2ba --- /dev/null +++ b/src/Persistent_cohomology/example/alpha_complex_3d_helper.h @@ -0,0 +1,76 @@ +/* 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) 2014 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/>. + */ + +#ifndef EXAMPLE_PERSISTENT_COHOMOLOGY_ALPHA_COMPLEX_3D_HELPER_H_ +#define EXAMPLE_PERSISTENT_COHOMOLOGY_ALPHA_COMPLEX_3D_HELPER_H_ + +template<class Vertex_list, class Cell_handle> +Vertex_list from_cell(const Cell_handle& ch) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { +#ifdef DEBUG_TRACES + std::cout << "from cell[" << i << "]=" << ch->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(ch->vertex(i)); + } + return the_list; +} + +template<class Vertex_list, class Facet> +Vertex_list from_facet(const Facet& fct) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { + if (fct.second != i) { +#ifdef DEBUG_TRACES + std::cout << "from facet=[" << i << "]" << fct.first->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(fct.first->vertex(i)); + } + } + return the_list; +} + +template<class Vertex_list, class Edge_3> +Vertex_list from_edge(const Edge_3& edg) { + Vertex_list the_list; + for (auto i = 0; i < 4; i++) { + if ((edg.second == i) || (edg.third == i)) { +#ifdef DEBUG_TRACES + std::cout << "from edge[" << i << "]=" << edg.first->vertex(i)->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(edg.first->vertex(i)); + } + } + return the_list; +} + +template<class Vertex_list, class Vertex_handle> +Vertex_list from_vertex(const Vertex_handle& vh) { + Vertex_list the_list; +#ifdef DEBUG_TRACES + std::cout << "from vertex=" << vh->point() << std::endl; +#endif // DEBUG_TRACES + the_list.push_back(vh); + return the_list; +} + +#endif // EXAMPLE_PERSISTENT_COHOMOLOGY_ALPHA_COMPLEX_3D_HELPER_H_ diff --git a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp index 978dc942..ffb98283 100644 --- a/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp +++ b/src/Persistent_cohomology/example/alpha_complex_3d_persistence.cpp @@ -30,6 +30,8 @@ #include <CGAL/Alpha_shape_3.h> #include <CGAL/iterator.h> +#include "alpha_complex_3d_helper.h" + #include <fstream> #include <cmath> #include <string> @@ -40,84 +42,39 @@ #include <vector> // Alpha_shape_3 templates type definitions -typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; -typedef CGAL::Alpha_shape_vertex_base_3<Kernel> Vb; -typedef CGAL::Alpha_shape_cell_base_3<Kernel> Fb; -typedef CGAL::Triangulation_data_structure_3<Vb, Fb> Tds; -typedef CGAL::Delaunay_triangulation_3<Kernel, Tds> Triangulation_3; -typedef CGAL::Alpha_shape_3<Triangulation_3> Alpha_shape_3; +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel>; +using Fb = CGAL::Alpha_shape_cell_base_3<Kernel>; +using Tds = CGAL::Triangulation_data_structure_3<Vb, Fb>; +using Triangulation_3 = CGAL::Delaunay_triangulation_3<Kernel, Tds>; +using Alpha_shape_3 = CGAL::Alpha_shape_3<Triangulation_3>; // From file type definition -typedef Kernel::Point_3 Point_3; +using Point_3 = Kernel::Point_3; // filtration with alpha values needed type definition -typedef Alpha_shape_3::FT Alpha_value_type; -typedef CGAL::Object Object; -typedef CGAL::Dispatch_output_iterator< -CGAL::cpp11::tuple<Object, Alpha_value_type>, -CGAL::cpp11::tuple<std::back_insert_iterator< std::vector<Object> >, - std::back_insert_iterator< std::vector<Alpha_value_type> > > > Dispatch; -typedef Alpha_shape_3::Cell_handle Cell_handle; -typedef Alpha_shape_3::Facet Facet; -typedef Alpha_shape_3::Edge Edge_3; -typedef std::list<Alpha_shape_3::Vertex_handle> Vertex_list; +using Alpha_value_type = Alpha_shape_3::FT; +using Object = CGAL::Object; +using Dispatch = CGAL::Dispatch_output_iterator< + CGAL::cpp11::tuple<Object, Alpha_value_type>, + CGAL::cpp11::tuple<std::back_insert_iterator< std::vector<Object> >, + std::back_insert_iterator< std::vector<Alpha_value_type> > > >; +using Cell_handle = Alpha_shape_3::Cell_handle; +using Facet = Alpha_shape_3::Facet; +using Edge_3 = Alpha_shape_3::Edge; +using Vertex_handle = Alpha_shape_3::Vertex_handle; +using Vertex_list = std::list<Alpha_shape_3::Vertex_handle>; // 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; -typedef std::vector< Simplex_tree_vertex > Simplex_tree_vector_vertex; -typedef Gudhi::persistent_cohomology::Persistent_cohomology< ST, Gudhi::persistent_cohomology::Field_Zp > PCOH; - -Vertex_list from(const Cell_handle& ch) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { -#ifdef DEBUG_TRACES - std::cout << "from cell[" << i << "]=" << ch->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(ch->vertex(i)); - } - return the_list; -} - -Vertex_list from(const Facet& fct) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { - if (fct.second != i) { -#ifdef DEBUG_TRACES - std::cout << "from facet=[" << i << "]" << fct.first->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(fct.first->vertex(i)); - } - } - return the_list; -} - -Vertex_list from(const Edge_3& edg) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { - if ((edg.second == i) || (edg.third == i)) { -#ifdef DEBUG_TRACES - std::cout << "from edge[" << i << "]=" << edg.first->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(edg.first->vertex(i)); - } - } - return the_list; -} - -Vertex_list from(const Alpha_shape_3::Vertex_handle& vh) { - Vertex_list the_list; -#ifdef DEBUG_TRACES - std::cout << "from vertex=" << vh->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(vh); - return the_list; -} - -void usage(char * const progName) { +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>; +using Simplex_tree_vector_vertex = std::vector< Simplex_tree_vertex >; +using PCOH = Gudhi::persistent_cohomology::Persistent_cohomology< ST, Gudhi::persistent_cohomology::Field_Zp >; + +void usage(const std::string& progName) { std::cerr << "Usage: " << progName << " path_to_file_graph coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n"; exit(-1); @@ -185,30 +142,29 @@ int main(int argc, char * const argv[]) { for (auto object_iterator : the_objects) { // Retrieve Alpha shape vertex list from object if (const Cell_handle * cell = CGAL::object_cast<Cell_handle>(&object_iterator)) { - vertex_list = from(*cell); + vertex_list = from_cell<Vertex_list, Cell_handle>(*cell); count_cells++; if (dim_max < 3) { // Cell is of dim 3 dim_max = 3; } } else if (const Facet * facet = CGAL::object_cast<Facet>(&object_iterator)) { - vertex_list = from(*facet); + vertex_list = from_facet<Vertex_list, Facet>(*facet); count_facets++; if (dim_max < 2) { // Facet is of dim 2 dim_max = 2; } } else if (const Edge_3 * edge = CGAL::object_cast<Edge_3>(&object_iterator)) { - vertex_list = from(*edge); + vertex_list = from_edge<Vertex_list, Edge_3>(*edge); count_edges++; if (dim_max < 1) { // Edge_3 is of dim 1 dim_max = 1; } - } else if (const Alpha_shape_3::Vertex_handle * vertex = - CGAL::object_cast<Alpha_shape_3::Vertex_handle>(&object_iterator)) { + } else if (const Vertex_handle * vertex = CGAL::object_cast<Vertex_handle>(&object_iterator)) { count_vertices++; - vertex_list = from(*vertex); + vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex); } // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex Simplex_tree_vector_vertex the_simplex_tree; diff --git a/src/Persistent_cohomology/example/exact_alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/exact_alpha_complex_3d_persistence.cpp new file mode 100644 index 00000000..c016a596 --- /dev/null +++ b/src/Persistent_cohomology/example/exact_alpha_complex_3d_persistence.cpp @@ -0,0 +1,244 @@ +/* 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) 2014 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/>. + */ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Persistent_cohomology.h> +#include <gudhi/Points_3D_off_io.h> +#include <boost/variant.hpp> + +#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> +#include <CGAL/Delaunay_triangulation_3.h> +#include <CGAL/Alpha_shape_3.h> +#include <CGAL/iterator.h> + +#include "alpha_complex_3d_helper.h" + +#include <fstream> +#include <cmath> +#include <string> +#include <tuple> +#include <map> +#include <utility> +#include <list> +#include <vector> + +// Alpha_shape_3 templates type definitions +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using Exact_tag = CGAL::Tag_true; +using Vb = CGAL::Alpha_shape_vertex_base_3<Kernel, CGAL::Default, Exact_tag>; +using Fb = CGAL::Alpha_shape_cell_base_3<Kernel, CGAL::Default, Exact_tag>; +using Tds = CGAL::Triangulation_data_structure_3<Vb, Fb>; +using Triangulation_3 = CGAL::Delaunay_triangulation_3<Kernel, Tds>; +using Alpha_shape_3 = CGAL::Alpha_shape_3<Triangulation_3, Exact_tag>; + +// From file type definition +using Point_3 = Kernel::Point_3; + +// filtration with alpha values needed type definition +using Alpha_value_type = Alpha_shape_3::FT; +using Object = CGAL::Object; +using Dispatch = CGAL::Dispatch_output_iterator< + CGAL::cpp11::tuple<Object, Alpha_value_type>, + CGAL::cpp11::tuple<std::back_insert_iterator< std::vector<Object> >, + std::back_insert_iterator< std::vector<Alpha_value_type> > > >; +using Cell_handle = Alpha_shape_3::Cell_handle; +using Facet = Alpha_shape_3::Facet; +using Edge_3 = Alpha_shape_3::Edge; +using Vertex_handle = Alpha_shape_3::Vertex_handle; +using Vertex_list = std::list<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>; +using Simplex_tree_vector_vertex = std::vector< Simplex_tree_vertex >; +using PCOH = Gudhi::persistent_cohomology::Persistent_cohomology< ST, Gudhi::persistent_cohomology::Field_Zp >; + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << + " path_to_file_graph coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n"; + exit(-1); +} + +int main(int argc, char * const argv[]) { + // program args management + if (argc != 4) { + std::cerr << "Error: Number of arguments (" << argc << ") is not correct\n"; + usage(argv[0]); + } + + int coeff_field_characteristic = atoi(argv[2]); + + Filtration_value min_persistence = 0.0; + 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]); + } + + // Read points from file + std::string offInputFile(argv[1]); + // Read the OFF file (input file name given as parameter) and triangulate points + Gudhi::Points_3D_off_reader<Point_3> off_reader(offInputFile); + // Check the read operation was correct + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << offInputFile << std::endl; + usage(argv[0]); + } + + // Retrieve the triangulation + std::vector<Point_3> lp = off_reader.get_point_cloud(); + + // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. + Alpha_shape_3 as(lp.begin(), lp.end(), 0, Alpha_shape_3::GENERAL); +#ifdef DEBUG_TRACES + std::cout << "Alpha shape computed in GENERAL mode" << std::endl; +#endif // DEBUG_TRACES + + // filtration with alpha values from alpha shape + std::vector<Object> the_objects; + std::vector<Alpha_value_type> the_alpha_values; + + Dispatch disp = CGAL::dispatch_output<Object, Alpha_value_type>(std::back_inserter(the_objects), + std::back_inserter(the_alpha_values)); + + as.filtration_with_alpha_values(disp); +#ifdef DEBUG_TRACES + std::cout << "filtration_with_alpha_values returns : " << the_objects.size() << " objects" << std::endl; +#endif // DEBUG_TRACES + + Alpha_shape_3::size_type count_vertices = 0; + Alpha_shape_3::size_type count_edges = 0; + Alpha_shape_3::size_type count_facets = 0; + Alpha_shape_3::size_type count_cells = 0; + + // Loop on objects vector + Vertex_list vertex_list; + ST simplex_tree; + Alpha_shape_simplex_tree_map map_cgal_simplex_tree; + std::vector<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin(); + int dim_max = 0; + Filtration_value filtration_max = 0.0; + for (auto object_iterator : the_objects) { + // Retrieve Alpha shape vertex list from object + if (const Cell_handle * cell = CGAL::object_cast<Cell_handle>(&object_iterator)) { + vertex_list = from_cell<Vertex_list, Cell_handle>(*cell); + count_cells++; + if (dim_max < 3) { + // Cell is of dim 3 + dim_max = 3; + } + } else if (const Facet * facet = CGAL::object_cast<Facet>(&object_iterator)) { + vertex_list = from_facet<Vertex_list, Facet>(*facet); + count_facets++; + if (dim_max < 2) { + // Facet is of dim 2 + dim_max = 2; + } + } else if (const Edge_3 * edge = CGAL::object_cast<Edge_3>(&object_iterator)) { + vertex_list = from_edge<Vertex_list, Edge_3>(*edge); + count_edges++; + if (dim_max < 1) { + // Edge_3 is of dim 1 + dim_max = 1; + } + } else if (const Vertex_handle * vertex = CGAL::object_cast<Vertex_handle>(&object_iterator)) { + count_vertices++; + vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex); + } + // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex + Simplex_tree_vector_vertex the_simplex_tree; + for (auto the_alpha_shape_vertex : vertex_list) { + Alpha_shape_simplex_tree_map::iterator the_map_iterator = map_cgal_simplex_tree.find(the_alpha_shape_vertex); + if (the_map_iterator == map_cgal_simplex_tree.end()) { + // alpha shape not found + Simplex_tree_vertex vertex = map_cgal_simplex_tree.size(); +#ifdef DEBUG_TRACES + std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] not found - insert " << vertex << std::endl; +#endif // DEBUG_TRACES + the_simplex_tree.push_back(vertex); + map_cgal_simplex_tree.insert(Alpha_shape_simplex_tree_pair(the_alpha_shape_vertex, vertex)); + } else { + // alpha shape found + Simplex_tree_vertex vertex = the_map_iterator->second; +#ifdef DEBUG_TRACES + std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] found in " << vertex << std::endl; +#endif // DEBUG_TRACES + the_simplex_tree.push_back(vertex); + } + } + // Construction of the simplex_tree + // you can also use the_alpha_value_iterator->exact() + Filtration_value filtr = /*std::sqrt*/CGAL::to_double(the_alpha_value_iterator->exact()); +#ifdef DEBUG_TRACES + std::cout << "filtration = " << filtr << std::endl; +#endif // DEBUG_TRACES + if (filtr > filtration_max) { + filtration_max = filtr; + } + simplex_tree.insert_simplex(the_simplex_tree, filtr); + if (the_alpha_value_iterator != the_alpha_values.end()) + ++the_alpha_value_iterator; + else + std::cout << "This shall not happen" << std::endl; + } + simplex_tree.set_filtration(filtration_max); + simplex_tree.set_dimension(dim_max); + +#ifdef DEBUG_TRACES + std::cout << "vertices \t\t" << count_vertices << std::endl; + std::cout << "edges \t\t" << count_edges << std::endl; + std::cout << "facets \t\t" << count_facets << std::endl; + std::cout << "cells \t\t" << count_cells << std::endl; + + + std::cout << "Information of the Simplex Tree: " << std::endl; + std::cout << " Number of vertices = " << simplex_tree.num_vertices() << " "; + std::cout << " Number of simplices = " << simplex_tree.num_simplices() << std::endl << std::endl; + std::cout << " Dimension = " << simplex_tree.dimension() << " "; + std::cout << " filtration = " << simplex_tree.filtration() << std::endl << std::endl; +#endif // DEBUG_TRACES + +#ifdef DEBUG_TRACES + std::cout << "Iterator on vertices: " << std::endl; + for (auto vertex : simplex_tree.complex_vertex_range()) { + std::cout << vertex << " "; + } +#endif // DEBUG_TRACES + + // Sort the simplices in the order of the filtration + simplex_tree.initialize_filtration(); + + std::cout << "Simplex_tree dim: " << simplex_tree.dimension() << std::endl; + // Compute the persistence diagram of the complex + PCOH pcoh(simplex_tree); + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + pcoh.output_diagram(); + + return 0; +} 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 dbc42706..4f6ea40e 100644 --- a/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp +++ b/src/Persistent_cohomology/example/periodic_alpha_complex_3d_persistence.cpp @@ -31,6 +31,8 @@ #include <CGAL/Alpha_shape_3.h> #include <CGAL/iterator.h> +#include "alpha_complex_3d_helper.h" + #include <fstream> #include <cmath> #include <string> @@ -67,6 +69,7 @@ using Dispatch = CGAL::Dispatch_output_iterator< using Cell_handle = Alpha_shape_3::Cell_handle; using Facet = Alpha_shape_3::Facet; using Edge_3 = Alpha_shape_3::Edge; +using Vertex_handle = Alpha_shape_3::Vertex_handle; using Vertex_list = std::list<Alpha_shape_3::Vertex_handle>; // gudhi type definition @@ -79,52 +82,6 @@ using Simplex_tree_vector_vertex = std::vector< Simplex_tree_vertex >; using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology< ST, Gudhi::persistent_cohomology::Field_Zp >; -Vertex_list from(const Cell_handle& ch) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { -#ifdef DEBUG_TRACES - std::cout << "from cell[" << i << "]=" << ch->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(ch->vertex(i)); - } - return the_list; -} - -Vertex_list from(const Facet& fct) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { - if (fct.second != i) { -#ifdef DEBUG_TRACES - std::cout << "from facet=[" << i << "]" << fct.first->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(fct.first->vertex(i)); - } - } - return the_list; -} - -Vertex_list from(const Edge_3& edg) { - Vertex_list the_list; - for (auto i = 0; i < 4; i++) { - if ((edg.second == i) || (edg.third == i)) { -#ifdef DEBUG_TRACES - std::cout << "from edge[" << i << "]=" << edg.first->vertex(i)->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(edg.first->vertex(i)); - } - } - return the_list; -} - -Vertex_list from(const Alpha_shape_3::Vertex_handle& vh) { - Vertex_list the_list; -#ifdef DEBUG_TRACES - std::cout << "from vertex=" << vh->point() << std::endl; -#endif // DEBUG_TRACES - the_list.push_back(vh); - return the_list; -} - void usage(char * const progName) { std::cerr << "Usage: " << progName << " path_to_file_graph path_to_iso_cuboid_3_file coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n"; @@ -203,21 +160,21 @@ int main(int argc, char * const argv[]) { for (auto object_iterator : the_objects) { // Retrieve Alpha shape vertex list from object if (const Cell_handle * cell = CGAL::object_cast<Cell_handle>(&object_iterator)) { - vertex_list = from(*cell); + vertex_list = from_cell<Vertex_list, Cell_handle>(*cell); count_cells++; if (dim_max < 3) { // Cell is of dim 3 dim_max = 3; } } else if (const Facet * facet = CGAL::object_cast<Facet>(&object_iterator)) { - vertex_list = from(*facet); + vertex_list = from_facet<Vertex_list, Facet>(*facet); count_facets++; if (dim_max < 2) { // Facet is of dim 2 dim_max = 2; } } else if (const Edge_3 * edge = CGAL::object_cast<Edge_3>(&object_iterator)) { - vertex_list = from(*edge); + vertex_list = from_edge<Vertex_list, Edge_3>(*edge); count_edges++; if (dim_max < 1) { // Edge_3 is of dim 1 @@ -226,7 +183,7 @@ int main(int argc, char * const argv[]) { } else if (const Alpha_shape_3::Vertex_handle * vertex = CGAL::object_cast<Alpha_shape_3::Vertex_handle>(&object_iterator)) { count_vertices++; - vertex_list = from(*vertex); + vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex); } // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex Simplex_tree_vector_vertex the_simplex_tree; diff --git a/src/Persistent_cohomology/example/rips_persistence_step_by_step.cpp b/src/Persistent_cohomology/example/rips_persistence_step_by_step.cpp index c8f0921a..b159c62e 100644 --- a/src/Persistent_cohomology/example/rips_persistence_step_by_step.cpp +++ b/src/Persistent_cohomology/example/rips_persistence_step_by_step.cpp @@ -34,6 +34,13 @@ #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; diff --git a/src/Persistent_cohomology/example/weighted_alpha_complex_3d_persistence.cpp b/src/Persistent_cohomology/example/weighted_alpha_complex_3d_persistence.cpp new file mode 100644 index 00000000..5203548a --- /dev/null +++ b/src/Persistent_cohomology/example/weighted_alpha_complex_3d_persistence.cpp @@ -0,0 +1,263 @@ +/* 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) 2014 INRIA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Persistent_cohomology.h> +#include <gudhi/Points_3D_off_io.h> +#include <boost/variant.hpp> + +#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> +#include <CGAL/Regular_triangulation_euclidean_traits_3.h> +#include <CGAL/Regular_triangulation_3.h> +#include <CGAL/Alpha_shape_3.h> +#include <CGAL/iterator.h> + +#include "alpha_complex_3d_helper.h" + +#include <fstream> +#include <cmath> +#include <string> +#include <tuple> +#include <map> +#include <utility> +#include <list> +#include <vector> +#include <cstdlib> + +// Traits +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using Gt = CGAL::Regular_triangulation_euclidean_traits_3<Kernel>; +using Vb = CGAL::Alpha_shape_vertex_base_3<Gt>; +using Fb = CGAL::Alpha_shape_cell_base_3<Gt>; +using Tds = CGAL::Triangulation_data_structure_3<Vb, Fb>; +using Triangulation_3 = CGAL::Regular_triangulation_3<Gt,Tds>; +using Alpha_shape_3 = CGAL::Alpha_shape_3<Triangulation_3>; + +// From file type definition +using Point_3 = Gt::Bare_point; +using Weighted_point_3 = Gt::Weighted_point; + +// filtration with alpha values needed type definition +using Alpha_value_type = Alpha_shape_3::FT; +using Object = CGAL::Object; +using Dispatch = CGAL::Dispatch_output_iterator< + CGAL::cpp11::tuple<Object, Alpha_value_type>, + CGAL::cpp11::tuple<std::back_insert_iterator< std::vector<Object> >, + std::back_insert_iterator< std::vector<Alpha_value_type> > > >; +using Cell_handle = Alpha_shape_3::Cell_handle; +using Facet = Alpha_shape_3::Facet; +using Edge_3 = Alpha_shape_3::Edge; +using Vertex_handle = Alpha_shape_3::Vertex_handle; +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>; +using Simplex_tree_vector_vertex = std::vector< Simplex_tree_vertex >; +using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology< + ST, Gudhi::persistent_cohomology::Field_Zp >; + +void usage(char * const progName) { + std::cerr << "Usage: " << progName << + " path_to_file_graph path_to_weight_file coeff_field_characteristic[integer > 0] min_persistence[float >= -1.0]\n"; + exit(-1); +} + +int main(int argc, char * const argv[]) { + // program args management + if (argc != 5) { + std::cerr << "Error: Number of arguments (" << argc << ") 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]); + // Read the OFF file (input file name given as parameter) and triangulate points + Gudhi::Points_3D_off_reader<Point_3> off_reader(offInputFile); + // Check the read operation was correct + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << offInputFile << std::endl; + usage(argv[0]); + } + + // Retrieve the triangulation + std::vector<Point_3> lp = off_reader.get_point_cloud(); + + // Read weights information from file + std::ifstream weights_ifstr(argv[2]); + std::vector<Weighted_point_3> wp; + if (weights_ifstr.good()) { + double weight = 0.0; + std::size_t index = 0; + // Attempt read the weight in a double format, return false if it fails + while((weights_ifstr >> weight) && (index < lp.size())) + { + wp.push_back(Weighted_point_3(lp[index], weight)); + index++; + } + if (index != lp.size()) { + std::cerr << "Bad number of weights in file " << argv[2] << std::endl; + usage(argv[0]); + } + } else { + std::cerr << "Unable to read file " << argv[2] << std::endl; + usage(argv[0]); + } + + // alpha shape construction from points. CGAL has a strange behavior in REGULARIZED mode. + Alpha_shape_3 as(lp.begin(), lp.end(), 0, Alpha_shape_3::GENERAL); +#ifdef DEBUG_TRACES + std::cout << "Alpha shape computed in GENERAL mode" << std::endl; +#endif // DEBUG_TRACES + + // filtration with alpha values from alpha shape + std::vector<Object> the_objects; + std::vector<Alpha_value_type> the_alpha_values; + + Dispatch disp = CGAL::dispatch_output<Object, Alpha_value_type>(std::back_inserter(the_objects), + std::back_inserter(the_alpha_values)); + + as.filtration_with_alpha_values(disp); +#ifdef DEBUG_TRACES + std::cout << "filtration_with_alpha_values returns : " << the_objects.size() << " objects" << std::endl; +#endif // DEBUG_TRACES + + Alpha_shape_3::size_type count_vertices = 0; + Alpha_shape_3::size_type count_edges = 0; + Alpha_shape_3::size_type count_facets = 0; + Alpha_shape_3::size_type count_cells = 0; + + // Loop on objects vector + Vertex_list vertex_list; + ST simplex_tree; + Alpha_shape_simplex_tree_map map_cgal_simplex_tree; + std::vector<Alpha_value_type>::iterator the_alpha_value_iterator = the_alpha_values.begin(); + int dim_max = 0; + Filtration_value filtration_max = 0.0; + for (auto object_iterator : the_objects) { + // Retrieve Alpha shape vertex list from object + if (const Cell_handle * cell = CGAL::object_cast<Cell_handle>(&object_iterator)) { + vertex_list = from_cell<Vertex_list, Cell_handle>(*cell); + count_cells++; + if (dim_max < 3) { + // Cell is of dim 3 + dim_max = 3; + } + } else if (const Facet * facet = CGAL::object_cast<Facet>(&object_iterator)) { + vertex_list = from_facet<Vertex_list, Facet>(*facet); + count_facets++; + if (dim_max < 2) { + // Facet is of dim 2 + dim_max = 2; + } + } else if (const Edge_3 * edge = CGAL::object_cast<Edge_3>(&object_iterator)) { + vertex_list = from_edge<Vertex_list, Edge_3>(*edge); + count_edges++; + if (dim_max < 1) { + // Edge_3 is of dim 1 + dim_max = 1; + } + } else if (const Alpha_shape_3::Vertex_handle * vertex = + CGAL::object_cast<Alpha_shape_3::Vertex_handle>(&object_iterator)) { + count_vertices++; + vertex_list = from_vertex<Vertex_list, Vertex_handle>(*vertex); + } + // Construction of the vector of simplex_tree vertex from list of alpha_shapes vertex + Simplex_tree_vector_vertex the_simplex_tree; + for (auto the_alpha_shape_vertex : vertex_list) { + Alpha_shape_simplex_tree_map::iterator the_map_iterator = map_cgal_simplex_tree.find(the_alpha_shape_vertex); + if (the_map_iterator == map_cgal_simplex_tree.end()) { + // alpha shape not found + Simplex_tree_vertex vertex = map_cgal_simplex_tree.size(); +#ifdef DEBUG_TRACES + std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] not found - insert " << vertex << std::endl; +#endif // DEBUG_TRACES + the_simplex_tree.push_back(vertex); + map_cgal_simplex_tree.insert(Alpha_shape_simplex_tree_pair(the_alpha_shape_vertex, vertex)); + } else { + // alpha shape found + Simplex_tree_vertex vertex = the_map_iterator->second; +#ifdef DEBUG_TRACES + std::cout << "vertex [" << the_alpha_shape_vertex->point() << "] found in " << vertex << std::endl; +#endif // DEBUG_TRACES + the_simplex_tree.push_back(vertex); + } + } + // Construction of the simplex_tree + Filtration_value filtr = /*std::sqrt*/(*the_alpha_value_iterator); +#ifdef DEBUG_TRACES + std::cout << "filtration = " << filtr << std::endl; +#endif // DEBUG_TRACES + if (filtr > filtration_max) { + filtration_max = filtr; + } + simplex_tree.insert_simplex(the_simplex_tree, filtr); + if (the_alpha_value_iterator != the_alpha_values.end()) + ++the_alpha_value_iterator; + else + std::cout << "This shall not happen" << std::endl; + } + simplex_tree.set_filtration(filtration_max); + simplex_tree.set_dimension(dim_max); + +#ifdef DEBUG_TRACES + std::cout << "vertices \t\t" << count_vertices << std::endl; + std::cout << "edges \t\t" << count_edges << std::endl; + std::cout << "facets \t\t" << count_facets << std::endl; + std::cout << "cells \t\t" << count_cells << std::endl; + + + std::cout << "Information of the Simplex Tree: " << std::endl; + std::cout << " Number of vertices = " << simplex_tree.num_vertices() << " "; + std::cout << " Number of simplices = " << simplex_tree.num_simplices() << std::endl << std::endl; + std::cout << " Dimension = " << simplex_tree.dimension() << " "; + std::cout << " filtration = " << simplex_tree.filtration() << std::endl << std::endl; +#endif // DEBUG_TRACES + +#ifdef DEBUG_TRACES + std::cout << "Iterator on vertices: " << std::endl; + for (auto vertex : simplex_tree.complex_vertex_range()) { + std::cout << vertex << " "; + } +#endif // DEBUG_TRACES + + // Sort the simplices in the order of the filtration + simplex_tree.initialize_filtration(); + + std::cout << "Simplex_tree dim: " << simplex_tree.dimension() << std::endl; + // Compute the persistence diagram of the complex + Persistent_cohomology pcoh(simplex_tree, true); + // initializes the coefficient field for homology + pcoh.init_coefficients(coeff_field_characteristic); + + pcoh.compute_persistent_cohomology(min_persistence); + + pcoh.output_diagram(); + + return 0; +} diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h index b3339b7d..672fda48 100644 --- a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h +++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology.h @@ -603,7 +603,7 @@ class Persistent_cohomology { */ std::vector<int> betti_numbers() const { // Init Betti numbers vector with zeros until Simplicial complex dimension - std::vector<int> betti_numbers(cpx_->dimension(), 0); + std::vector<int> betti_numbers(dim_max_, 0); for (auto pair : persistent_pairs_) { // Count never ended persistence intervals @@ -642,8 +642,7 @@ class Persistent_cohomology { */ std::vector<int> persistent_betti_numbers(Filtration_value from, Filtration_value to) const { // Init Betti numbers vector with zeros until Simplicial complex dimension - std::vector<int> betti_numbers(cpx_->dimension(), 0); - + std::vector<int> betti_numbers(dim_max_, 0); for (auto pair : persistent_pairs_) { // Count persistence intervals that covers the given interval // null_simplex test : if the function is called with to=+infinity, we still get something useful. And it will diff --git a/src/Rips_complex/concept/Simplicial_complex_for_rips.h b/src/Rips_complex/concept/SimplicialComplexForRips.h index dc871177..7dab0615 100644 --- a/src/Rips_complex/concept/Simplicial_complex_for_rips.h +++ b/src/Rips_complex/concept/SimplicialComplexForRips.h @@ -31,11 +31,10 @@ namespace rips_complex { * complex, that can be created from a `Rips_complex`. The only available model for the moment is the `Simplex_tree`. */ struct SimplicialComplexForRips { - /** \brief Handle to specify the simplex filtration value. */ + /** \brief Type used to store the filtration values of the simplicial complex. */ typedef unspecified Filtration_value; - /** \brief Inserts a given range `Gudhi::rips_complex::Rips_complex::OneSkeletonGraph` in the simplicial - * complex. */ + /** \brief Inserts a given `Gudhi::rips_complex::Rips_complex::OneSkeletonGraph` in the simplicial complex. */ template<class OneSkeletonGraph> void insert_graph(const OneSkeletonGraph& skel_graph); diff --git a/src/Rips_complex/doc/COPYRIGHT b/src/Rips_complex/doc/COPYRIGHT new file mode 100644 index 00000000..594b7d03 --- /dev/null +++ b/src/Rips_complex/doc/COPYRIGHT @@ -0,0 +1,19 @@ +The files of this directory are 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) 2015 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/>. diff --git a/src/Rips_complex/doc/Intro_rips_complex.h b/src/Rips_complex/doc/Intro_rips_complex.h index 64fd34bc..8e374c09 100644 --- a/src/Rips_complex/doc/Intro_rips_complex.h +++ b/src/Rips_complex/doc/Intro_rips_complex.h @@ -48,8 +48,10 @@ namespace rips_complex { * 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 when required. + * 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" * @@ -57,6 +59,10 @@ namespace rips_complex { * 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 @@ -68,7 +74,7 @@ namespace rips_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 + * When launching (Rips maximal distance between 2 points is 12.0, is expanded until dimension 1 - one skeleton graph * in other words): * * \code $> ./oneskeletonripspoints @@ -85,7 +91,7 @@ namespace rips_complex { * Then it creates a `Simplex_tree` with it. * * - * Then, it is asked to display information about the rips complex. + * Then, it is asked to display information about the Rips complex. * * \include Rips_complex/example_rips_complex_from_off_file.cpp * @@ -111,7 +117,7 @@ namespace rips_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 + * When launching (Rips maximal distance between 2 points is 1.0, is expanded until dimension 1 - one skeleton graph * with other words): * * \code $> ./oneskeletonripsdistance @@ -127,7 +133,7 @@ namespace rips_complex { * Then it creates a `Simplex_tree` with it. * * - * Then, it is asked to display information about the rips complex. + * Then, it is asked to display information about the Rips complex. * * \include Rips_complex/example_rips_complex_from_csv_distance_matrix_file.cpp * 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 index 90bd8e38..bbc3c755 100644 --- 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 @@ -29,7 +29,7 @@ int main() { distances.push_back({0.11, 0.39, 0.97, 0.30}); // ---------------------------------------------------------------------------- - // Init of a rips complex from points + // Init of a Rips complex from points // ---------------------------------------------------------------------------- double threshold = 1.0; Rips_complex rips_complex_from_points(distances, threshold); @@ -37,13 +37,13 @@ int main() { Simplex_tree stree; rips_complex_from_points.create_complex(stree, 1); // ---------------------------------------------------------------------------- - // Display information about the one skeleton rips complex + // 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::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 << " ( "; 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 index 5d1216a0..3fd69ebc 100644 --- a/src/Rips_complex/example/example_one_skeleton_rips_from_points.cpp +++ b/src/Rips_complex/example/example_one_skeleton_rips_from_points.cpp @@ -24,7 +24,7 @@ int main() { points.push_back({9.0, 17.0}); // ---------------------------------------------------------------------------- - // Init of a rips complex from points + // Init of a Rips complex from points // ---------------------------------------------------------------------------- double threshold = 12.0; Rips_complex rips_complex_from_points(points, threshold, Euclidean_distance()); @@ -32,13 +32,13 @@ int main() { Simplex_tree stree; rips_complex_from_points.create_complex(stree, 1); // ---------------------------------------------------------------------------- - // Display information about the one skeleton rips complex + // 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::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 << " ( "; 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 index cc6c3a33..7ae8126f 100644 --- 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 @@ -1,5 +1,5 @@ #include <gudhi/Rips_complex.h> -// to construct Rips_complex from a OFF file of points +// to construct Rips_complex from a csv file representing a distance matrix #include <gudhi/reader_utils.h> #include <gudhi/Simplex_tree.h> #include <gudhi/distance_functions.h> @@ -29,7 +29,7 @@ int main(int argc, char **argv) { using Distance_matrix = std::vector<std::vector<Filtration_value>>; // ---------------------------------------------------------------------------- - // Init of a rips complex from a distance matrix in a csv file + // 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); @@ -50,13 +50,13 @@ int main(int argc, char **argv) { std::ostream output_stream(streambufffer); // ---------------------------------------------------------------------------- - // Display information about the rips complex + // 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]:" << + 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 << " ( "; 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 index b6c961d0..a1e4e255 100644 --- a/src/Rips_complex/example/example_rips_complex_from_off_file.cpp +++ b/src/Rips_complex/example/example_rips_complex_from_off_file.cpp @@ -29,7 +29,7 @@ int main(int argc, char **argv) { using Rips_complex = Gudhi::rips_complex::Rips_complex<Filtration_value>; // ---------------------------------------------------------------------------- - // Init of a rips complex from an OFF file + // 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()); @@ -49,13 +49,13 @@ int main(int argc, char **argv) { std::ostream output_stream(streambufffer); // ---------------------------------------------------------------------------- - // Display information about the rips complex + // 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]:" << + 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 << " ( "; diff --git a/src/Rips_complex/example/full_skeleton_rips_for_doc.txt b/src/Rips_complex/example/full_skeleton_rips_for_doc.txt index 319931e0..55de4ab8 100644 --- a/src/Rips_complex/example/full_skeleton_rips_for_doc.txt +++ b/src/Rips_complex/example/full_skeleton_rips_for_doc.txt @@ -1,5 +1,5 @@ Rips complex is of dimension 3 - 24 simplices - 7 vertices. -Iterator on rips complex simplices in the filtration order, with [filtration value]: +Iterator on Rips complex simplices in the filtration order, with [filtration value]: ( 0 ) -> [0] ( 1 ) -> [0] ( 2 ) -> [0] diff --git a/src/Rips_complex/example/one_skeleton_rips_for_doc.txt b/src/Rips_complex/example/one_skeleton_rips_for_doc.txt index b0e25cc5..706512a5 100644 --- a/src/Rips_complex/example/one_skeleton_rips_for_doc.txt +++ b/src/Rips_complex/example/one_skeleton_rips_for_doc.txt @@ -1,5 +1,5 @@ Rips complex is of dimension 1 - 18 simplices - 7 vertices. -Iterator on rips complex simplices in the filtration order, with [filtration value]: +Iterator on Rips complex simplices in the filtration order, with [filtration value]: ( 0 ) -> [0] ( 1 ) -> [0] ( 2 ) -> [0] diff --git a/src/Rips_complex/include/gudhi/Rips_complex.h b/src/Rips_complex/include/gudhi/Rips_complex.h index f0f39db8..1e4b76a7 100644 --- a/src/Rips_complex/include/gudhi/Rips_complex.h +++ b/src/Rips_complex/include/gudhi/Rips_complex.h @@ -51,7 +51,7 @@ namespace rips_complex { * 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 must meet `SimplicialComplexForRips` concept. + * \tparam Filtration_value is the type used to store the filtration values of the simplicial complex. */ template<typename Filtration_value> class Rips_complex { @@ -70,31 +70,31 @@ class Rips_complex { /** \brief Rips_complex constructor from a list of points. * * @param[in] points Range of points. - * @param[in] threshold rips value. + * @param[in] threshold Rips value. * @param[in] distance distance function that returns a `Filtration_value` from 2 given points. * - * \tparam InputPointRange must be a range for which `std::begin` and `std::end` return input iterators on a + * \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 `InputPointRange`, and that returns a `Filtration_value`. + * `Point` is a point from the `ForwardPointRange`, and that returns a `Filtration_value`. */ - template<typename InputPointRange, typename Distance > - Rips_complex(const InputPointRange& points, Filtration_value threshold, Distance distance) { - compute_proximity_graph<InputPointRange, Distance >(points, threshold, distance); + 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. + * @param[in] threshold Rips value. * - * \tparam InputDistanceRange 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 \leqslant j \leqslant + * \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 InputDistanceRange> - Rips_complex(const InputDistanceRange& distance_matrix, Filtration_value threshold) { + 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];}); } @@ -105,7 +105,7 @@ class Rips_complex { * \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. + * @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. * */ @@ -126,14 +126,14 @@ class Rips_complex { * 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 InputPointRange furnishes `.begin()` and `.end()` + * \tparam ForwardPointRange furnishes `.begin()` and `.end()` * methods. * * \tparam Distance furnishes `operator()(const Point& p1, const Point& p2)`, where - * `Point` is a point from the `InputPointRange`, and that returns a `Filtration_value`. + * `Point` is a point from the `ForwardPointRange`, and that returns a `Filtration_value`. */ - template< typename InputPointRange, typename Distance > - void compute_proximity_graph(const InputPointRange& points, Filtration_value threshold, + 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; @@ -144,7 +144,7 @@ class Rips_complex { // -------------------------------------------------------------------------------------------- // 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) { + 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); @@ -153,7 +153,6 @@ class Rips_complex { edges_fil.push_back(fil); } } - ++idx_u; } // -------------------------------------------------------------------------------------------- diff --git a/src/Rips_complex/test/test_rips_complex.cpp b/src/Rips_complex/test/test_rips_complex.cpp index 1bdd0512..ae68ba0d 100644 --- a/src/Rips_complex/test/test_rips_complex.cpp +++ b/src/Rips_complex/test/test_rips_complex.cpp @@ -51,12 +51,12 @@ bool are_almost_the_same(float a, float b) { BOOST_AUTO_TEST_CASE(RIPS_DOC_OFF_file) { // ---------------------------------------------------------------------------- // - // Init of a rips complex from a 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=" << + std::cout << "========== OFF FILE NAME = " << off_file_name << " - Rips threshold=" << rips_threshold << "==========" << std::endl; Gudhi::Points_off_reader<Point> off_reader(off_file_name); @@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(Rips_complex_from_points) { points.push_back(Point(coords.begin(), coords.end())); // ---------------------------------------------------------------------------- - // Init of a rips complex from the list of points + // Init of a Rips complex from the list of points // ---------------------------------------------------------------------------- Rips_complex rips_complex_from_points(points, 2.0, Custom_square_euclidean_distance()); @@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(Rips_complex_from_points) { 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; + 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++; @@ -236,12 +236,12 @@ BOOST_AUTO_TEST_CASE(Rips_complex_from_points) { BOOST_AUTO_TEST_CASE(Rips_doc_csv_file) { // ---------------------------------------------------------------------------- // - // Init of a rips complex from a OFF 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=" << + 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); @@ -332,12 +332,12 @@ BOOST_AUTO_TEST_CASE(Rips_doc_csv_file) { BOOST_AUTO_TEST_CASE(Rips_create_complex_throw) { // ---------------------------------------------------------------------------- // - // Init of a rips complex from a 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=" << + std::cout << "========== OFF FILE NAME = " << off_file_name << " - Rips threshold=" << rips_threshold << "==========" << std::endl; Gudhi::Points_off_reader<Point> off_reader(off_file_name); diff --git a/src/Simplex_tree/doc/COPYRIGHT b/src/Simplex_tree/doc/COPYRIGHT new file mode 100644 index 00000000..34345bef --- /dev/null +++ b/src/Simplex_tree/doc/COPYRIGHT @@ -0,0 +1,19 @@ +The files of this directory are 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) 2015 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/>. diff --git a/src/Skeleton_blocker/doc/COPYRIGHT b/src/Skeleton_blocker/doc/COPYRIGHT new file mode 100644 index 00000000..1de850d7 --- /dev/null +++ b/src/Skeleton_blocker/doc/COPYRIGHT @@ -0,0 +1,18 @@ +The files of this directory are part of the Gudhi Library. The Gudhi library +(Geometric Understanding in Higher Dimensions) is a generic C++ library for +computational topology. + +Author(s): David Salinas +Copyright (C) 2015 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/>. diff --git a/src/Tangential_complex/doc/COPYRIGHT b/src/Tangential_complex/doc/COPYRIGHT new file mode 100644 index 00000000..c4df0f64 --- /dev/null +++ b/src/Tangential_complex/doc/COPYRIGHT @@ -0,0 +1,19 @@ +The files of this directory are part of the Gudhi Library. The Gudhi library +(Geometric Understanding in Higher Dimensions) is a generic C++ library for +computational topology. + +Author(s): Clement Jamin + +Copyright (C) 2015 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/>. diff --git a/src/Witness_complex/concept/Simplicial_complex_for_witness.h b/src/Witness_complex/concept/SimplicialComplexForWitness.h index caaf0db6..d78cc83f 100644 --- a/src/Witness_complex/concept/Simplicial_complex_for_witness.h +++ b/src/Witness_complex/concept/SimplicialComplexForWitness.h @@ -27,57 +27,70 @@ namespace Gudhi { namespace witness_complex { -/** \brief The concept Simplicial_Complex describes the requirements +/** \brief The concept SimplicialComplexForWitness describes the requirements * for a type to implement a simplicial complex, - * used for example to build a 'Witness_complex'. + * used for example to build a Witness_complex or Strong_witness_complex. */ struct SimplicialComplexForWitness { /** Handle to specify a simplex. */ typedef unspecified Simplex_handle; - /** Handle to specify a vertex. Must be a non-negative integer. */ - typedef unspecified Vertex_handle; + // /** Handle to specify a vertex. Must be a non-negative integer. */ + // typedef unspecified Vertex_handle; - /** Returns a Simplex_hanlde that is different from all simplex handles + /** \brief Returns a Simplex_hanlde that is different from all simplex handles * of the simplices. */ Simplex_handle null_simplex(); - /** \brief Iterator over the simplices of the complex, - * in an arbitrary order. - * - * 'value_type' must be 'Simplex_handle'.*/ - typedef unspecified Complex_simplex_range; - - /** - * \brief Returns a range over all the simplices of a - * complex. + /** Returns the number of vertices in the simplicial complex */ - Complex_simplex_range complex_simplex_range(); - - /** \brief Iterator over vertices of a simplex. - * - * 'value type' must be 'Vertex_handle'.*/ - typedef unspecified Simplex_vertex_range; - - /** \brief Returns a range over vertices of a given - * simplex. */ - Simplex_vertex_range simplex_vertex_range(Simplex_handle const & simplex); - + std::size_t num_vertices(); + /** \brief Return type of an insertion of a simplex */ typedef unspecified Insertion_result_type; /** \brief Inserts a simplex with vertices from a given range * 'vertex_range' in the simplicial complex. + * The function is only used in Witness_complex class + * and by construction, it is not necessary to check if + * the faces are in the simplicial complex before insertion. + * The simplex is given the filtration value 'filtration'. + * Filtration_value should be convertible from double. + * The return type is not used. * */ template< typedef Input_vertex_range > - Insertion_result_type insert_simplex(Input_vertex_range const & vertex_range); + Insertion_result_type insert_simplex(Input_vertex_range const & vertex_range, Filtration_value filtration); + /** \brief Inserts a simplex and all its faces + * with vertices from a given range + * 'vertex_range' in the simplicial complex. + * The function is only used in Strong_witness_complex class. + * All inserted simplices are given the filtration + * value 'filtration'. + * Filtration_value should be convertible from double. + * The return type is not used. + */ + + template< typedef Input_vertex_range, + typedef Filtration_value> + Insertion_result_type insert_simplex_and_subfaces(Input_vertex_range const & vertex_range, Filtration_value filtration); + /** \brief Finds a simplex with vertices given by a range * * If a simplex exists, its Simplex_handle is returned. * Otherwise null_simplex() is returned. */ template< typedef Input_vertex_range > Simplex_handle find(Input_vertex_range const & vertex_range); + + /** \brief Sets the dimension of the simplicial complex to + * 'dimension'. + */ + void set_dimension(int dimension); + + /** \brief Returns the filtration of the simplex given by + * the simplex handle 'sh'. + */ + double filtration(Simplex_handle sh); }; } // namespace witness_complex diff --git a/src/Witness_complex/doc/COPYRIGHT b/src/Witness_complex/doc/COPYRIGHT new file mode 100644 index 00000000..7d032c87 --- /dev/null +++ b/src/Witness_complex/doc/COPYRIGHT @@ -0,0 +1,19 @@ +The files of this directory are part of the Gudhi Library. The Gudhi library +(Geometric Understanding in Higher Dimensions) is a generic C++ library for +computational topology. + +Author(s): Siargey Kachanovich + +Copyright (C) 2015 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/>. diff --git a/src/Witness_complex/doc/Witness_complex_doc.h b/src/Witness_complex/doc/Witness_complex_doc.h index 60dfd27b..171a185f 100644 --- a/src/Witness_complex/doc/Witness_complex_doc.h +++ b/src/Witness_complex/doc/Witness_complex_doc.h @@ -8,31 +8,106 @@ \image html "Witness_complex_representation.png" "Witness complex representation" - \section Definitions + \section witnessdefinitions Definitions - Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$: + Witness complex is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$: \li \f$W\f$ set of **witnesses** and - \li \f$L \subseteq W\f$ set of **landmarks**. + \li \f$L\f$ set of **landmarks**. - The simplices are based on landmarks - and a simplex belongs to the witness complex if and only if it is witnessed, that is: + Even though often the set of landmarks \f$L\f$ is a subset of the set of witnesses \f$ W\f$, it is not a requirement for the current implementation. - \f$ \sigma \subset L \f$ is witnessed if there exists a point \f$w \in W\f$ such that - w is closer to the vertices of \f$ \sigma \f$ than other points in \f$ L \f$ and all of its faces are witnessed as well. - - The data structure is described in \cite boissonnatmariasimplextreealgorithmica . + Landmarks are the vertices of the simplicial complex + and witnesses help to decide on which simplices are inserted via a predicate "is witnessed". - \section Implementation + De Silva and Carlsson in their paper \cite de2004topological differentiate **weak witnessing** and **strong witnessing**: - The principal class of this module is Gudhi::Witness_complex. + - *weak*: \f$ \sigma \subset L \f$ is witnessed by \f$ w \in W\f$ if \f$ \forall l \in \sigma,\ \forall l' \in \mathbf{L \setminus \sigma},\ d(w,l) \leq d(w,l') \f$ + - *strong*: \f$ \sigma \subset L \f$ is witnessed by \f$ w \in W\f$ if \f$ \forall l \in \sigma,\ \forall l' \in \mathbf{L},\ d(w,l) \leq d(w,l') \f$ - In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, where each row represents a witness and consists of landmarks sorted by distance to this witness. - This table can be constructed by two additional classes Landmark_choice_by_furthest_point and Landmark_choice_by_random_point also included in the module. + where \f$ d(.,.) \f$ is a distance function. - *\image html "bench_Cy8.png" "Running time as function on number of landmarks" width=10cm - *\image html "bench_sphere.png" "Running time as function on number of witnesses for |L|=300" width=10cm + Both definitions can be relaxed by a real value \f$\alpha\f$: + + - *weak*: \f$ \sigma \subset L \f$ is \f$\alpha\f$-witnessed by \f$ w \in W\f$ if \f$ \forall l \in \sigma,\ \forall l' \in \mathbf{L \setminus \sigma},\ d(w,l)^2 \leq d(w,l')^2 + \alpha^2 \f$ + - *strong*: \f$ \sigma \subset L \f$ is \f$\alpha\f$-witnessed by \f$ w \in W\f$ if \f$ \forall l \in \sigma,\ \forall l' \in \mathbf{L},\ d(w,l)^2 \leq d(w,l')^2 + \alpha^2 \f$ + + which leads to definitions of **weak relaxed witness complex** (or just relaxed witness complex for short) and **strong relaxed witness complex** respectively. + + \image html "swit.svg" "Strongly witnessed simplex" + + In particular case of 0-relaxation, weak complex corresponds to **witness complex** introduced in \cite de2004topological, whereas 0-relaxed strong witness complex consists of just vertices and is not very interesting. + Hence for small relaxation weak version is preferable. + However, to capture the homotopy type (for example using Gudhi::persistent_cohomology::Persistent_cohomology) it is often necessary to work with higher filtration values. In this case strong relaxed witness complex is faster to compute and offers similar results. + + \section witnessimplementation Implementation + The two complexes described above are implemented in the corresponding classes + - Gudhi::witness_complex::Witness_complex + - Gudhi::witness_complex::Euclidean_witness_complex + - Gudhi::witness_complex::Strong_witness_complex + - Gudhi::witness_complex::Euclidean_strong_witness_complex + + The construction of the Euclidean versions of complexes follow the same scheme: + 1. Construct a search tree on landmarks (for that Gudhi::spatial_searching::Kd_tree_search is used internally). + 2. Construct lists of nearest landmarks for each witness (special structure Gudhi::witness_complex::Active_witness is used internally). + 3. Construct the witness complex for nearest landmark lists. + + In the non-Euclidean classes, the lists of nearest landmarks are supposed to be given as input. + + The constructors take on the steps 1 and 2, while the function 'create_complex' executes the step 3. + + \section witnessexample1 Example 1: Constructing weak relaxed witness complex from an off file + + Let's start with a simple example, which reads an off point file and computes a weak witness complex. + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Euclidean_witness_complex.h> +#include <gudhi/pick_n_random_points.h> +#include <gudhi/Points_off_io.h> + +#include <CGAL/Epick_d.h> + +#include <string> +#include <vector> + +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< Point_d > Point_vector; + +int main(int argc, char * const argv[]) { + std::string file_name = argv[1]; + int nbL = atoi(argv[2]), lim_dim = atoi(argv[4]); + double alpha2 = atof(argv[3]); + Gudhi::Simplex_tree<> simplex_tree; + + // Read the point file + Point_vector point_vector, landmarks; + Gudhi::Points_off_reader<Point_d> off_reader(file_name); + point_vector = Point_vector(off_reader.get_point_cloud()); + + // Choose landmarks + Gudhi::subsampling::pick_n_random_points(point_vector, nbL, std::back_inserter(landmarks)); + + // Compute witness complex + Witness_complex witness_complex(landmarks, + point_vector); + + witness_complex.create_complex(simplex_tree, alpha2, lim_dim); +} + + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + \section witnessexample2 Example2: Computing persistence using strong relaxed witness complex + + Here is an example of constructing a strong witness complex filtration and computing persistence on it: + + \include Witness_complex/example_strong_witness_persistence.cpp \copyright GNU General Public License v3. diff --git a/src/Witness_complex/doc/Witness_complex_representation.ipe b/src/Witness_complex/doc/Witness_complex_representation.ipe new file mode 100644 index 00000000..f9c45d5d --- /dev/null +++ b/src/Witness_complex/doc/Witness_complex_representation.ipe @@ -0,0 +1,280 @@ +<?xml version="1.0"?> +<!DOCTYPE ipe SYSTEM "ipe.dtd"> +<ipe version="70107" creator="Ipe 7.1.10"> +<info created="D:20161010162425" modified="D:20161010162828"/> +<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="arrow/ptarc(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/fptarc(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="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="Large" value="\Large"/> +<textsize name="LARGE" value="\LARGE"/> +<textsize name="huge" value="\huge"/> +<textsize name="Huge" value="\Huge"/> +<textsize name="small" value="\small"/> +<textsize name="footnote" value="\footnotesize"/> +<textsize name="tiny" value="\tiny"/> +<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"/> +<opacity name="10%" value="0.1"/> +<opacity name="30%" value="0.3"/> +<opacity name="50%" value="0.5"/> +<opacity name="75%" value="0.75"/> +<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"/> +<use layer="alpha" name="mark/fdisk(sfx)" pos="288 672" size="normal" stroke="darkblue" fill="white"/> +<path stroke="darkblue"> +48.8262 0 0 48.8262 288 672 e +</path> +<text transformations="translations" pos="292 676" stroke="darkblue" type="label" width="6.559" height="4.289" depth="0" valign="baseline">$\omega$</text> +<path stroke="black"> +284 720 m +280 624 l +268 648 l +h +</path> +<use name="mark/fdisk(sfx)" pos="284 720" size="normal" stroke="black" fill="white"/> +<use name="mark/fdisk(sfx)" pos="268 648" size="normal" stroke="black" fill="white"/> +<use name="mark/fdisk(sfx)" pos="280 624" size="normal" stroke="black" fill="white"/> +<text matrix="1 0 0 1 0 8" transformations="translations" pos="268 672" stroke="black" type="label" width="6.05" height="4.289" depth="0" valign="baseline">$\sigma$</text> +<use name="mark/fdisk(sfx)" pos="344 672" size="normal" stroke="black" fill="white"/> +<use name="mark/fdisk(sfx)" pos="356 716" size="normal" stroke="black" fill="white"/> +<use name="mark/fdisk(sfx)" pos="364 628" size="normal" stroke="black" fill="white"/> +<use name="mark/fdisk(sfx)" pos="244 708" size="normal" stroke="black" fill="white"/> +<use name="mark/fdisk(sfx)" pos="196 632" size="normal" stroke="black" fill="white"/> +<use name="mark/fdisk(sfx)" pos="200 696" size="normal" stroke="black" fill="white"/> +<use name="mark/fdisk(sfx)" pos="168 716" size="normal" stroke="black" fill="white"/> +</page> +</ipe> diff --git a/src/Witness_complex/doc/Witness_complex_representation.png b/src/Witness_complex/doc/Witness_complex_representation.png Binary files differindex 1d31a490..16e0504e 100644 --- a/src/Witness_complex/doc/Witness_complex_representation.png +++ b/src/Witness_complex/doc/Witness_complex_representation.png diff --git a/src/Witness_complex/doc/swit.svg b/src/Witness_complex/doc/swit.svg new file mode 100644 index 00000000..6ffb5fff --- /dev/null +++ b/src/Witness_complex/doc/swit.svg @@ -0,0 +1,1303 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:ns0="http://www.iki.fi/pav/software/textext/" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="113.73116mm" + height="84.14254mm" + viewBox="0 0 402.98441 298.14286" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="swit.svg"> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.98994949" + inkscape:cx="402.72174" + inkscape:cy="258.46971" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1366" + inkscape:window-height="704" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lend" + style="overflow:visible" + inkscape:isstock="true"> + <path + inkscape:connector-curvature="0" + id="path5009" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z" + style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1pt;stroke-opacity:1" + transform="matrix(-0.8,0,0,-0.8,-10,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lend-8" + style="overflow:visible" + inkscape:isstock="true"> + <path + inkscape:connector-curvature="0" + id="path5009-5" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z" + style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1pt;stroke-opacity:1" + transform="matrix(-0.8,0,0,-0.8,-10,0)" /> + </marker> + </defs> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + transform="translate(-130.29351,-300.82484)" + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="148.57143" + cy="449.89627" + cx="338.71756" + id="path4136" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <path + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="m 318.19805,571.02449 0,-94.95433 -64.64976,-92.42896 164.14979,-30.80966 42.4264,120.71323 -141.92643,3.03046 100.0051,-123.23861 z" + id="path4301" + inkscape:connector-curvature="0" /> + <path + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="m 318.70313,571.52957 -65.65992,-187.3833 206.5762,88.89343 z" + id="path4303" + inkscape:connector-curvature="0" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="450.05875" + cx="338.13837" + id="path4138" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <g + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + id="g4147" + ns0:preamble="/home/siarzhuk/GitDrive/2015Gudhi/Aid/preamble.ini" + ns0:text="$w$" + transform="matrix(2.7020226,0,0,2.7020226,-261.85036,103.80999)" + style="fill:#000080"> + <defs + id="defs4149"> + <g + id="g4151"> + <symbol + id="textext-20f8880a-0" + overflow="visible" + style="overflow:visible"> + <path + id="path4154" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-20f8880a-1" + overflow="visible" + style="overflow:visible"> + <path + id="path4157" + d="M 4.609375,-3.375 C 4.65625,-3.59375 4.75,-3.96875 4.75,-4.03125 c 0,-0.171875 -0.140625,-0.265625 -0.28125,-0.265625 -0.125,0 -0.296875,0.078125 -0.375,0.28125 -0.03125,0.0625 -0.5,1.96875 -0.5625,2.234375 C 3.453125,-1.484375 3.4375,-1.3125 3.4375,-1.125 c 0,0.109375 0,0.125 0.015625,0.171875 -0.234375,0.53125 -0.53125,0.84375 -0.921875,0.84375 -0.796875,0 -0.796875,-0.734375 -0.796875,-0.90625 0,-0.3125 0.046875,-0.703125 0.515625,-1.9375 0.109375,-0.296875 0.171875,-0.4375 0.171875,-0.640625 0,-0.4375 -0.328125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 C 0.84375,-3.875 1.21875,-4.1875 1.578125,-4.1875 c 0.09375,0 0.25,0.015625 0.25,0.328125 0,0.25 -0.109375,0.53125 -0.1875,0.703125 -0.4375,1.171875 -0.546875,1.625 -0.546875,2.015625 0,0.90625 0.65625,1.25 1.40625,1.25 0.171875,0 0.640625,0 1.03125,-0.703125 0.265625,0.640625 0.953125,0.703125 1.25,0.703125 0.75,0 1.1875,-0.625 1.453125,-1.21875 0.328125,-0.78125 0.65625,-2.125 0.65625,-2.59375 0,-0.546875 -0.265625,-0.703125 -0.4375,-0.703125 -0.25,0 -0.5,0.265625 -0.5,0.484375 0,0.125 0.0625,0.1875 0.140625,0.265625 0.109375,0.109375 0.359375,0.359375 0.359375,0.84375 0,0.34375 -0.28125,1.3125 -0.546875,1.828125 -0.25,0.53125 -0.609375,0.875 -1.09375,0.875 -0.46875,0 -0.734375,-0.296875 -0.734375,-0.875 0,-0.265625 0.0625,-0.578125 0.109375,-0.71875 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + </g> + </defs> + <g + id="textext-20f8880a-2" + style="fill:#000080"> + <g + id="g4160" + style="fill:#000080;fill-opacity:1"> + <use + id="use4162" + y="134.765" + x="223.43201" + xlink:href="#textext-20f8880a-1" + width="100%" + height="100%" + style="fill:#000080" /> + </g> + </g> + </g> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="383.79077" + cx="252.85715" + id="path4138-3" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="353.07648" + cx="418.57144" + id="path4138-3-7" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="475.93362" + cx="317.85715" + id="path4138-3-0" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="570.21936" + cx="317.85715" + id="path4138-3-9" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="473.07648" + cx="459.28571" + id="path4138-3-3" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="478.07648" + cx="133.57143" + id="path4138-3-6" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="320.21936" + cx="155.71428" + id="path4138-3-06" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="340.73929" + cx="490.7774" + id="path4138-3-2" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="559.76758" + cx="490.60406" + id="path4138-3-61" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <g + id="g4147-8" + ns0:preamble="/home/siarzhuk/GitDrive/2015Gudhi/Aid/preamble.ini" + ns0:text="$w$" + transform="matrix(2.7020226,0,0,2.7020226,-152.29409,72.785446)" + style="fill:#000000"> + <defs + id="defs4149-7"> + <g + id="g4151-9"> + <symbol + id="textext-20f8880a-0-2" + overflow="visible" + style="overflow:visible"> + <path + id="path4154-0" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-20f8880a-1-2" + overflow="visible" + style="overflow:visible"> + <path + id="path4157-3" + d="M 4.609375,-3.375 C 4.65625,-3.59375 4.75,-3.96875 4.75,-4.03125 c 0,-0.171875 -0.140625,-0.265625 -0.28125,-0.265625 -0.125,0 -0.296875,0.078125 -0.375,0.28125 -0.03125,0.0625 -0.5,1.96875 -0.5625,2.234375 C 3.453125,-1.484375 3.4375,-1.3125 3.4375,-1.125 c 0,0.109375 0,0.125 0.015625,0.171875 -0.234375,0.53125 -0.53125,0.84375 -0.921875,0.84375 -0.796875,0 -0.796875,-0.734375 -0.796875,-0.90625 0,-0.3125 0.046875,-0.703125 0.515625,-1.9375 0.109375,-0.296875 0.171875,-0.4375 0.171875,-0.640625 0,-0.4375 -0.328125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 C 0.84375,-3.875 1.21875,-4.1875 1.578125,-4.1875 c 0.09375,0 0.25,0.015625 0.25,0.328125 0,0.25 -0.109375,0.53125 -0.1875,0.703125 -0.4375,1.171875 -0.546875,1.625 -0.546875,2.015625 0,0.90625 0.65625,1.25 1.40625,1.25 0.171875,0 0.640625,0 1.03125,-0.703125 0.265625,0.640625 0.953125,0.703125 1.25,0.703125 0.75,0 1.1875,-0.625 1.453125,-1.21875 0.328125,-0.78125 0.65625,-2.125 0.65625,-2.59375 0,-0.546875 -0.265625,-0.703125 -0.4375,-0.703125 -0.25,0 -0.5,0.265625 -0.5,0.484375 0,0.125 0.0625,0.1875 0.140625,0.265625 0.109375,0.109375 0.359375,0.359375 0.359375,0.84375 0,0.34375 -0.28125,1.3125 -0.546875,1.828125 -0.25,0.53125 -0.609375,0.875 -1.09375,0.875 -0.46875,0 -0.734375,-0.296875 -0.734375,-0.875 0,-0.265625 0.0625,-0.578125 0.109375,-0.71875 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + </g> + </defs> + <g + id="textext-20f8880a-2-7" + style="fill:#000000" /> + </g> + <g + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + id="g4558" + style="fill:#000080" + transform="matrix(2.7020226,0,0,2.7020226,-254.3195,202.59004)" + ns0:preamble="/home/siarzhuk/GitDrive/2015Gudhi/Aid/preamble.ini" + ns0:text="$\\sigma \\subset L$"> + <defs + id="defs4560"> + <g + id="g4562"> + <symbol + id="textext-b73c230a-0" + overflow="visible" + style="overflow:visible"> + <path + id="path4565" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-b73c230a-1" + overflow="visible" + style="overflow:visible"> + <path + id="path4568" + d="m 5.15625,-3.71875 c 0.140625,0 0.5,0 0.5,-0.34375 0,-0.234375 -0.21875,-0.234375 -0.390625,-0.234375 l -2.28125,0 c -1.5,0 -2.609375,1.640625 -2.609375,2.828125 0,0.875 0.59375,1.578125 1.5,1.578125 1.171875,0 2.5,-1.203125 2.5,-2.734375 0,-0.171875 0,-0.65625 -0.3125,-1.09375 z M 1.890625,-0.109375 C 1.390625,-0.109375 1,-0.46875 1,-1.1875 c 0,-0.296875 0.109375,-1.109375 0.46875,-1.703125 0.421875,-0.6875 1.015625,-0.828125 1.359375,-0.828125 0.828125,0 0.90625,0.65625 0.90625,0.96875 0,0.46875 -0.203125,1.28125 -0.53125,1.796875 -0.390625,0.578125 -0.9375,0.84375 -1.3125,0.84375 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-b73c230a-2" + overflow="visible" + style="overflow:visible"> + <path + id="path4571" + d="M 3.734375,-6.03125 C 3.8125,-6.390625 3.84375,-6.5 4.78125,-6.5 c 0.296875,0 0.375,0 0.375,-0.1875 0,-0.125 -0.109375,-0.125 -0.15625,-0.125 -0.328125,0 -1.140625,0.03125 -1.46875,0.03125 -0.296875,0 -1.03125,-0.03125 -1.328125,-0.03125 -0.0625,0 -0.1875,0 -0.1875,0.203125 0,0.109375 0.09375,0.109375 0.28125,0.109375 0.015625,0 0.203125,0 0.375,0.015625 0.171875,0.03125 0.265625,0.03125 0.265625,0.171875 0,0.03125 0,0.0625 -0.03125,0.1875 L 1.5625,-0.78125 c -0.09375,0.390625 -0.109375,0.46875 -0.90625,0.46875 -0.171875,0 -0.265625,0 -0.265625,0.203125 C 0.390625,0 0.484375,0 0.65625,0 l 4.625,0 C 5.515625,0 5.515625,0 5.578125,-0.171875 L 6.375,-2.328125 c 0.03125,-0.109375 0.03125,-0.125 0.03125,-0.140625 0,-0.03125 -0.03125,-0.109375 -0.109375,-0.109375 -0.09375,0 -0.109375,0.0625 -0.171875,0.21875 -0.34375,0.90625 -0.78125,2.046875 -2.5,2.046875 l -0.9375,0 c -0.140625,0 -0.171875,0 -0.21875,0 -0.109375,-0.015625 -0.140625,-0.03125 -0.140625,-0.109375 0,-0.03125 0,-0.046875 0.046875,-0.21875 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-b73c230a-3" + overflow="visible" + style="overflow:visible"> + <path + id="path4574" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-b73c230a-4" + overflow="visible" + style="overflow:visible"> + <path + id="path4577" + d="m 6.5625,-4.984375 c 0.171875,0 0.359375,0 0.359375,-0.203125 0,-0.203125 -0.1875,-0.203125 -0.359375,-0.203125 l -2.671875,0 c -1.703125,0 -3.0625,1.296875 -3.0625,2.890625 0,1.609375 1.359375,2.90625 3.0625,2.90625 l 2.671875,0 c 0.171875,0 0.359375,0 0.359375,-0.203125 C 6.921875,0 6.734375,0 6.5625,0 L 3.90625,0 c -1.546875,0 -2.6875,-1.15625 -2.6875,-2.5 0,-1.328125 1.140625,-2.484375 2.6875,-2.484375 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + </g> + </defs> + <g + id="textext-b73c230a-5"> + <g + id="g4580" + style="fill:#000000;fill-opacity:1"> + <use + id="use4582" + y="134.765" + x="223.43201" + xlink:href="#textext-b73c230a-1" + width="100%" + height="100%" /> + </g> + <g + id="g4584" + style="fill:#000000;fill-opacity:1"> + <use + id="use4586" + y="134.765" + x="232.25" + xlink:href="#textext-b73c230a-4" + width="100%" + height="100%" /> + </g> + <g + id="g4588" + style="fill:#000000;fill-opacity:1"> + <use + id="use4590" + y="134.765" + x="242.76601" + xlink:href="#textext-b73c230a-2" + width="100%" + height="100%" /> + </g> + </g> + </g> + <path + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + style="fill:#000080;fill-rule:evenodd;stroke:#000080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)" + d="m 337.85714,449.50504 148.57143,-8.57143" + id="path5000" + inkscape:connector-curvature="0" /> + <g + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + ns0:text="$\\sqrt{d(w,L)^2 + \\alpha^2}$" + ns0:preamble="/home/siarzhuk/GitDrive/2015Gudhi/Aid/preamble.ini" + transform="matrix(1.3935573,-0.10159094,0.10159094,1.3935573,55.220877,276.38005)" + style="fill:#000080;stroke:#000080" + id="g5407"> + <defs + id="defs5409"> + <g + id="g5411"> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-0"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="" + id="path5414" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-1"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="m 4.234375,11.5625 c 0.296875,0 0.3125,-0.01563 0.40625,-0.203125 l 5.453125,-11.375 c 0.07813,-0.140625 0.07813,-0.15625 0.07813,-0.1875 0,-0.109375 -0.07813,-0.203125 -0.203125,-0.203125 -0.125,0 -0.171875,0.09375 -0.21875,0.203125 L 4.609375,10.53125 2.484375,5.578125 1.09375,6.65625 1.25,6.8125 1.953125,6.265625 Z m 0,0" + id="path5417" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-2"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="" + id="path5420" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-3"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="m 5.140625,-6.8125 c 0,0 0,-0.109375 -0.125,-0.109375 -0.15625,0 -1.09375,0.09375 -1.265625,0.109375 -0.078125,0.015625 -0.140625,0.0625 -0.140625,0.1875 0,0.125 0.09375,0.125 0.234375,0.125 0.484375,0 0.5,0.0625 0.5,0.171875 L 4.3125,-6.125 3.71875,-3.765625 C 3.53125,-4.140625 3.25,-4.40625 2.796875,-4.40625 c -1.15625,0 -2.390625,1.46875 -2.390625,2.921875 0,0.9375 0.546875,1.59375 1.3125,1.59375 0.203125,0 0.703125,-0.046875 1.296875,-0.75 0.078125,0.421875 0.4375,0.75 0.90625,0.75 0.359375,0 0.578125,-0.234375 0.75,-0.546875 0.15625,-0.359375 0.296875,-0.96875 0.296875,-0.984375 0,-0.109375 -0.09375,-0.109375 -0.125,-0.109375 -0.09375,0 -0.109375,0.046875 -0.140625,0.1875 -0.171875,0.640625 -0.34375,1.234375 -0.75,1.234375 -0.28125,0 -0.296875,-0.265625 -0.296875,-0.453125 0,-0.25 0.015625,-0.3125 0.046875,-0.484375 z m -2.0625,5.625 C 3.015625,-1 3.015625,-0.984375 2.875,-0.8125 2.4375,-0.265625 2.03125,-0.109375 1.75,-0.109375 c -0.5,0 -0.640625,-0.546875 -0.640625,-0.9375 0,-0.5 0.3125,-1.71875 0.546875,-2.1875 0.3125,-0.578125 0.75,-0.953125 1.15625,-0.953125 0.640625,0 0.78125,0.8125 0.78125,0.875 0,0.0625 -0.015625,0.125 -0.03125,0.171875 z m 0,0" + id="path5423" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-4"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="M 4.609375,-3.375 C 4.65625,-3.59375 4.75,-3.96875 4.75,-4.03125 c 0,-0.171875 -0.140625,-0.265625 -0.28125,-0.265625 -0.125,0 -0.296875,0.078125 -0.375,0.28125 -0.03125,0.0625 -0.5,1.96875 -0.5625,2.234375 C 3.453125,-1.484375 3.4375,-1.3125 3.4375,-1.125 c 0,0.109375 0,0.125 0.015625,0.171875 -0.234375,0.53125 -0.53125,0.84375 -0.921875,0.84375 -0.796875,0 -0.796875,-0.734375 -0.796875,-0.90625 0,-0.3125 0.046875,-0.703125 0.515625,-1.9375 0.109375,-0.296875 0.171875,-0.4375 0.171875,-0.640625 0,-0.4375 -0.328125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 C 0.84375,-3.875 1.21875,-4.1875 1.578125,-4.1875 c 0.09375,0 0.25,0.015625 0.25,0.328125 0,0.25 -0.109375,0.53125 -0.1875,0.703125 -0.4375,1.171875 -0.546875,1.625 -0.546875,2.015625 0,0.90625 0.65625,1.25 1.40625,1.25 0.171875,0 0.640625,0 1.03125,-0.703125 0.265625,0.640625 0.953125,0.703125 1.25,0.703125 0.75,0 1.1875,-0.625 1.453125,-1.21875 0.328125,-0.78125 0.65625,-2.125 0.65625,-2.59375 0,-0.546875 -0.265625,-0.703125 -0.4375,-0.703125 -0.25,0 -0.5,0.265625 -0.5,0.484375 0,0.125 0.0625,0.1875 0.140625,0.265625 0.109375,0.109375 0.359375,0.359375 0.359375,0.84375 0,0.34375 -0.28125,1.3125 -0.546875,1.828125 -0.25,0.53125 -0.609375,0.875 -1.09375,0.875 -0.46875,0 -0.734375,-0.296875 -0.734375,-0.875 0,-0.265625 0.0625,-0.578125 0.109375,-0.71875 z m 0,0" + id="path5426" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-5"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="m 2.03125,-0.015625 c 0,-0.65625 -0.25,-1.046875 -0.640625,-1.046875 -0.328125,0 -0.53125,0.25 -0.53125,0.53125 C 0.859375,-0.265625 1.0625,0 1.390625,0 1.5,0 1.640625,-0.046875 1.734375,-0.125 1.765625,-0.15625 1.78125,-0.15625 1.78125,-0.15625 c 0.015625,0 0.015625,0 0.015625,0.140625 0,0.75 -0.34375,1.34375 -0.671875,1.671875 -0.109375,0.109375 -0.109375,0.125 -0.109375,0.15625 0,0.078125 0.046875,0.109375 0.09375,0.109375 0.109375,0 0.921875,-0.765625 0.921875,-1.9375 z m 0,0" + id="path5429" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-6"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="M 3.734375,-6.03125 C 3.8125,-6.390625 3.84375,-6.5 4.78125,-6.5 c 0.296875,0 0.375,0 0.375,-0.1875 0,-0.125 -0.109375,-0.125 -0.15625,-0.125 -0.328125,0 -1.140625,0.03125 -1.46875,0.03125 -0.296875,0 -1.03125,-0.03125 -1.328125,-0.03125 -0.0625,0 -0.1875,0 -0.1875,0.203125 0,0.109375 0.09375,0.109375 0.28125,0.109375 0.015625,0 0.203125,0 0.375,0.015625 0.171875,0.03125 0.265625,0.03125 0.265625,0.171875 0,0.03125 0,0.0625 -0.03125,0.1875 L 1.5625,-0.78125 c -0.09375,0.390625 -0.109375,0.46875 -0.90625,0.46875 -0.171875,0 -0.265625,0 -0.265625,0.203125 C 0.390625,0 0.484375,0 0.65625,0 l 4.625,0 C 5.515625,0 5.515625,0 5.578125,-0.171875 L 6.375,-2.328125 c 0.03125,-0.109375 0.03125,-0.125 0.03125,-0.140625 0,-0.03125 -0.03125,-0.109375 -0.109375,-0.109375 -0.09375,0 -0.109375,0.0625 -0.171875,0.21875 -0.34375,0.90625 -0.78125,2.046875 -2.5,2.046875 l -0.9375,0 c -0.140625,0 -0.171875,0 -0.21875,0 -0.109375,-0.015625 -0.140625,-0.03125 -0.140625,-0.109375 0,-0.03125 0,-0.046875 0.046875,-0.21875 z m 0,0" + id="path5432" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-7"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="m 4.75,-2.359375 c 0,-1.5625 -0.921875,-2.046875 -1.65625,-2.046875 -1.375,0 -2.6875,1.421875 -2.6875,2.828125 0,0.9375 0.59375,1.6875 1.625,1.6875 0.625,0 1.34375,-0.234375 2.09375,-0.84375 0.125,0.53125 0.453125,0.84375 0.90625,0.84375 0.53125,0 0.84375,-0.546875 0.84375,-0.703125 0,-0.078125 -0.0625,-0.109375 -0.125,-0.109375 -0.0625,0 -0.09375,0.03125 -0.125,0.109375 -0.1875,0.484375 -0.546875,0.484375 -0.5625,0.484375 -0.3125,0 -0.3125,-0.78125 -0.3125,-1.015625 0,-0.203125 0,-0.234375 0.109375,-0.34375 C 5.796875,-2.65625 6,-3.8125 6,-3.8125 6,-3.84375 5.984375,-3.921875 5.875,-3.921875 c -0.09375,0 -0.09375,0.03125 -0.140625,0.21875 -0.1875,0.625 -0.515625,1.375 -0.984375,1.96875 z m -0.65625,1.375 c -0.890625,0.765625 -1.65625,0.875 -2.046875,0.875 -0.59375,0 -0.90625,-0.453125 -0.90625,-1.09375 0,-0.484375 0.265625,-1.5625 0.578125,-2.0625 C 2.1875,-4 2.734375,-4.1875 3.078125,-4.1875 c 0.984375,0 0.984375,1.3125 0.984375,2.078125 0,0.375 0,0.953125 0.03125,1.125 z m 0,0" + id="path5435" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-8"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="" + id="path5438" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-9"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="m 3.296875,2.390625 c 0,-0.03125 0,-0.046875 -0.171875,-0.21875 C 1.890625,0.921875 1.5625,-0.96875 1.5625,-2.5 c 0,-1.734375 0.375,-3.46875 1.609375,-4.703125 0.125,-0.125 0.125,-0.140625 0.125,-0.171875 0,-0.078125 -0.03125,-0.109375 -0.09375,-0.109375 -0.109375,0 -1,0.6875 -1.59375,1.953125 -0.5,1.09375 -0.625,2.203125 -0.625,3.03125 0,0.78125 0.109375,1.984375 0.65625,3.125 C 2.25,1.84375 3.09375,2.5 3.203125,2.5 c 0.0625,0 0.09375,-0.03125 0.09375,-0.109375 z m 0,0" + id="path5441" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-10"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="m 2.875,-2.5 c 0,-0.765625 -0.109375,-1.96875 -0.65625,-3.109375 -0.59375,-1.21875 -1.453125,-1.875 -1.546875,-1.875 -0.0625,0 -0.109375,0.046875 -0.109375,0.109375 0,0.03125 0,0.046875 0.1875,0.234375 0.984375,0.984375 1.546875,2.5625 1.546875,4.640625 0,1.71875 -0.359375,3.46875 -1.59375,4.71875 C 0.5625,2.34375 0.5625,2.359375 0.5625,2.390625 0.5625,2.453125 0.609375,2.5 0.671875,2.5 0.765625,2.5 1.671875,1.8125 2.25,0.546875 2.765625,-0.546875 2.875,-1.65625 2.875,-2.5 Z m 0,0" + id="path5444" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-11"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="m 4.078125,-2.296875 2.78125,0 C 7,-2.296875 7.1875,-2.296875 7.1875,-2.5 7.1875,-2.6875 7,-2.6875 6.859375,-2.6875 l -2.78125,0 0,-2.796875 c 0,-0.140625 0,-0.328125 -0.203125,-0.328125 -0.203125,0 -0.203125,0.1875 -0.203125,0.328125 l 0,2.796875 -2.78125,0 c -0.140625,0 -0.328125,0 -0.328125,0.1875 0,0.203125 0.1875,0.203125 0.328125,0.203125 l 2.78125,0 0,2.796875 c 0,0.140625 0,0.328125 0.203125,0.328125 0.203125,0 0.203125,-0.1875 0.203125,-0.328125 z m 0,0" + id="path5447" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-12"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="" + id="path5450" /> + </symbol> + <symbol + style="overflow:visible" + overflow="visible" + id="textext-da5ef958-13"> + <path + inkscape:connector-curvature="0" + style="stroke:none" + d="m 3.515625,-1.265625 -0.234375,0 c -0.015625,0.15625 -0.09375,0.5625 -0.1875,0.625 -0.046875,0.046875 -0.578125,0.046875 -0.6875,0.046875 l -1.28125,0 c 0.734375,-0.640625 0.984375,-0.84375 1.390625,-1.171875 0.515625,-0.40625 1,-0.84375 1,-1.5 0,-0.84375 -0.734375,-1.359375 -1.625,-1.359375 -0.859375,0 -1.453125,0.609375 -1.453125,1.25 0,0.34375 0.296875,0.390625 0.375,0.390625 0.15625,0 0.359375,-0.125 0.359375,-0.375 0,-0.125 -0.046875,-0.375 -0.40625,-0.375 C 0.984375,-4.21875 1.453125,-4.375 1.78125,-4.375 c 0.703125,0 1.0625,0.546875 1.0625,1.109375 0,0.609375 -0.4375,1.078125 -0.65625,1.328125 L 0.515625,-0.265625 C 0.4375,-0.203125 0.4375,-0.1875 0.4375,0 l 2.875,0 z m 0,0" + id="path5453" /> + </symbol> + </g> + </defs> + <g + style="fill:#000080;stroke:#000080" + id="textext-da5ef958-14"> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5456"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-1" + x="223.43201" + y="126.247" + id="use5458" /> + </g> + <path + inkscape:connector-curvature="0" + style="fill:#000080;stroke:#000080;stroke-width:0.398;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" + d="m -4.6875e-4,0.001125 59.07031275,0" + transform="matrix(1,0,0,-1,233.395,126.048)" + id="path5460" /> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5462"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-3" + x="233.395" + y="134.765" + id="use5464" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5466"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-9" + x="238.58" + y="134.765" + id="use5468" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5470"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-4" + x="242.455" + y="134.765" + id="use5472" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5474"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-5" + x="249.85622" + y="134.765" + id="use5476" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5478"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-6" + x="254.28758" + y="134.765" + id="use5480" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5482"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-10" + x="261.06299" + y="134.765" + id="use5484" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5486"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-13" + x="264.93701" + y="131.88699" + id="use5488" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5490"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-11" + x="271.621" + y="134.765" + id="use5492" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5494"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-7" + x="281.58301" + y="134.765" + id="use5496" /> + </g> + <g + style="fill:#000080;fill-opacity:1;stroke:#000080" + id="g5498"> + <use + style="fill:#000080;stroke:#000080" + height="100%" + width="100%" + xlink:href="#textext-da5ef958-13" + x="287.99301" + y="131.88699" + id="use5500" /> + </g> + </g> + </g> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="148.57143" + cy="449.89627" + cx="738.71753" + id="path4136-7" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="450.05875" + cx="738.13837" + id="path4138-8" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <g + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + id="g4147-5" + ns0:preamble="/home/siarzhuk/GitDrive/2015Gudhi/Aid/preamble.ini" + ns0:text="$w$" + transform="matrix(2.7020226,0,0,2.7020226,138.14964,103.80999)" + style="fill:#000080"> + <defs + id="defs4149-9"> + <g + id="g4151-7"> + <symbol + id="textext-20f8880a-0-5" + overflow="visible" + style="overflow:visible"> + <path + id="path4154-3" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-20f8880a-1-8" + overflow="visible" + style="overflow:visible"> + <path + id="path4157-8" + d="M 4.609375,-3.375 C 4.65625,-3.59375 4.75,-3.96875 4.75,-4.03125 c 0,-0.171875 -0.140625,-0.265625 -0.28125,-0.265625 -0.125,0 -0.296875,0.078125 -0.375,0.28125 -0.03125,0.0625 -0.5,1.96875 -0.5625,2.234375 C 3.453125,-1.484375 3.4375,-1.3125 3.4375,-1.125 c 0,0.109375 0,0.125 0.015625,0.171875 -0.234375,0.53125 -0.53125,0.84375 -0.921875,0.84375 -0.796875,0 -0.796875,-0.734375 -0.796875,-0.90625 0,-0.3125 0.046875,-0.703125 0.515625,-1.9375 0.109375,-0.296875 0.171875,-0.4375 0.171875,-0.640625 0,-0.4375 -0.328125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 C 0.84375,-3.875 1.21875,-4.1875 1.578125,-4.1875 c 0.09375,0 0.25,0.015625 0.25,0.328125 0,0.25 -0.109375,0.53125 -0.1875,0.703125 -0.4375,1.171875 -0.546875,1.625 -0.546875,2.015625 0,0.90625 0.65625,1.25 1.40625,1.25 0.171875,0 0.640625,0 1.03125,-0.703125 0.265625,0.640625 0.953125,0.703125 1.25,0.703125 0.75,0 1.1875,-0.625 1.453125,-1.21875 0.328125,-0.78125 0.65625,-2.125 0.65625,-2.59375 0,-0.546875 -0.265625,-0.703125 -0.4375,-0.703125 -0.25,0 -0.5,0.265625 -0.5,0.484375 0,0.125 0.0625,0.1875 0.140625,0.265625 0.109375,0.109375 0.359375,0.359375 0.359375,0.84375 0,0.34375 -0.28125,1.3125 -0.546875,1.828125 -0.25,0.53125 -0.609375,0.875 -1.09375,0.875 -0.46875,0 -0.734375,-0.296875 -0.734375,-0.875 0,-0.265625 0.0625,-0.578125 0.109375,-0.71875 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + </g> + </defs> + <g + id="textext-20f8880a-2-3" + style="fill:#000080"> + <g + id="g4160-1" + style="fill:#000080;fill-opacity:1"> + <use + id="use4162-8" + y="134.765" + x="223.43201" + xlink:href="#textext-20f8880a-1-8" + width="100%" + height="100%" + style="fill:#000080" /> + </g> + </g> + </g> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="342.37451" + cx="681.14148" + id="path4138-3-96" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="353.07648" + cx="818.57141" + id="path4138-3-7-4" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="492.09607" + cx="668.35968" + id="path4138-3-0-3" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="570.21936" + cx="717.85718" + id="path4138-3-9-3" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="473.07648" + cx="859.28564" + id="path4138-3-3-3" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="478.07648" + cx="533.57141" + id="path4138-3-6-8" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="350.52393" + cx="594.1001" + id="path4138-3-06-6" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="331.64792" + cx="927.14288" + id="path4138-3-2-0" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <circle + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + r="2.7779195" + cy="505.21936" + cx="930" + id="path4138-3-61-4" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <g + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + id="g4558-8" + style="fill:#000080" + transform="matrix(2.7020226,0,0,2.7020226,145.6805,202.59004)" + ns0:preamble="/home/siarzhuk/GitDrive/2015Gudhi/Aid/preamble.ini" + ns0:text="$\\sigma \\subset L$"> + <defs + id="defs4560-8"> + <g + id="g4562-8"> + <symbol + id="textext-b73c230a-0-9" + overflow="visible" + style="overflow:visible"> + <path + id="path4565-7" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-b73c230a-1-7" + overflow="visible" + style="overflow:visible"> + <path + id="path4568-6" + d="m 5.15625,-3.71875 c 0.140625,0 0.5,0 0.5,-0.34375 0,-0.234375 -0.21875,-0.234375 -0.390625,-0.234375 l -2.28125,0 c -1.5,0 -2.609375,1.640625 -2.609375,2.828125 0,0.875 0.59375,1.578125 1.5,1.578125 1.171875,0 2.5,-1.203125 2.5,-2.734375 0,-0.171875 0,-0.65625 -0.3125,-1.09375 z M 1.890625,-0.109375 C 1.390625,-0.109375 1,-0.46875 1,-1.1875 c 0,-0.296875 0.109375,-1.109375 0.46875,-1.703125 0.421875,-0.6875 1.015625,-0.828125 1.359375,-0.828125 0.828125,0 0.90625,0.65625 0.90625,0.96875 0,0.46875 -0.203125,1.28125 -0.53125,1.796875 -0.390625,0.578125 -0.9375,0.84375 -1.3125,0.84375 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-b73c230a-2-4" + overflow="visible" + style="overflow:visible"> + <path + id="path4571-3" + d="M 3.734375,-6.03125 C 3.8125,-6.390625 3.84375,-6.5 4.78125,-6.5 c 0.296875,0 0.375,0 0.375,-0.1875 0,-0.125 -0.109375,-0.125 -0.15625,-0.125 -0.328125,0 -1.140625,0.03125 -1.46875,0.03125 -0.296875,0 -1.03125,-0.03125 -1.328125,-0.03125 -0.0625,0 -0.1875,0 -0.1875,0.203125 0,0.109375 0.09375,0.109375 0.28125,0.109375 0.015625,0 0.203125,0 0.375,0.015625 0.171875,0.03125 0.265625,0.03125 0.265625,0.171875 0,0.03125 0,0.0625 -0.03125,0.1875 L 1.5625,-0.78125 c -0.09375,0.390625 -0.109375,0.46875 -0.90625,0.46875 -0.171875,0 -0.265625,0 -0.265625,0.203125 C 0.390625,0 0.484375,0 0.65625,0 l 4.625,0 C 5.515625,0 5.515625,0 5.578125,-0.171875 L 6.375,-2.328125 c 0.03125,-0.109375 0.03125,-0.125 0.03125,-0.140625 0,-0.03125 -0.03125,-0.109375 -0.109375,-0.109375 -0.09375,0 -0.109375,0.0625 -0.171875,0.21875 -0.34375,0.90625 -0.78125,2.046875 -2.5,2.046875 l -0.9375,0 c -0.140625,0 -0.171875,0 -0.21875,0 -0.109375,-0.015625 -0.140625,-0.03125 -0.140625,-0.109375 0,-0.03125 0,-0.046875 0.046875,-0.21875 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-b73c230a-3-0" + overflow="visible" + style="overflow:visible"> + <path + id="path4574-3" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-b73c230a-4-0" + overflow="visible" + style="overflow:visible"> + <path + id="path4577-9" + d="m 6.5625,-4.984375 c 0.171875,0 0.359375,0 0.359375,-0.203125 0,-0.203125 -0.1875,-0.203125 -0.359375,-0.203125 l -2.671875,0 c -1.703125,0 -3.0625,1.296875 -3.0625,2.890625 0,1.609375 1.359375,2.90625 3.0625,2.90625 l 2.671875,0 c 0.171875,0 0.359375,0 0.359375,-0.203125 C 6.921875,0 6.734375,0 6.5625,0 L 3.90625,0 c -1.546875,0 -2.6875,-1.15625 -2.6875,-2.5 0,-1.328125 1.140625,-2.484375 2.6875,-2.484375 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + </g> + </defs> + <g + id="textext-b73c230a-5-2"> + <g + id="g4580-5" + style="fill:#000000;fill-opacity:1"> + <use + id="use4582-4" + y="134.765" + x="223.43201" + xlink:href="#textext-b73c230a-1-7" + width="100%" + height="100%" /> + </g> + <g + id="g4584-0" + style="fill:#000000;fill-opacity:1"> + <use + id="use4586-5" + y="134.765" + x="232.25" + xlink:href="#textext-b73c230a-4-0" + width="100%" + height="100%" /> + </g> + <g + id="g4588-9" + style="fill:#000000;fill-opacity:1"> + <use + id="use4590-4" + y="134.765" + x="242.76601" + xlink:href="#textext-b73c230a-2-4" + width="100%" + height="100%" /> + </g> + </g> + </g> + <path + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + style="fill:#000080;fill-rule:evenodd;stroke:#000080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-8)" + d="m 737.85714,449.50504 148.57143,-8.57143" + id="path5000-6" + inkscape:connector-curvature="0" /> + <circle + r="80.779091" + cy="449.46512" + cx="737.3952" + id="path6334" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1.06622958;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.19868871, 3.19868871;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + <g + id="g6495" + style="fill:#000080;stroke:#000080" + transform="matrix(1.3952558,-0.07472613,0.07472613,1.3952558,431.03302,272.05923)" + ns0:preamble="/home/siarzhuk/GitDrive/2015Gudhi/Aid/preamble.ini" + ns0:text="$\\sqrt{d(w,L \\setminus \\sigma)^2 + \\alpha^2}$"> + <defs + id="defs6497"> + <g + id="g6499"> + <symbol + id="textext-c0d6e8dc-0" + overflow="visible" + style="overflow:visible"> + <path + id="path6502" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-1" + overflow="visible" + style="overflow:visible"> + <path + id="path6505" + d="m 4.234375,11.5625 c 0.296875,0 0.3125,-0.01563 0.40625,-0.203125 l 5.453125,-11.375 c 0.07813,-0.140625 0.07813,-0.15625 0.07813,-0.1875 0,-0.109375 -0.07813,-0.203125 -0.203125,-0.203125 -0.125,0 -0.171875,0.09375 -0.21875,0.203125 L 4.609375,10.53125 2.484375,5.578125 1.09375,6.65625 1.25,6.8125 1.953125,6.265625 Z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-2" + overflow="visible" + style="overflow:visible"> + <path + id="path6508" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-3" + overflow="visible" + style="overflow:visible"> + <path + id="path6511" + d="m 5.140625,-6.8125 c 0,0 0,-0.109375 -0.125,-0.109375 -0.15625,0 -1.09375,0.09375 -1.265625,0.109375 -0.078125,0.015625 -0.140625,0.0625 -0.140625,0.1875 0,0.125 0.09375,0.125 0.234375,0.125 0.484375,0 0.5,0.0625 0.5,0.171875 L 4.3125,-6.125 3.71875,-3.765625 C 3.53125,-4.140625 3.25,-4.40625 2.796875,-4.40625 c -1.15625,0 -2.390625,1.46875 -2.390625,2.921875 0,0.9375 0.546875,1.59375 1.3125,1.59375 0.203125,0 0.703125,-0.046875 1.296875,-0.75 0.078125,0.421875 0.4375,0.75 0.90625,0.75 0.359375,0 0.578125,-0.234375 0.75,-0.546875 0.15625,-0.359375 0.296875,-0.96875 0.296875,-0.984375 0,-0.109375 -0.09375,-0.109375 -0.125,-0.109375 -0.09375,0 -0.109375,0.046875 -0.140625,0.1875 -0.171875,0.640625 -0.34375,1.234375 -0.75,1.234375 -0.28125,0 -0.296875,-0.265625 -0.296875,-0.453125 0,-0.25 0.015625,-0.3125 0.046875,-0.484375 z m -2.0625,5.625 C 3.015625,-1 3.015625,-0.984375 2.875,-0.8125 2.4375,-0.265625 2.03125,-0.109375 1.75,-0.109375 c -0.5,0 -0.640625,-0.546875 -0.640625,-0.9375 0,-0.5 0.3125,-1.71875 0.546875,-2.1875 0.3125,-0.578125 0.75,-0.953125 1.15625,-0.953125 0.640625,0 0.78125,0.8125 0.78125,0.875 0,0.0625 -0.015625,0.125 -0.03125,0.171875 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-4" + overflow="visible" + style="overflow:visible"> + <path + id="path6514" + d="M 4.609375,-3.375 C 4.65625,-3.59375 4.75,-3.96875 4.75,-4.03125 c 0,-0.171875 -0.140625,-0.265625 -0.28125,-0.265625 -0.125,0 -0.296875,0.078125 -0.375,0.28125 -0.03125,0.0625 -0.5,1.96875 -0.5625,2.234375 C 3.453125,-1.484375 3.4375,-1.3125 3.4375,-1.125 c 0,0.109375 0,0.125 0.015625,0.171875 -0.234375,0.53125 -0.53125,0.84375 -0.921875,0.84375 -0.796875,0 -0.796875,-0.734375 -0.796875,-0.90625 0,-0.3125 0.046875,-0.703125 0.515625,-1.9375 0.109375,-0.296875 0.171875,-0.4375 0.171875,-0.640625 0,-0.4375 -0.328125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 C 0.84375,-3.875 1.21875,-4.1875 1.578125,-4.1875 c 0.09375,0 0.25,0.015625 0.25,0.328125 0,0.25 -0.109375,0.53125 -0.1875,0.703125 -0.4375,1.171875 -0.546875,1.625 -0.546875,2.015625 0,0.90625 0.65625,1.25 1.40625,1.25 0.171875,0 0.640625,0 1.03125,-0.703125 0.265625,0.640625 0.953125,0.703125 1.25,0.703125 0.75,0 1.1875,-0.625 1.453125,-1.21875 0.328125,-0.78125 0.65625,-2.125 0.65625,-2.59375 0,-0.546875 -0.265625,-0.703125 -0.4375,-0.703125 -0.25,0 -0.5,0.265625 -0.5,0.484375 0,0.125 0.0625,0.1875 0.140625,0.265625 0.109375,0.109375 0.359375,0.359375 0.359375,0.84375 0,0.34375 -0.28125,1.3125 -0.546875,1.828125 -0.25,0.53125 -0.609375,0.875 -1.09375,0.875 -0.46875,0 -0.734375,-0.296875 -0.734375,-0.875 0,-0.265625 0.0625,-0.578125 0.109375,-0.71875 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-5" + overflow="visible" + style="overflow:visible"> + <path + id="path6517" + d="m 2.03125,-0.015625 c 0,-0.65625 -0.25,-1.046875 -0.640625,-1.046875 -0.328125,0 -0.53125,0.25 -0.53125,0.53125 C 0.859375,-0.265625 1.0625,0 1.390625,0 1.5,0 1.640625,-0.046875 1.734375,-0.125 1.765625,-0.15625 1.78125,-0.15625 1.78125,-0.15625 c 0.015625,0 0.015625,0 0.015625,0.140625 0,0.75 -0.34375,1.34375 -0.671875,1.671875 -0.109375,0.109375 -0.109375,0.125 -0.109375,0.15625 0,0.078125 0.046875,0.109375 0.09375,0.109375 0.109375,0 0.921875,-0.765625 0.921875,-1.9375 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-6" + overflow="visible" + style="overflow:visible"> + <path + id="path6520" + d="M 3.734375,-6.03125 C 3.8125,-6.390625 3.84375,-6.5 4.78125,-6.5 c 0.296875,0 0.375,0 0.375,-0.1875 0,-0.125 -0.109375,-0.125 -0.15625,-0.125 -0.328125,0 -1.140625,0.03125 -1.46875,0.03125 -0.296875,0 -1.03125,-0.03125 -1.328125,-0.03125 -0.0625,0 -0.1875,0 -0.1875,0.203125 0,0.109375 0.09375,0.109375 0.28125,0.109375 0.015625,0 0.203125,0 0.375,0.015625 0.171875,0.03125 0.265625,0.03125 0.265625,0.171875 0,0.03125 0,0.0625 -0.03125,0.1875 L 1.5625,-0.78125 c -0.09375,0.390625 -0.109375,0.46875 -0.90625,0.46875 -0.171875,0 -0.265625,0 -0.265625,0.203125 C 0.390625,0 0.484375,0 0.65625,0 l 4.625,0 C 5.515625,0 5.515625,0 5.578125,-0.171875 L 6.375,-2.328125 c 0.03125,-0.109375 0.03125,-0.125 0.03125,-0.140625 0,-0.03125 -0.03125,-0.109375 -0.109375,-0.109375 -0.09375,0 -0.109375,0.0625 -0.171875,0.21875 -0.34375,0.90625 -0.78125,2.046875 -2.5,2.046875 l -0.9375,0 c -0.140625,0 -0.171875,0 -0.21875,0 -0.109375,-0.015625 -0.140625,-0.03125 -0.140625,-0.109375 0,-0.03125 0,-0.046875 0.046875,-0.21875 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-7" + overflow="visible" + style="overflow:visible"> + <path + id="path6523" + d="m 5.15625,-3.71875 c 0.140625,0 0.5,0 0.5,-0.34375 0,-0.234375 -0.21875,-0.234375 -0.390625,-0.234375 l -2.28125,0 c -1.5,0 -2.609375,1.640625 -2.609375,2.828125 0,0.875 0.59375,1.578125 1.5,1.578125 1.171875,0 2.5,-1.203125 2.5,-2.734375 0,-0.171875 0,-0.65625 -0.3125,-1.09375 z M 1.890625,-0.109375 C 1.390625,-0.109375 1,-0.46875 1,-1.1875 c 0,-0.296875 0.109375,-1.109375 0.46875,-1.703125 0.421875,-0.6875 1.015625,-0.828125 1.359375,-0.828125 0.828125,0 0.90625,0.65625 0.90625,0.96875 0,0.46875 -0.203125,1.28125 -0.53125,1.796875 -0.390625,0.578125 -0.9375,0.84375 -1.3125,0.84375 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-8" + overflow="visible" + style="overflow:visible"> + <path + id="path6526" + d="m 4.75,-2.359375 c 0,-1.5625 -0.921875,-2.046875 -1.65625,-2.046875 -1.375,0 -2.6875,1.421875 -2.6875,2.828125 0,0.9375 0.59375,1.6875 1.625,1.6875 0.625,0 1.34375,-0.234375 2.09375,-0.84375 0.125,0.53125 0.453125,0.84375 0.90625,0.84375 0.53125,0 0.84375,-0.546875 0.84375,-0.703125 0,-0.078125 -0.0625,-0.109375 -0.125,-0.109375 -0.0625,0 -0.09375,0.03125 -0.125,0.109375 -0.1875,0.484375 -0.546875,0.484375 -0.5625,0.484375 -0.3125,0 -0.3125,-0.78125 -0.3125,-1.015625 0,-0.203125 0,-0.234375 0.109375,-0.34375 C 5.796875,-2.65625 6,-3.8125 6,-3.8125 6,-3.84375 5.984375,-3.921875 5.875,-3.921875 c -0.09375,0 -0.09375,0.03125 -0.140625,0.21875 -0.1875,0.625 -0.515625,1.375 -0.984375,1.96875 z m -0.65625,1.375 c -0.890625,0.765625 -1.65625,0.875 -2.046875,0.875 -0.59375,0 -0.90625,-0.453125 -0.90625,-1.09375 0,-0.484375 0.265625,-1.5625 0.578125,-2.0625 C 2.1875,-4 2.734375,-4.1875 3.078125,-4.1875 c 0.984375,0 0.984375,1.3125 0.984375,2.078125 0,0.375 0,0.953125 0.03125,1.125 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-9" + overflow="visible" + style="overflow:visible"> + <path + id="path6529" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-10" + overflow="visible" + style="overflow:visible"> + <path + id="path6532" + d="m 3.296875,2.390625 c 0,-0.03125 0,-0.046875 -0.171875,-0.21875 C 1.890625,0.921875 1.5625,-0.96875 1.5625,-2.5 c 0,-1.734375 0.375,-3.46875 1.609375,-4.703125 0.125,-0.125 0.125,-0.140625 0.125,-0.171875 0,-0.078125 -0.03125,-0.109375 -0.09375,-0.109375 -0.109375,0 -1,0.6875 -1.59375,1.953125 -0.5,1.09375 -0.625,2.203125 -0.625,3.03125 0,0.78125 0.109375,1.984375 0.65625,3.125 C 2.25,1.84375 3.09375,2.5 3.203125,2.5 c 0.0625,0 0.09375,-0.03125 0.09375,-0.109375 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-11" + overflow="visible" + style="overflow:visible"> + <path + id="path6535" + d="m 2.875,-2.5 c 0,-0.765625 -0.109375,-1.96875 -0.65625,-3.109375 -0.59375,-1.21875 -1.453125,-1.875 -1.546875,-1.875 -0.0625,0 -0.109375,0.046875 -0.109375,0.109375 0,0.03125 0,0.046875 0.1875,0.234375 0.984375,0.984375 1.546875,2.5625 1.546875,4.640625 0,1.71875 -0.359375,3.46875 -1.59375,4.71875 C 0.5625,2.34375 0.5625,2.359375 0.5625,2.390625 0.5625,2.453125 0.609375,2.5 0.671875,2.5 0.765625,2.5 1.671875,1.8125 2.25,0.546875 2.765625,-0.546875 2.875,-1.65625 2.875,-2.5 Z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-12" + overflow="visible" + style="overflow:visible"> + <path + id="path6538" + d="m 4.078125,-2.296875 2.78125,0 C 7,-2.296875 7.1875,-2.296875 7.1875,-2.5 7.1875,-2.6875 7,-2.6875 6.859375,-2.6875 l -2.78125,0 0,-2.796875 c 0,-0.140625 0,-0.328125 -0.203125,-0.328125 -0.203125,0 -0.203125,0.1875 -0.203125,0.328125 l 0,2.796875 -2.78125,0 c -0.140625,0 -0.328125,0 -0.328125,0.1875 0,0.203125 0.1875,0.203125 0.328125,0.203125 l 2.78125,0 0,2.796875 c 0,0.140625 0,0.328125 0.203125,0.328125 0.203125,0 0.203125,-0.1875 0.203125,-0.328125 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-13" + overflow="visible" + style="overflow:visible"> + <path + id="path6541" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-14" + overflow="visible" + style="overflow:visible"> + <path + id="path6544" + d="m 4,2.25 c 0.046875,0.140625 0.09375,0.25 0.234375,0.25 0.109375,0 0.1875,-0.09375 0.1875,-0.203125 0,-0.03125 0,-0.046875 -0.046875,-0.15625 l -3.40625,-9.375 c -0.0625,-0.171875 -0.09375,-0.25 -0.21875,-0.25 -0.109375,0 -0.203125,0.09375 -0.203125,0.203125 0,0.03125 0,0.046875 0.046875,0.15625 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-15" + overflow="visible" + style="overflow:visible"> + <path + id="path6547" + d="" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + <symbol + id="textext-c0d6e8dc-16" + overflow="visible" + style="overflow:visible"> + <path + id="path6550" + d="m 3.515625,-1.265625 -0.234375,0 c -0.015625,0.15625 -0.09375,0.5625 -0.1875,0.625 -0.046875,0.046875 -0.578125,0.046875 -0.6875,0.046875 l -1.28125,0 c 0.734375,-0.640625 0.984375,-0.84375 1.390625,-1.171875 0.515625,-0.40625 1,-0.84375 1,-1.5 0,-0.84375 -0.734375,-1.359375 -1.625,-1.359375 -0.859375,0 -1.453125,0.609375 -1.453125,1.25 0,0.34375 0.296875,0.390625 0.375,0.390625 0.15625,0 0.359375,-0.125 0.359375,-0.375 0,-0.125 -0.046875,-0.375 -0.40625,-0.375 C 0.984375,-4.21875 1.453125,-4.375 1.78125,-4.375 c 0.703125,0 1.0625,0.546875 1.0625,1.109375 0,0.609375 -0.4375,1.078125 -0.65625,1.328125 L 0.515625,-0.265625 C 0.4375,-0.203125 0.4375,-0.1875 0.4375,0 l 2.875,0 z m 0,0" + style="stroke:none" + inkscape:connector-curvature="0" /> + </symbol> + </g> + </defs> + <g + id="textext-c0d6e8dc-17" + style="fill:#000080;stroke:#000080"> + <g + id="g6553" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6555" + y="126.247" + x="223.43201" + xlink:href="#textext-c0d6e8dc-1" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <path + id="path6557" + transform="matrix(1,0,0,-1,233.395,126.048)" + d="m -4.6875e-4,0.001125 74.52734375,0" + style="fill:#000080;stroke:#000080;stroke-width:0.398;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" + inkscape:connector-curvature="0" /> + <g + id="g6559" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6561" + y="134.765" + x="233.395" + xlink:href="#textext-c0d6e8dc-3" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6563" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6565" + y="134.765" + x="238.58" + xlink:href="#textext-c0d6e8dc-10" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6567" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6569" + y="134.765" + x="242.455" + xlink:href="#textext-c0d6e8dc-4" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6571" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6573" + y="134.765" + x="249.85622" + xlink:href="#textext-c0d6e8dc-5" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6575" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6577" + y="134.765" + x="254.28758" + xlink:href="#textext-c0d6e8dc-6" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6579" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6581" + y="134.765" + x="263.27701" + xlink:href="#textext-c0d6e8dc-14" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6583" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6585" + y="134.765" + x="270.47198" + xlink:href="#textext-c0d6e8dc-7" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6587" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6589" + y="134.765" + x="276.522" + xlink:href="#textext-c0d6e8dc-11" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6591" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6593" + y="131.88699" + x="280.397" + xlink:href="#textext-c0d6e8dc-16" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6595" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6597" + y="134.765" + x="287.07999" + xlink:href="#textext-c0d6e8dc-12" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6599" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6601" + y="134.765" + x="297.043" + xlink:href="#textext-c0d6e8dc-8" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + <g + id="g6603" + style="fill:#000080;fill-opacity:1;stroke:#000080"> + <use + id="use6605" + y="131.88699" + x="303.453" + xlink:href="#textext-c0d6e8dc-16" + width="100%" + height="100%" + style="fill:#000080;stroke:#000080" /> + </g> + </g> + </g> + </g> + <g + transform="translate(-130.29351,-300.82484)" + style="display:none" + inkscape:label="Layer 2" + id="layer2" + inkscape:groupmode="layer"> + <circle + r="32.857143" + cy="448.79074" + cx="337.85715" + id="path5639" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + </g> +</svg> diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 857ec819..9990c541 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -1,17 +1,48 @@ cmake_minimum_required(VERSION 2.6) project(Witness_complex_examples) -# A simple example - add_executable( witness_complex_from_file witness_complex_from_file.cpp ) - add_test( witness_complex_from_bunny ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_from_file - ${CMAKE_SOURCE_DIR}/data/points/bunny_5000.off 100) +add_executable ( Witness_complex_example_nearest_landmark_table example_nearest_landmark_table.cpp ) +target_link_libraries(Witness_complex_example_nearest_landmark_table ${Boost_SYSTEM_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(Witness_complex_example_nearest_landmark_table ${TBB_LIBRARIES}) +endif() +add_test(Witness_complex_test_nearest_landmark_table Witness_complex_example_nearest_landmark_table) +# CGAL and Eigen3 are required for Euclidean version of Witness if(CGAL_FOUND) if (NOT CGAL_VERSION VERSION_LESS 4.6.0) if (EIGEN3_FOUND) - add_executable ( witness_complex_sphere witness_complex_sphere.cpp ) - target_link_libraries(witness_complex_sphere ${Boost_SYSTEM_LIBRARY} ${CGAL_LIBRARY}) - add_test( witness_complex_sphere_10 ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_sphere 10) + add_executable( Witness_complex_example_off example_witness_complex_off.cpp ) + target_link_libraries(Witness_complex_example_off ${Boost_SYSTEM_LIBRARY}) + add_executable( Witness_complex_example_strong_off example_strong_witness_complex_off.cpp ) + target_link_libraries(Witness_complex_example_strong_off ${Boost_SYSTEM_LIBRARY}) + add_executable ( Witness_complex_example_sphere example_witness_complex_sphere.cpp ) + target_link_libraries(Witness_complex_example_sphere ${Boost_SYSTEM_LIBRARY}) + + add_executable ( Witness_complex_example_witness_persistence example_witness_complex_persistence.cpp ) + target_link_libraries(Witness_complex_example_witness_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) + + add_executable ( Witness_complex_example_strong_witness_persistence example_strong_witness_persistence.cpp ) + target_link_libraries(Witness_complex_example_strong_witness_persistence ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) + + if (TBB_FOUND) + target_link_libraries(Witness_complex_example_witness_persistence ${TBB_LIBRARIES}) + target_link_libraries(Witness_complex_example_strong_witness_persistence ${TBB_LIBRARIES}) + endif() + + add_test(Witness_complex_off_test_torus + ${CMAKE_CURRENT_BINARY_DIR}/Witness_complex_example_off + ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off 20 1.0 3) + add_test(Witness_complex_strong_off_test_torus + ${CMAKE_CURRENT_BINARY_DIR}/Witness_complex_example_strong_off + ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off 20 1.0 3) + add_test(Witness_complex_test_sphere_10 Witness_complex_example_sphere 10) + add_test(Witness_complex_test_torus_persistence + ${CMAKE_CURRENT_BINARY_DIR}/Witness_complex_example_witness_persistence + ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off -l 20 -a 0.5) + add_test(Witness_complex_strong_test_torus_persistence + ${CMAKE_CURRENT_BINARY_DIR}/Witness_complex_example_strong_witness_persistence + ${CMAKE_SOURCE_DIR}/data/points/tore3D_1307.off -l 20 -a 0.5) endif(EIGEN3_FOUND) endif (NOT CGAL_VERSION VERSION_LESS 4.6.0) endif() diff --git a/src/Witness_complex/example/example_nearest_landmark_table.cpp b/src/Witness_complex/example/example_nearest_landmark_table.cpp new file mode 100644 index 00000000..b8594212 --- /dev/null +++ b/src/Witness_complex/example/example_nearest_landmark_table.cpp @@ -0,0 +1,69 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2016 INRIA (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_PARAMETER_MAX_ARITY 12 + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Witness_complex.h> +#include <gudhi/Persistent_cohomology.h> + +#include <iostream> +#include <fstream> +#include <utility> +#include <string> +#include <vector> + +int main(int argc, char * const argv[]) { + using Nearest_landmark_range = std::vector<std::pair<std::size_t, double>>; + using Nearest_landmark_table = std::vector<Nearest_landmark_range>; + using Witness_complex = Gudhi::witness_complex::Witness_complex<Nearest_landmark_table>; + using Simplex_tree = Gudhi::Simplex_tree<>; + using Field_Zp = Gudhi::persistent_cohomology::Field_Zp; + using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<Simplex_tree, Field_Zp>; + + Simplex_tree simplex_tree; + Nearest_landmark_table nlt; + + // Example contains 5 witnesses and 5 landmarks + Nearest_landmark_range w0 = {std::make_pair(0, 0), std::make_pair(1, 1), std::make_pair(2, 2), + std::make_pair(3, 3), std::make_pair(4, 4)}; nlt.push_back(w0); + Nearest_landmark_range w1 = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(3, 2), + std::make_pair(4, 3), std::make_pair(0, 4)}; nlt.push_back(w1); + Nearest_landmark_range w2 = {std::make_pair(2, 0), std::make_pair(3, 1), std::make_pair(4, 2), + std::make_pair(0, 3), std::make_pair(1, 4)}; nlt.push_back(w2); + Nearest_landmark_range w3 = {std::make_pair(3, 0), std::make_pair(4, 1), std::make_pair(0, 2), + std::make_pair(1, 3), std::make_pair(2, 4)}; nlt.push_back(w3); + Nearest_landmark_range w4 = {std::make_pair(4, 0), std::make_pair(0, 1), std::make_pair(1, 2), + std::make_pair(2, 3), std::make_pair(3, 4)}; nlt.push_back(w4); + + Witness_complex witness_complex(nlt); + witness_complex.create_complex(simplex_tree, 4.1); + + std::cout << "Number of simplices: " << simplex_tree.num_simplices() << std::endl; + + Persistent_cohomology pcoh(simplex_tree); + // initializes the coefficient field for homology + pcoh.init_coefficients(11); + + pcoh.compute_persistent_cohomology(-0.1); + pcoh.output_diagram(); +} diff --git a/src/Witness_complex/example/witness_complex_from_file.cpp b/src/Witness_complex/example/example_strong_witness_complex_off.cpp index 5dd18d0a..0ee9ee90 100644 --- a/src/Witness_complex/example/witness_complex_from_file.cpp +++ b/src/Witness_complex/example/example_strong_witness_complex_off.cpp @@ -4,7 +4,7 @@ * * Author(s): Siargey Kachanovich * - * Copyright (C) 2015 INRIA + * Copyright (C) 2016 INRIA (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 @@ -20,15 +20,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sys/types.h> -#include <sys/stat.h> - -#include <gudhi/Points_off_io.h> #include <gudhi/Simplex_tree.h> -#include <gudhi/Witness_complex.h> -#include <gudhi/Construct_closest_landmark_table.h> +#include <gudhi/Euclidean_strong_witness_complex.h> #include <gudhi/pick_n_random_points.h> -#include <gudhi/reader_utils.h> +#include <gudhi/Points_off_io.h> + +#include <CGAL/Epick_d.h> #include <iostream> #include <fstream> @@ -36,49 +33,47 @@ #include <string> #include <vector> -typedef Gudhi::Simplex_tree<> Simplex_tree; -typedef std::vector< Simplex_tree::Vertex_handle > typeVectorVertex; -typedef std::vector< std::vector <double> > Point_Vector; +using K = CGAL::Epick_d<CGAL::Dynamic_dimension_tag>; +using Point_d = typename K::Point_d; +using Witness_complex = Gudhi::witness_complex::Euclidean_strong_witness_complex<K>; +using Point_vector = std::vector<Point_d>; int main(int argc, char * const argv[]) { - if (argc != 3) { + if (argc != 5) { std::cerr << "Usage: " << argv[0] - << " path_to_point_file.off nbL \n"; + << " path_to_point_file number_of_landmarks max_squared_alpha limit_dimension\n"; return 0; } - std::string off_file_name = argv[1]; - int nbL = atoi(argv[2]); + std::string file_name = argv[1]; + int nbL = atoi(argv[2]), lim_dim = atoi(argv[4]); + double alpha2 = atof(argv[3]); clock_t start, end; + Gudhi::Simplex_tree<> simplex_tree; - // Construct the Simplex Tree - Simplex_tree simplex_tree; - - // Read the OFF file (input file name given as parameter) and triangulate points - Gudhi::Points_off_reader<std::vector <double>> off_reader(off_file_name); - // Check the read operation was correct - if (!off_reader.is_valid()) { - std::cerr << "Unable to read file " << off_file_name << std::endl; - } // Read the point file - Point_Vector point_vector = off_reader.get_point_cloud(); + Point_vector point_vector, landmarks; + Gudhi::Points_off_reader<Point_d> off_reader(file_name); + if (!off_reader.is_valid()) { + std::cerr << "Strong witness complex - Unable to read file " << file_name << "\n"; + exit(-1); // ----- >> + } + point_vector = Point_vector(off_reader.get_point_cloud()); + std::cout << "Successfully read " << point_vector.size() << " points.\n"; - std::cout << "Ambient dimension is " << point_vector[0].size() << ".\n"; + std::cout << "Ambient dimension is " << point_vector[0].dimension() << ".\n"; // Choose landmarks - start = clock(); - std::vector<std::vector< int > > knn; - Point_Vector landmarks; - Gudhi::subsampling::pick_n_random_points(point_vector, 100, std::back_inserter(landmarks)); - Gudhi::witness_complex::construct_closest_landmark_table<Simplex_tree::Filtration_value>(point_vector, landmarks, knn); - end = clock(); - std::cout << "Landmark choice for " << nbL << " landmarks took " - << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s. \n"; + Gudhi::subsampling::pick_n_random_points(point_vector, nbL, std::back_inserter(landmarks)); // Compute witness complex start = clock(); - Gudhi::witness_complex::witness_complex(knn, nbL, point_vector[0].size(), simplex_tree); + Witness_complex witness_complex(landmarks, + point_vector); + + witness_complex.create_complex(simplex_tree, alpha2, lim_dim); end = clock(); - std::cout << "Witness complex took " + std::cout << "Strong witness complex took " << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s. \n"; + std::cout << "Number of simplices is: " << simplex_tree.num_simplices() << "\n"; } diff --git a/src/Witness_complex/example/example_strong_witness_persistence.cpp b/src/Witness_complex/example/example_strong_witness_persistence.cpp new file mode 100644 index 00000000..f786fe7b --- /dev/null +++ b/src/Witness_complex/example/example_strong_witness_persistence.cpp @@ -0,0 +1,171 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2016 INRIA (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/Simplex_tree.h> +#include <gudhi/Euclidean_strong_witness_complex.h> +#include <gudhi/Persistent_cohomology.h> +#include <gudhi/Points_off_io.h> +#include <gudhi/pick_n_random_points.h> + +#include <boost/program_options.hpp> + +#include <CGAL/Epick_d.h> + +#include <string> +#include <vector> +#include <limits> // infinity + +using K = CGAL::Epick_d<CGAL::Dynamic_dimension_tag>; +using Point_d = K::Point_d; + +using Point_vector = std::vector<Point_d>; +using Strong_witness_complex = Gudhi::witness_complex::Euclidean_strong_witness_complex<K>; +using SimplexTree = Gudhi::Simplex_tree<>; + +using Filtration_value = SimplexTree::Filtration_value; + +using Field_Zp = Gudhi::persistent_cohomology::Field_Zp; +using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<SimplexTree, Field_Zp>; + +void program_options(int argc, char * argv[] + , int & nbL + , std::string & file_name + , std::string & filediag + , Filtration_value & max_squared_alpha + , int & p + , int & dim_max + , Filtration_value & min_persistence); + +int main(int argc, char * argv[]) { + std::string file_name; + std::string filediag; + Filtration_value max_squared_alpha; + int p, nbL, lim_d; + Filtration_value min_persistence; + SimplexTree simplex_tree; + + program_options(argc, argv, nbL, file_name, filediag, max_squared_alpha, p, lim_d, min_persistence); + + // Extract the points from the file file_name + Point_vector witnesses, landmarks; + Gudhi::Points_off_reader<Point_d> off_reader(file_name); + if (!off_reader.is_valid()) { + std::cerr << "Witness complex - Unable to read file " << file_name << "\n"; + exit(-1); // ----- >> + } + witnesses = Point_vector(off_reader.get_point_cloud()); + std::cout << "Successfully read " << witnesses.size() << " points.\n"; + std::cout << "Ambient dimension is " << witnesses[0].dimension() << ".\n"; + + // Choose landmarks from witnesses + Gudhi::subsampling::pick_n_random_points(witnesses, nbL, std::back_inserter(landmarks)); + + // Compute witness complex + Strong_witness_complex strong_witness_complex(landmarks, + witnesses); + + strong_witness_complex.create_complex(simplex_tree, max_squared_alpha, lim_d); + + 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[] + , int & nbL + , std::string & file_name + , std::string & filediag + , Filtration_value & max_squared_alpha + , int & p + , int & dim_max + , Filtration_value & min_persistence) { + namespace po = boost::program_options; + + po::options_description hidden("Hidden options"); + hidden.add_options() + ("input-file", po::value<std::string>(&file_name), + "Name of file containing a point set in off format."); + + po::options_description visible("Allowed options", 100); + Filtration_value default_alpha = std::numeric_limits<Filtration_value>::infinity(); + visible.add_options() + ("help,h", "produce help message") + ("landmarks,l", po::value<int>(&nbL), + "Number of landmarks to choose from the point cloud.") + ("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-sq-alpha,a", po::value<Filtration_value>(&max_squared_alpha)->default_value(default_alpha), + "Maximal squared relaxation parameter.") + ("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)->default_value(0), + "Minimal lifetime of homology feature to be recorded. Default is 0. Enter a negative value to see zero length intervals") + ("cpx-dimension,d", po::value<int>(&dim_max)->default_value(std::numeric_limits<int>::max()), + "Maximal dimension of the strong witness complex we want to compute."); + + 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 Strong witness 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/Witness_complex/example/example_witness_complex_off.cpp b/src/Witness_complex/example/example_witness_complex_off.cpp new file mode 100644 index 00000000..b36dac0d --- /dev/null +++ b/src/Witness_complex/example/example_witness_complex_off.cpp @@ -0,0 +1,60 @@ +#include <sys/types.h> +#include <sys/stat.h> + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Euclidean_witness_complex.h> +#include <gudhi/pick_n_random_points.h> +#include <gudhi/Points_off_io.h> + +#include <CGAL/Epick_d.h> + +#include <iostream> +#include <fstream> +#include <ctime> +#include <string> +#include <vector> + +using K = CGAL::Epick_d<CGAL::Dynamic_dimension_tag>; +using Point_d = K::Point_d; +using Witness_complex = Gudhi::witness_complex::Euclidean_witness_complex<K>; +using Point_vector = std::vector< Point_d >; + +int main(int argc, char * const argv[]) { + if (argc != 5) { + std::cerr << "Usage: " << argv[0] + << " path_to_point_file number_of_landmarks max_squared_alpha limit_dimension\n"; + return 0; + } + + std::string file_name = argv[1]; + int nbL = atoi(argv[2]), lim_dim = atoi(argv[4]); + double alpha2 = atof(argv[3]); + clock_t start, end; + Gudhi::Simplex_tree<> simplex_tree; + + // Read the point file + Point_vector point_vector, landmarks; + Gudhi::Points_off_reader<Point_d> off_reader(file_name); + if (!off_reader.is_valid()) { + std::cerr << "Witness complex - Unable to read file " << file_name << "\n"; + exit(-1); // ----- >> + } + point_vector = Point_vector(off_reader.get_point_cloud()); + + std::cout << "Successfully read " << point_vector.size() << " points.\n"; + std::cout << "Ambient dimension is " << point_vector[0].dimension() << ".\n"; + + // Choose landmarks + Gudhi::subsampling::pick_n_random_points(point_vector, nbL, std::back_inserter(landmarks)); + + // Compute witness complex + start = clock(); + Witness_complex witness_complex(landmarks, + point_vector); + + witness_complex.create_complex(simplex_tree, alpha2, lim_dim); + end = clock(); + std::cout << "Witness complex took " + << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s. \n"; + std::cout << "Number of simplices is: " << simplex_tree.num_simplices() << "\n"; +} diff --git a/src/Witness_complex/example/example_witness_complex_persistence.cpp b/src/Witness_complex/example/example_witness_complex_persistence.cpp new file mode 100644 index 00000000..a1146922 --- /dev/null +++ b/src/Witness_complex/example/example_witness_complex_persistence.cpp @@ -0,0 +1,171 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2016 INRIA (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/Simplex_tree.h> +#include <gudhi/Euclidean_witness_complex.h> +#include <gudhi/Persistent_cohomology.h> +#include <gudhi/Points_off_io.h> +#include <gudhi/pick_n_random_points.h> + +#include <boost/program_options.hpp> + +#include <CGAL/Epick_d.h> + +#include <string> +#include <vector> +#include <limits> // infinity + +using K = CGAL::Epick_d<CGAL::Dynamic_dimension_tag>; +using Point_d = K::Point_d; + +using Point_vector = std::vector<Point_d>; +using Witness_complex = Gudhi::witness_complex::Euclidean_witness_complex<K>; +using SimplexTree = Gudhi::Simplex_tree<>; + +using Filtration_value = SimplexTree::Filtration_value; + +using Field_Zp = Gudhi::persistent_cohomology::Field_Zp; +using Persistent_cohomology = Gudhi::persistent_cohomology::Persistent_cohomology<SimplexTree, Field_Zp>; + +void program_options(int argc, char * argv[] + , int & nbL + , std::string & file_name + , std::string & filediag + , Filtration_value & max_squared_alpha + , int & p + , int & dim_max + , Filtration_value & min_persistence); + +int main(int argc, char * argv[]) { + std::string file_name; + std::string filediag; + Filtration_value max_squared_alpha; + int p, nbL, lim_d; + Filtration_value min_persistence; + SimplexTree simplex_tree; + + program_options(argc, argv, nbL, file_name, filediag, max_squared_alpha, p, lim_d, min_persistence); + + // Extract the points from the file file_name + Point_vector witnesses, landmarks; + Gudhi::Points_off_reader<Point_d> off_reader(file_name); + if (!off_reader.is_valid()) { + std::cerr << "Witness complex - Unable to read file " << file_name << "\n"; + exit(-1); // ----- >> + } + witnesses = Point_vector(off_reader.get_point_cloud()); + std::cout << "Successfully read " << witnesses.size() << " points.\n"; + std::cout << "Ambient dimension is " << witnesses[0].dimension() << ".\n"; + + // Choose landmarks from witnesses + Gudhi::subsampling::pick_n_random_points(witnesses, nbL, std::back_inserter(landmarks)); + + // Compute witness complex + Witness_complex witness_complex(landmarks, + witnesses); + + witness_complex.create_complex(simplex_tree, max_squared_alpha, lim_d); + + 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[] + , int & nbL + , std::string & file_name + , std::string & filediag + , Filtration_value & max_squared_alpha + , int & p + , int & dim_max + , Filtration_value & min_persistence) { + namespace po = boost::program_options; + + po::options_description hidden("Hidden options"); + hidden.add_options() + ("input-file", po::value<std::string>(&file_name), + "Name of file containing a point set in off format."); + + Filtration_value default_alpha = std::numeric_limits<Filtration_value>::infinity(); + po::options_description visible("Allowed options", 100); + visible.add_options() + ("help,h", "produce help message") + ("landmarks,l", po::value<int>(&nbL), + "Number of landmarks to choose from the point cloud.") + ("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-sq-alpha,a", po::value<Filtration_value>(&max_squared_alpha)->default_value(default_alpha), + "Maximal squared relaxation parameter.") + ("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)->default_value(0), + "Minimal lifetime of homology feature to be recorded. Default is 0. Enter a negative value to see zero length intervals") + ("cpx-dimension,d", po::value<int>(&dim_max)->default_value(std::numeric_limits<int>::max()), + "Maximal dimension of the weak witness complex we want to compute."); + + 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 Weak witness 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/Witness_complex/example/witness_complex_sphere.cpp b/src/Witness_complex/example/example_witness_complex_sphere.cpp index 60e02225..06fe3889 100644 --- a/src/Witness_complex/example/witness_complex_sphere.cpp +++ b/src/Witness_complex/example/example_witness_complex_sphere.cpp @@ -4,7 +4,7 @@ * * Author(s): Siargey Kachanovich * - * Copyright (C) 2015 INRIA + * Copyright (C) 2016 INRIA (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 @@ -19,18 +19,16 @@ * 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_PARAMETER_MAX_ARITY 12 - -#include <sys/types.h> -#include <sys/stat.h> +#define BOOST_PARAMETER_MAX_ARITY 12 #include <gudhi/Simplex_tree.h> -#include <gudhi/Witness_complex.h> -#include <gudhi/Construct_closest_landmark_table.h> +#include <gudhi/Euclidean_witness_complex.h> #include <gudhi/pick_n_random_points.h> #include <gudhi/reader_utils.h> +#include <CGAL/Epick_d.h> + #include <iostream> #include <fstream> #include <ctime> @@ -40,8 +38,6 @@ #include "generators.h" -typedef Gudhi::Simplex_tree<> Simplex_tree; - /** Write a gnuplot readable file. * Data range is a random access range of pairs (arg, value) */ @@ -54,6 +50,9 @@ void write_data(Data_range & data, std::string filename) { } int main(int argc, char * const argv[]) { + using Kernel = CGAL::Epick_d<CGAL::Dynamic_dimension_tag>; + using Witness_complex = Gudhi::witness_complex::Euclidean_witness_complex<Kernel>; + if (argc != 2) { std::cerr << "Usage: " << argv[0] << " number_of_landmarks \n"; @@ -63,13 +62,12 @@ int main(int argc, char * const argv[]) { int number_of_landmarks = atoi(argv[1]); clock_t start, end; - // Construct the Simplex Tree - Simplex_tree simplex_tree; - std::vector< std::pair<int, double> > l_time; - // Read the point file + // Generate points for (int nbP = 500; nbP < 10000; nbP += 500) { + // Construct the Simplex Tree + Gudhi::Simplex_tree<> simplex_tree; Point_Vector point_vector, landmarks; generate_points_sphere(point_vector, nbP, 4); std::cout << "Successfully generated " << point_vector.size() << " points.\n"; @@ -77,12 +75,12 @@ int main(int argc, char * const argv[]) { // Choose landmarks start = clock(); - std::vector<std::vector< int > > knn; - Gudhi::subsampling::pick_n_random_points(point_vector, 100, std::back_inserter(landmarks)); - Gudhi::witness_complex::construct_closest_landmark_table<Simplex_tree::Filtration_value>(point_vector, landmarks, knn); + Gudhi::subsampling::pick_n_random_points(point_vector, number_of_landmarks, std::back_inserter(landmarks)); // Compute witness complex - Gudhi::witness_complex::witness_complex(knn, number_of_landmarks, point_vector[0].size(), simplex_tree); + Witness_complex witness_complex(landmarks, + point_vector); + witness_complex.create_complex(simplex_tree, 0); end = clock(); double time = static_cast<double>(end - start) / CLOCKS_PER_SEC; std::cout << "Witness complex for " << number_of_landmarks << " landmarks took " diff --git a/src/Witness_complex/example/generators.h b/src/Witness_complex/example/generators.h index ac445261..7df43db5 100644 --- a/src/Witness_complex/example/generators.h +++ b/src/Witness_complex/example/generators.h @@ -25,17 +25,19 @@ #include <CGAL/Epick_d.h> #include <CGAL/point_generators_d.h> +#include <CGAL/Random.h> #include <fstream> #include <string> #include <vector> +#include <cmath> -typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K; -typedef K::FT FT; -typedef K::Point_d Point_d; -typedef std::vector<Point_d> Point_Vector; -typedef CGAL::Random_points_in_cube_d<Point_d> Random_cube_iterator; -typedef CGAL::Random_points_in_ball_d<Point_d> Random_point_iterator; +using K = CGAL::Epick_d<CGAL::Dynamic_dimension_tag>; +using FT = K::FT; +using Point_d = K::Point_d; +using Point_Vector = std::vector<Point_d>; +using Random_cube_iterator = CGAL::Random_points_in_cube_d<Point_d>; +using Random_point_iterator = CGAL::Random_points_in_ball_d<Point_d>; /** * \brief Rock age method of reading off file @@ -144,4 +146,21 @@ void generate_points_sphere(Point_Vector& W, int nbP, int dim) { W.push_back(*rp++); } +/** \brief Generate nbP points on a (flat) d-torus embedded in R^{2d} + * + */ +void generate_points_torus(Point_Vector& W, int nbP, int dim) { + CGAL::Random rand; + const double pi = std::acos(-1); + for (int i = 0; i < nbP; i++) { + std::vector<FT> point; + for (int j = 0; j < dim; j++) { + double alpha = rand.uniform_real(static_cast<double>(0), 2*pi); + point.push_back(sin(alpha)); + point.push_back(cos(alpha)); + } + W.push_back(Point_d(point)); + } +} + #endif // EXAMPLE_WITNESS_COMPLEX_GENERATORS_H_ diff --git a/src/Witness_complex/include/gudhi/Active_witness/Active_witness.h b/src/Witness_complex/include/gudhi/Active_witness/Active_witness.h new file mode 100644 index 00000000..d41a6811 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Active_witness/Active_witness.h @@ -0,0 +1,67 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2016 INRIA (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/>. + */ + +#ifndef ACTIVE_WITNESS_ACTIVE_WITNESS_H_ +#define ACTIVE_WITNESS_ACTIVE_WITNESS_H_ + +#include <gudhi/Active_witness/Active_witness_iterator.h> +#include <list> + +namespace Gudhi { + +namespace witness_complex { + + /* \class Active_witness + * \brief Class representing a list of nearest neighbors to a given witness. + * \details Every element is a pair of a landmark identifier and the squared distance to it. + */ +template< typename Id_distance_pair, + typename INS_range > +class Active_witness { + public: + typedef Active_witness<Id_distance_pair, INS_range> ActiveWitness; + typedef typename INS_range::iterator INS_iterator; + typedef Active_witness_iterator< ActiveWitness, Id_distance_pair, INS_iterator > iterator; + typedef typename std::list<Id_distance_pair> Table; + + Table nearest_landmark_table_; + INS_range search_range_; + INS_iterator iterator_next_; + INS_iterator iterator_end_; + + Active_witness(const INS_range& search_range) + : search_range_(search_range), iterator_next_(search_range_.begin()), iterator_end_(search_range_.end()) { + } + + iterator begin() { + return iterator(this, nearest_landmark_table_.begin()); + } + + iterator end() { + return iterator(this); + } +}; + +} // namespace witness_complex +} // namespace Gudhi + +#endif // ACTIVE_WITNESS_ACTIVE_WITNESS_H_ diff --git a/src/Witness_complex/include/gudhi/Active_witness/Active_witness_iterator.h b/src/Witness_complex/include/gudhi/Active_witness/Active_witness_iterator.h new file mode 100644 index 00000000..0a05173a --- /dev/null +++ b/src/Witness_complex/include/gudhi/Active_witness/Active_witness_iterator.h @@ -0,0 +1,108 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2016 INRIA (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/>. + */ + +#ifndef ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_ +#define ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_ + +#include <boost/iterator/iterator_facade.hpp> +#include <list> + +namespace Gudhi { + +namespace witness_complex { + +/* \brief Iterator in the nearest landmark list. + * \details After the iterator reaches the end of the list, + * the list is augmented by a (nearest landmark, distance) pair if possible. + * If all the landmarks are present in the list, iterator returns the specific end value + * of the corresponding 'Active_witness' object. + */ +template< typename Active_witness, + typename Id_distance_pair, + typename INS_iterator > +class Active_witness_iterator + : public boost::iterator_facade< Active_witness_iterator <Active_witness, Id_distance_pair, INS_iterator>, + Id_distance_pair const, + boost::forward_traversal_tag, + Id_distance_pair const> { + friend class boost::iterator_core_access; + + typedef typename std::list<Id_distance_pair>::iterator Pair_iterator; + typedef typename Gudhi::witness_complex::Active_witness_iterator<Active_witness, + Id_distance_pair, + INS_iterator> Iterator; + + Active_witness *aw_; + Pair_iterator lh_; // landmark handle + bool is_end_; // true only if the pointer is end and there are no more neighbors to add + + public: + Active_witness_iterator(Active_witness* aw) + : aw_(aw), lh_(aw_->nearest_landmark_table_.end()), is_end_(true) { + } + + Active_witness_iterator(Active_witness* aw, const Pair_iterator& lh) + : aw_(aw), lh_(lh) { + is_end_ = false; + if (lh_ == aw_->nearest_landmark_table_.end()) { + if (aw_->iterator_next_ == aw_->iterator_end_) { + is_end_ = true; + } else { + aw_->nearest_landmark_table_.push_back(*aw_->iterator_next_); + lh_ = --aw_->nearest_landmark_table_.end(); + ++(aw_->iterator_next_); + } + } + } + + private : + Id_distance_pair& dereference() const { + return *lh_; + } + + bool equal(const Iterator& other) const { + return (is_end_ == other.is_end_) || (lh_ == other.lh_); + } + + void increment() { + // the neighbor search can't be at the end iterator of a list + GUDHI_CHECK(!is_end_ && lh_ != aw_->nearest_landmark_table_.end(), + std::logic_error("Wrong active witness increment.")); + // if the id of the current landmark is the same as the last one + + lh_++; + if (lh_ == aw_->nearest_landmark_table_.end()) { + if (aw_->iterator_next_ == aw_->iterator_end_) { + is_end_ = true; + } else { + aw_->nearest_landmark_table_.push_back(*aw_->iterator_next_); + lh_ = std::prev(aw_->nearest_landmark_table_.end()); + ++(aw_->iterator_next_); + } + } + } +}; + +} // namespace witness_complex +} // namespace Gudhi + +#endif // ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_ diff --git a/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h b/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h deleted file mode 100644 index a8cdd096..00000000 --- a/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h +++ /dev/null @@ -1,92 +0,0 @@ -/* 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): Siargey Kachanovich - * - * Copyright (C) 2015 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 CONSTRUCT_CLOSEST_LANDMARK_TABLE_H_ -#define CONSTRUCT_CLOSEST_LANDMARK_TABLE_H_ - -#include <boost/range/size.hpp> - -#include <queue> // for priority_queue<> -#include <utility> // for pair<> -#include <iterator> -#include <vector> -#include <set> - -namespace Gudhi { - -namespace witness_complex { - - /** - * \ingroup witness_complex - * \brief Construct the closest landmark tables for all witnesses. - * \details Output a table 'knn', each line of which represents a witness and - * consists of landmarks sorted by - * euclidean distance from the corresponding witness. - * - * The type WitnessContainer is a random access range and - * the type LandmarkContainer is a range. - * The type KNearestNeighbors can be seen as - * Witness_range<Closest_landmark_range<Vertex_handle>>, where - * Witness_range and Closest_landmark_range are random access ranges and - * Vertex_handle is the label type of a vertex in a simplicial complex. - * Closest_landmark_range needs to have push_back operation. - */ - - template <typename FiltrationValue, - typename WitnessContainer, - typename LandmarkContainer, - typename KNearestNeighbours> - void construct_closest_landmark_table(WitnessContainer const &points, - LandmarkContainer const &landmarks, - KNearestNeighbours &knn) { - int nbP = boost::size(points); - assert(nbP >= boost::size(landmarks)); - - int dim = boost::size(*std::begin(points)); - typedef std::pair<double, int> dist_i; - typedef bool (*comp)(dist_i, dist_i); - knn = KNearestNeighbours(nbP); - for (int points_i = 0; points_i < nbP; points_i++) { - std::priority_queue<dist_i, std::vector<dist_i>, comp> l_heap([](dist_i j1, dist_i j2) { - return j1.first > j2.first; - }); - typename LandmarkContainer::const_iterator landmarks_it; - int landmarks_i = 0; - for (landmarks_it = landmarks.begin(), landmarks_i = 0; landmarks_it != landmarks.end(); - ++landmarks_it, landmarks_i++) { - dist_i dist = std::make_pair(Euclidean_distance()(points[points_i], *landmarks_it), - landmarks_i); - l_heap.push(dist); - } - for (int i = 0; i < dim + 1; i++) { - dist_i dist = l_heap.top(); - knn[points_i].push_back(dist.second); - l_heap.pop(); - } - } - } - -} // namespace witness_complex - -} // namespace Gudhi - -#endif // CONSTRUCT_CLOSEST_LANDMARK_TABLE_H_ diff --git a/src/Witness_complex/include/gudhi/Euclidean_strong_witness_complex.h b/src/Witness_complex/include/gudhi/Euclidean_strong_witness_complex.h new file mode 100644 index 00000000..fb669ef8 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Euclidean_strong_witness_complex.h @@ -0,0 +1,104 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA (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/>. + */ + +#ifndef EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_ +#define EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_ + +#include <gudhi/Strong_witness_complex.h> +#include <gudhi/Active_witness/Active_witness.h> +#include <gudhi/Kd_tree_search.h> + +#include <utility> +#include <vector> + +namespace Gudhi { + +namespace witness_complex { + +/** + * \private + * \class Euclidean_strong_witness_complex + * \brief Constructs strong witness complex for given sets of witnesses and landmarks in Euclidean space. + * \ingroup witness_complex + * + * \tparam Kernel_ requires a <a target="_blank" + * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class. + */ +template< class Kernel_ > +class Euclidean_strong_witness_complex + : public Strong_witness_complex<std::vector<typename Gudhi::spatial_searching::Kd_tree_search<Kernel_, + std::vector<typename Kernel_::Point_d>>::INS_range>> { + private: + typedef Kernel_ K; + typedef typename K::Point_d Point_d; + typedef std::vector<Point_d> Point_range; + typedef Gudhi::spatial_searching::Kd_tree_search<Kernel_, Point_range> Kd_tree; + typedef typename Kd_tree::INS_range Nearest_landmark_range; + typedef typename std::vector<Nearest_landmark_range> Nearest_landmark_table; + + typedef typename Nearest_landmark_range::Point_with_transformed_distance Id_distance_pair; + typedef typename Id_distance_pair::first_type Landmark_id; + typedef Landmark_id Vertex_handle; + + private: + Point_range landmarks_; + Kd_tree landmark_tree_; + using Strong_witness_complex<Nearest_landmark_table>::nearest_landmark_table_; + + public: + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /* @name Constructor + */ + + //@{ + + /** + * \brief Initializes member variables before constructing simplicial complex. + * \details Records landmarks from the range 'landmarks' into a + * table internally, as well as witnesses from the range 'witnesses'. + * Both ranges should have value_type Kernel_::Point_d. + */ + template< typename LandmarkRange, + typename WitnessRange > + Euclidean_strong_witness_complex(const LandmarkRange & landmarks, + const WitnessRange & witnesses) + : landmarks_(std::begin(landmarks), std::end(landmarks)), landmark_tree_(landmarks_) { + nearest_landmark_table_.reserve(boost::size(witnesses)); + for (auto w : witnesses) + nearest_landmark_table_.push_back(landmark_tree_.query_incremental_nearest_neighbors(w)); + } + + /** \brief Returns the point corresponding to the given vertex. + */ + template <typename Vertex_handle> + Point_d get_point(Vertex_handle vertex) const { + return landmarks_[vertex]; + } + + //@} +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_ diff --git a/src/Witness_complex/include/gudhi/Euclidean_witness_complex.h b/src/Witness_complex/include/gudhi/Euclidean_witness_complex.h new file mode 100644 index 00000000..6afe9a5d --- /dev/null +++ b/src/Witness_complex/include/gudhi/Euclidean_witness_complex.h @@ -0,0 +1,106 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA (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/>. + */ + +#ifndef EUCLIDEAN_WITNESS_COMPLEX_H_ +#define EUCLIDEAN_WITNESS_COMPLEX_H_ + +#include <gudhi/Witness_complex.h> +#include <gudhi/Active_witness/Active_witness.h> +#include <gudhi/Kd_tree_search.h> + +#include <utility> +#include <vector> +#include <list> +#include <limits> + +namespace Gudhi { + +namespace witness_complex { + +/** + * \private + * \class Euclidean_witness_complex + * \brief Constructs (weak) witness complex for given sets of witnesses and landmarks in Euclidean space. + * \ingroup witness_complex + * + * \tparam Kernel_ requires a <a target="_blank" + * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class. + */ +template< class Kernel_ > +class Euclidean_witness_complex + : public Witness_complex<std::vector<typename Gudhi::spatial_searching::Kd_tree_search<Kernel_, + std::vector<typename Kernel_::Point_d>>::INS_range>> { + private: + typedef Kernel_ K; + typedef typename K::Point_d Point_d; + typedef std::vector<Point_d> Point_range; + typedef Gudhi::spatial_searching::Kd_tree_search<Kernel_, Point_range> Kd_tree; + typedef typename Kd_tree::INS_range Nearest_landmark_range; + typedef typename std::vector<Nearest_landmark_range> Nearest_landmark_table; + + typedef typename Nearest_landmark_range::Point_with_transformed_distance Id_distance_pair; + typedef typename Id_distance_pair::first_type Landmark_id; + typedef Landmark_id Vertex_handle; + + private: + Point_range landmarks_; + Kd_tree landmark_tree_; + using Witness_complex<Nearest_landmark_table>::nearest_landmark_table_; + + public: + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /* @name Constructor + */ + + //@{ + + /** + * \brief Initializes member variables before constructing simplicial complex. + * \details Records landmarks from the range 'landmarks' into a + * table internally, as well as witnesses from the range 'witnesses'. + * Both ranges should have value_type Kernel_::Point_d. + */ + template< typename LandmarkRange, + typename WitnessRange > + Euclidean_witness_complex(const LandmarkRange & landmarks, + const WitnessRange & witnesses) + : landmarks_(std::begin(landmarks), std::end(landmarks)), landmark_tree_(landmarks) { + nearest_landmark_table_.reserve(boost::size(witnesses)); + for (auto w : witnesses) + nearest_landmark_table_.push_back(landmark_tree_.query_incremental_nearest_neighbors(w)); + } + + /** \brief Returns the point corresponding to the given vertex. + * @param[in] vertex Vertex handle of the point to retrieve. + */ + Point_d get_point(Vertex_handle vertex) const { + return landmarks_[vertex]; + } + + //@} +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // EUCLIDEAN_WITNESS_COMPLEX_H_ diff --git a/src/Witness_complex/include/gudhi/Strong_witness_complex.h b/src/Witness_complex/include/gudhi/Strong_witness_complex.h new file mode 100644 index 00000000..a973ddb7 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Strong_witness_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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA (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/>. + */ + +#ifndef STRONG_WITNESS_COMPLEX_H_ +#define STRONG_WITNESS_COMPLEX_H_ + +#include <gudhi/Active_witness/Active_witness.h> + +#include <utility> +#include <vector> +#include <list> +#include <limits> + +namespace Gudhi { + +namespace witness_complex { + +/* \private + * \class Strong_witness_complex + * \brief Constructs strong witness complex for a given table of nearest landmarks with respect to witnesses. + * \ingroup witness_complex + * + * \tparam Nearest_landmark_table_ needs to be a range of a range of pairs of nearest landmarks and distances. + * The class Nearest_landmark_table_::value_type must be a copiable range. + * The range of pairs must admit a member type 'iterator'. The dereference type + * of the pair range iterator needs to be 'std::pair<std::size_t, double>'. + */ +template< class Nearest_landmark_table_ > +class Strong_witness_complex { + private: + typedef typename Nearest_landmark_table_::value_type Nearest_landmark_range; + typedef std::size_t Witness_id; + typedef std::size_t Landmark_id; + typedef std::pair<Landmark_id, double> Id_distance_pair; + typedef Active_witness<Id_distance_pair, Nearest_landmark_range> ActiveWitness; + typedef std::list< ActiveWitness > ActiveWitnessList; + typedef std::vector< Landmark_id > typeVectorVertex; + typedef std::vector<Nearest_landmark_range> Nearest_landmark_table_internal; + typedef Landmark_id Vertex_handle; + + protected: + Nearest_landmark_table_internal nearest_landmark_table_; + + public: + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /* @name Constructor + */ + + //@{ + + Strong_witness_complex() { + } + + /** + * \brief Initializes member variables before constructing simplicial complex. + * \details Records nearest landmark table. + * @param[in] nearest_landmark_table needs to be a range of a range of pairs of nearest landmarks and distances. + * The class Nearest_landmark_table_::value_type must be a copiable range. + * The range of pairs must admit a member type 'iterator'. The dereference type + * of the pair range iterator needs to be 'std::pair<std::size_t, double>'. + */ + Strong_witness_complex(Nearest_landmark_table_ const & nearest_landmark_table) + : nearest_landmark_table_(std::begin(nearest_landmark_table), std::end(nearest_landmark_table)) { + } + + /** \brief Outputs the strong witness complex of relaxation 'max_alpha_square' + * in a simplicial complex data structure. + * \details The function returns true if the construction is successful and false otherwise. + * @param[out] complex Simplicial complex data structure, which is a model of + * SimplicialComplexForWitness concept. + * @param[in] max_alpha_square Maximal squared relaxation parameter. + * @param[in] limit_dimension Represents the maximal dimension of the simplicial complex + * (default value = no limit). + */ + template < typename SimplicialComplexForWitness > + bool create_complex(SimplicialComplexForWitness& complex, + double max_alpha_square, + Landmark_id limit_dimension = std::numeric_limits<Landmark_id>::max()) const { + Landmark_id complex_dim = 0; + if (complex.num_vertices() > 0) { + std::cerr << "Strong witness complex cannot create complex - complex is not empty.\n"; + return false; + } + if (max_alpha_square < 0) { + std::cerr << "Strong witness complex cannot create complex - squared relaxation parameter must be " + << "non-negative.\n"; + return false; + } + if (limit_dimension < 0) { + std::cerr << "Strong witness complex cannot create complex - limit dimension must be non-negative.\n"; + return false; + } + for (auto w : nearest_landmark_table_) { + ActiveWitness aw(w); + typeVectorVertex simplex; + typename ActiveWitness::iterator aw_it = aw.begin(); + float lim_dist2 = aw.begin()->second + max_alpha_square; + while ((Landmark_id)simplex.size() <= limit_dimension && aw_it != aw.end() && aw_it->second < lim_dist2) { + simplex.push_back(aw_it->first); + complex.insert_simplex_and_subfaces(simplex, aw_it->second - aw.begin()->second); + aw_it++; + } + // continue inserting limD-faces of the following simplices + typeVectorVertex& vertices = simplex; // 'simplex' now will be called vertices + while (aw_it != aw.end() && aw_it->second < lim_dist2) { + typeVectorVertex facet = {}; + add_all_faces_of_dimension(limit_dimension, vertices, vertices.begin(), aw_it, + aw_it->second - aw.begin()->second, facet, complex); + vertices.push_back(aw_it->first); + aw_it++; + } + if ((Landmark_id)simplex.size() - 1 > complex_dim) + complex_dim = simplex.size() - 1; + } + complex.set_dimension(complex_dim); + return true; + } + + private: + /* \brief Adds recursively all the faces of a certain dimension dim-1 witnessed by the same witness. + * Iterator is needed to know until how far we can take landmarks to form simplexes. + * simplex is the prefix of the simplexes to insert. + * The landmark pointed by aw_it is added to all formed simplices. + */ + template < typename SimplicialComplexForWitness > + void add_all_faces_of_dimension(Landmark_id dim, + typeVectorVertex& vertices, + typename typeVectorVertex::iterator curr_it, + typename ActiveWitness::iterator aw_it, + double filtration_value, + typeVectorVertex& simplex, + SimplicialComplexForWitness& sc) const { + if (dim > 0) { + while (curr_it != vertices.end()) { + simplex.push_back(*curr_it); + ++curr_it; + add_all_faces_of_dimension(dim-1, + vertices, + curr_it, + aw_it, + filtration_value, + simplex, + sc); + simplex.pop_back(); + add_all_faces_of_dimension(dim, + vertices, + curr_it, + aw_it, + filtration_value, + simplex, + sc); + } + } else if (dim == 0) { + simplex.push_back(aw_it->first); + sc.insert_simplex_and_subfaces(simplex, filtration_value); + simplex.pop_back(); + } + } + //@} +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // STRONG_WITNESS_COMPLEX_H_ diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h index 1eb126f1..e2791f76 100644 --- a/src/Witness_complex/include/gudhi/Witness_complex.h +++ b/src/Witness_complex/include/gudhi/Witness_complex.h @@ -4,7 +4,7 @@ * * Author(s): Siargey Kachanovich * - * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (France) + * Copyright (C) 2015 INRIA (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 @@ -23,64 +23,44 @@ #ifndef WITNESS_COMPLEX_H_ #define WITNESS_COMPLEX_H_ -// Needed for the adjacency graph in bad link search -#include <boost/graph/graph_traits.hpp> -#include <boost/graph/adjacency_list.hpp> -#include <boost/graph/connected_components.hpp> +#include <gudhi/Active_witness/Active_witness.h> +#include <gudhi/Witness_complex/all_faces_in.h> -#include <boost/range/size.hpp> - -#include <gudhi/distance_functions.h> - -#include <algorithm> #include <utility> #include <vector> #include <list> -#include <set> -#include <queue> #include <limits> -#include <ctime> -#include <iostream> namespace Gudhi { namespace witness_complex { -// /* -// * \private -// \class Witness_complex -// \brief Constructs the witness complex for the given set of witnesses and landmarks. -// \ingroup witness_complex -// */ -template< class SimplicialComplex> +/** + * \private + * \class Witness_complex + * \brief Constructs (weak) witness complex for a given table of nearest landmarks with respect to witnesses. + * \ingroup witness_complex + * + * \tparam Nearest_landmark_table_ needs to be a range of a range of pairs of nearest landmarks and distances. + * The class Nearest_landmark_table_::value_type must be a copiable range. + * The range of pairs must admit a member type 'iterator'. The dereference type + * of the pair range iterator needs to be 'std::pair<std::size_t, double>'. +*/ +template< class Nearest_landmark_table_ > class Witness_complex { private: - struct Active_witness { - int witness_id; - int landmark_id; - - Active_witness(int witness_id_, int landmark_id_) - : witness_id(witness_id_), - landmark_id(landmark_id_) { } - }; - - private: - typedef typename SimplicialComplex::Simplex_handle Simplex_handle; - typedef typename SimplicialComplex::Vertex_handle Vertex_handle; - - typedef std::vector< double > Point_t; - typedef std::vector< Point_t > Point_Vector; - - typedef std::vector< Vertex_handle > typeVectorVertex; - typedef std::pair< Simplex_handle, bool > typePairSimplexBool; - - typedef int Witness_id; - typedef int Landmark_id; - typedef std::list< Vertex_handle > ActiveWitnessList; - - private: - int nbL_; // Number of landmarks - SimplicialComplex& sc_; // Simplicial complex + typedef typename Nearest_landmark_table_::value_type Nearest_landmark_range; + typedef std::size_t Witness_id; + typedef std::size_t Landmark_id; + typedef std::pair<Landmark_id, double> Id_distance_pair; + typedef Active_witness<Id_distance_pair, Nearest_landmark_range> ActiveWitness; + typedef std::list< ActiveWitness > ActiveWitnessList; + typedef std::vector< Landmark_id > typeVectorVertex; + typedef std::vector<Nearest_landmark_range> Nearest_landmark_table_internal; + typedef Landmark_id Vertex_handle; + + protected: + Nearest_landmark_table_internal nearest_landmark_table_; public: ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -89,174 +69,136 @@ class Witness_complex { //@{ - // Witness_range<Closest_landmark_range<Vertex_handle>> + Witness_complex() { + } - /* - * \brief Iterative construction of the witness complex. - * \details The witness complex is written in sc_ basing on a matrix knn of - * nearest neighbours of the form {witnesses}x{landmarks}. - * - * The type KNearestNeighbors can be seen as - * Witness_range<Closest_landmark_range<Vertex_handle>>, where - * Witness_range and Closest_landmark_range are random access ranges. - * - * Constructor takes into account at most (dim+1) - * first landmarks from each landmark range to construct simplices. - * - * Landmarks are supposed to be in [0,nbL_-1] + /** + * \brief Initializes member variables before constructing simplicial complex. + * \details Records nearest landmark table. + * @param[in] nearest_landmark_table needs to be a range of a range of pairs of nearest landmarks and distances. + * The class Nearest_landmark_table_::value_type must be a copiable range. + * The range of pairs must admit a member type 'iterator'. The dereference type + * of the pair range iterator needs to be 'std::pair<std::size_t, double>'. */ - template< typename KNearestNeighbors > - Witness_complex(KNearestNeighbors const & knn, - int nbL, - int dim, - SimplicialComplex & sc) : nbL_(nbL), sc_(sc) { - // Construction of the active witness list - int nbW = boost::size(knn); - typeVectorVertex vv; - int counter = 0; - /* The list of still useful witnesses - * it will diminuish in the course of iterations - */ - ActiveWitnessList active_w; // = new ActiveWitnessList(); - for (Vertex_handle i = 0; i != nbL_; ++i) { - // initial fill of 0-dimensional simplices - // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore - counter++; - vv = {i}; - sc_.insert_simplex(vv); - // TODO(SK) Error if not inserted : normally no need here though + + Witness_complex(Nearest_landmark_table_ const & nearest_landmark_table) + : nearest_landmark_table_(std::begin(nearest_landmark_table), std::end(nearest_landmark_table)) { + } + + /** \brief Outputs the (weak) witness complex of relaxation 'max_alpha_square' + * in a simplicial complex data structure. + * \details The function returns true if the construction is successful and false otherwise. + * @param[out] complex Simplicial complex data structure compatible which is a model of + * SimplicialComplexForWitness concept. + * @param[in] max_alpha_square Maximal squared relaxation parameter. + * @param[in] limit_dimension Represents the maximal dimension of the simplicial complex + * (default value = no limit). + */ + template < typename SimplicialComplexForWitness > + bool create_complex(SimplicialComplexForWitness& complex, + double max_alpha_square, + std::size_t limit_dimension = std::numeric_limits<std::size_t>::max()) const { + if (complex.num_vertices() > 0) { + std::cerr << "Witness complex cannot create complex - complex is not empty.\n"; + return false; } - int k = 1; /* current dimension in iterative construction */ - for (int i = 0; i != nbW; ++i) - active_w.push_back(i); - while (!active_w.empty() && k < dim) { - typename ActiveWitnessList::iterator it = active_w.begin(); - while (it != active_w.end()) { - typeVectorVertex simplex_vector; - /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/ - bool ok = all_faces_in(knn, *it, k); - if (ok) { - for (int i = 0; i != k + 1; ++i) - simplex_vector.push_back(knn[*it][i]); - sc_.insert_simplex(simplex_vector); - // TODO(SK) Error if not inserted : normally no need here though - ++it; - } else { - active_w.erase(it++); // First increase the iterator and then erase the previous element - } + if (max_alpha_square < 0) { + std::cerr << "Witness complex cannot create complex - squared relaxation parameter must be non-negative.\n"; + return false; + } + if (limit_dimension < 0) { + std::cerr << "Witness complex cannot create complex - limit dimension must be non-negative.\n"; + return false; + } + ActiveWitnessList active_witnesses; + Landmark_id k = 0; /* current dimension in iterative construction */ + for (auto w : nearest_landmark_table_) + active_witnesses.push_back(ActiveWitness(w)); + while (!active_witnesses.empty() && k <= limit_dimension) { + typename ActiveWitnessList::iterator aw_it = active_witnesses.begin(); + std::vector<Landmark_id> simplex; + simplex.reserve(k+1); + while (aw_it != active_witnesses.end()) { + bool ok = add_all_faces_of_dimension(k, + max_alpha_square, + std::numeric_limits<double>::infinity(), + aw_it->begin(), + simplex, + complex, + aw_it->end()); + assert(simplex.empty()); + if (!ok) + active_witnesses.erase(aw_it++); // First increase the iterator and then erase the previous element + else + aw_it++; } k++; } + complex.set_dimension(k-1); + return true; } //@} private: - /* \brief Check if the facets of the k-dimensional simplex witnessed - * by witness witness_id are already in the complex. - * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id + /* \brief Adds recursively all the faces of a certain dimension dim witnessed by the same witness. + * Iterator is needed to know until how far we can take landmarks to form simplexes. + * simplex is the prefix of the simplexes to insert. + * The output value indicates if the witness rests active or not. */ - template <typename KNearestNeighbors> - bool all_faces_in(KNearestNeighbors const &knn, int witness_id, int k) { - std::vector< Vertex_handle > facet; - // CHECK ALL THE FACETS - for (int i = 0; i != k + 1; ++i) { - facet = {}; - for (int j = 0; j != k + 1; ++j) { - if (j != i) { - facet.push_back(knn[witness_id][j]); + template < typename SimplicialComplexForWitness > + bool add_all_faces_of_dimension(int dim, + double alpha2, + double norelax_dist2, + typename ActiveWitness::iterator curr_l, + std::vector<Landmark_id>& simplex, + SimplicialComplexForWitness& sc, + typename ActiveWitness::iterator end) const { + if (curr_l == end) + return false; + bool will_be_active = false; + typename ActiveWitness::iterator l_it = curr_l; + if (dim > 0) { + for (; l_it != end && l_it->second - alpha2 <= norelax_dist2; ++l_it) { + simplex.push_back(l_it->first); + if (sc.find(simplex) != sc.null_simplex()) { + typename ActiveWitness::iterator next_it = l_it; + will_be_active = add_all_faces_of_dimension(dim-1, + alpha2, + norelax_dist2, + ++next_it, + simplex, + sc, + end) || will_be_active; } - } // endfor - if (sc_.find(facet) == sc_.null_simplex()) - return false; - } // endfor - return true; - } - - template <typename T> - static void print_vector(const std::vector<T>& v) { - std::cout << "["; - if (!v.empty()) { - std::cout << *(v.begin()); - for (auto it = v.begin() + 1; it != v.end(); ++it) { - std::cout << ","; - std::cout << *it; + assert(!simplex.empty()); + simplex.pop_back(); + // If norelax_dist is infinity, change to first omitted distance + if (l_it->second <= norelax_dist2) + norelax_dist2 = l_it->second; } - } - std::cout << "]"; - } - - public: - // /* - // * \brief Verification if every simplex in the complex is witnessed by witnesses in knn. - // * \param print_output =true will print the witnesses for each simplex - // * \remark Added for debugging purposes. - // */ - template< class KNearestNeighbors > - bool is_witness_complex(KNearestNeighbors const & knn, bool print_output) { - for (Simplex_handle sh : sc_.complex_simplex_range()) { - bool is_witnessed = false; - typeVectorVertex simplex; - int nbV = 0; // number of verticed in the simplex - for (Vertex_handle v : sc_.simplex_vertex_range(sh)) - simplex.push_back(v); - nbV = simplex.size(); - for (typeVectorVertex w : knn) { - bool has_vertices = true; - for (Vertex_handle v : simplex) - if (std::find(w.begin(), w.begin() + nbV, v) == w.begin() + nbV) { - has_vertices = false; - } - if (has_vertices) { - is_witnessed = true; - if (print_output) { - std::cout << "The simplex "; - print_vector(simplex); - std::cout << " is witnessed by the witness "; - print_vector(w); - std::cout << std::endl; - } - break; - } - } - if (!is_witnessed) { - if (print_output) { - std::cout << "The following simplex is not witnessed "; - print_vector(simplex); - std::cout << std::endl; + } else if (dim == 0) { + for (;l_it != end && l_it->second - alpha2 <= norelax_dist2; ++l_it) { + simplex.push_back(l_it->first); + double filtration_value = 0; + // if norelax_dist is infinite, relaxation is 0. + if (l_it->second > norelax_dist2) + filtration_value = l_it->second - norelax_dist2; + if (all_faces_in(simplex, &filtration_value, sc)) { + will_be_active = true; + sc.insert_simplex(simplex, filtration_value); } - assert(is_witnessed); - return false; + assert(!simplex.empty()); + simplex.pop_back(); + // If norelax_dist is infinity, change to first omitted distance + if (l_it->second < norelax_dist2) + norelax_dist2 = l_it->second; } } - return true; + return will_be_active; } }; - /** - * \ingroup witness_complex - * \brief Iterative construction of the witness complex. - * \details The witness complex is written in simplicial complex sc_ - * basing on a matrix knn of - * nearest neighbours of the form {witnesses}x{landmarks}. - * - * The type KNearestNeighbors can be seen as - * Witness_range<Closest_landmark_range<Vertex_handle>>, where - * Witness_range and Closest_landmark_range are random access ranges. - * - * Procedure takes into account at most (dim+1) - * first landmarks from each landmark range to construct simplices. - * - * Landmarks are supposed to be in [0,nbL_-1] - */ - template <class KNearestNeighbors, class SimplicialComplexForWitness> - void witness_complex(KNearestNeighbors const & knn, - int nbL, - int dim, - SimplicialComplexForWitness & sc) { - Witness_complex<SimplicialComplexForWitness>(knn, nbL, dim, sc); - } - } // namespace witness_complex } // namespace Gudhi diff --git a/src/Witness_complex/include/gudhi/Witness_complex/all_faces_in.h b/src/Witness_complex/include/gudhi/Witness_complex/all_faces_in.h new file mode 100644 index 00000000..b68d75a1 --- /dev/null +++ b/src/Witness_complex/include/gudhi/Witness_complex/all_faces_in.h @@ -0,0 +1,55 @@ +/* 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): Siargey Kachanovich + * + * Copyright (C) 2015 INRIA (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/>. + */ + +#ifndef WITNESS_COMPLEX_ALL_FACES_IN_H_ +#define WITNESS_COMPLEX_ALL_FACES_IN_H_ + +/* \brief Check if the facets of the k-dimensional simplex witnessed + * by witness witness_id are already in the complex. + * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id + */ +template < typename SimplicialComplexForWitness, + typename Simplex > + bool all_faces_in(Simplex& simplex, + double* filtration_value, + SimplicialComplexForWitness& sc) { + typedef typename SimplicialComplexForWitness::Simplex_handle Simplex_handle; + + if (simplex.size() == 1) + return true; /* Add vertices unconditionally */ + + Simplex facet; + for (typename Simplex::iterator not_it = simplex.begin(); not_it != simplex.end(); ++not_it) { + facet.clear(); + for (typename Simplex::iterator it = simplex.begin(); it != simplex.end(); ++it) + if (it != not_it) + facet.push_back(*it); + Simplex_handle facet_sh = sc.find(facet); + if (facet_sh == sc.null_simplex()) + return false; + else if (sc.filtration(facet_sh) > *filtration_value) + *filtration_value = sc.filtration(facet_sh); + } + return true; + } + +#endif // WITNESS_COMPLEX_ALL_FACES_IN_H_ diff --git a/src/Witness_complex/test/CMakeLists.txt b/src/Witness_complex/test/CMakeLists.txt index bb55b0f1..12b3be56 100644 --- a/src/Witness_complex/test/CMakeLists.txt +++ b/src/Witness_complex/test/CMakeLists.txt @@ -10,21 +10,33 @@ if (GPROF_PATH) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") endif() -add_executable ( simple_witness_complexUT simple_witness_complex.cpp ) -target_link_libraries(simple_witness_complexUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) +add_executable ( Witness_complex_test_simple_witness_complex test_simple_witness_complex.cpp ) +target_link_libraries(Witness_complex_test_simple_witness_complex ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) +if (TBB_FOUND) + target_link_libraries(Witness_complex_test_simple_witness_complex ${TBB_LIBRARIES}) +endif(TBB_FOUND) # Unitary tests definition and xml result file generation -add_test(NAME simple_witness_complexUT - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/simple_witness_complexUT +add_test(NAME simple_witness_complex + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/Witness_complex_test_simple_witness_complex # XML format for Jenkins xUnit plugin - --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/simple_witness_complexUT.xml --log_level=test_suite --report_level=no) + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/Witness_complex_test_simple_witness_complexUT.xml --log_level=test_suite --report_level=no) -add_executable ( witness_complex_pointsUT witness_complex_points.cpp ) -target_link_libraries(witness_complex_pointsUT ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - -# Unitary tests definition and xml result file generation -add_test(NAME witness_complex_pointsUT - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/witness_complex_pointsUT - # XML format for Jenkins xUnit plugin - --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/witness_complex_pointsUT.xml --log_level=test_suite --report_level=no) +# CGAL and Eigen3 are required for Euclidean version of Witness +if(CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + if (EIGEN3_FOUND) + add_executable ( Witness_complex_test_euclidean_simple_witness_complex test_euclidean_simple_witness_complex.cpp ) + target_link_libraries(Witness_complex_test_euclidean_simple_witness_complex ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(Witness_complex_test_euclidean_simple_witness_complex ${TBB_LIBRARIES}) + endif(TBB_FOUND) + # Unitary tests definition and xml result file generation + add_test(NAME euclidean_simple_witness_complex + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/Witness_complex_test_euclidean_simple_witness_complex + # XML format for Jenkins xUnit plugin + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/Witness_complex_test_euclidean_simple_witness_complexUT.xml --log_level=test_suite --report_level=no) + endif(EIGEN3_FOUND) + endif (NOT CGAL_VERSION VERSION_LESS 4.6.0) +endif() diff --git a/src/Witness_complex/test/simple_witness_complex.cpp b/src/Witness_complex/test/simple_witness_complex.cpp deleted file mode 100644 index 6be39f58..00000000 --- a/src/Witness_complex/test/simple_witness_complex.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* 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): Siargey Kachanovich - * - * Copyright (C) 2016 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/>. - */ - -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "simple_witness_complex" -#include <boost/test/unit_test.hpp> -#include <boost/mpl/list.hpp> - -#include <gudhi/Simplex_tree.h> -#include <gudhi/Witness_complex.h> - -#include <iostream> -#include <ctime> -#include <vector> - -typedef Gudhi::Simplex_tree<> Simplex_tree; -typedef std::vector< Simplex_tree::Vertex_handle > typeVectorVertex; -typedef Gudhi::witness_complex::Witness_complex<Simplex_tree> WitnessComplex; - -BOOST_AUTO_TEST_CASE(simple_witness_complex) { - Simplex_tree complex; - std::vector< typeVectorVertex > knn; - - knn.push_back({1, 0, 5, 2, 6, 3, 4}); - knn.push_back({2, 6, 4, 5, 0, 1, 3}); - knn.push_back({3, 4, 2, 1, 5, 6, 0}); - knn.push_back({4, 2, 1, 3, 5, 6, 0}); - knn.push_back({5, 1, 6, 0, 2, 3, 4}); - knn.push_back({6, 0, 5, 2, 1, 3, 4}); - knn.push_back({0, 5, 6, 1, 2, 3, 4}); - knn.push_back({2, 6, 4, 5, 3, 1, 0}); - knn.push_back({1, 2, 5, 4, 3, 6, 0}); - knn.push_back({3, 4, 0, 6, 5, 1, 2}); - knn.push_back({5, 0, 1, 3, 6, 2, 4}); - knn.push_back({5, 6, 1, 0, 2, 3, 4}); - knn.push_back({1, 6, 0, 5, 2, 3, 4}); - WitnessComplex witnessComplex(knn, 7, 7, complex); - - BOOST_CHECK(witnessComplex.is_witness_complex(knn, false)); -} diff --git a/src/Witness_complex/test/test_euclidean_simple_witness_complex.cpp b/src/Witness_complex/test/test_euclidean_simple_witness_complex.cpp new file mode 100644 index 00000000..62fd1157 --- /dev/null +++ b/src/Witness_complex/test/test_euclidean_simple_witness_complex.cpp @@ -0,0 +1,135 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "euclidean_simple_witness_complex" +#include <boost/test/unit_test.hpp> +#include <boost/mpl/list.hpp> + +#include <CGAL/Epick_d.h> + +#include <gudhi/Simplex_tree.h> + +#include <gudhi/Witness_complex.h> +#include <gudhi/Euclidean_witness_complex.h> +#include <gudhi/Strong_witness_complex.h> +#include <gudhi/Euclidean_strong_witness_complex.h> + +#include <gudhi/Kd_tree_search.h> + +#include <iostream> +#include <ctime> +#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; +typedef typename Kernel::Point_d Point_d; +typedef Gudhi::witness_complex::Euclidean_witness_complex<Kernel> EuclideanWitnessComplex; +typedef Gudhi::witness_complex::Euclidean_strong_witness_complex<Kernel> EuclideanStrongWitnessComplex; + +typedef std::vector<Point_d> Point_range; +typedef Gudhi::spatial_searching::Kd_tree_search<Kernel, Point_range> Kd_tree; +typedef Kd_tree::INS_range Nearest_landmark_range; +typedef std::vector<Nearest_landmark_range> Nearest_landmark_table; +typedef Gudhi::witness_complex::Witness_complex<Nearest_landmark_table> WitnessComplex; +typedef Gudhi::witness_complex::Strong_witness_complex<Nearest_landmark_table> StrongWitnessComplex; + + +/* All landmarks and witnesses are taken on the grid in the following manner. + LWLWL + WW.WW + L...L + WW.WW + LWLWL + + Witness complex consists of 8 vertices, 12 edges and 4 triangles + */ + +BOOST_AUTO_TEST_CASE(simple_witness_complex) { + Simplex_tree complex, relaxed_complex, strong_relaxed_complex, strong_relaxed_complex2; + Simplex_tree complex_ne, relaxed_complex_ne, strong_relaxed_complex_ne, strong_relaxed_complex2_ne; + + Point_range witnesses, landmarks; + + landmarks.push_back(Point_d(std::vector<FT>{-2,-2})); + landmarks.push_back(Point_d(std::vector<FT>{-2, 0})); + landmarks.push_back(Point_d(std::vector<FT>{-2, 2})); + landmarks.push_back(Point_d(std::vector<FT>{ 0,-2})); + landmarks.push_back(Point_d(std::vector<FT>{ 0, 2})); + landmarks.push_back(Point_d(std::vector<FT>{ 2,-2})); + landmarks.push_back(Point_d(std::vector<FT>{ 2, 0})); + landmarks.push_back(Point_d(std::vector<FT>{ 2, 2})); + witnesses.push_back(Point_d(std::vector<FT>{-2,-1})); + witnesses.push_back(Point_d(std::vector<FT>{-2, 1})); + witnesses.push_back(Point_d(std::vector<FT>{-1,-2})); + witnesses.push_back(Point_d(std::vector<FT>{-1,-1})); + witnesses.push_back(Point_d(std::vector<FT>{-1, 1})); + witnesses.push_back(Point_d(std::vector<FT>{-1, 2})); + witnesses.push_back(Point_d(std::vector<FT>{ 1,-2})); + witnesses.push_back(Point_d(std::vector<FT>{ 1,-1})); + witnesses.push_back(Point_d(std::vector<FT>{ 1, 1})); + witnesses.push_back(Point_d(std::vector<FT>{ 1, 2})); + witnesses.push_back(Point_d(std::vector<FT>{ 2,-1})); + witnesses.push_back(Point_d(std::vector<FT>{ 2, 1})); + + Kd_tree landmark_tree(landmarks); + Nearest_landmark_table nearest_landmark_table; + for (auto w: witnesses) + nearest_landmark_table.push_back(landmark_tree.query_incremental_nearest_neighbors(w)); + + // Weak witness complex: Euclidean version + EuclideanWitnessComplex eucl_witness_complex(landmarks, + witnesses); + eucl_witness_complex.create_complex(complex, 0); + + std::cout << "complex.num_simplices() = " << complex.num_simplices() << std::endl; + BOOST_CHECK(complex.num_simplices() == 24); + + eucl_witness_complex.create_complex(relaxed_complex, 8.01); + + std::cout << "relaxed_complex.num_simplices() = " << relaxed_complex.num_simplices() << std::endl; + BOOST_CHECK(relaxed_complex.num_simplices() == 239); + // The corner simplex {0,2,5,7} and its cofaces are missing. + + // Weak witness complex: non-Euclidean version + WitnessComplex witness_complex(nearest_landmark_table); + witness_complex.create_complex(complex_ne, 0); + + std::cout << "complex.num_simplices() = " << complex_ne.num_simplices() << std::endl; + BOOST_CHECK(complex_ne.num_simplices() == 24); + + witness_complex.create_complex(relaxed_complex_ne, 8.01); + + std::cout << "relaxed_complex.num_simplices() = " << relaxed_complex_ne.num_simplices() << std::endl; + BOOST_CHECK(relaxed_complex_ne.num_simplices() == 239); + + + // Strong complex : Euclidean version + EuclideanStrongWitnessComplex eucl_strong_witness_complex(landmarks, + witnesses); + + eucl_strong_witness_complex.create_complex(strong_relaxed_complex, 9.1); + eucl_strong_witness_complex.create_complex(strong_relaxed_complex2, 9.1, 2); + + std::cout << "strong_relaxed_complex.num_simplices() = " << strong_relaxed_complex.num_simplices() << std::endl; + BOOST_CHECK(strong_relaxed_complex.num_simplices() == 239); + + std::cout << "strong_relaxed_complex2.num_simplices() = " << strong_relaxed_complex2.num_simplices() << std::endl; + BOOST_CHECK(strong_relaxed_complex2.num_simplices() == 92); + + + // Strong complex : non-Euclidean version + StrongWitnessComplex strong_witness_complex(nearest_landmark_table); + + strong_witness_complex.create_complex(strong_relaxed_complex_ne, 9.1); + strong_witness_complex.create_complex(strong_relaxed_complex2_ne, 9.1, 2); + + std::cout << "strong_relaxed_complex.num_simplices() = " << strong_relaxed_complex_ne.num_simplices() << std::endl; + BOOST_CHECK(strong_relaxed_complex_ne.num_simplices() == 239); + + std::cout << "strong_relaxed_complex2.num_simplices() = " << strong_relaxed_complex2_ne.num_simplices() << std::endl; + BOOST_CHECK(strong_relaxed_complex2_ne.num_simplices() == 92); + + + // 8 vertices, 28 edges, 56 triangles +} diff --git a/src/Witness_complex/test/test_simple_witness_complex.cpp b/src/Witness_complex/test/test_simple_witness_complex.cpp new file mode 100644 index 00000000..9e3509d3 --- /dev/null +++ b/src/Witness_complex/test/test_simple_witness_complex.cpp @@ -0,0 +1,53 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "simple_witness_complex" +#include <boost/test/unit_test.hpp> +#include <boost/mpl/list.hpp> + +#include <gudhi/Simplex_tree.h> + +#include <gudhi/Witness_complex.h> + +#include <iostream> +#include <vector> +#include <utility> + + +BOOST_AUTO_TEST_CASE(simple_witness_complex) { + using Nearest_landmark_range = std::vector<std::pair<std::size_t, double>>; + using Nearest_landmark_table = std::vector<Nearest_landmark_range>; + using Witness_complex = Gudhi::witness_complex::Witness_complex<Nearest_landmark_table>; + using Simplex_tree = Gudhi::Simplex_tree<>; + + Simplex_tree stree; + Nearest_landmark_table nlt; + + // Example contains 5 witnesses and 5 landmarks + Nearest_landmark_range w0 = {std::make_pair(0, 0), std::make_pair(1, 1), std::make_pair(2, 2), + std::make_pair(3, 3), std::make_pair(4, 4)}; nlt.push_back(w0); + Nearest_landmark_range w1 = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(3, 2), + std::make_pair(4, 3), std::make_pair(0, 4)}; nlt.push_back(w1); + Nearest_landmark_range w2 = {std::make_pair(2, 0), std::make_pair(3, 1), std::make_pair(4, 2), + std::make_pair(0, 3), std::make_pair(1, 4)}; nlt.push_back(w2); + Nearest_landmark_range w3 = {std::make_pair(3, 0), std::make_pair(4, 1), std::make_pair(0, 2), + std::make_pair(1, 3), std::make_pair(2, 4)}; nlt.push_back(w3); + Nearest_landmark_range w4 = {std::make_pair(4, 0), std::make_pair(0, 1), std::make_pair(1, 2), + std::make_pair(2, 3), std::make_pair(3, 4)}; nlt.push_back(w4); + + Witness_complex witness_complex(nlt); + BOOST_CHECK(witness_complex.create_complex(stree, 4.1)); + + std::cout << "Number of simplices: " << stree.num_simplices() << std::endl; + BOOST_CHECK(stree.num_simplices() == 31); + + // Check when complex not empty + BOOST_CHECK(!witness_complex.create_complex(stree, 4.1)); + + // Check when max_alpha_square negative + Simplex_tree stree2; + BOOST_CHECK(!witness_complex.create_complex(stree2, -0.02)); + + witness_complex.create_complex(stree2, 4.1, 2); + std::cout << "Number of simplices: " << stree2.num_simplices() << std::endl; + BOOST_CHECK(stree2.num_simplices() == 25); + +} diff --git a/src/Witness_complex/test/witness_complex_points.cpp b/src/Witness_complex/test/witness_complex_points.cpp deleted file mode 100644 index 92f53417..00000000 --- a/src/Witness_complex/test/witness_complex_points.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* 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): Siargey Kachanovich - * - * Copyright (C) 2016 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/>. - */ - -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "witness_complex_points" -#include <boost/test/unit_test.hpp> -#include <boost/mpl/list.hpp> - -#include <gudhi/Simplex_tree.h> -#include <gudhi/Witness_complex.h> -#include <gudhi/Construct_closest_landmark_table.h> -#include <gudhi/pick_n_random_points.h> - -#include <iostream> -#include <vector> - -typedef std::vector<double> Point; -typedef Gudhi::Simplex_tree<> Simplex_tree; -typedef std::vector< Simplex_tree::Vertex_handle > typeVectorVertex; -typedef Gudhi::witness_complex::Witness_complex<Simplex_tree> WitnessComplex; - -BOOST_AUTO_TEST_CASE(witness_complex_points) { - std::vector< typeVectorVertex > knn; - std::vector< Point > points, landmarks; - // Add grid points as witnesses - for (double i = 0; i < 10; i += 1.0) - for (double j = 0; j < 10; j += 1.0) - for (double k = 0; k < 10; k += 1.0) - points.push_back(Point({i, j, k})); - - bool b_print_output = false; - // First test: random choice - Simplex_tree complex1; - Gudhi::subsampling::pick_n_random_points(points, 100, std::back_inserter(landmarks)); - Gudhi::witness_complex::construct_closest_landmark_table<Simplex_tree::Filtration_value>(points, landmarks, knn); - assert(!knn.empty()); - WitnessComplex witnessComplex1(knn, 100, 3, complex1); - BOOST_CHECK(witnessComplex1.is_witness_complex(knn, b_print_output)); -} diff --git a/src/cmake/modules/FindGMPXX.cmake b/src/cmake/modules/FindGMPXX.cmake index 277e4b19..dda302c0 100644 --- a/src/cmake/modules/FindGMPXX.cmake +++ b/src/cmake/modules/FindGMPXX.cmake @@ -33,6 +33,10 @@ if(GMP_FOUND) DOC "Path to the GMPXX library" ) + if ( GMPXX_LIBRARIES ) + get_filename_component(GMPXX_LIBRARIES_DIR ${GMPXX_LIBRARIES} PATH CACHE ) + endif() + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GMPXX "DEFAULT_MSG" GMPXX_LIBRARIES GMPXX_INCLUDE_DIR ) diff --git a/src/cmake/modules/GUDHI_user_version_target.txt b/src/cmake/modules/GUDHI_user_version_target.txt index 71e35353..e4c4ca93 100644 --- a/src/cmake/modules/GUDHI_user_version_target.txt +++ b/src/cmake/modules/GUDHI_user_version_target.txt @@ -1,8 +1,6 @@ # Some functionnalities requires CMake 2.8.11 minimum if (NOT CMAKE_VERSION VERSION_LESS 2.8.11) - string(TIMESTAMP DATE_AND_TIME "%Y-%m-%d-%H-%M-%S") - # Definition of the custom target user_version add_custom_target(user_version) @@ -11,6 +9,7 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.11) set(GUDHI_USER_VERSION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${USER_VERSION_DIR}) else() # set the GUDHI_USER_VERSION_DIR with timestamp and Gudhi version number + string(TIMESTAMP DATE_AND_TIME "%Y-%m-%d-%H-%M-%S") set(GUDHI_USER_VERSION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${DATE_AND_TIME}_GUDHI_${GUDHI_VERSION}) endif() @@ -21,6 +20,8 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.11) COMMENT "user_version creation in ${GUDHI_USER_VERSION_DIR}") add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${CMAKE_SOURCE_DIR}/Conventions.txt ${GUDHI_USER_VERSION_DIR}/Conventions.txt) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/README ${GUDHI_USER_VERSION_DIR}/README) add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/COPYING ${GUDHI_USER_VERSION_DIR}/COPYING) @@ -40,76 +41,53 @@ 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}/biblio ${GUDHI_USER_VERSION_DIR}/biblio) add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_SOURCE_DIR}/src/cython ${GUDHI_USER_VERSION_DIR}/cython) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/data ${GUDHI_USER_VERSION_DIR}/data) add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/src/cmake ${GUDHI_USER_VERSION_DIR}/cmake) add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${CMAKE_SOURCE_DIR}/src/debian ${GUDHI_USER_VERSION_DIR}/debian) - 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;Nerve_GIC;Persistent_cohomology;Rips_complex;Simplex_tree;Skeleton_blocker;Spatial_searching;Subsampling;Tangential_complex;Witness_complex") - + set(GUDHI_DIRECTORIES "doc;example;concept") + set(GUDHI_INCLUDE_DIRECTORIES "include/gudhi;include/gudhi_patches") + foreach(GUDHI_MODULE ${GUDHI_MODULES}) - # doc files - file(GLOB GUDHI_DOC_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/doc/*) - - foreach(GUDHI_DOC_FILE ${GUDHI_DOC_FILES}) - get_filename_component(GUDHI_DOC_FILE_NAME ${GUDHI_DOC_FILE} NAME) - # GUDHI_DOC_FILE can be a file or a directory - if(IS_DIRECTORY ${GUDHI_DOC_FILE}) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${GUDHI_DOC_FILE} ${GUDHI_USER_VERSION_DIR}/doc/${GUDHI_MODULE}/${GUDHI_DOC_FILE_NAME}) - else() - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${GUDHI_DOC_FILE} ${GUDHI_USER_VERSION_DIR}/doc/${GUDHI_MODULE}/${GUDHI_DOC_FILE_NAME}) - endif() - endforeach() - - # example files - file(GLOB GUDHI_EXAMPLE_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/example/*) - - foreach(GUDHI_EXAMPLE_FILE ${GUDHI_EXAMPLE_FILES}) - get_filename_component(GUDHI_EXAMPLE_FILE_NAME ${GUDHI_EXAMPLE_FILE} NAME) - # GUDHI_EXAMPLE_FILE can be a file or a directory - if(IS_DIRECTORY ${GUDHI_EXAMPLE_FILE}) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${GUDHI_EXAMPLE_FILE} ${GUDHI_USER_VERSION_DIR}/example/${GUDHI_MODULE}/${GUDHI_EXAMPLE_FILE_NAME}) - else() - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${GUDHI_EXAMPLE_FILE} ${GUDHI_USER_VERSION_DIR}/example/${GUDHI_MODULE}/${GUDHI_EXAMPLE_FILE_NAME}) - endif() - endforeach() - - # 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/${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/${GUDHI_INCLUDE_FILE_NAME}) - endif() - endforeach() - - # concept files - file(GLOB GUDHI_CONCEPT_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/concept/*.h) - - foreach(GUDHI_CONCEPT_FILE ${GUDHI_CONCEPT_FILES}) - get_filename_component(GUDHI_CONCEPT_FILE_NAME ${GUDHI_CONCEPT_FILE} NAME) - # GUDHI_CONCEPT_FILE can be a file or a directory - if(IS_DIRECTORY ${GUDHI_CONCEPT_FILE}) - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${GUDHI_CONCEPT_FILE} ${GUDHI_USER_VERSION_DIR}/concept/${GUDHI_MODULE}/${GUDHI_CONCEPT_FILE_NAME}) - else() - add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${GUDHI_CONCEPT_FILE} ${GUDHI_USER_VERSION_DIR}/concept/${GUDHI_MODULE}/${GUDHI_CONCEPT_FILE_NAME}) - endif() - endforeach() - endforeach() + foreach(GUDHI_DIRECTORY ${GUDHI_DIRECTORIES}) + # Find files + file(GLOB GUDHI_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/${GUDHI_DIRECTORY}/*) + + foreach(GUDHI_FILE ${GUDHI_FILES}) + get_filename_component(GUDHI_FILE_NAME ${GUDHI_FILE} NAME) + # GUDHI_FILE can be a file or a directory + if(IS_DIRECTORY ${GUDHI_FILE}) + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${GUDHI_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_DIRECTORY}/${GUDHI_MODULE}/${GUDHI_FILE_NAME}) + else() + add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy ${GUDHI_FILE} ${GUDHI_USER_VERSION_DIR}/${GUDHI_DIRECTORY}/${GUDHI_MODULE}/${GUDHI_FILE_NAME}) + endif() + endforeach() + endforeach(GUDHI_DIRECTORY ${GUDHI_DIRECTORIES}) + + foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) + # include files + file(GLOB GUDHI_INCLUDE_FILES ${CMAKE_SOURCE_DIR}/src/${GUDHI_MODULE}/${GUDHI_INCLUDE_DIRECTORY}/*) + + 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}/${GUDHI_INCLUDE_DIRECTORY}/${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}/${GUDHI_INCLUDE_DIRECTORY}/${GUDHI_INCLUDE_FILE_NAME}) + endif() + endforeach() + endforeach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) + + endforeach(GUDHI_MODULE ${GUDHI_MODULES}) endif() diff --git a/src/common/doc/header.html b/src/common/doc/header.html index a6f3ed9c..94e641b2 100644 --- a/src/common/doc/header.html +++ b/src/common/doc/header.html @@ -9,7 +9,7 @@ <!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME--> <!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME--> <!-- GUDHI website css for header BEGIN --> -<link rel="stylesheet" type="text/css" href="http://gudhi.gforge.inria.fr/assets/css/styles_feeling_responsive.css" /> +<link rel="stylesheet" type="text/css" href="http://pages.saclay.inria.fr/vincent.rouvreau/gudhi/gudhi-doc-2.0.0/assets/css/styles_feeling_responsive.css" /> <!-- GUDHI website css for header END --> <link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/> <script type="text/javascript" src="$relpath^jquery.js"></script> @@ -25,6 +25,13 @@ $extrastylesheet <!-- GUDHI website header BEGIN --> <div id="navigation" class="sticky"> <nav class="top-bar" role="navigation" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1 class="show-for-small-only"><a href="http://gudhi.gforge.inria.fr" class="icon-tree"> GUDHI C++ library</a></h1> + </li> + <!-- Remove the class "menu-icon" to get rid of menu icon. Take out "Menu" to just have icon alone --> + <li class="toggle-topbar menu-icon"><a href="#"><span>Navigation</span></a></li> + </ul> <section class="top-bar-section"> <ul class="right"> <li class="divider"></li> @@ -37,7 +44,7 @@ $extrastylesheet <a href="#">Project</a> <ul class="dropdown"> <li><a href="http://gudhi.gforge.inria.fr/people/">People</a></li> - <li><a href="http://gudhi.gforge.inria.fr/getinvolved/">Get involved</a></li> + <li><a href="http://gudhi.gforge.inria.fr/keepintouch/">Keep in touch</a></li> <li><a href="http://gudhi.gforge.inria.fr/partners/">Partners and Funding</a></li> <li><a href="http://gudhi.gforge.inria.fr/relatedprojects/">Related projects</a></li> <li><a href="http://gudhi.gforge.inria.fr/theyaretalkingaboutus/">They are talking about us</a></li> @@ -49,11 +56,18 @@ $extrastylesheet <ul class="dropdown"> <li><a href="http://gudhi.gforge.inria.fr/licensing/">Licensing</a></li> <li><a href="https://gforge.inria.fr/frs/?group_id=3865" target="_blank">Get the sources</a></li> - <li><a href="http://gudhi.gforge.inria.fr/doc/latest/installation.html">Installation manual</a></li> </ul> </li> <li class="divider"></li> - <li><a href="http://gudhi.gforge.inria.fr/doc/latest/">Documentation</a></li> + <li class="has-dropdown"> + <a href="#">Documentation</a> + <ul class="dropdown"> + <li><a href="http://gudhi.gforge.inria.fr/doc/latest/">C++ documentation</a></li> + <li><a href="http://gudhi.gforge.inria.fr/doc/latest/installation.html">C++ installation manual</a></li> + <li><a href="http://gudhi.gforge.inria.fr/cython/latest/">Cython documentation</a></li> + <li><a href="http://gudhi.gforge.inria.fr/cython/latest/installation.html">Cython installation manual</a></li> + </ul> + </li> <li class="divider"></li> <li><a href="http://gudhi.gforge.inria.fr/interfaces/">Interfaces</a></li> <li class="divider"></li> @@ -62,7 +76,7 @@ $extrastylesheet </nav> </div><!-- /#navigation --> <!-- GUDHI website header BEGIN --> - + <div id="top"><!-- do not remove this div, it is closed by doxygen! --> <!--BEGIN TITLEAREA--> diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 60c9cd07..593faea5 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -3,7 +3,9 @@ * \image html "Gudhi_banner.png" "" width=20cm * * \section Introduction Introduction - * The Gudhi library (Geometry Understanding in Higher Dimensions) is a generic open source C++ library for + * The GUDHI library (Geometry Understanding in Higher Dimensions) is a generic open source + * <a class="el" target="_blank" href="http://gudhi.gforge.inria.fr/doc/latest/">C++ library</a>, with a + * <a class="el" target="_blank" href="http://gudhi.gforge.inria.fr/cython/latest/">Cython interface</a>, for * Computational Topology and Topological Data Analysis * (<a class="el" target="_blank" href="https://en.wikipedia.org/wiki/Topological_data_analysis">TDA</a>). * The GUDHI library intends to help the development of new algorithmic solutions in TDA and their transfer to @@ -62,7 +64,7 @@ <tr> <td width="25%"> <b>Author:</b> Clément Maria, Pawel Dlotko, Vincent Rouvreau<br> - <b>Introduced in:</b> GUDHI 1.4.0<br> + <b>Introduced in:</b> GUDHI 2.0.0<br> <b>Copyright:</b> GPL v3<br> </td> <td width="75%"> @@ -118,8 +120,9 @@ <tr> <td width="25%"> <b>Author:</b> Clément Jamin<br> - <b>Introduced in:</b> GUDHI 1.4.0<br> + <b>Introduced in:</b> GUDHI 2.0.0<br> <b>Copyright:</b> GPL v3<br> + <b>Requires:</b> \ref cgal ≥ 4.8.0 and \ref eigen3 </td> <td width="75%"> A Tangential Delaunay complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a> @@ -139,6 +142,7 @@ <b>Author:</b> Siargey Kachanovich<br> <b>Introduced in:</b> GUDHI 1.3.0<br> <b>Copyright:</b> GPL v3<br> + <b>Euclidean version requires:</b> \ref cgal ≥ 4.6.0 and \ref eigen3 </td> <td width="75%"> Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$. @@ -155,7 +159,7 @@ <tr> <td width="25%"> <b>Author:</b> François Godi<br> - <b>Introduced in:</b> GUDHI 1.4.0<br> + <b>Introduced in:</b> GUDHI 2.0.0<br> <b>Copyright:</b> GPL v3<br> <b>Requires:</b> \ref cgal ≥ 4.8.0 and \ref eigen3 </td> @@ -211,11 +215,11 @@ </table> */ -/*! \page installation Gudhi installation +/*! \page installation GUDHI installation * \tableofcontents - * As Gudhi is a header only library, there is no need to install the library. + * As GUDHI is a header only library, there is no need to install the library. * - * Examples of Gudhi headers inclusion can be found in \ref demos. + * Examples of GUDHI headers inclusion can be found in \ref demos. * * \section compiling Compiling * The library uses c++11 and requires <a target="_blank" href="http://www.boost.org/">Boost</a> with version 1.48.0 or @@ -234,6 +238,15 @@ make \endverbatim * To test your build, run the following command in a terminal: * \verbatim make test \endverbatim * + * \subsection documentationgeneration Documentation + * To generate the documentation, <a target="_blank" href="http://www.doxygen.org/">Doxygen</a> is required. + * Run the following command in a terminal: +\verbatim +make doxygen +# Documentation will be generated in the folder YYYY-MM-DD-hh-mm-ss_GUDHI_X.Y.Z/doc/html/ +# You can customize the directory name by calling `cmake -DUSER_VERSION_DIR=/my/custom/folder` +\endverbatim + * * \section optionallibrary Optional third-party library * \subsection gmp GMP * The multi-field persistent homology algorithm requires GMP which is a free library for arbitrary-precision @@ -249,6 +262,10 @@ make \endverbatim * \subsection cgal CGAL * The \ref alpha_complex data structure, \ref bottleneck_distance, and few examples requires CGAL, which is a C++ * library which provides easy access to efficient and reliable geometric algorithms. + * + * \note There is no need to install CGAL, you can just <CODE>cmake . && make</CODE> CGAL (or even + * <CODE>cmake -DCGAL_HEADER_ONLY=ON .</CODE> for CGAL version ≥ 4.8.0), thereafter you will be able to compile + * GUDHI by calling <CODE>cmake -DCGAL_DIR=/your/path/to/CGAL-X.Y .. && make</CODE> * * Having CGAL version 4.4.0 or higher installed is recommended. The procedure to install this library according to * your operating system is detailed here http://doc.cgal.org/latest/Manual/installation.html @@ -257,6 +274,10 @@ make \endverbatim * Library</a> (CGAL \cite cgal:eb-15b) and will not be built if CGAL is not installed: * \li <a href="_persistent_cohomology_2alpha_complex_3d_persistence_8cpp-example.html"> * Persistent_cohomology/alpha_complex_3d_persistence.cpp</a> + * \li <a href="_persistent_cohomology_2exact_alpha_complex_3d_persistence_8cpp-example.html"> + * Persistent_cohomology/exact_alpha_complex_3d_persistence.cpp</a> + * \li <a href="_persistent_cohomology_2weighted_alpha_complex_3d_persistence_8cpp-example.html"> + * Persistent_cohomology/weighted_alpha_complex_3d_persistence.cpp</a> * \li <a href="_simplex_tree_2example_alpha_shapes_3_simplex_tree_from_off_file_8cpp-example.html"> * Simplex_tree/example_alpha_shapes_3_simplex_tree_from_off_file.cpp</a> * @@ -348,6 +369,10 @@ make \endverbatim * 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_2exact_alpha_complex_3d_persistence_8cpp-example.html"> + * Persistent_cohomology/exact_alpha_complex_3d_persistence.cpp</a> + * \li <a href="_persistent_cohomology_2weighted_alpha_complex_3d_persistence_8cpp-example.html"> + * Persistent_cohomology/weighted_alpha_complex_3d_persistence.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"> @@ -361,7 +386,7 @@ make \endverbatim * Please help us improving the quality of the GUDHI library. You may report bugs or suggestions to: * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim * - * Gudhi is open to external contributions. If you want to join our development team, please contact us. + * GUDHI is open to external contributions. If you want to join our development team, please contact us. * */ @@ -376,7 +401,7 @@ make \endverbatim * \verbinclude biblio/how_to_cite_gudhi.bib */ -// List of Gudhi examples - Doxygen needs at least a file tag to analyse comments +// List of GUDHI examples - Doxygen needs at least a file tag to analyse comments /*! @file Examples * @example Alpha_complex/Alpha_complex_from_off.cpp * @example Alpha_complex/Alpha_complex_from_points.cpp @@ -392,6 +417,8 @@ 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/exact_alpha_complex_3d_persistence.cpp + * @example Persistent_cohomology/weighted_alpha_complex_3d_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 @@ -412,7 +439,11 @@ make \endverbatim * @example Skeleton_blocker/Skeleton_blocker_link.cpp * @example Tangential_complex/example_basic.cpp * @example Tangential_complex/example_with_perturb.cpp - * @example Witness_complex/witness_complex_from_file.cpp - * @example Witness_complex/witness_complex_sphere.cpp + * @example Witness_complex/example_nearest_landmark_table.cpp + * @example Witness_complex/example_strong_witness_complex_off.cpp + * @example Witness_complex/example_strong_witness_persistence.cpp + * @example Witness_complex/example_witness_complex_off.cpp + * @example Witness_complex/example_witness_complex_persistence.cpp + * @example Witness_complex/example_witness_complex_sphere.cpp */ diff --git a/src/common/include/gudhi/distance_functions.h b/src/common/include/gudhi/distance_functions.h index 5891ef0e..7bf97c23 100644 --- a/src/common/include/gudhi/distance_functions.h +++ b/src/common/include/gudhi/distance_functions.h @@ -24,6 +24,8 @@ #define DISTANCE_FUNCTIONS_H_ #include <cmath> // for std::sqrt +#include <type_traits> // for std::decay +#include <iterator> // for std::begin, std::end /** @file * @brief Global distance functions @@ -34,7 +36,7 @@ class Euclidean_distance { public: template< typename Point > - auto operator()(const Point& p1, const Point& p2) -> typename std::decay<decltype(*std::begin(p1))>::type { + auto operator()(const Point& p1, const Point& p2) const -> typename std::decay<decltype(*std::begin(p1))>::type { auto it1 = p1.begin(); auto it2 = p2.begin(); typename Point::value_type dist = 0.; diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt new file mode 100644 index 00000000..25cf952e --- /dev/null +++ b/src/cython/CMakeLists.txt @@ -0,0 +1,230 @@ +cmake_minimum_required(VERSION 2.8) +project(Cython) + +macro( find_the_lib placeholder THE_LIBS ) + set (THE_LIB_WE_FOUND "NO") + foreach(THE_LIB ${THE_LIBS}) + if(EXISTS ${THE_LIB}) + get_filename_component(THE_LIB_WE ${THE_LIB} NAME_WE) + if (NOT THE_LIB_WE_FOUND) + set (THE_LIB_WE_FOUND "YES") + set(returnValue "${THE_LIB_WE}") + endif(NOT THE_LIB_WE_FOUND) + endif(EXISTS ${THE_LIB}) + endforeach(THE_LIB ${THE_LIBS}) +endmacro( find_the_lib ) + +FIND_PROGRAM( PYTHON_PATH python ) +FIND_PROGRAM( CYTHON_PATH cython ) + +if(PYTHON_PATH AND CYTHON_PATH) + find_package(Boost REQUIRED COMPONENTS system REQUIRED) + + if(NOT Boost_FOUND) + message(FATAL_ERROR "NOTICE: This demo requires Boost and will not be compiled.") + else(NOT Boost_FOUND) + + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") + if(WIN32) + set( returnValue "" ) + find_the_lib (${returnValue} ${Boost_SYSTEM_LIBRARY}) + set(BOOST_SYSTEM_LIB_NAME ${returnValue}) + else() + set(BOOST_SYSTEM_LIB_NAME "boost_system") + endif() + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'${BOOST_SYSTEM_LIB_NAME}', ") + + # Gudhi and CGAL compilation option + if(MSVC) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'/fp:strict', ") + else(MSVC) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-std=c++11', ") + endif(MSVC) + if(CMAKE_COMPILER_IS_GNUCXX) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ") + endif(CMAKE_COMPILER_IS_GNUCXX) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ") + endif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + if (DEBUG_TRACES) + # For programs to be more verbose + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") + endif() + + find_package(Eigen3 3.1.0) + + if (EIGEN3_FOUND) + # No problem, even if no CGAL found + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") + endif (EIGEN3_FOUND) + + # Copy recursively include, cython, example, doc and test repositories before packages finding + # Some tests and doc files are removed in case some packages are not found + file(COPY include DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY cython DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY example DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY test DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY doc DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + # Developper version for doc images + file(GLOB GUDHI_DEV_DOC_IMAGES "${CMAKE_SOURCE_DIR}/src/*/doc/*.png") + file(COPY ${GUDHI_DEV_DOC_IMAGES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/img") + file(GLOB GUDHI_DEV_DOC_IMAGES "${CMAKE_SOURCE_DIR}/src/*/doc/*.svg") + file(COPY ${GUDHI_DEV_DOC_IMAGES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/img") + # User version for doc images + file(GLOB GUDHI_USER_DOC_IMAGES "${CMAKE_SOURCE_DIR}/doc/*/*.png") + file(COPY ${GUDHI_USER_DOC_IMAGES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/img") + file(GLOB GUDHI_USER_DOC_IMAGES "${CMAKE_SOURCE_DIR}/doc/*/*.svg") + file(COPY ${GUDHI_USER_DOC_IMAGES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/img") + # Biblio + file(GLOB GUDHI_BIB_FILES "${CMAKE_SOURCE_DIR}/biblio/*.bib") + file(COPY ${GUDHI_BIB_FILES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + # Cubical complex perseus doc example + file(GLOB GUDHI_CUBICAL_PERSEUS_FILES "${CMAKE_SOURCE_DIR}/data/bitmap/*cubicalcomplexdoc.txt") + file(COPY ${GUDHI_CUBICAL_PERSEUS_FILES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + file(COPY "${CMAKE_SOURCE_DIR}/data/distance_matrix/full_square_distance_matrix.csv" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + # Persistence graphical tools examples + file(COPY "${CMAKE_SOURCE_DIR}/data/bitmap/3d_torus.txt" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + file(COPY "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + + if (NOT CGAL_VERSION VERSION_LESS 4.8.1) + # If CGAL_VERSION >= 4.8.1, include subsampling + # CGAL things are done in CGAL_VERSION >= 4.8.0 + set(GUDHI_CYTHON_SUBSAMPLING "include 'cython/subsampling.pyx'") + else (NOT CGAL_VERSION VERSION_LESS 4.8.1) + # Remove alpha complex unitary tests + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test/test_subsampling.py) + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/subsampling_ref.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/subsampling_sum.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/subsampling_user.rst") + endif (NOT CGAL_VERSION VERSION_LESS 4.8.1) + if (NOT CGAL_VERSION VERSION_LESS 4.8.0) + # If CGAL_VERSION >= 4.8.0, include tangential complex + set(GUDHI_CYTHON_TANGENTIAL_COMPLEX "include 'cython/tangential_complex.pyx'") + set(GUDHI_CYTHON_BOTTLENECK_DISTANCE "include 'cython/bottleneck_distance.pyx'") + else (NOT CGAL_VERSION VERSION_LESS 4.8.0) + # Remove tangential complex and bottleneck unitary tests + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test/test_tangential_complex.py) + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test/test_bottleneck_distance.py) + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/bottleneck_distance_ref.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/bottleneck_distance_sum.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/bottleneck_distance_user.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/tangential_complex_ref.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/tangential_complex_sum.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/tangential_complex_user.rst") + endif (NOT CGAL_VERSION VERSION_LESS 4.8.0) + if (NOT CGAL_VERSION VERSION_LESS 4.7.0) + # If CGAL_VERSION >= 4.7.0, include alpha + set(GUDHI_CYTHON_ALPHA_COMPLEX "include 'cython/alpha_complex.pyx'") + else (NOT CGAL_VERSION VERSION_LESS 4.7.0) + # Remove alpha complex unitary tests + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test/test_alpha_complex.py) + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/alpha_complex_ref.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/alpha_complex_sum.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/alpha_complex_user.rst") + endif (NOT CGAL_VERSION VERSION_LESS 4.7.0) + if (NOT CGAL_VERSION VERSION_LESS 4.6.0) + # If CGAL_VERSION >= 4.6.0, include euclidean versions of witness complex + set(GUDHI_CYTHON_EUCLIDEAN_WITNESS_COMPLEX + "include 'cython/euclidean_witness_complex.pyx'\ninclude 'cython/euclidean_strong_witness_complex.pyx'\n") + else (NOT CGAL_VERSION VERSION_LESS 4.6.0) + # Remove alpha complex unitary tests + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test/test_euclidean_witness_complex.py) + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/euclidean_witness_complex_ref.rst") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/doc/euclidean_strong_witness_complex_ref.rst") + endif (NOT CGAL_VERSION VERSION_LESS 4.6.0) + + if(CGAL_FOUND) + # Add CGAL compilation args + if(CGAL_HEADER_ONLY) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") + else(CGAL_HEADER_ONLY) + if(WIN32) + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'CGAL-vc140-mt-4.7', ") + else(WIN32) + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'CGAL', ") + endif(WIN32) + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") + endif(CGAL_HEADER_ONLY) + # GMP and GMPXX are not required, but if present, CGAL will link with them. + if(GMP_FOUND) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") + if(WIN32) + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'libgmp-10', ") + else(WIN32) + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'gmp', ") + endif(WIN32) + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ") + if(GMPXX_FOUND) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ") + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'gmpxx', ") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMPXX_LIBRARIES_DIR}', ") + endif(GMPXX_FOUND) + endif(GMP_FOUND) + endif(CGAL_FOUND) + + # Specific for Mac + if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-mmacosx-version-min=10.9', ") + set(GUDHI_CYTHON_EXTRA_LINK_ARGS "${GUDHI_CYTHON_EXTRA_LINK_ARGS}'-mmacosx-version-min=10.9', ") + endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + + # Loop on INCLUDE_DIRECTORIES PROPERTY + get_property(GUDHI_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) + foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${GUDHI_INCLUDE_DIRECTORY}', ") + endforeach() + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${CMAKE_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/include', ") + + if (TBB_FOUND) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ") + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'tbb', 'tbbmalloc', ") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${TBB_LIBRARY_DIRS}', ") + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") + endif() + + # Generate cythonize_gudhi.py file to cythonize Gudhi + configure_file(cythonize_gudhi.py.in "${CMAKE_CURRENT_BINARY_DIR}/cythonize_gudhi.py" @ONLY) + # Generate gudhi.pyx - Gudhi cython file + configure_file(gudhi.pyx.in "${CMAKE_CURRENT_BINARY_DIR}/gudhi.pyx" @ONLY) + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND python "${CMAKE_CURRENT_BINARY_DIR}/cythonize_gudhi.py" "build_ext" "--inplace") + + add_custom_target(cython ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" + COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests") + + if(UNIX) + set( ENV{PYTHONPATH} $ENV{PYTHONPATH}:${CMAKE_CURRENT_BINARY_DIR}/ ) + endif(UNIX) + + # Unitary tests are available through py.test + find_program( PYTEST_PATH py.test ) + if(PYTEST_PATH) + add_test( + NAME gudhi_cython_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${PYTEST_PATH}) + set_tests_properties(gudhi_cython_py_test PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}") + endif(PYTEST_PATH) + + # Documentation generation is available through sphinx + find_program( SPHINX_PATH sphinx-build ) + if(SPHINX_PATH) + if (UNIX) + add_custom_target(sphinx + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" + COMMAND make html doctest) + else (UNIX) + add_custom_target(sphinx + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + COMMAND make.bat html) + endif (UNIX) + endif(SPHINX_PATH) + endif(NOT Boost_FOUND) +endif(PYTHON_PATH AND CYTHON_PATH) diff --git a/src/cython/CONVENTIONS b/src/cython/CONVENTIONS new file mode 100644 index 00000000..804e97f3 --- /dev/null +++ b/src/cython/CONVENTIONS @@ -0,0 +1,9 @@ +Gudhi is following PEP8 conventions. + +Please refer to: +https://www.python.org/dev/peps/pep-0008/ + +A summary: + - modules (filenames) should have short, all-lowercase names, and they can contain underscores. + - packages (directories) should have short, all-lowercase names, preferably without underscores. + - classes should use the CapWords convention.
\ No newline at end of file diff --git a/src/cython/README b/src/cython/README new file mode 100644 index 00000000..7d2c4491 --- /dev/null +++ b/src/cython/README @@ -0,0 +1,3 @@ + +If you do not want to install the package, just launch the following command to help Python to find the compiled package : +$> export PYTHONPATH=`pwd`:$PYTHONPATH diff --git a/src/cython/cython/alpha_complex.pyx b/src/cython/cython/alpha_complex.pyx new file mode 100644 index 00000000..da537c2e --- /dev/null +++ b/src/cython/cython/alpha_complex.pyx @@ -0,0 +1,121 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Alpha_complex_interface.h" namespace "Gudhi": + cdef cppclass Alpha_complex_interface "Gudhi::alpha_complex::Alpha_complex_interface": + Alpha_complex_interface(vector[vector[double]] points) + # bool from_file is a workaround for cython to find the correct signature + Alpha_complex_interface(string off_file, bool from_file) + vector[double] get_point(int vertex) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + +# AlphaComplex python interface +cdef class AlphaComplex: + """AlphaComplex is a simplicial complex constructed from the finite cells + of a Delaunay Triangulation. + + The filtration value of each simplex is computed as the square of the + circumradius of the simplex if the circumsphere is empty (the simplex is + then said to be Gabriel), and as the minimum of the filtration values of + the codimension 1 cofaces that make it not Gabriel otherwise. + + All simplices that have a filtration value strictly greater than a given + alpha squared value are not inserted into the complex. + + .. note:: + + When Alpha_complex is constructed with an infinite value of alpha, the + complex is a Delaunay complex. + + """ + + cdef Alpha_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=None, off_file=''): + """AlphaComplex constructor. + + :param points: A list of points in d-Dimension. + :type points: list of list of double + + Or + + :param off_file: An OFF file style name. + :type off_file: string + """ + + # The real cython constructor + def __cinit__(self, points=None, off_file=''): + if off_file is not '': + if os.path.isfile(off_file): + self.thisptr = new Alpha_complex_interface(off_file, True) + else: + print("file " + off_file + " not found.") + else: + if points is None: + # Empty Alpha construction + points=[] + self.thisptr = new Alpha_complex_interface(points) + + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if AlphaComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def get_point(self, vertex): + """This function returns the point corresponding to a given vertex. + + :param vertex: The vertex. + :type vertex: int + :rtype: list of float + :returns: the point. + """ + cdef vector[double] point = self.thisptr.get_point(vertex) + return point + + def create_simplex_tree(self, max_alpha_square=float('inf')): + """ + :param max_alpha_square: The maximum alpha square threshold the + simplices shall not exceed. Default is set to infinity. + :type max_alpha_square: float + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square) + return simplex_tree diff --git a/src/cython/cython/bottleneck_distance.pyx b/src/cython/cython/bottleneck_distance.pyx new file mode 100644 index 00000000..ee3e6ef9 --- /dev/null +++ b/src/cython/cython/bottleneck_distance.pyx @@ -0,0 +1,59 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +import os + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Bottleneck_distance_interface.h" namespace "Gudhi::persistence_diagram": + double bottleneck(vector[pair[double, double]], vector[pair[double, double]], double) + double bottleneck(vector[pair[double, double]], vector[pair[double, double]]) + +def bottleneck_distance(diagram_1, diagram_2, e=0.0): + """This function returns the point corresponding to a given vertex. + + :param diagram_1: The first diagram. + :type diagram_1: vector[pair[double, double]] + :param diagram_2: The second diagram. + :type diagram_2: vector[pair[double, double]] + :param e: 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. + :type e: float + :rtype: float + :returns: the bottleneck distance. + """ + if e is 0.0: + return bottleneck(diagram_1, diagram_2) + else: + return bottleneck(diagram_1, diagram_2, e) diff --git a/src/cython/cython/cubical_complex.pyx b/src/cython/cython/cubical_complex.pyx new file mode 100644 index 00000000..e1344f49 --- /dev/null +++ b/src/cython/cython/cubical_complex.pyx @@ -0,0 +1,197 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Cubical_complex_interface.h" namespace "Gudhi": + cdef cppclass Bitmap_cubical_complex_base_interface "Gudhi::Cubical_complex::Cubical_complex_interface<>": + Bitmap_cubical_complex_base_interface(vector[unsigned] dimensions, vector[double] top_dimensional_cells) + Bitmap_cubical_complex_base_interface(string perseus_file) + int num_simplices() + int dimension() + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Cubical_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Cubical_complex::Cubical_complex_interface<>>": + Cubical_complex_persistence_interface(Bitmap_cubical_complex_base_interface * st, bool persistence_dim_max) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + vector[pair[double,double]] intervals_in_dimension(int dimension) + +# CubicalComplex python interface +cdef class CubicalComplex: + """The CubicalComplex is an example of a structured complex useful in + computational mathematics (specially rigorous numerics) and image + analysis. + """ + cdef Bitmap_cubical_complex_base_interface * thisptr + + cdef Cubical_complex_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + """CubicalComplex constructor from dimensions and + top_dimensional_cells or from a perseus file style name. + + :param dimensions: A list of number of top dimensional cells. + :type dimensions: list of int + :param top_dimensional_cells: A list of top dimensional cells. + :type top_dimensional_cells: list of double + + Or + + :param perseus_file: A perseus file style name. + :type perseus_file: string + """ + + # The real cython constructor + def __cinit__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + if (dimensions is not None) and (top_dimensional_cells is not None) and (perseus_file is ''): + self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) + elif (dimensions is None) and (top_dimensional_cells is None) and (perseus_file is not ''): + if os.path.isfile(perseus_file): + self.thisptr = new Bitmap_cubical_complex_base_interface(perseus_file) + else: + print("file " + perseus_file + " not found.") + else: + print("CubicalComplex can be constructed from dimensions and " + "top_dimensional_cells or from a perseus file style name.") + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if CubicalComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + + def persistence(self, homology_coeff_field=11, min_persistence=0): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: list of pairs(dimension, pair(birth, death)) -- the + persistence of the simplicial complex. + """ + if self.pcohptr != NULL: + del self.pcohptr + if self.thisptr != NULL: + self.pcohptr = new Cubical_complex_persistence_interface(self.thisptr, True) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: list of int -- The Betti numbers ([B0, B1, ..., Bn]). + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: list of int -- The persistent Betti numbers ([B0, B1, ..., + Bn]). + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + return pbn_result + + def persistence_intervals_in_dimension(self, dimension): + """This function returns the persistence intervals of the simplicial + complex in a specific dimension. + + :param dimension: The specific dimension. + :type from_value: int. + :returns: The persistence intervals. + :rtype: list of pair of float + + :note: intervals_in_dim function requires persistence function to be + launched first. + """ + cdef vector[pair[double,double]] intervals_result + if self.pcohptr != NULL: + intervals_result = self.pcohptr.intervals_in_dimension(dimension) + else: + print("intervals_in_dim function requires persistence function" + " to be launched first.") + return intervals_result diff --git a/src/cython/cython/euclidean_strong_witness_complex.pyx b/src/cython/cython/euclidean_strong_witness_complex.pyx new file mode 100644 index 00000000..c1523892 --- /dev/null +++ b/src/cython/cython/euclidean_strong_witness_complex.pyx @@ -0,0 +1,97 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Euclidean_strong_witness_complex_interface.h" namespace "Gudhi": + cdef cppclass Euclidean_strong_witness_complex_interface "Gudhi::witness_complex::Euclidean_strong_witness_complex_interface": + Euclidean_strong_witness_complex_interface(vector[vector[double]] landmarks, vector[vector[double]] witnesses) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, + unsigned limit_dimension) + vector[double] get_point(unsigned vertex) + +# EuclideanStrongWitnessComplex python interface +cdef class EuclideanStrongWitnessComplex: + """Constructs strong witness complex for given sets of witnesses and + landmarks in Euclidean space. + """ + + cdef Euclidean_strong_witness_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, landmarks=None, witnesses=None): + """WitnessComplex constructor. + + :param landmarks: A list of landmarks (in the point cloud). + :type landmarks: list of list of double + + :param witnesses: The point cloud. + :type witnesses: list of list of double + """ + + # The real cython constructor + def __cinit__(self, landmarks=None, witnesses=None): + if landmarks is not None and witnesses is not None: + self.thisptr = new Euclidean_strong_witness_complex_interface(landmarks, witnesses) + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if WitnessComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def create_simplex_tree(self, max_alpha_square, limit_dimension = -1): + """ + :param max_alpha_square: The maximum alpha square threshold the + simplices shall not exceed. Default is set to infinity. + :type max_alpha_square: float + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + if limit_dimension is not -1: + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square, limit_dimension) + else: + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square) + return simplex_tree + + def get_point(self, vertex): + """This function returns the point corresponding to a given vertex. + + :param vertex: The vertex. + :type vertex: int. + :returns: The point. + :rtype: list of float + """ + cdef vector[double] point = self.thisptr.get_point(vertex) + return point + diff --git a/src/cython/cython/euclidean_witness_complex.pyx b/src/cython/cython/euclidean_witness_complex.pyx new file mode 100644 index 00000000..7c443b6b --- /dev/null +++ b/src/cython/cython/euclidean_witness_complex.pyx @@ -0,0 +1,97 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Euclidean_witness_complex_interface.h" namespace "Gudhi": + cdef cppclass Euclidean_witness_complex_interface "Gudhi::witness_complex::Euclidean_witness_complex_interface": + Euclidean_witness_complex_interface(vector[vector[double]] landmarks, vector[vector[double]] witnesses) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, + unsigned limit_dimension) + vector[double] get_point(unsigned vertex) + +# EuclideanWitnessComplex python interface +cdef class EuclideanWitnessComplex: + """Constructs (weak) witness complex for given sets of witnesses and + landmarks in Euclidean space. + """ + + cdef Euclidean_witness_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, landmarks=None, witnesses=None): + """WitnessComplex constructor. + + :param landmarks: A list of landmarks (in the point cloud). + :type landmarks: list of list of double + + :param witnesses: The point cloud. + :type witnesses: list of list of double + """ + + # The real cython constructor + def __cinit__(self, landmarks=None, witnesses=None): + if landmarks is not None and witnesses is not None: + self.thisptr = new Euclidean_witness_complex_interface(landmarks, witnesses) + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if WitnessComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def create_simplex_tree(self, max_alpha_square, limit_dimension = -1): + """ + :param max_alpha_square: The maximum alpha square threshold the + simplices shall not exceed. Default is set to infinity. + :type max_alpha_square: float + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + if limit_dimension is not -1: + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square, limit_dimension) + else: + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square) + return simplex_tree + + def get_point(self, vertex): + """This function returns the point corresponding to a given vertex. + + :param vertex: The vertex. + :type vertex: int. + :returns: The point. + :rtype: list of float + """ + cdef vector[double] point = self.thisptr.get_point(vertex) + return point + diff --git a/src/cython/cython/off_reader.pyx b/src/cython/cython/off_reader.pyx new file mode 100644 index 00000000..78c37969 --- /dev/null +++ b/src/cython/cython/off_reader.pyx @@ -0,0 +1,49 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.string cimport string +import os + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Off_reader_interface.h" namespace "Gudhi": + vector[vector[double]] read_points_from_OFF_file(string off_file) + +def read_off(off_file=''): + """Read points from OFF file. + + :param off_file: An OFF file style name. + :type off_file: string + + :returns: The point set. + :rtype: vector[vector[double]] + """ + if off_file is not '': + if os.path.isfile(off_file): + return read_points_from_OFF_file(off_file) + else: + print("file " + off_file + " not found.") + diff --git a/src/cython/cython/periodic_cubical_complex.pyx b/src/cython/cython/periodic_cubical_complex.pyx new file mode 100644 index 00000000..1445d429 --- /dev/null +++ b/src/cython/cython/periodic_cubical_complex.pyx @@ -0,0 +1,197 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Cubical_complex_interface.h" namespace "Gudhi": + cdef cppclass Periodic_cubical_complex_base_interface "Gudhi::Cubical_complex::Cubical_complex_interface<Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double>>": + Periodic_cubical_complex_base_interface(vector[unsigned] dimensions, vector[double] top_dimensional_cells) + Periodic_cubical_complex_base_interface(string perseus_file) + int num_simplices() + int dimension() + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Periodic_cubical_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Cubical_complex::Cubical_complex_interface<Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double>>>": + Periodic_cubical_complex_persistence_interface(Periodic_cubical_complex_base_interface * st, bool persistence_dim_max) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + vector[pair[double,double]] intervals_in_dimension(int dimension) + +# PeriodicCubicalComplex python interface +cdef class PeriodicCubicalComplex: + """The PeriodicCubicalComplex is an example of a structured complex useful + in computational mathematics (specially rigorous numerics) and image + analysis. + """ + cdef Periodic_cubical_complex_base_interface * thisptr + + cdef Periodic_cubical_complex_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + """PeriodicCubicalComplex constructor from dimensions and + top_dimensional_cells or from a perseus file style name. + + :param dimensions: A list of number of top dimensional cells. + :type dimensions: list of int + :param top_dimensional_cells: A list of top dimensional cells. + :type top_dimensional_cells: list of double + + Or + + :param perseus_file: A perseus file style name. + :type perseus_file: string + """ + + # The real cython constructor + def __cinit__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + if (dimensions is not None) and (top_dimensional_cells is not None) and (perseus_file is ''): + self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, top_dimensional_cells) + elif (dimensions is None) and (top_dimensional_cells is None) and (perseus_file is not ''): + if os.path.isfile(perseus_file): + self.thisptr = new Periodic_cubical_complex_base_interface(perseus_file) + else: + print("file " + perseus_file + " not found.") + else: + print("CubicalComplex can be constructed from dimensions and " + "top_dimensional_cells or from a perseus file style name.") + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if PeriodicCubicalComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + + def persistence(self, homology_coeff_field=11, min_persistence=0): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: list of pairs(dimension, pair(birth, death)) -- the + persistence of the simplicial complex. + """ + if self.pcohptr != NULL: + del self.pcohptr + if self.thisptr != NULL: + self.pcohptr = new Periodic_cubical_complex_persistence_interface(self.thisptr, True) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: list of int -- The Betti numbers ([B0, B1, ..., Bn]). + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: list of int -- The persistent Betti numbers ([B0, B1, ..., + Bn]). + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + return pbn_result + + def persistence_intervals_in_dimension(self, dimension): + """This function returns the persistence intervals of the simplicial + complex in a specific dimension. + + :param dimension: The specific dimension. + :type from_value: int. + :returns: The persistence intervals. + :rtype: list of pair of float + + :note: intervals_in_dim function requires persistence function to be + launched first. + """ + cdef vector[pair[double,double]] intervals_result + if self.pcohptr != NULL: + intervals_result = self.pcohptr.intervals_in_dimension(dimension) + else: + print("intervals_in_dim function requires persistence function" + " to be launched first.") + return intervals_result diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py new file mode 100755 index 00000000..a984633e --- /dev/null +++ b/src/cython/cython/persistence_graphical_tools.py @@ -0,0 +1,152 @@ +import matplotlib.pyplot as plt +import numpy as np + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +def __min_birth_max_death(persistence): + """This function returns (min_birth, max_death) from the persistence. + + :param persistence: The persistence to plot. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :returns: (float, float) -- (min_birth, max_death). + """ + # Look for minimum birth date and maximum death date for plot optimisation + max_death = 0 + min_birth = persistence[0][1][0] + for interval in reversed(persistence): + if float(interval[1][1]) != float('inf'): + if float(interval[1][1]) > max_death: + max_death = float(interval[1][1]) + if float(interval[1][0]) > max_death: + max_death = float(interval[1][0]) + if float(interval[1][0]) < min_birth: + min_birth = float(interval[1][0]) + return (min_birth, max_death) + +""" +Only 13 colors for the palette +""" +palette = ['#ff0000', '#00ff00', '#0000ff', '#00ffff', '#ff00ff', '#ffff00', + '#000000', '#880000', '#008800', '#000088', '#888800', '#880088', + '#008888'] + +def show_palette_values(alpha=0.6): + """This function shows palette color values in function of the dimension. + + :param alpha: alpha value in [0.0, 1.0] for horizontal bars (default is 0.6). + :type alpha: float. + :returns: plot -- An horizontal bar plot of dimensions color. + """ + colors = [] + for color in palette: + colors.append(color) + + y_pos = np.arange(len(palette)) + + plt.barh(y_pos, y_pos + 1, align='center', alpha=alpha, color=colors) + plt.ylabel('Dimension') + plt.title('Dimension palette values') + + plt.show() + +def plot_persistence_barcode(persistence, alpha=0.6): + """This function plots the persistence bar code. + + :param persistence: The persistence to plot. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param alpha: alpha value in [0.0, 1.0] for horizontal bars (default is 0.6). + :type alpha: float. + :returns: plot -- An horizontal bar plot of persistence. + """ + (min_birth, max_death) = __min_birth_max_death(persistence) + ind = 0 + delta = ((max_death - min_birth) / 10.0) + # Replace infinity values with max_death + delta for bar code to be more + # readable + infinity = max_death + delta + axis_start = min_birth - delta + # Draw horizontal bars in loop + for interval in reversed(persistence): + if float(interval[1][1]) != float('inf'): + # Finite death case + plt.barh(ind, (interval[1][1] - interval[1][0]), height=0.8, + left = interval[1][0], alpha=alpha, + color = palette[interval[0]]) + else: + # Infinite death case for diagram to be nicer + plt.barh(ind, (infinity - interval[1][0]), height=0.8, + left = interval[1][0], alpha=alpha, + color = palette[interval[0]]) + ind = ind + 1 + + plt.title('Persistence barcode') + # Ends plot on infinity value and starts a little bit before min_birth + plt.axis([axis_start, infinity, 0, ind]) + plt.show() + +def plot_persistence_diagram(persistence, alpha=0.6): + """This function plots the persistence diagram. + + :param persistence: The persistence to plot. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param alpha: alpha value in [0.0, 1.0] for points and horizontal infinity line (default is 0.6). + :type alpha: float. + :returns: plot -- An diagram plot of persistence. + """ + (min_birth, max_death) = __min_birth_max_death(persistence) + ind = 0 + delta = ((max_death - min_birth) / 10.0) + # Replace infinity values with max_death + delta for diagram to be more + # readable + infinity = max_death + delta + axis_start = min_birth - delta + + # line display of equation : birth = death + x = np.linspace(axis_start, infinity, 1000) + # infinity line and text + plt.plot(x, x, color='k', linewidth=1.0) + plt.plot(x, [infinity] * len(x), linewidth=1.0, color='k', alpha=alpha) + plt.text(axis_start, infinity, r'$\infty$', color='k', alpha=alpha) + + # Draw points in loop + for interval in reversed(persistence): + if float(interval[1][1]) != float('inf'): + # Finite death case + plt.scatter(interval[1][0], interval[1][1], alpha=alpha, + color = palette[interval[0]]) + else: + # Infinite death case for diagram to be nicer + plt.scatter(interval[1][0], infinity, alpha=alpha, + color = palette[interval[0]]) + ind = ind + 1 + + plt.title('Persistence diagram') + plt.xlabel('Birth') + plt.ylabel('Death') + # Ends plot on infinity value and starts a little bit before min_birth + plt.axis([axis_start, infinity, axis_start, infinity + delta]) + plt.show() diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx new file mode 100644 index 00000000..6bfb4482 --- /dev/null +++ b/src/cython/cython/rips_complex.pyx @@ -0,0 +1,125 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Rips_complex_interface.h" namespace "Gudhi": + cdef cppclass Rips_complex_interface "Gudhi::rips_complex::Rips_complex_interface": + Rips_complex_interface(vector[vector[double]] values, double threshold, bool euclidean) + # bool from_file is a workaround for cython to find the correct signature + Rips_complex_interface(string file_name, double threshold, bool euclidean, bool from_file) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, int dim_max) + +# RipsComplex python interface +cdef class RipsComplex: + """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. + """ + + cdef Rips_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=None, off_file='', distance_matrix=None, csv_file='', max_edge_length=float('inf')): + """RipsComplex constructor. + + :param max_edge_length: Rips value. + :type max_edge_length: int + + :param points: A list of points in d-Dimension. + :type points: list of list of double + + Or + + :param off_file: An OFF file style name. + :type off_file: string + + Or + + :param distance_matrix: A distance matrix (full square or lower + triangular). + :type points: list of list of double + + Or + + :param csv_file: A csv file style name containing a full square or a + lower triangular distance matrix. + :type csv_file: string + """ + + # The real cython constructor + def __cinit__(self, points=None, off_file='', distance_matrix=None, csv_file='', max_edge_length=float('inf')): + if off_file is not '': + if os.path.isfile(off_file): + self.thisptr = new Rips_complex_interface(off_file, + max_edge_length, + True, + True) + else: + print("file " + off_file + " not found.") + elif csv_file is not '': + if os.path.isfile(csv_file): + self.thisptr = new Rips_complex_interface(csv_file, + max_edge_length, + False, + True) + else: + print("file " + csv_file + " not found.") + elif distance_matrix is not None: + self.thisptr = new Rips_complex_interface(distance_matrix, max_edge_length, False) + else: + if points is None: + # Empty Rips construction + points=[] + self.thisptr = new Rips_complex_interface(points, max_edge_length, True) + + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if RipsComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def create_simplex_tree(self, max_dimension=1): + """ + :param max_dimension: graph expansion for rips until this given maximal + dimension. + :type max_dimension: int + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_dimension) + return simplex_tree diff --git a/src/cython/cython/simplex_tree.pyx b/src/cython/cython/simplex_tree.pyx new file mode 100644 index 00000000..148227e1 --- /dev/null +++ b/src/cython/cython/simplex_tree.pyx @@ -0,0 +1,427 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp cimport bool + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": + cdef cppclass Simplex_tree_options_full_featured: + pass + + cdef cppclass Simplex_tree_interface_full_featured "Gudhi::Simplex_tree_interface<Gudhi::Simplex_tree_options_full_featured>": + Simplex_tree() + double filtration() + double simplex_filtration(vector[int] simplex) + void set_filtration(double filtration) + void initialize_filtration() + int num_vertices() + int num_simplices() + void set_dimension(int dimension) + int dimension() + bint find_simplex(vector[int] simplex) + bint insert_simplex_and_subfaces(vector[int] simplex, + double filtration) + bint insert_simplex(vector[int] simplex, double filtration) + vector[pair[vector[int], double]] get_filtered_tree() + vector[pair[vector[int], double]] get_skeleton_tree(int dimension) + vector[pair[vector[int], double]] get_star(vector[int] simplex) + vector[pair[vector[int], double]] get_cofaces(vector[int] simplex, + int dimension) + void remove_maximal_simplex(vector[int] simplex) + void expansion(int max_dim) + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>": + Simplex_tree_persistence_interface(Simplex_tree_interface_full_featured * st, bool persistence_dim_max) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + vector[pair[double,double]] intervals_in_dimension(int dimension) + +# SimplexTree python interface +cdef class SimplexTree: + """The simplex tree is an efficient and flexible data structure for + representing general (filtered) simplicial complexes. The data structure + is described in Jean-Daniel Boissonnat and Clément Maria. The Simplex + Tree: An Efficient Data Structure for General Simplicial Complexes. + Algorithmica, pages 1–22, 2014. + + This class is a filtered, with keys, and non contiguous vertices version + of the simplex tree. + """ + cdef Simplex_tree_interface_full_featured * thisptr + + cdef Simplex_tree_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self): + """SimplexTree constructor. + """ + + # The real cython constructor + def __cinit__(self): + self.thisptr = new Simplex_tree_interface_full_featured() + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if SimplexTree pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def get_filtration(self): + """This function returns the main simplicial complex filtration value. + + :returns: The simplicial complex filtration value. + :rtype: float + """ + return self.thisptr.filtration() + + def filtration(self, simplex): + """This function returns the simplicial complex filtration value for a + given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: The simplicial complex filtration value. + :rtype: float + """ + return self.thisptr.simplex_filtration(simplex) + + def set_filtration(self, filtration): + """This function sets the main simplicial complex filtration value. + + :param filtration: The filtration value. + :type filtration: float. + """ + self.thisptr.set_filtration(<double> filtration) + + def initialize_filtration(self): + """This function initializes and sorts the simplicial complex + filtration vector. + + .. note:: + + This function must be launched before persistence, betti_numbers, + persistent_betti_numbers or get_filtered_tree after inserting or + removing simplices. + """ + self.thisptr.initialize_filtration() + + def num_vertices(self): + """This function returns the number of vertices of the simplicial + complex. + + :returns: The simplicial complex number of vertices. + :rtype: int + """ + return self.thisptr.num_vertices() + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: the simplicial complex number of simplices. + :rtype: int + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: the simplicial complex dimension. + :rtype: int + """ + return self.thisptr.dimension() + + def set_dimension(self, dimension): + """This function sets the dimension of the simplicial complex. + + insert and remove_maximal_simplex functions do not update dimension + value of the `SimplexTree`. + + `AlphaComplex`, `RipsComplex`, `TangentialComplex` and `WitnessComplex` + automatically sets the correct dimension in their `create_simplex_tree` + functions. + + :param dimension: The new dimension value. + :type dimension: int. + """ + self.thisptr.set_dimension(<int>dimension) + + def find(self, simplex): + """This function returns if the N-simplex was found in the simplicial + complex or not. + + :param simplex: The N-simplex to find, represented by a list of vertex. + :type simplex: list of int. + :returns: true if the simplex was found, false otherwise. + :rtype: bool + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.find_simplex(complex) + + def insert_simplex(self, simplex, filtration=0.0): + """This function inserts the given N-simplex with the given filtration + value (default value is '0.0'). + + :param simplex: The N-simplex to insert, represented by a list of + vertex. + :type simplex: list of int. + :param filtration: The filtration value of the simplex. + :type filtration: float. + :returns: true if the simplex was found, false otherwise. + :rtype: bool + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.insert_simplex(complex, <double>filtration) + + def insert_simplex_and_subfaces(self, simplex, filtration=0.0): + """This function inserts the given N-simplex and its subfaces with the + given filtration value (default value is '0.0'). + + :param simplex: The N-simplex to insert, represented by a list of + vertex. + :type simplex: list of int. + :param filtration: The filtration value of the simplex. + :type filtration: float. + :returns: true if the simplex was found, false otherwise. + :rtype: bool + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.insert_simplex_and_subfaces(complex, + <double>filtration) + + def get_filtered_tree(self): + """This function returns the tree sorted by increasing filtration + values. + + :returns: The tree sorted by increasing filtration values. + :rtype: list of tuples(simplex, filtration) + """ + cdef vector[pair[vector[int], double]] filtered_tree \ + = self.thisptr.get_filtered_tree() + ct = [] + for filtered_complex in filtered_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v, filtered_complex.second)) + return ct + + def get_skeleton_tree(self, dimension): + """This function returns the tree skeleton of a maximum given + dimension. + + :param dimension: The skeleton dimension value. + :type dimension: int. + :returns: The skeleton tree of a maximum dimension. + :rtype: list of tuples(simplex, filtration) + """ + cdef vector[pair[vector[int], double]] sk_tree \ + = self.thisptr.get_skeleton_tree(<int>dimension) + ct = [] + for filtered_complex in sk_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v, filtered_complex.second)) + return ct + + def get_star(self, simplex): + """This function returns the stars of a given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: The star tree of a simplex. + :rtype: list of tuples(simplex, filtration) + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + cdef vector[pair[vector[int], double]] stars \ + = self.thisptr.get_star(complex) + ct = [] + for filtered_complex in stars: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v, filtered_complex.second)) + return ct + + def get_cofaces(self, simplex, codimension): + """This function returns the cofaces of a given N-simplex with a + given codimension. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :param codimension: The codimension. If codimension = 0, all cofaces + are returned (equivalent of get_star function) + :type codimension: int. + :returns: The coface tree of a simplex. + :rtype: list of tuples(simplex, filtration) + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + cdef vector[pair[vector[int], double]] cofaces \ + = self.thisptr.get_cofaces(complex, <int>codimension) + ct = [] + for filtered_complex in cofaces: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v, filtered_complex.second)) + return ct + + def remove_maximal_simplex(self, simplex): + """This function removes a given maximal N-simplex from the simplicial + complex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + """ + self.thisptr.remove_maximal_simplex(simplex) + + def expansion(self, max_dim): + """Expands the Simplex_tree containing only its one skeleton + until dimension max_dim. + + The expanded simplicial complex until dimension :math:`d` + attached to a graph :math:`G` is the maximal simplicial complex of + dimension at most :math:`d` admitting the graph :math:`G` as + :math:`1`-skeleton. + The filtration value assigned to a simplex is the maximal filtration + value of one of its edges. + + The Simplex_tree must contain no simplex of dimension bigger than + 1 when calling the method. + + :param max_dim: The maximal dimension. + :type max_dim: int. + """ + self.thisptr.expansion(max_dim) + + def persistence(self, homology_coeff_field=11, min_persistence=0, persistence_dim_max = False): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: The persistence of the simplicial complex. + :rtype: list of pairs(dimension, pair(birth, death)) + """ + if self.pcohptr != NULL: + del self.pcohptr + self.pcohptr = new Simplex_tree_persistence_interface(self.thisptr, persistence_dim_max) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: The Betti numbers ([B0, B1, ..., Bn]). + :rtype: list of int + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + else: + print("betti_numbers function requires persistence function" + " to be launched first.") + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: The persistent Betti numbers ([B0, B1, ..., Bn]). + :rtype: list of int + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + else: + print("persistent_betti_numbers function requires persistence function" + " to be launched first.") + return pbn_result + + def persistence_intervals_in_dimension(self, dimension): + """This function returns the persistence intervals of the simplicial + complex in a specific dimension. + + :param dimension: The specific dimension. + :type from_value: int. + :returns: The persistence intervals. + :rtype: list of pair of float + + :note: intervals_in_dim function requires persistence function to be + launched first. + """ + cdef vector[pair[double,double]] intervals_result + if self.pcohptr != NULL: + intervals_result = self.pcohptr.intervals_in_dimension(dimension) + else: + print("intervals_in_dim function requires persistence function" + " to be launched first.") + return intervals_result diff --git a/src/cython/cython/strong_witness_complex.pyx b/src/cython/cython/strong_witness_complex.pyx new file mode 100644 index 00000000..770b46f5 --- /dev/null +++ b/src/cython/cython/strong_witness_complex.pyx @@ -0,0 +1,81 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Strong_witness_complex_interface.h" namespace "Gudhi": + cdef cppclass Strong_witness_complex_interface "Gudhi::witness_complex::Strong_witness_complex_interface": + Strong_witness_complex_interface(vector[vector[pair[size_t, double]]] nearest_landmark_table) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, + unsigned limit_dimension) + +# StrongWitnessComplex python interface +cdef class StrongWitnessComplex: + """Constructs (strong) witness complex for a given table of nearest + landmarks with respect to witnesses. + """ + + cdef Strong_witness_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, nearest_landmark_table=None): + """StrongWitnessComplex constructor. + + :param nearest_landmark_table: A list of nearest landmark. + :type nearest_landmark_table: list of list of pair of unsigned and double + """ + + # The real cython constructor + def __cinit__(self, nearest_landmark_table=None): + if nearest_landmark_table is not None: + self.thisptr = new Strong_witness_complex_interface(nearest_landmark_table) + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if StrongWitnessComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def create_simplex_tree(self, max_alpha_square, limit_dimension = -1): + """ + :param max_alpha_square: The maximum alpha square threshold the + simplices shall not exceed. Default is set to infinity. + :type max_alpha_square: float + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + if limit_dimension is not -1: + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square, limit_dimension) + else: + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square) + return simplex_tree diff --git a/src/cython/cython/subsampling.pyx b/src/cython/cython/subsampling.pyx new file mode 100644 index 00000000..a25d196d --- /dev/null +++ b/src/cython/cython/subsampling.pyx @@ -0,0 +1,139 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Subsampling_interface.h" namespace "Gudhi::subsampling": + vector[vector[double]] subsampling_n_farthest_points(vector[vector[double]] points, unsigned nb_points) + vector[vector[double]] subsampling_n_farthest_points(vector[vector[double]] points, unsigned nb_points, unsigned starting_point) + vector[vector[double]] subsampling_n_farthest_points_from_file(string off_file, unsigned nb_points) + vector[vector[double]] subsampling_n_farthest_points_from_file(string off_file, unsigned nb_points, unsigned starting_point) + vector[vector[double]] subsampling_n_random_points(vector[vector[double]] points, unsigned nb_points) + vector[vector[double]] subsampling_n_random_points_from_file(string off_file, unsigned nb_points) + vector[vector[double]] subsampling_sparsify_points(vector[vector[double]] points, double min_squared_dist) + vector[vector[double]] subsampling_sparsify_points_from_file(string off_file, double min_squared_dist) + +def choose_n_farthest_points(points=None, off_file='', nb_points=0, starting_point = ''): + """Subsample by a greedy strategy of iteratively adding the farthest point + from the current chosen point set to the subsampling. + The iteration starts with the landmark `starting point`. + + :param points: The input point set. + :type points: vector[vector[double]]. + + Or + + :param off_file: An OFF file style name. + :type off_file: string + + :param nb_points: Number of points of the subsample. + :type nb_points: unsigned. + :param starting_point: The iteration starts with the landmark `starting \ + point`,which is the index of the poit to start with. If not set, this \ + index is choosen randomly. + :type starting_point: unsigned. + :returns: The subsample point set. + :rtype: vector[vector[double]] + """ + if off_file is not '': + if os.path.isfile(off_file): + if starting_point is '': + return subsampling_n_farthest_points_from_file(off_file, + nb_points) + else: + return subsampling_n_farthest_points_from_file(off_file, + nb_points, + starting_point) + else: + print("file " + off_file + " not found.") + else: + if points is None: + # Empty points + points=[] + if starting_point is '': + return subsampling_n_farthest_points(points, nb_points) + else: + return subsampling_n_farthest_points(points, nb_points, + starting_point) + +def pick_n_random_points(points=None, off_file='', nb_points=0): + """Subsample a point set by picking random vertices. + + :param points: The input point set. + :type points: vector[vector[double]]. + + Or + + :param off_file: An OFF file style name. + :type off_file: string + + :param nb_points: Number of points of the subsample. + :type nb_points: unsigned. + :returns: The subsample point set. + :rtype: vector[vector[double]] + """ + if off_file is not '': + if os.path.isfile(off_file): + return subsampling_n_random_points_from_file(off_file, nb_points) + else: + print("file " + off_file + " not found.") + else: + if points is None: + # Empty points + points=[] + return subsampling_n_random_points(points, nb_points) + +def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): + """Subsample a point set by picking random vertices. + + :param points: The input point set. + :type points: vector[vector[double]]. + + Or + + :param off_file: An OFF file style name. + :type off_file: string + + :param min_squared_dist: Number of points of the subsample. + :type min_squared_dist: unsigned. + :returns: The subsample point set. + :rtype: vector[vector[double]] + """ + if off_file is not '': + if os.path.isfile(off_file): + return subsampling_sparsify_points_from_file(off_file, + min_squared_dist) + else: + print("file " + off_file + " not found.") + else: + if points is None: + # Empty points + points=[] + return subsampling_sparsify_points(points, min_squared_dist) diff --git a/src/cython/cython/tangential_complex.pyx b/src/cython/cython/tangential_complex.pyx new file mode 100644 index 00000000..52bd8111 --- /dev/null +++ b/src/cython/cython/tangential_complex.pyx @@ -0,0 +1,151 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Tangential_complex_interface.h" namespace "Gudhi": + cdef cppclass Tangential_complex_interface "Gudhi::tangential_complex::Tangential_complex_interface": + Tangential_complex_interface(vector[vector[double]] points) + # bool from_file is a workaround for cython to find the correct signature + Tangential_complex_interface(string off_file, bool from_file) + vector[double] get_point(unsigned vertex) + unsigned number_of_vertices() + unsigned number_of_simplices() + unsigned number_of_inconsistent_simplices() + unsigned number_of_inconsistent_stars() + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree) + void fix_inconsistencies_using_perturbation(double max_perturb, double time_limit) + +# TangentialComplex python interface +cdef class TangentialComplex: + """The class Tangential_complex represents a tangential complex. After the + computation of the complex, an optional post-processing called perturbation + can be run to attempt to remove inconsistencies. + """ + + cdef Tangential_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=None, off_file=''): + """TangentialComplex constructor. + + :param points: A list of points in d-Dimension. + :type points: list of list of double + + Or + + :param off_file: An OFF file style name. + :type off_file: string + """ + + # The real cython constructor + def __cinit__(self, points=None, off_file=''): + if off_file is not '': + if os.path.isfile(off_file): + self.thisptr = new Tangential_complex_interface(off_file, True) + else: + print("file " + off_file + " not found.") + else: + if points is None: + # Empty tangential construction + points=[] + self.thisptr = new Tangential_complex_interface(points) + + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if TangentialComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def get_point(self, vertex): + """This function returns the point corresponding to a given vertex. + + :param vertex: The vertex. + :type vertex: int. + :returns: The point. + :rtype: list of float + """ + cdef vector[double] point = self.thisptr.get_point(vertex) + return point + + def num_vertices(self): + """ + :returns: The number of vertices. + :rtype: unsigned + """ + return self.thisptr.number_of_vertices() + + def num_simplices(self): + """ + :returns: Total number of simplices in stars (including duplicates that appear in several stars). + :rtype: unsigned + """ + return self.thisptr.number_of_simplices() + + def num_inconsistent_simplices(self): + """ + :returns: The number of inconsistent simplices. + :rtype: unsigned + """ + return self.thisptr.number_of_inconsistent_simplices() + + def num_inconsistent_stars(self): + """ + :returns: The number of stars containing at least one inconsistent simplex. + :rtype: unsigned + """ + return self.thisptr.number_of_inconsistent_stars() + + def create_simplex_tree(self): + """Exports the complex into a simplex tree. + + :returns: A simplex tree created from the complex. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + self.thisptr.create_simplex_tree(simplex_tree.thisptr) + return simplex_tree + + def fix_inconsistencies_using_perturbation(self, max_perturb, time_limit=-1.0): + """Attempts to fix inconsistencies by perturbing the point positions. + + :param max_perturb: Maximum length of the translations used by the + perturbation. + :type max_perturb: double + :param time_limit: Time limit in seconds. If -1, no time limit is set. + :type time_limit: double + """ + self.thisptr.fix_inconsistencies_using_perturbation(max_perturb, + time_limit) diff --git a/src/cython/cython/witness_complex.pyx b/src/cython/cython/witness_complex.pyx new file mode 100644 index 00000000..96d122bb --- /dev/null +++ b/src/cython/cython/witness_complex.pyx @@ -0,0 +1,81 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Witness_complex_interface.h" namespace "Gudhi": + cdef cppclass Witness_complex_interface "Gudhi::witness_complex::Witness_complex_interface": + Witness_complex_interface(vector[vector[pair[size_t, double]]] nearest_landmark_table) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, + unsigned limit_dimension) + +# WitnessComplex python interface +cdef class WitnessComplex: + """Constructs (weak) witness complex for a given table of nearest landmarks + with respect to witnesses. + """ + + cdef Witness_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, nearest_landmark_table=None): + """WitnessComplex constructor. + + :param nearest_landmark_table: A list of nearest landmark. + :type nearest_landmark_table: list of list of pair of unsigned and double + """ + + # The real cython constructor + def __cinit__(self, nearest_landmark_table=None): + if nearest_landmark_table is not None: + self.thisptr = new Witness_complex_interface(nearest_landmark_table) + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if WitnessComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def create_simplex_tree(self, max_alpha_square, limit_dimension = -1): + """ + :param max_alpha_square: The maximum alpha square threshold the + simplices shall not exceed. Default is set to infinity. + :type max_alpha_square: float + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + if limit_dimension is not -1: + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square, limit_dimension) + else: + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square) + return simplex_tree diff --git a/src/cython/cythonize_gudhi.py.in b/src/cython/cythonize_gudhi.py.in new file mode 100644 index 00000000..5a97e9f3 --- /dev/null +++ b/src/cython/cythonize_gudhi.py.in @@ -0,0 +1,48 @@ +from distutils.core import setup, Extension +from Cython.Build import cythonize + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +gudhi = Extension( + "gudhi", + sources = ['gudhi.pyx',], + language = 'c++', + extra_compile_args=[@GUDHI_CYTHON_EXTRA_COMPILE_ARGS@], + extra_link_args=[@GUDHI_CYTHON_EXTRA_LINK_ARGS@], + libraries=[@GUDHI_CYTHON_LIBRARIES@], + library_dirs=[@GUDHI_CYTHON_LIBRARY_DIRS@], + include_dirs = [@GUDHI_CYTHON_INCLUDE_DIRS@], +) + +setup( + name = 'gudhi', + author='Vincent Rouvreau', + author_email='gudhi-contact@lists.gforge.inria.fr', + version='0.1.0', + url='http://gudhi.gforge.inria.fr/', + ext_modules = cythonize(gudhi), +) diff --git a/src/cython/doc/Makefile b/src/cython/doc/Makefile new file mode 100644 index 00000000..be3ff7c4 --- /dev/null +++ b/src/cython/doc/Makefile @@ -0,0 +1,181 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -f examples.inc + rm -rf $(BUILDDIR)/* + +# GUDHI specific : Examples.inc is generated with generate_examples.py (and deleted on clean) + +html: + ./generate_examples.py + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pouet.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pouet.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/pouet" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pouet" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/src/cython/doc/_templates/layout.html b/src/cython/doc/_templates/layout.html new file mode 100644 index 00000000..af0eef64 --- /dev/null +++ b/src/cython/doc/_templates/layout.html @@ -0,0 +1,270 @@ +{# + basic/layout.html + ~~~~~~~~~~~~~~~~~ + + Master layout template for Sphinx themes. + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- block doctype -%} +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +{%- endblock %} +{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} +{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} +{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and + (sidebars != []) %} +{%- set url_root = pathto('', 1) %} +{# XXX necessary? #} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + +{%- macro relbar() %} + <div class="related" role="navigation" aria-label="related navigation"> + <h3>{{ _('Navigation') }}</h3> + <ul> + {%- for rellink in rellinks %} + <li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}> + <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}" + {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a> + {%- if not loop.first %}{{ reldelim2 }}{% endif %}</li> + {%- endfor %} + {%- block rootrellink %} + <li class="nav-item nav-item-0"><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li> + {%- endblock %} + {%- for parent in parents %} + <li class="nav-item nav-item-{{ loop.index }}"><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li> + {%- endfor %} + {%- block relbaritems %} {% endblock %} + </ul> + </div> +{%- endmacro %} + +{%- macro sidebar() %} + {%- if render_sidebar %} + <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> + <div class="sphinxsidebarwrapper"> + {%- block sidebarlogo %} + {%- if logo %} + <p class="logo"><a href="{{ pathto(master_doc) }}"> + <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/> + </a></p> + {%- endif %} + {%- endblock %} + {%- if sidebars != None %} + {#- new style sidebar: explicitly include/exclude templates #} + {%- for sidebartemplate in sidebars %} + {%- include sidebartemplate %} + {%- endfor %} + {%- else %} + {#- old style sidebars: using blocks -- should be deprecated #} + {%- block sidebartoc %} +<h2><a href="index.html">GUDHI</a></h2> +<h2><a href="installation.html">GUDHI installation</a></h2> +<h2><a href="citation.html">Acknowledging the GUDHI library</a></h2> +<h2><a href="genindex.html">Index</a></h2> +<h2><a href="examples.html">Examples</a></h2> + + {%- include "localtoc.html" %} + {%- endblock %} + {%- block sidebarrel %} + {%- include "relations.html" %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- include "sourcelink.html" %} + {%- endblock %} + {%- if customsidebar %} + {%- include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- include "searchbox.html" %} + {%- endblock %} + {%- endif %} + </div> + </div> + {%- endif %} +{%- endmacro %} + +{%- macro script() %} + <script type="text/javascript"> + var DOCUMENTATION_OPTIONS = { + URL_ROOT: '{{ url_root }}', + VERSION: '{{ release|e }}', + COLLAPSE_INDEX: false, + FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}', + HAS_SOURCE: {{ has_source|lower }} + }; + </script> + {%- for scriptfile in script_files %} + <script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script> + {%- endfor %} +{%- endmacro %} + +{%- macro css() %} +<!-- GUDHI website css for header BEGIN --> +<link rel="stylesheet" type="text/css" href="http://gudhi.gforge.inria.fr/assets/css/styles_feeling_responsive.css" /> +<!-- GUDHI website css for header END --> + <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" /> + <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" /> + {%- for cssfile in css_files %} + <link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" /> + {%- endfor %} +{%- endmacro %} +<!-- GUDHI website html class for header BEGIN --> +<html xmlns="http://www.w3.org/1999/xhtml" class="no-js" lang="en"> +<!-- GUDHI website html class for header END --> + <head> + <meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" /> + {{ metatags }} + {%- block htmltitle %} + <title>{{ title|striptags|e }}{{ titlesuffix }}</title> + {%- endblock %} + {{ css() }} + {%- if not embedded %} + {{ script() }} + {%- if use_opensearch %} + <link rel="search" type="application/opensearchdescription+xml" + title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" + href="{{ pathto('_static/opensearch.xml', 1) }}"/> + {%- endif %} + {%- if favicon %} + <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/> + {%- endif %} + {%- endif %} +{%- block linktags %} + {%- if hasdoc('about') %} + <link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" /> + {%- endif %} + {%- if hasdoc('genindex') %} + <link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" /> + {%- endif %} + {%- if hasdoc('search') %} + <link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" /> + {%- endif %} + {%- if hasdoc('copyright') %} + <link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" /> + {%- endif %} + <link rel="top" title="{{ docstitle|e }}" href="{{ pathto(master_doc) }}" /> + {%- if parents %} + <link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" /> + {%- endif %} + {%- if next %} + <link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" /> + {%- endif %} + {%- if prev %} + <link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" /> + {%- endif %} +{%- endblock %} +{%- block extrahead %} {% endblock %} + </head> + <body role="document"> + <!-- GUDHI website header BEGIN --> + <div id="navigation" class="sticky"> + <nav class="top-bar" role="navigation" data-topbar> + <ul class="title-area"> + <li class="name"> + <h1 class="show-for-small-only"><a href="http://gudhi.gforge.inria.fr" class="icon-tree"> GUDHI C++ library</a></h1> + </li> + <!-- Remove the class "menu-icon" to get rid of menu icon. Take out "Menu" to just have icon alone --> + <li class="toggle-topbar menu-icon"><a href="#"><span>Navigation</span></a></li> + </ul> + <section class="top-bar-section"> + <ul class="right"> + <li class="divider"></li> + <li><a href="http://gudhi.gforge.inria.fr/contact/">Contact</a></li> + </ul> + <ul class="left"> + <li><a href="http://gudhi.gforge.inria.fr/"> <img src="http://gudhi.gforge.inria.fr/assets/img/home.png" alt=" GUDHI"> GUDHI </a></li> + <li class="divider"></li> + <li class="has-dropdown"> + <a href="#">Project</a> + <ul class="dropdown"> + <li><a href="http://gudhi.gforge.inria.fr/people/">People</a></li> + <li><a href="http://gudhi.gforge.inria.fr/keepintouch/">Keep in touch</a></li> + <li><a href="http://gudhi.gforge.inria.fr/partners/">Partners and Funding</a></li> + <li><a href="http://gudhi.gforge.inria.fr/relatedprojects/">Related projects</a></li> + <li><a href="http://gudhi.gforge.inria.fr/theyaretalkingaboutus/">They are talking about us</a></li> + </ul> + </li> + <li class="divider"></li> + <li class="has-dropdown"> + <a href="#">Download</a> + <ul class="dropdown"> + <li><a href="http://gudhi.gforge.inria.fr/licensing/">Licensing</a></li> + <li><a href="https://gforge.inria.fr/frs/?group_id=3865" target="_blank">Get the sources</a></li> + </ul> + </li> + <li class="divider"></li> + <li class="has-dropdown"> + <a href="#">Documentation</a> + <ul class="dropdown"> + <li><a href="http://gudhi.gforge.inria.fr/doc/latest/">C++ documentation</a></li> + <li><a href="http://gudhi.gforge.inria.fr/doc/latest/installation.html">C++ installation manual</a></li> + <li><a href="http://gudhi.gforge.inria.fr/cython/latest/">Cython documentation</a></li> + <li><a href="http://gudhi.gforge.inria.fr/cython/latest/installation.html">Cython installation manual</a></li> + </ul> + </li> + <li class="divider"></li> + <li><a href="http://gudhi.gforge.inria.fr/interfaces/">Interfaces</a></li> + <li class="divider"></li> + </ul> + </section> + </nav> + </div><!-- /#navigation --> + <!-- GUDHI website header BEGIN --> + + +{%- block header %}{% endblock %} + +{%- block relbar1 %}{% endblock %} + +{%- block content %} + {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %} + + <div class="document"> + {%- block document %} + <div class="documentwrapper"> + {%- if render_sidebar %} + <div class="bodywrapper"> + {%- endif %} + <div class="body" role="main"> + {% block body %} {% endblock %} + </div> + {%- if render_sidebar %} + </div> + {%- endif %} + </div> + {%- endblock %} + + {%- block sidebar2 %}{{ sidebar() }}{% endblock %} + <div class="clearer"></div> + </div> +{%- endblock %} + +{%- block relbar2 %}{% endblock %} + +{%- block footer %} + <div class="footer" role="contentinfo"> + {%- if show_copyright %} + {%- if hasdoc('copyright') %} + {% trans path=pathto('copyright'), copyright=copyright|e %}© <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %} + {%- else %} + {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- endif %} + {%- endif %} + {%- if last_updated %} + {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} + {%- endif %} + {%- if show_sphinx %} + {% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %} + {%- endif %} + </div> +{%- endblock %} + </body> +</html> + diff --git a/src/cython/doc/alpha_complex_ref.rst b/src/cython/doc/alpha_complex_ref.rst new file mode 100644 index 00000000..6a122b09 --- /dev/null +++ b/src/cython/doc/alpha_complex_ref.rst @@ -0,0 +1,10 @@ +============================== +Alpha complex reference manual +============================== + +.. autoclass:: gudhi.AlphaComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.AlphaComplex.__init__ diff --git a/src/cython/doc/alpha_complex_sum.rst b/src/cython/doc/alpha_complex_sum.rst new file mode 100644 index 00000000..8437e901 --- /dev/null +++ b/src/cython/doc/alpha_complex_sum.rst @@ -0,0 +1,22 @@ +================================================================= =================================== =================================== +:Author: Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +:Requires: CGAL :math:`\geq` 4.7.0 Eigen3 +================================================================= =================================== =================================== + ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| .. figure:: | Alpha_complex is a simplicial complex constructed from the finite | +| img/alpha_complex_representation.png | cells of a Delaunay Triangulation. | +| :alt: Alpha complex representation | | +| :figclass: align-center | The filtration value of each simplex is computed as the square of the | +| | circumradius of the simplex if the circumsphere is empty (the simplex | +| Alpha complex representation | is then said to be Gabriel), and as the minimum of the filtration | +| | values of the codimension 1 cofaces that make it not Gabriel | +| | otherwise. All simplices that have a filtration value strictly | +| | greater than a given alpha squared value are not inserted into the | +| | complex. | +| | | +| | This package requires having CGAL version 4.7 or higher (4.8.1 is | +| | advised for better perfomances). | ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| :doc:`alpha_complex_user` | :doc:`alpha_complex_ref` | ++----------------------------------------------------------------+------------------------------------------------------------------------+ diff --git a/src/cython/doc/alpha_complex_user.rst b/src/cython/doc/alpha_complex_user.rst new file mode 100644 index 00000000..68e53a77 --- /dev/null +++ b/src/cython/doc/alpha_complex_user.rst @@ -0,0 +1,205 @@ +========================= +Alpha complex user manual +========================= +Definition +---------- + +.. include:: alpha_complex_sum.rst + +Alpha_complex is constructing a :doc:`Simplex_tree <simplex_tree_sum>` using +`Delaunay Triangulation <http://doc.cgal.org/latest/Triangulation/index.html#Chapter_Triangulations>`_ +:cite:`cgal:hdj-t-15b` from `CGAL <http://www.cgal.org/>`_ (the Computational Geometry Algorithms Library +:cite:`cgal:eb-15b`). + +Remarks +^^^^^^^ +When Alpha_complex is constructed with an infinite value of :math:`\alpha`, the complex is a Delaunay complex. + +Example from points +------------------- + +This example builds the Delaunay triangulation from the given points, and initializes the alpha complex with it: + +.. testcode:: + + import gudhi + alpha_complex = gudhi.AlphaComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]]) + + simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=60.0) + result_str = 'Alpha complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtered_tree(): + print(filtered_value) + +The output is: + +.. testoutput:: + + Alpha complex is of dimension 2 - 25 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([2], 0.0) + ([3], 0.0) + ([4], 0.0) + ([5], 0.0) + ([6], 0.0) + ([2, 3], 6.25) + ([4, 5], 7.25) + ([0, 2], 8.5) + ([0, 1], 9.25) + ([1, 3], 10.0) + ([1, 2], 11.25) + ([1, 2, 3], 12.5) + ([0, 1, 2], 12.995867768595042) + ([5, 6], 13.25) + ([2, 4], 20.0) + ([4, 6], 22.736686390532547) + ([4, 5, 6], 22.736686390532547) + ([3, 6], 30.25) + ([2, 6], 36.5) + ([2, 3, 6], 36.5) + ([2, 4, 6], 37.24489795918368) + ([0, 4], 59.710743801652896) + ([0, 2, 4], 59.710743801652896) + + +Algorithm +--------- + +Data structure +^^^^^^^^^^^^^^ + +In order to build the alpha complex, first, a Simplex tree is built from the cells of a Delaunay Triangulation. +(The filtration value is set to NaN, which stands for unknown value): + +.. figure:: + img/alpha_complex_doc.png + :figclass: align-center + :alt: Simplex tree structure construction example + + Simplex tree structure construction example + +Filtration value computation algorithm +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + **for** i : dimension :math:`\rightarrow` 0 **do** + **for all** :math:`\sigma` of dimension i + **if** filtration(:math:`\sigma`) is NaN **then** + filtration(:math:`\sigma`) = :math:`\alpha^2(\sigma)` + **end if** + + *//propagate alpha filtration value* + + **for all** :math:`\tau` face of :math:`\sigma` + **if** filtration(:math:`\tau`) is not NaN **then** + filtration(:math:`\tau`) = filtration(:math:`\sigma`) + **end if** + **end for** + **end for** + **end for** + + make_filtration_non_decreasing() + + prune_above_filtration() + +Dimension 2 +^^^^^^^^^^^ + +From the example above, it means the algorithm looks into each triangle ([0,1,2], [0,2,4], [1,2,3], ...), +computes the filtration value of the triangle, and then propagates the filtration value as described +here: + +.. figure:: + img/alpha_complex_doc_420.png + :figclass: align-center + :alt: Filtration value propagation example + + Filtration value propagation example + +Dimension 1 +^^^^^^^^^^^ + +Then, the algorithm looks into each edge ([0,1], [0,2], [1,2], ...), +computes the filtration value of the edge (in this case, propagation will have no effect). + +Dimension 0 +^^^^^^^^^^^ + +Finally, the algorithm looks into each vertex ([0], [1], [2], [3], [4], [5] and [6]) and +sets the filtration value (0 in case of a vertex - propagation will have no effect). + +Non decreasing filtration values +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As the squared radii computed by CGAL are an approximation, it might happen that these alpha squared values do not +quite define a proper filtration (i.e. non-decreasing with respect to inclusion). +We fix that up by calling `Simplex_tree::make_filtration_non_decreasing()` (cf. +`C++ version <http://gudhi.gforge.inria.fr/doc/latest/index.html>`_). + +Prune above given filtration value +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The simplex tree is pruned from the given maximum alpha squared value (cf. `Simplex_tree::prune_above_filtration()` +int he `C++ version <http://gudhi.gforge.inria.fr/doc/latest/index.html>`_). +In the following example, the value is given by the user as argument of the program. + + +Example from OFF file +^^^^^^^^^^^^^^^^^^^^^ + +This example builds the Delaunay triangulation from the points given by an OFF file, and initializes the alpha complex +with it. + + +Then, it is asked to display information about the alpha complex: + +.. testcode:: + + import gudhi + alpha_complex = gudhi.AlphaComplex(off_file='alphacomplexdoc.off') + simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=59.0) + result_str = 'Alpha complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtered_tree(): + print(filtered_value) + +the program output is: + +.. testoutput:: + + Alpha complex is of dimension 2 - 23 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([2], 0.0) + ([3], 0.0) + ([4], 0.0) + ([5], 0.0) + ([6], 0.0) + ([2, 3], 6.25) + ([4, 5], 7.25) + ([0, 2], 8.5) + ([0, 1], 9.25) + ([1, 3], 10.0) + ([1, 2], 11.25) + ([1, 2, 3], 12.5) + ([0, 1, 2], 12.995867768595042) + ([5, 6], 13.25) + ([2, 4], 20.0) + ([4, 6], 22.736686390532547) + ([4, 5, 6], 22.736686390532547) + ([3, 6], 30.25) + ([2, 6], 36.5) + ([2, 3, 6], 36.5) + ([2, 4, 6], 37.24489795918368) + +============== +CGAL citations +============== + +.. bibliography:: how_to_cite_cgal.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/doc/bottleneck_distance_sum.rst b/src/cython/doc/bottleneck_distance_sum.rst new file mode 100644 index 00000000..5c475d0d --- /dev/null +++ b/src/cython/doc/bottleneck_distance_sum.rst @@ -0,0 +1,15 @@ +================================================================= =================================== =================================== +:Author: François Godi :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +:Requires: CGAL :math:`\geq` 4.8.0 +================================================================= =================================== =================================== + ++-----------------------------------------------------------------+----------------------------------------------------------------------+ +| .. figure:: | Bottleneck distance measures the similarity between two persistence | +| img/perturb_pd.png | diagrams. It's the shortest distance b for which there exists a | +| :figclass: align-center | perfect matching between the points of the two diagrams (+ all the | +| | diagonal points) such that any couple of matched points are at | +| Bottleneck distance is the length of | distance at most b. | +| the longest edge | | ++-----------------------------------------------------------------+----------------------------------------------------------------------+ +| :doc:`bottleneck_distance_user` | | ++-----------------------------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/bottleneck_distance_user.rst b/src/cython/doc/bottleneck_distance_user.rst new file mode 100644 index 00000000..3bc170f4 --- /dev/null +++ b/src/cython/doc/bottleneck_distance_user.rst @@ -0,0 +1,37 @@ +=============================== +Bottleneck distance user manual +=============================== +Definition +---------- + +.. include:: bottleneck_distance_sum.rst + +Function +-------- +.. autofunction:: gudhi.bottleneck_distance + + +Basic example +------------- + +This example computes the bottleneck distance from 2 persistence diagrams: + +.. testcode:: + + import gudhi + + diag1 = [[2.7, 3.7],[9.6, 14.],[34.2, 34.974], [3.,float('Inf')]] + diag2 = [[2.8, 4.45],[9.5, 14.1],[3.2,float('Inf')]] + + message = "Bottleneck distance approximation=" + repr(gudhi.bottleneck_distance(diag1, diag2, 0.1)) + print(message) + + message = "Bottleneck distance exact value=" + repr(gudhi.bottleneck_distance(diag1, diag2)) + print(message) + +The output is: + +.. testoutput:: + + Bottleneck distance approximation=0.8081763781405569 + Bottleneck distance exact value=0.75 diff --git a/src/cython/doc/citation.rst b/src/cython/doc/citation.rst new file mode 100644 index 00000000..6cdfb7cc --- /dev/null +++ b/src/cython/doc/citation.rst @@ -0,0 +1,15 @@ +Acknowledging the GUDHI library +############################### + +We kindly ask users to cite the GUDHI library as appropriately as possible in +their papers, and to mention the use of the GUDHI library on the web pages of +their projects using GUDHI and provide us with links to these web pages. Feel +free to contact us in case you have any question or remark on this topic. + +We provide GUDHI bibtex entries for the modules of the User and Reference +Manual, as well as for publications directly related to the GUDHI library. + +GUDHI bibtex +************ + +.. literalinclude:: how_to_cite_gudhi.bib diff --git a/src/cython/doc/conf.py b/src/cython/doc/conf.py new file mode 100755 index 00000000..42bfd59c --- /dev/null +++ b/src/cython/doc/conf.py @@ -0,0 +1,278 @@ +# -*- coding: utf-8 -*- +# +# GUDHI documentation build configuration file, created by +# sphinx-quickstart on Thu Jun 30 09:55:51 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# Path to Gudhi.so from source path +sys.path.insert(0, os.path.abspath('..')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'matplotlib.sphinxext.plot_directive', + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.todo', + 'sphinx.ext.mathjax', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', + 'sphinxcontrib.bibtex', +] + +todo_include_todos = True +# plot option : do not show hyperlinks (Source code, png, hires.png, pdf) +plot_html_show_source_link = False +plot_html_show_formats = False +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'GUDHI' +copyright = u'2016, GUDHI Editorial Board' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '2.0' +# The full version, including alpha/beta/rc tags. +release = '2.0.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'classic' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { + "sidebarbgcolor": "#A1ADCD", + "sidebartextcolor": "black", + "sidebarlinkcolor": "#334D5C", +} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {'installation': 'installation.html'} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'GUDHIdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'GUDHI.tex', u'GUDHI Documentation', + u'Vincent Rouvreau', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'gudhi', u'GUDHI Documentation', + [u'Vincent Rouvreau'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'GUDHI', u'GUDHI Documentation', + u'Vincent Rouvreau', 'GUDHI', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/src/cython/doc/cubical_complex_ref.rst b/src/cython/doc/cubical_complex_ref.rst new file mode 100644 index 00000000..84aa4223 --- /dev/null +++ b/src/cython/doc/cubical_complex_ref.rst @@ -0,0 +1,9 @@ +Cubical complex reference manual +################################ + +.. autoclass:: gudhi.CubicalComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.CubicalComplex.__init__ diff --git a/src/cython/doc/cubical_complex_sum.rst b/src/cython/doc/cubical_complex_sum.rst new file mode 100644 index 00000000..3ddf6375 --- /dev/null +++ b/src/cython/doc/cubical_complex_sum.rst @@ -0,0 +1,15 @@ +================================================================= =================================== =================================== +:Author: Pawel Dlotko :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +================================================================= =================================== =================================== + ++-----------------------------------------------------------------+----------------------------------------------------------------------+ +| .. figure:: | The cubical complex is an example of a structured complex useful in | +| img/Cubical_complex_representation.png | computational mathematics (specially rigorous numerics) and image | +| :alt: Cubical complex representation | analysis. | +| :figclass: align-center | | +| | | +| Cubical complex representation | | ++-----------------------------------------------------------------+----------------------------------------------------------------------+ +| :doc:`cubical_complex_user` | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | ++-----------------------------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/cubical_complex_user.rst b/src/cython/doc/cubical_complex_user.rst new file mode 100644 index 00000000..692acdd9 --- /dev/null +++ b/src/cython/doc/cubical_complex_user.rst @@ -0,0 +1,161 @@ +=========================== +Cubical complex user manual +=========================== +Definition +---------- + +===================================== ===================================== ===================================== +:Author: Pawel Dlotko :Introduced in: GUDHI PYTHON 2.0.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== + ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`cubical_complex_user` | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ + +The cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous +numerics) and image analysis. + +An *elementary interval* is an interval of a form :math:`[n,n+1]`, or :math:`[n,n]`, for :math:`n \in \mathcal{Z}`. +The first one is called *non-degenerate*, while the second one is a *degenerate* interval. A +*boundary of a elementary interval* is a chain :math:`\partial [n,n+1] = [n+1,n+1]-[n,n]` in case of +non-degenerated elementary interval and :math:`\partial [n,n] = 0` in case of degenerate elementary interval. An +*elementary cube* :math:`C` is a product of elementary intervals, :math:`C=I_1 \times \ldots \times I_n`. +*Embedding dimension* of a cube is n, the number of elementary intervals (degenerate or not) in the product. +A *dimension of a cube* :math:`C=I_1 \times ... \times I_n` is the number of non degenerate elementary +intervals in the product. A *boundary of a cube* :math:`C=I_1 \times \ldots \times I_n` is a chain obtained +in the following way: + +.. math:: + + \partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n). + +A *cubical complex* :math:`\mathcal{K}` is a collection of cubes closed under operation of taking boundary +(i.e. boundary of every cube from the collection is in the collection). A cube :math:`C` in cubical complex +:math:`\mathcal{K}` is *maximal* if it is not in a boundary of any other cube in :math:`\mathcal{K}`. A +*support* of a cube :math:`C` is the set in :math:`\mathbb{R}^n` occupied by :math:`C` (:math:`n` is the embedding +dimension of :math:`C`). + +Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical +complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may +be a set of two elements). + +For further details and theory of cubical complexes, please consult :cite:`kaczynski2004computational` as well as the +following paper :cite:`peikert2012topological`. + +Data structure. +--------------- + +The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in +:math:`\mathbb{R}^n`. This extra assumption allows for a memory efficient way of storing cubical complexes in a form +of so called bitmaps. Let +:math:`R = [b_1,e_1] \times \ldots \times [b_n,e_n]`, for :math:`b_1,...b_n,e_1,...,e_n \in \mathbb{Z}`, +:math:`b_i \leq d_i` be the considered rectangular region and let :math:`\mathcal{K}` be a filtered +cubical complex having the rectangle :math:`R` as its support. Note that the structure of the coordinate system gives +a way a lexicographical ordering of cells of :math:`\mathcal{K}`. This ordering is a base of the presented +bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector of the values +of filtration. This, together with dimension of :math:`\mathcal{K}` and the sizes of :math:`\mathcal{K}` in all +directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube +:math:`C \in \mathcal{K}`. + +.. figure:: + img/Cubical_complex_representation.png + :alt: Cubical complex. + :figclass: align-center + + Cubical complex. + +Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical +complexes in :math:`\mathbb{R}`. The number of all cubes in each direction is equal :math:`2n+1`, where :math:`n` is +the number of maximal cubes in the considered direction. Let us consider a cube at the position :math:`k` in the +bitmap. +Knowing the sizes of the bitmap, by a series of modulo operation, we can determine which elementary intervals are +present in the product that gives the cube :math:`C`. In a similar way, we can compute boundary and the coboundary of +each cube. Further details can be found in the literature. + +Input Format. +------------- + +In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star +filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users +who want to use the code directly. They can be found in the :doc:`cubical_complex_ref`. +Currently one input from a text file is used. It uses a format used already in +`Perseus software <http://www.sas.upenn.edu/~vnanda/perseus/>`_ by Vidit Nanda. +Below we are providing a description of the format. The first line contains a number d begin the dimension of the +bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3 +in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 +20 4 7 6 5 in the example below). + +.. figure:: + img/exampleBitmap.png + :alt: Example of a input data. + :figclass: align-center + + Example of a input data. + +The input file for the following complex is: + +.. literalinclude:: cubicalcomplexdoc.txt + +.. centered:: cubicalcomplexdoc.txt + +.. testcode:: + + import gudhi + cubical_complex = gudhi.CubicalComplex(perseus_file='cubicalcomplexdoc.txt') + result_str = 'Cubical complex is of dimension ' + repr(cubical_complex.dimension()) + ' - ' + \ + repr(cubical_complex.num_simplices()) + ' simplices.' + print(result_str) + +the program output is: + +.. testoutput:: + + Cubical complex is of dimension 2 - 49 simplices. + +Periodic boundary conditions. +----------------------------- + +Often one would like to impose periodic boundary conditions to the cubical complex (cf. +:doc:`periodic_cubical_complex_ref`). +Let :math:`I_1\times ... \times I_n` be a box that is decomposed with a cubical complex :math:`\mathcal{K}`. +Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex +:math:`\mathcal{K}` are considered the same. In particular, if for a bitmap :math:`\mathcal{K}` periodic boundary +conditions are imposed in all directions, then complex :math:`\mathcal{K}` became n-dimensional torus. One can use +various constructors from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical +complex with periodic boundary conditions. One can also use Perseus style input files. To indicate periodic boundary +conditions in a given direction, then number of top dimensional cells in this direction have to be multiplied by -1. +For instance: + +.. literalinclude:: periodiccubicalcomplexdoc.txt + +.. centered:: periodiccubicalcomplexdoc.txt + +Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + +.. testcode:: + + import gudhi + periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='periodiccubicalcomplexdoc.txt') + result_str = 'Periodic cubical complex is of dimension ' + repr(periodic_cc.dimension()) + ' - ' + \ + repr(periodic_cc.num_simplices()) + ' simplices.' + print(result_str) + +the program output is: + +.. testoutput:: + + Periodic cubical complex is of dimension 2 - 42 simplices. + +Examples. +--------- + +End user programs are available in cython/example/ folder. + +Bibliography +************ + +.. bibliography:: bibliography.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/doc/euclidean_strong_witness_complex_ref.rst b/src/cython/doc/euclidean_strong_witness_complex_ref.rst new file mode 100644 index 00000000..bebf0f9a --- /dev/null +++ b/src/cython/doc/euclidean_strong_witness_complex_ref.rst @@ -0,0 +1,10 @@ +================================================= +Euclidean strong witness complex reference manual +================================================= + +.. autoclass:: gudhi.EuclideanStrongWitnessComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.EuclideanStrongWitnessComplex.__init__ diff --git a/src/cython/doc/euclidean_witness_complex_ref.rst b/src/cython/doc/euclidean_witness_complex_ref.rst new file mode 100644 index 00000000..29b8806f --- /dev/null +++ b/src/cython/doc/euclidean_witness_complex_ref.rst @@ -0,0 +1,10 @@ +========================================== +Euclidean witness complex reference manual +========================================== + +.. autoclass:: gudhi.EuclideanWitnessComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.EuclideanWitnessComplex.__init__ diff --git a/src/cython/doc/examples.rst b/src/cython/doc/examples.rst new file mode 100644 index 00000000..a89e0596 --- /dev/null +++ b/src/cython/doc/examples.rst @@ -0,0 +1,4 @@ +Examples +######## + +.. include:: examples.inc diff --git a/src/cython/doc/generate_examples.py b/src/cython/doc/generate_examples.py new file mode 100755 index 00000000..d64d506c --- /dev/null +++ b/src/cython/doc/generate_examples.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +from os import listdir + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2017 INRIA" +__license__ = "GPL v3" + +""" +generate_examples.py generates examples.inc to be included in examples.rst. +Refer to Makefile and make.bat to see if it is correctly launched. +""" + +output_file = open('examples.inc','w') + +output_file.write('.. only:: builder_html\n\n') + +for file in listdir('../example/'): + output_file.write(" * :download:`" + file + " <../example/" + file + ">`\n") + +output_file.close() diff --git a/src/cython/doc/img/graphical_tools_representation.png b/src/cython/doc/img/graphical_tools_representation.png Binary files differnew file mode 100644 index 00000000..9759f7ba --- /dev/null +++ b/src/cython/doc/img/graphical_tools_representation.png diff --git a/src/cython/doc/index.rst b/src/cython/doc/index.rst new file mode 100644 index 00000000..fca63d65 --- /dev/null +++ b/src/cython/doc/index.rst @@ -0,0 +1,87 @@ +GUDHI documentation +################### + +.. image:: img/Gudhi_banner.png + :align: center + +Introduction +************ + +The Gudhi library (Geometry Understanding in Higher Dimensions) is a generic +open source `C++ library <http://gudhi.gforge.inria.fr/doc/latest/>`_, with a +`Cython interface <http://gudhi.gforge.inria.fr/cython/latest/>`_, for +Computational Topology and Topological Data Analysis +(`TDA <https://en.wikipedia.org/wiki/Topological_data_analysis>`_). +The GUDHI library intends to help the development of new algorithmic solutions +in TDA and their transfer to applications. It provides robust, efficient, +flexible and easy to use implementations of state-of-the-art algorithms and +data structures. + +The current release of the GUDHI library includes: + +* Data structures to represent, construct and manipulate simplicial complexes. +* Algorithms to compute persistent homology and multi-field persistent homology. +* Simplication of simplicial complexes by edge contraction. + +All data-structures are generic and several of their aspects can be +parameterized via template classes. We refer to :cite:`gudhilibrary_ICMS14` +for a detailed description of the design of the library. + +Data structures +*************** + +Alpha complex +============= + +.. include:: alpha_complex_sum.rst + +Cubical complex +=============== + +.. include:: cubical_complex_sum.rst + +Rips complex +============ + +.. include:: rips_complex_sum.rst + +Simplex tree +============ + +.. include:: simplex_tree_sum.rst + +Tangential complex +================== + +.. include:: tangential_complex_sum.rst + +Witness complex +=============== + +.. include:: witness_complex_sum.rst + + +Toolbox +******* + +Bottleneck distance +=================== + +.. include:: bottleneck_distance_sum.rst + +Persistence cohomology +====================== + +.. include:: persistent_cohomology_sum.rst + +Persistence graphical tools +=========================== + +.. include:: persistence_graphical_tools_sum.rst + +Bibliography +************ + +.. bibliography:: bibliography.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/doc/installation.rst b/src/cython/doc/installation.rst new file mode 100644 index 00000000..e7d8c210 --- /dev/null +++ b/src/cython/doc/installation.rst @@ -0,0 +1,171 @@ +Installation +############ + +Compiling +********* + +The library uses c++11 and requires `Boost <http://www.boost.org/>`_ with version +1.48.0 or more recent. It is a multi-platform library and compiles on Linux, +Mac OSX and Visual Studio 2015. +It also requires cmake to generate makefiles, and cython to compile the +library. + +GUDHI Cythonization +=================== + +To build the GUDHI cython module, run the following commands in a terminal: + +.. code-block:: bash + + cd /path-to-gudhi/ + mkdir build + cd build/ + cmake .. + make cython + +A list of examples is available here. + +Test suites +=========== + +To test your build, `py.test <http://doc.pytest.org>`_ is required. Run the +following command in a terminal: + +.. code-block:: bash + + cd /path-to-gudhi/build/src/cython + # For windows, you have to set PYTHONPATH environment variable + export PYTHONPATH='$PYTHONPATH:/path-to-gudhi/build/src/cython' + py.test + +Documentation +============= + +To build the documentation, `sphinx-doc <http://http://www.sphinx-doc.org>`_ is +required. Please refer to *conf.py* file to see which +`sphinx-doc <http://http://www.sphinx-doc.org>`_ modules are required to +generate the documentation. Run the following commands in a terminal: + +.. code-block:: bash + + make sphinx + +Optional third-party library +**************************** + +CGAL +==== + +The :doc:`Alpha complex </alpha_complex_user>`, +:doc:`Tangential complex </tangential_complex_user>` and +:doc:`Witness complex </witness_complex_user>` data structures, and +:doc:`Bottleneck distance </bottleneck_distance_user>` requires CGAL, which is a +C++ library which provides easy access to efficient and reliable geometric +algorithms. + +Having CGAL version 4.6.0 or higher installed is recommended. The procedure to +install this library according to your operating system is detailed +`here <http://doc.cgal.org/latest/Manual/installation.html>`_. + +The following examples require the Computational Geometry Algorithms Library: + +.. only:: builder_html + + * :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py>` + * :download:`euclidean_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py>` + +The following example requires CGAL version ≥ 4.7.0: + +.. only:: builder_html + + * :download:`alpha_complex_diagram_persistence_from_off_file_example.py <../example/alpha_complex_diagram_persistence_from_off_file_example.py>` + * :download:`alpha_complex_from_points_example.py <../example/alpha_complex_from_points_example.py>` + +The following example requires CGAL version ≥ 4.8.0: + +.. only:: builder_html + + * :download:`bottleneck_basic_example.py <../example/bottleneck_basic_example.py>` + * :download:`tangential_complex_plain_homology_from_off_file_example.py <../example/tangential_complex_plain_homology_from_off_file_example.py>` + +Eigen3 +====== + +The :doc:`Alpha complex </alpha_complex_user>`, +:doc:`Tangential complex </tangential_complex_user>` and +:doc:`Witness complex </witness_complex_user>` data structures and few +examples requires `Eigen3 <http://eigen.tuxfamily.org/>`_, a C++ template +library for linear algebra: matrices, vectors, numerical solvers, and related +algorithms. + +The following examples require the `Eigen3 <http://eigen.tuxfamily.org/>`_: + +.. only:: builder_html + + * :download:`alpha_complex_diagram_persistence_from_off_file_example.py <../example/alpha_complex_diagram_persistence_from_off_file_example.py>` + * :download:`alpha_complex_from_points_example.py <../example/alpha_complex_from_points_example.py>` + * :download:`tangential_complex_plain_homology_from_off_file_example.py <../example/tangential_complex_plain_homology_from_off_file_example.py>` + * :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py>` + * :download:`euclidean_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py>` + +Matplotlib +========== + +The :doc:`persistence graphical tools </persistence_graphical_tools_user>` +module requires `Matplotlib <http://matplotlib.org>`_, a Python 2D plotting +library which produces publication quality figures in a variety of hardcopy +formats and interactive environments across platforms. + +The following examples require the `Matplotlib <http://matplotlib.org>`_: + +.. only:: builder_html + + * :download:`alpha_complex_diagram_persistence_from_off_file_example.py <../example/alpha_complex_diagram_persistence_from_off_file_example.py>` + * :download:`gudhi_graphical_tools_example.py <../example/gudhi_graphical_tools_example.py>` + * :download:`periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py <../example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py>` + * :download:`rips_complex_diagram_persistence_from_off_file_example.py <../example/rips_complex_diagram_persistence_from_off_file_example.py>` + * :download:`rips_persistence_diagram.py <../example/rips_persistence_diagram.py>` + * :download:`rips_complex_diagram_persistence_from_distance_matrix_file_example.py <../example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py>` + * :download:`tangential_complex_plain_homology_from_off_file_example.py <../example/tangential_complex_plain_homology_from_off_file_example.py>` + * :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py>` + * :download:`euclidean_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py>` + +Numpy +===== + +The :doc:`persistence graphical tools </persistence_graphical_tools_user>` +module requires `NumPy <http://numpy.org>`_, a fundamental package for +scientific computing with Python. + +The following examples require the `NumPy <http://numpy.org>`_: + +.. only:: builder_html + + * :download:`alpha_complex_diagram_persistence_from_off_file_example.py <../example/alpha_complex_diagram_persistence_from_off_file_example.py>` + * :download:`gudhi_graphical_tools_example.py <../example/gudhi_graphical_tools_example.py>` + * :download:`periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py <../example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py>` + * :download:`rips_complex_diagram_persistence_from_off_file_example.py <../example/rips_complex_diagram_persistence_from_off_file_example.py>` + * :download:`rips_persistence_diagram.py <../example/rips_persistence_diagram.py>` + * :download:`rips_complex_diagram_persistence_from_distance_matrix_file_example.py <../example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py>` + * :download:`tangential_complex_plain_homology_from_off_file_example.py <../example/tangential_complex_plain_homology_from_off_file_example.py>` + * :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py>` + * :download:`euclidean_witness_complex_diagram_persistence_from_off_file_example.py <../example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py>` + +Threading Building Blocks +========================= + +`Intel® TBB <https://www.threadingbuildingblocks.org/>`_ lets you easily write +parallel C++ programs that take full advantage of multicore performance, that +are portable and composable, and that have future-proof scalability. + +Having Intel® TBB installed is recommended to parallelize and accelerate some +GUDHI computations. + +Bug reports and contributions +***************************** + +Please help us improving the quality of the GUDHI library. You may report bugs or suggestions to: + + Contact: gudhi-users@lists.gforge.inria.fr + +GUDHI is open to external contributions. If you want to join our development team, please contact us. diff --git a/src/cython/doc/make.bat b/src/cython/doc/make.bat new file mode 100644 index 00000000..ba009a90 --- /dev/null +++ b/src/cython/doc/make.bat @@ -0,0 +1,246 @@ +@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ del examples.inc
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+:: GUDHI specific : Examples.inc is generated with generate_examples.py (and deleted on clean)
+
+if "%1" == "html" (
+ generate_examples.py
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pouet.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pouet.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %BUILDDIR%/..
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %BUILDDIR%/..
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+:end
diff --git a/src/cython/doc/periodic_cubical_complex_ref.rst b/src/cython/doc/periodic_cubical_complex_ref.rst new file mode 100644 index 00000000..c6190a1b --- /dev/null +++ b/src/cython/doc/periodic_cubical_complex_ref.rst @@ -0,0 +1,9 @@ +Periodic cubical complex reference manual +######################################### + +.. autoclass:: gudhi.PeriodicCubicalComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.PeriodicCubicalComplex.__init__ diff --git a/src/cython/doc/persistence_graphical_tools_ref.rst b/src/cython/doc/persistence_graphical_tools_ref.rst new file mode 100644 index 00000000..27c2f68a --- /dev/null +++ b/src/cython/doc/persistence_graphical_tools_ref.rst @@ -0,0 +1,8 @@ +============================================ +Persistence graphical tools reference manual +============================================ + +.. autofunction:: gudhi.__min_birth_max_death +.. autofunction:: gudhi.show_palette_values +.. autofunction:: gudhi.plot_persistence_barcode +.. autofunction:: gudhi.plot_persistence_diagram diff --git a/src/cython/doc/persistence_graphical_tools_sum.rst b/src/cython/doc/persistence_graphical_tools_sum.rst new file mode 100644 index 00000000..d602daa7 --- /dev/null +++ b/src/cython/doc/persistence_graphical_tools_sum.rst @@ -0,0 +1,12 @@ +================================================================= =================================== =================================== +:Author: Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +:Requires: Matplotlib Numpy +================================================================= =================================== =================================== + ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ +| .. figure:: | These graphical tools comes on top of persistence results and allows | +| img/graphical_tools_representation.png | the user to build easily barcode and persistence diagram. | +| | | ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ +| :doc:`persistence_graphical_tools_user` | :doc:`persistence_graphical_tools_ref` | ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ diff --git a/src/cython/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst new file mode 100644 index 00000000..f713e971 --- /dev/null +++ b/src/cython/doc/persistence_graphical_tools_user.rst @@ -0,0 +1,67 @@ +======================================= +Persistence graphical tools user manual +======================================= +Definition +---------- +.. include:: persistence_graphical_tools_sum.rst + + +Show palette values +------------------- + +This function is useful to show the color palette values of dimension: + + +.. testcode:: + + import gudhi + gudhi.show_palette_values(alpha=1.0) + +.. plot:: + + import gudhi + gudhi.show_palette_values(alpha=1.0) + +Show persistence as a barcode +----------------------------- + +This function can display the persistence result as a barcode: + +.. testcode:: + + import gudhi + + periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='3d_torus.txt') + diag = periodic_cc.persistence() + gudhi.plot_persistence_barcode(diag) + +.. plot:: + + import gudhi + + periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='3d_torus.txt') + diag = periodic_cc.persistence() + gudhi.plot_persistence_barcode(diag) + +Show persistence as a diagram +----------------------------- + +This function can display the persistence result as a diagram: + +.. testcode:: + + import gudhi + + rips_complex = gudhi.RipsComplex(off_file='tore3D_300.off', max_edge_length=2.0) + simplex_tree = rips_complex.create_simplex_tree(max_dimension=3) + diag = simplex_tree.persistence() + gudhi.plot_persistence_diagram(diag) + +.. plot:: + + import gudhi + + rips_complex = gudhi.RipsComplex(off_file='tore3D_300.off', max_edge_length=2.0) + simplex_tree = rips_complex.create_simplex_tree(max_dimension=3) + diag = simplex_tree.persistence() + gudhi.plot_persistence_diagram(diag) diff --git a/src/cython/doc/persistent_cohomology_sum.rst b/src/cython/doc/persistent_cohomology_sum.rst new file mode 100644 index 00000000..d1f79cb4 --- /dev/null +++ b/src/cython/doc/persistent_cohomology_sum.rst @@ -0,0 +1,27 @@ +================================================================= =================================== =================================== +:Author: Clément Maria :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +================================================================= =================================== =================================== + ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ +| .. figure:: | The theory of homology consists in attaching to a topological space | +| img/3DTorus_poch.png | a sequence of (homology) groups, capturing global topological | +| :figclass: align-center | features like connected components, holes, cavities, etc. Persistent | +| | homology studies the evolution -- birth, life and death -- of these | +| Rips Persistent Cohomology on a 3D | features when the topological space is changing. Consequently, the | +| Torus | theory is essentially composed of three elements: topological spaces, | +| | their homology groups and an evolution scheme. | +| | | +| | Computation of persistent cohomology using the algorithm of | +| | :cite:`DBLP:journals/dcg/SilvaMV11` and | +| | :cite:`DBLP:journals/corr/abs-1208-5018` and the Compressed | +| | Annotation Matrix implementation of | +| | :cite:`DBLP:conf/esa/BoissonnatDM13`. | +| | | ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ +| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | +| | feature for reference: | +| | | +| | * :doc:`simplex_tree_ref` | +| | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | ++-----------------------------------------------------------------+-----------------------------------------------------------------------+ diff --git a/src/cython/doc/persistent_cohomology_user.rst b/src/cython/doc/persistent_cohomology_user.rst new file mode 100644 index 00000000..69be3b86 --- /dev/null +++ b/src/cython/doc/persistent_cohomology_user.rst @@ -0,0 +1,115 @@ +================================= +Persistent cohomology user manual +================================= +Definition +---------- +===================================== ===================================== ===================================== +:Author: Clément Maria :Introduced in: GUDHI PYTHON 2.0.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== + ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | +| | feature for reference: | +| | | +| | * :doc:`simplex_tree_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ + + +Computation of persistent cohomology using the algorithm of :cite:`DBLP:journals/dcg/SilvaMV11` and +:cite:`DBLP:journals/corr/abs-1208-5018` and the Compressed Annotation Matrix implementation of +:cite:`DBLP:conf/esa/BoissonnatDM13`. + +The theory of homology consists in attaching to a topological space a sequence of (homology) groups, capturing global +topological features like connected components, holes, cavities, etc. Persistent homology studies the evolution -- +birth, life and death -- of these features when the topological space is changing. Consequently, the theory is +essentially composed of three elements: + +* topological spaces +* their homology groups +* an evolution scheme. + +Topological Spaces +------------------ + +Topological spaces are represented by simplicial complexes. +Let :math:`V = \{1, \cdots ,|V|\}` be a set of *vertices*. +A *simplex* :math:`\sigma` is a subset of vertices :math:`\sigma \subseteq V`. +A *simplicial complex* :math:`\mathbf{K}` on :math:`V` is a collection of simplices :math:`\{\sigma\}`, +:math:`\sigma \subseteq V`, such that :math:`\tau \subseteq \sigma \in \mathbf{K} \Rightarrow \tau \in \mathbf{K}`. +The dimension :math:`n=|\sigma|-1` of :math:`\sigma` is its number of elements minus 1. +A *filtration* of a simplicial complex is a function :math:`f:\mathbf{K} \rightarrow \mathbb{R}` satisfying +:math:`f(\tau)\leq f(\sigma)` whenever :math:`\tau \subseteq \sigma`. + +Homology +-------- + +For a ring :math:`\mathcal{R}`, the group of *n-chains*, denoted :math:`\mathbf{C}_n(\mathbf{K},\mathcal{R})`, of +:math:`\mathbf{K}` is the group of formal sums of n-simplices with :math:`\mathcal{R}` coefficients. The +*boundary operator* is a linear operator +:math:`\partial_n: \mathbf{C}_n(\mathbf{K},\mathcal{R}) \rightarrow \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R})` +such that :math:`\partial_n \sigma = \partial_n [v_0, \cdots , v_n] = \sum_{i=0}^n (-1)^{i}[v_0,\cdots ,\widehat{v_i}, \cdots,v_n]`, +where :math:`\widehat{v_i}` means :math:`v_i` is omitted from the list. The chain groups form a sequence: + +.. math:: + + \cdots \ \ \mathbf{C}_n(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_n\ } + \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R}) \xrightarrow{\partial_{n-1}} \cdots \xrightarrow{\ \partial_2 \ } + \mathbf{C}_1(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_1 \ } \mathbf{C}_0(\mathbf{K},\mathcal{R}) + +of finitely many groups :math:`\mathbf{C}_n(\mathbf{K},\mathcal{R})` and homomorphisms :math:`\partial_n`, indexed by +the dimension :math:`n \geq 0`. The boundary operators satisfy the property :math:`\partial_n \circ \partial_{n+1}=0` +for every :math:`n > 0` and we define the homology groups: + +.. math:: + + \mathbf{H}_n(\mathbf{K},\mathcal{R}) = \ker \partial_n / \mathrm{im} \ \partial_{n+1} + +We refer to :cite:`Munkres-elementsalgtop1984` for an introduction to homology +theory and to :cite:`DBLP:books/daglib/0025666` for an introduction to persistent homology. + +Indexing Scheme +--------------- + +"Changing" a simplicial complex consists in applying a simplicial map. An *indexing scheme* is a directed graph +together with a traversal order, such that two consecutive nodes in the graph are connected by an arrow (either forward +or backward). +The nodes represent simplicial complexes and the directed edges simplicial maps. + +From the computational point of view, there are two types of indexing schemes of interest in persistent homology: + +* linear ones + :math:`\bullet \longrightarrow \bullet \longrightarrow \cdots \longrightarrow \bullet \longrightarrow \bullet` + in persistent homology :cite:`DBLP:journals/dcg/ZomorodianC05`, +* zigzag ones + :math:`\bullet \longrightarrow \bullet \longleftarrow \cdots \longrightarrow \bullet \longleftarrow \bullet` + in zigzag persistent homology :cite:`DBLP:journals/focm/CarlssonS10`. + +These indexing schemes have a natural left-to-right traversal order, and we describe them with ranges and iterators. +In the current release of the Gudhi library, only the linear case is implemented. + +In the following, we consider the case where the indexing scheme is induced by a filtration. + +Ordering the simplices by increasing filtration values (breaking ties so as a simplex appears after its subsimplices of +same filtration value) provides an indexing scheme. + +Examples +-------- + +We provide several example files: run these examples with -h for details on their use. + +.. only:: builder_html + + * :download:`alpha_complex_diagram_persistence_from_off_file_example.py <../example/alpha_complex_diagram_persistence_from_off_file_example.py>` + * :download:`periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py <../example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py>` + * :download:`rips_complex_diagram_persistence_from_off_file_example.py <../example/rips_complex_diagram_persistence_from_off_file_example.py>` + * :download:`rips_persistence_diagram.py <../example/rips_persistence_diagram.py>` + * :download:`rips_complex_diagram_persistence_from_distance_matrix_file_example.py <../example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py>` + * :download:`random_cubical_complex_persistence_example.py <../example/random_cubical_complex_persistence_example.py>` + * :download:`tangential_complex_plain_homology_from_off_file_example.py <../example/tangential_complex_plain_homology_from_off_file_example.py>` + +Bibliography +************ + +.. bibliography:: bibliography.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/doc/pyplots/barcode_persistence.py b/src/cython/doc/pyplots/barcode_persistence.py new file mode 100755 index 00000000..c06ac5a7 --- /dev/null +++ b/src/cython/doc/pyplots/barcode_persistence.py @@ -0,0 +1,5 @@ +import gudhi + +periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='../3d_torus.txt') +diag = periodic_cc.persistence() +gudhi.plot_persistence_barcode(diag) diff --git a/src/cython/doc/pyplots/diagram_persistence.py b/src/cython/doc/pyplots/diagram_persistence.py new file mode 100755 index 00000000..b4714fe3 --- /dev/null +++ b/src/cython/doc/pyplots/diagram_persistence.py @@ -0,0 +1,5 @@ +import gudhi + +alpha_complex = gudhi.AlphaComplex(off_file='../tore3D_300.off') +diag = alpha_complex.persistence() +gudhi.plot_persistence_diagram(diag) diff --git a/src/cython/doc/pyplots/show_palette_values.py b/src/cython/doc/pyplots/show_palette_values.py new file mode 100755 index 00000000..e72a55fd --- /dev/null +++ b/src/cython/doc/pyplots/show_palette_values.py @@ -0,0 +1,2 @@ +import gudhi +gudhi.show_palette_values(alpha=1.0) diff --git a/src/cython/doc/rips_complex_ref.rst b/src/cython/doc/rips_complex_ref.rst new file mode 100644 index 00000000..b17dc4e0 --- /dev/null +++ b/src/cython/doc/rips_complex_ref.rst @@ -0,0 +1,10 @@ +============================= +Rips complex reference manual +============================= + +.. autoclass:: gudhi.RipsComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.RipsComplex.__init__ diff --git a/src/cython/doc/rips_complex_sum.rst b/src/cython/doc/rips_complex_sum.rst new file mode 100644 index 00000000..2b65fc19 --- /dev/null +++ b/src/cython/doc/rips_complex_sum.rst @@ -0,0 +1,17 @@ +================================================================= =================================== =================================== +:Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +================================================================= =================================== =================================== + ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| .. figure:: | Rips complex is a simplicial complex constructed from a one skeleton | +| img/rips_complex_representation.png | graph. | +| :figclass: align-center | | +| | The filtration value of each edge is computed from a user-given | +| Rips complex representation | distance function and is inserted until a user-given threshold | +| | value. | +| | | +| | This complex can be built from a point cloud and a distance function, | +| | or from a distance matrix. | ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| :doc:`rips_complex_user` | :doc:`rips_complex_ref` | ++----------------------------------------------------------------+------------------------------------------------------------------------+ diff --git a/src/cython/doc/rips_complex_user.rst b/src/cython/doc/rips_complex_user.rst new file mode 100644 index 00000000..027c3bf7 --- /dev/null +++ b/src/cython/doc/rips_complex_user.rst @@ -0,0 +1,237 @@ +========================= +Rips complex user manual +========================= +Definition +---------- + +======================================================= ===================================== ===================================== +:Authors: Clément Maria, Pawel Dlotko, Vincent Rouvreau :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +======================================================= ===================================== ===================================== + ++-------------------------------------------+----------------------------------------------------------------------+ +| :doc:`rips_complex_user` | :doc:`rips_complex_ref` | ++-------------------------------------------+----------------------------------------------------------------------+ + +`Rips complex <https://en.wikipedia.org/wiki/Vietoris%E2%80%93Rips_complex>`_ is a one skeleton graph that allows to +construct a simplicial complex from it. The input can be a point cloud with a given distance function, or a distance +matrix. + +The 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). + +.. figure:: + img/rips_complex_representation.png + :align: center + + 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 :math:`max(filtration(4,5), filtration(4,6), filtration(5,6))`. And so on for simplex (0,1,2,3). + +If the Rips_complex interfaces are not detailed enough for your need, please refer to rips_persistence_step_by_step.cpp +example, where the graph construction over the Simplex_tree is more detailed. + +Point cloud +----------- + +Example from a point cloud +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This example builds the one skeleton graph from the given points, and max_edge_length value. +Then it creates a :doc:`Simplex_tree <simplex_tree_ref>` with it. + +Finally, it is asked to display information about the simplicial complex. + +.. testcode:: + + import gudhi + rips_complex = gudhi.RipsComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]], + max_edge_length=12.0) + + simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) + result_str = 'Rips complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtered_tree(): + print(filtered_value) + +When launching (Rips maximal distance between 2 points is 12.0, is expanded +until dimension 1 - one skeleton graph in other words), the output is: + +.. testoutput:: + + Rips complex is of dimension 1 - 18 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([2], 0.0) + ([3], 0.0) + ([4], 0.0) + ([5], 0.0) + ([6], 0.0) + ([2, 3], 5.0) + ([4, 5], 5.385164807134504) + ([0, 2], 5.830951894845301) + ([0, 1], 6.082762530298219) + ([1, 3], 6.324555320336759) + ([1, 2], 6.708203932499369) + ([5, 6], 7.280109889280518) + ([2, 4], 8.94427190999916) + ([0, 3], 9.433981132056603) + ([4, 6], 9.486832980505138) + ([3, 6], 11.0) + +Example from OFF file +^^^^^^^^^^^^^^^^^^^^^ + +This example builds the :doc:`Rips_complex <rips_complex_ref>` from the given +points in an OFF file, and max_edge_length value. +Then it creates a :doc:`Simplex_tree <simplex_tree_ref>` with it. + +Finally, it is asked to display information about the Rips complex. + + +.. testcode:: + + import gudhi + rips_complex = gudhi.RipsComplex(off_file='alphacomplexdoc.off', max_edge_length=12.0) + simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) + result_str = 'Rips complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtered_tree(): + print(filtered_value) + +the program output is: + +.. testoutput:: + + Rips complex is of dimension 1 - 18 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([2], 0.0) + ([3], 0.0) + ([4], 0.0) + ([5], 0.0) + ([6], 0.0) + ([2, 3], 5.0) + ([4, 5], 5.385164807134504) + ([0, 2], 5.830951894845301) + ([0, 1], 6.082762530298219) + ([1, 3], 6.324555320336759) + ([1, 2], 6.708203932499369) + ([5, 6], 7.280109889280518) + ([2, 4], 8.94427190999916) + ([0, 3], 9.433981132056603) + ([4, 6], 9.486832980505138) + ([3, 6], 11.0) + +Distance matrix +--------------- + +Example from a distance matrix +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This example builds the one skeleton graph from the given distance matrix, and max_edge_length value. +Then it creates a :doc:`Simplex_tree <simplex_tree_ref>` with it. + +Finally, it is asked to display information about the simplicial complex. + +.. testcode:: + + import gudhi + rips_complex = gudhi.RipsComplex(distance_matrix=[[], + [6.0827625303], + [5.8309518948, 6.7082039325], + [9.4339811321, 6.3245553203, 5], + [13.0384048104, 15.6524758425, 8.94427191, 12.0415945788], + [18.0277563773, 19.6468827044, 13.152946438, 14.7648230602, 5.3851648071], + [17.88854382, 17.1172427686, 12.0830459736, 11, 9.4868329805, 7.2801098893]], + max_edge_length=12.0) + + simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) + result_str = 'Rips complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtered_tree(): + print(filtered_value) + +When launching (Rips maximal distance between 2 points is 12.0, is expanded +until dimension 1 - one skeleton graph in other words), the output is: + +.. testoutput:: + + Rips complex is of dimension 1 - 18 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([2], 0.0) + ([3], 0.0) + ([4], 0.0) + ([5], 0.0) + ([6], 0.0) + ([2, 3], 5.0) + ([4, 5], 5.3851648071) + ([0, 2], 5.8309518948) + ([0, 1], 6.0827625303) + ([1, 3], 6.3245553203) + ([1, 2], 6.7082039325) + ([5, 6], 7.2801098893) + ([2, 4], 8.94427191) + ([0, 3], 9.4339811321) + ([4, 6], 9.4868329805) + ([3, 6], 11.0) + +Example from csv file +^^^^^^^^^^^^^^^^^^^^^ + +This example builds the :doc:`Rips_complex <rips_complex_ref>` from the given +points in an OFF file, and max_edge_length value. +Then it creates a :doc:`Simplex_tree <simplex_tree_ref>` with it. + +Finally, it is asked to display information about the Rips complex. + + +.. testcode:: + + import gudhi + rips_complex = gudhi.RipsComplex(csv_file='full_square_distance_matrix.csv', max_edge_length=12.0) + simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) + result_str = 'Rips complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtered_tree(): + print(filtered_value) + +the program output is: + +.. testoutput:: + + Rips complex is of dimension 1 - 18 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([2], 0.0) + ([3], 0.0) + ([4], 0.0) + ([5], 0.0) + ([6], 0.0) + ([2, 3], 5.0) + ([4, 5], 5.3851648071) + ([0, 2], 5.8309518948) + ([0, 1], 6.0827625303) + ([1, 3], 6.3245553203) + ([1, 2], 6.7082039325) + ([5, 6], 7.2801098893) + ([2, 4], 8.94427191) + ([0, 3], 9.4339811321) + ([4, 6], 9.4868329805) + ([3, 6], 11.0) diff --git a/src/cython/doc/simplex_tree_ref.rst b/src/cython/doc/simplex_tree_ref.rst new file mode 100644 index 00000000..6d196843 --- /dev/null +++ b/src/cython/doc/simplex_tree_ref.rst @@ -0,0 +1,10 @@ +============================= +Simplex tree reference manual +============================= + +.. autoclass:: gudhi.SimplexTree + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.SimplexTree.__init__ diff --git a/src/cython/doc/simplex_tree_sum.rst b/src/cython/doc/simplex_tree_sum.rst new file mode 100644 index 00000000..3174fb62 --- /dev/null +++ b/src/cython/doc/simplex_tree_sum.rst @@ -0,0 +1,14 @@ +================================================================= =================================== =================================== +:Author: Clément Maria :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +================================================================= =================================== =================================== + ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| .. figure:: | The simplex tree is an efficient and flexible data structure for | +| img/Simplex_tree_representation.png | representing general (filtered) simplicial complexes. | +| :alt: Simplex tree representation | | +| :figclass: align-center | The data structure is described in | +| | :cite:`boissonnatmariasimplextreealgorithmica` | +| Simplex tree representation | | ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| :doc:`simplex_tree_user` | :doc:`simplex_tree_ref` | ++----------------------------------------------------------------+------------------------------------------------------------------------+ diff --git a/src/cython/doc/simplex_tree_user.rst b/src/cython/doc/simplex_tree_user.rst new file mode 100644 index 00000000..6b55c4e7 --- /dev/null +++ b/src/cython/doc/simplex_tree_user.rst @@ -0,0 +1,67 @@ +======================== +Simplex tree user manual +======================== +Definition +---------- + +.. include:: simplex_tree_sum.rst + +A simplicial complex :math:`\mathbf{K}` on a set of vertices :math:`V = \{1, \cdots ,|V|\}` is a collection of +simplices :math:`\{\sigma\}`, :math:`\sigma \subseteq V` such that +:math:`\tau \subseteq \sigma \in \mathbf{K} \rightarrow \tau \in \mathbf{K}`. The dimension :math:`n=|\sigma|-1` of +:math:`\sigma` is its number of elements minus `1`. + +A filtration of a simplicial complex is a function :math:`f:\mathbf{K} \rightarrow \mathbb{R}` satisfying +:math:`f(\tau)\leq f(\sigma)` whenever :math:`\tau \subseteq \sigma`. Ordering the simplices by increasing filtration +values (breaking ties so as a simplex appears after its subsimplices of same filtration value) provides an indexing +scheme. + + +Implementation +-------------- + +There are two implementation of complexes. The first on is the Simplex_tree data structure. +The simplex tree is an efficient and flexible data structure for representing general (filtered) simplicial complexes. +The data structure is described in :cite`boissonnatmariasimplextreealgorithmica`. + +The second one is the Hasse_complex. The Hasse complex is a data structure representing explicitly all co-dimension 1 +incidence relations in a complex. It is consequently faster when accessing the boundary of a simplex, but is less +compact and harder to construct from scratch. + +Example +------- + +.. testcode:: + + import gudhi + st = gudhi.SimplexTree() + if st.insert_simplex([0, 1]): + print("[0, 1] inserted") + if st.insert_simplex_and_subfaces([0, 1, 2], filtration=4.0): + print("[0, 1, 2] inserted") + if st.find([0, 1]): + print("[0, 1] found") + print("num_vertices=", st.num_vertices()) + print("num_simplices=", st.num_simplices()) + print("skeleton_tree(2) =") + for sk_value in st.get_skeleton_tree(2): + print(sk_value) + + +The output is: + +.. testoutput:: + + [0, 1] inserted + [0, 1, 2] inserted + [0, 1] found + ('num_vertices=', 3) + ('num_simplices=', 7) + skeleton_tree(2) = + ([0, 1, 2], 4.0) + ([0, 1], 0.0) + ([0, 2], 4.0) + ([0], 0.0) + ([1, 2], 4.0) + ([1], 4.0) + ([2], 4.0) diff --git a/src/cython/doc/strong_witness_complex_ref.rst b/src/cython/doc/strong_witness_complex_ref.rst new file mode 100644 index 00000000..4ed4fe46 --- /dev/null +++ b/src/cython/doc/strong_witness_complex_ref.rst @@ -0,0 +1,10 @@ +======================================= +Strong witness complex reference manual +======================================= + +.. autoclass:: gudhi.StrongWitnessComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.StrongWitnessComplex.__init__ diff --git a/src/cython/doc/tangential_complex_ref.rst b/src/cython/doc/tangential_complex_ref.rst new file mode 100644 index 00000000..35589475 --- /dev/null +++ b/src/cython/doc/tangential_complex_ref.rst @@ -0,0 +1,10 @@ +=================================== +Tangential complex reference manual +=================================== + +.. autoclass:: gudhi.TangentialComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.TangentialComplex.__init__ diff --git a/src/cython/doc/tangential_complex_sum.rst b/src/cython/doc/tangential_complex_sum.rst new file mode 100644 index 00000000..2b05bc10 --- /dev/null +++ b/src/cython/doc/tangential_complex_sum.rst @@ -0,0 +1,15 @@ +================================================================= =================================== =================================== +:Author: Clément Jamin :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +:Requires: CGAL :math:`\geq` 4.8.0 Eigen3 +================================================================= =================================== =================================== + ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| .. figure:: | A Tangential Delaunay complex is a simplicial complex designed to | +| img/tc_examples.png | reconstruct a :math:`k`-dimensional manifold embedded in :math:`d`- | +| :figclass: align-center | dimensional Euclidean space. The input is a point sample coming from | +| | an unknown manifold. The running time depends only linearly on the | +| **Tangential complex representation** | extrinsic dimension :math:`d` and exponentially on the intrinsic | +| | dimension :math:`k`. | ++----------------------------------------------------------------+------------------------------------------------------------------------+ +| :doc:`tangential_complex_user` | :doc:`tangential_complex_ref` | ++----------------------------------------------------------------+------------------------------------------------------------------------+ diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst new file mode 100644 index 00000000..6a7e6e41 --- /dev/null +++ b/src/cython/doc/tangential_complex_user.rst @@ -0,0 +1,195 @@ +============================== +Tangential complex user manual +============================== +.. include:: tangential_complex_sum.rst + +Definition +---------- + +A Tangential Delaunay complex is a simplicial complex designed to reconstruct a +:math:`k`-dimensional smooth manifold embedded in :math:`d`-dimensional +Euclidean space. The input is a point sample coming from an unknown manifold, +which means that the points lie close to a structure of "small" intrinsic +dimension. The running time depends only linearly on the extrinsic dimension +:math:`d` and exponentially on the intrinsic dimension :math:`k`. + +An extensive description of the Tangential complex can be found in +:cite:`tangentialcomplex2014`. + +What is a Tangential Complex? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Let us start with the description of the Tangential complex of a simple +example, with :math:`k = 1` and :math:`d = 2`. The input data is 4 points +:math:`P` located on a curve embedded in 2D. + +.. figure:: img/tc_example_01.png + :alt: The input + :figclass: align-center + + The input + +For each point :math:`p`, estimate its tangent subspace :math:`T_p` (e.g. +using PCA). + +.. figure:: img/tc_example_02.png + :alt: The estimated normals + :figclass: align-center + + The estimated normals + + +Let us add the Voronoi diagram of the points in orange. For each point +:math:`p`, construct its star in the Delaunay triangulation of :math:`P` +restricted to :math:`T_p`. + +.. figure:: img/tc_example_03.png + :alt: The Voronoi diagram + :figclass: align-center + + The Voronoi diagram + +The Tangential Delaunay complex is the union of those stars. + +In practice, neither the ambient Voronoi diagram nor the ambient Delaunay +triangulation is computed. Instead, local :math:`k`-dimensional regular +triangulations are computed with a limited number of points as we only need the +star of each point. More details can be found in :cite:`tangentialcomplex2014`. + +Inconsistencies +^^^^^^^^^^^^^^^ +Inconsistencies between the stars can occur. An inconsistency occurs when a +simplex is not in the star of all its vertices. + +Let us take the same example. + +.. figure:: img/tc_example_07_before.png + :alt: Before + :figclass: align-center + + Before + +Let us slightly move the tangent subspace :math:`T_q` + +.. figure:: img/tc_example_07_after.png + :alt: After + :figclass: align-center + + After + +Now, the star of :math:`Q` contains :math:`QP`, but the star of :math:`P` does +not contain :math:`QP`. We have an inconsistency. + +.. figure:: img/tc_example_08.png + :alt: After + :figclass: align-center + + After + +One way to solve inconsistencies is to randomly perturb the positions of the +points involved in an inconsistency. In the current implementation, this +perturbation is done in the tangent subspace of each point. The maximum +perturbation radius is given as a parameter to the constructor. + +In most cases, we recommend to provide a point set where the minimum distance +between any two points is not too small. This can be achieved using the +functions provided by the Subsampling module. Then, a good value to start with +for the maximum perturbation radius would be around half the minimum distance +between any two points. The Example with perturbation below shows an example of +such a process. + +In most cases, this process is able to dramatically reduce the number of +inconsistencies, but is not guaranteed to succeed. + +Output +^^^^^^ +The result of the computation is exported as a Simplex_tree. It is the union of +the stars of all the input points. A vertex in the Simplex Tree is the index of +the point in the range provided by the user. The point corresponding to a +vertex can also be obtained through the Tangential_complex::get_point function. +Note that even if the positions of the points are perturbed, their original +positions are kept (e.g. Tangential_complex::get_point returns the original +position of the point). + +The result can be obtained after the computation of the Tangential complex +itself and/or after the perturbation process. + + +Simple example +-------------- + +This example builds the Tangential complex of point set read in an OFF file. + +.. testcode:: + + import gudhi + tc = gudhi.TangentialComplex(off_file='alphacomplexdoc.off') + result_str = 'Tangential contains ' + repr(tc.num_simplices()) + \ + ' simplices - ' + repr(tc.num_vertices()) + ' vertices.' + print(result_str) + + st = tc.create_simplex_tree() + result_str = 'Simplex tree is of dimension ' + repr(st.dimension()) + \ + ' - ' + repr(st.num_simplices()) + ' simplices - ' + \ + repr(st.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in st.get_filtered_tree(): + print(filtered_value) + +The output is: + +.. testoutput:: + + Tangential contains 12 simplices - 7 vertices. + Simplex tree is of dimension 1 - 15 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([0, 1], 0.0) + ([2], 0.0) + ([0, 2], 0.0) + ([1, 2], 0.0) + ([3], 0.0) + ([1, 3], 0.0) + ([4], 0.0) + ([2, 4], 0.0) + ([5], 0.0) + ([4, 5], 0.0) + ([6], 0.0) + ([3, 6], 0.0) + ([5, 6], 0.0) + + +Example with perturbation +------------------------- + +This example builds the Tangential complex of a point set, then tries to solve +inconsistencies by perturbing the positions of points involved in inconsistent +simplices. + +.. testcode:: + + import gudhi + tc = gudhi.TangentialComplex(points=[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]) + result_str = 'Tangential contains ' + repr(tc.num_vertices()) + ' vertices.' + print(result_str) + + if tc.num_inconsistent_simplices() > 0: + print('Tangential contains inconsistencies.') + + tc.fix_inconsistencies_using_perturbation(10, 60) + if tc.num_inconsistent_simplices() == 0: + print('Inconsistencies has been fixed.') + +The output is: + +.. testoutput:: + + Tangential contains 4 vertices. + Inconsistencies has been fixed. + +Bibliography +************ + +.. bibliography:: bibliography.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/doc/todos.rst b/src/cython/doc/todos.rst new file mode 100644 index 00000000..78972a4c --- /dev/null +++ b/src/cython/doc/todos.rst @@ -0,0 +1,5 @@ +========== +To be done +========== + +.. todolist:: diff --git a/src/cython/doc/witness_complex_ref.rst b/src/cython/doc/witness_complex_ref.rst new file mode 100644 index 00000000..c78760cb --- /dev/null +++ b/src/cython/doc/witness_complex_ref.rst @@ -0,0 +1,10 @@ +================================ +Witness complex reference manual +================================ + +.. autoclass:: gudhi.WitnessComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.WitnessComplex.__init__ diff --git a/src/cython/doc/witness_complex_sum.rst b/src/cython/doc/witness_complex_sum.rst new file mode 100644 index 00000000..b65522ba --- /dev/null +++ b/src/cython/doc/witness_complex_sum.rst @@ -0,0 +1,17 @@ +================================================================= =================================== =================================== +:Author: Siargey Kachanovich :Introduced in: GUDHI 2.0.0 :Copyright: GPL v3 +:Euclidean version requires: CGAL :math:`\geq` 4.6.0 Eigen3 +================================================================= =================================== =================================== + ++-----------------------------------------------------------------+----------------------------------------------------------------------+ +| .. image:: | Witness complex :math:`Wit(W,L)` is a simplicial complex defined on | +| img/Witness_complex_representation.png | two sets of points in :math:`\mathbb{R}^D`. | +| | | +| | The data structure is described in | +| | :cite:`boissonnatmariasimplextreealgorithmica`. | ++-----------------------------------------------------------------+----------------------------------------------------------------------+ +| :doc:`witness_complex_user` | * :doc:`witness_complex_ref` | +| | * :doc:`strong_witness_complex_ref` | +| | * :doc:`euclidean_witness_complex_ref` | +| | * :doc:`euclidean_strong_witness_complex_ref` | ++-----------------------------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/witness_complex_user.rst b/src/cython/doc/witness_complex_user.rst new file mode 100644 index 00000000..07945361 --- /dev/null +++ b/src/cython/doc/witness_complex_user.rst @@ -0,0 +1,135 @@ +=========================== +Witness complex user manual +=========================== +Definition +---------- + +.. include:: witness_complex_sum.rst + + +Definitions +----------- + +Witness complex is a simplicial complex defined on two sets of points in :math:`\mathbb{R}^D`: + +- :math:`W` set of **witnesses** and +- :math:`L` set of **landmarks**. + +Even though often the set of landmarks :math:`L` is a subset of the set of witnesses :math:`W`, it is not a requirement +for the current implementation. + +Landmarks are the vertices of the simplicial complex and witnesses help to decide on which simplices are inserted via a +predicate "is witnessed". + +De Silva and Carlsson in their paper :cite:`de2004topological` differentiate **weak witnessing** and +**strong witnessing**: + +- *weak*: :math:`\sigma \subset L` is witnessed by :math:`w \in W` if :math:`\forall l \in \sigma,\ \forall l' \in \mathbf{L \setminus \sigma},\ d(w,l) \leq d(w,l')` +- *strong*: :math:`\sigma \subset L` is witnessed by :math:`w \in W` if :math:`\forall l \in \sigma,\ \forall l' \in \mathbf{L},\ d(w,l) \leq d(w,l')` + +where :math:`d(.,.)` is a distance function. + +Both definitions can be relaxed by a real value :math:`\alpha`: + +- *weak*: :math:`\sigma \subset L` is :math:`\alpha`-witnessed by :math:`w \in W` if :math:`\forall l \in \sigma,\ \forall l' \in \mathbf{L \setminus \sigma},\ d(w,l)^2 \leq d(w,l')^2 + \alpha^2` +- *strong*: :math:`\sigma \subset L` is :math:`\alpha`-witnessed by :math:`w \in W` if :math:`\forall l \in \sigma,\ \forall l' \in \mathbf{L},\ d(w,l)^2 \leq d(w,l')^2 + \alpha^2` + +which leads to definitions of **weak relaxed witness complex** (or just relaxed witness complex for short) and +**strong relaxed witness complex** respectively. + +.. figure:: img/swit.svg + :alt: Strongly witnessed simplex + :figclass: align-center + + Strongly witnessed simplex + + +In particular case of 0-relaxation, weak complex corresponds to **witness complex** introduced in +:cite:`de2004topological`, whereas 0-relaxed strong witness complex consists of just vertices and is not very +interesting. Hence for small relaxation weak version is preferable. +However, to capture the homotopy type (for example using Gudhi::persistent_cohomology::Persistent_cohomology) it is +often necessary to work with higher filtration values. In this case strong relaxed witness complex is faster to compute +and offers similar results. + +Implementation +-------------- + +The two complexes described above are implemented in the corresponding classes + +- :doc:`witness_complex_ref` +- :doc:`strong_witness_complex_ref` +- :doc:`euclidean_witness_complex_ref` +- :doc:`euclidean_strong_witness_complex_ref` + +The construction of the Euclidean versions of complexes follow the same scheme: + +1. Construct a search tree on landmarks. +2. Construct lists of nearest landmarks for each witness. +3. Construct the witness complex for nearest landmark lists. + +In the non-Euclidean classes, the lists of nearest landmarks are supposed to be given as input. + +The constructors take on the steps 1 and 2, while the function 'create_complex' executes the step 3. + +Constructing weak relaxed witness complex from an off file +---------------------------------------------------------- + +Let's start with a simple example, which reads an off point file and computes a weak witness complex. + +.. code-block:: python + + import gudhi + import argparse + + parser = argparse.ArgumentParser(description='EuclideanWitnessComplex creation from ' + 'points read in a OFF file.', + epilog='Example: ' + 'example/witness_complex_diagram_persistence_from_off_file_example.py ' + '-f ../data/points/tore3D_300.off -a 1.0 -n 20 -d 2' + '- Constructs a alpha complex with the ' + 'points from the given OFF file.') + parser.add_argument("-f", "--file", type=str, required=True) + parser.add_argument("-a", "--max_alpha_square", type=float, required=True) + parser.add_argument("-n", "--number_of_landmarks", type=int, required=True) + parser.add_argument("-d", "--limit_dimension", type=int, required=True) + + args = parser.parse_args() + + with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("EuclideanWitnessComplex creation from points read in a OFF file") + + witnesses = gudhi.read_off(off_file=args.file) + landmarks = gudhi.pick_n_random_points(points=witnesses, nb_points=args.number_of_landmarks) + + message = "EuclideanWitnessComplex with max_edge_length=" + repr(args.max_alpha_square) + \ + " - Number of landmarks=" + repr(args.number_of_landmarks) + print(message) + + witness_complex = gudhi.EuclideanWitnessComplex(witnesses=witnesses, landmarks=landmarks) + simplex_tree = witness_complex.create_simplex_tree(max_alpha_square=args.max_alpha_square, + limit_dimension=args.limit_dimension) + + message = "Number of simplices=" + repr(simplex_tree.num_simplices()) + print(message) + else: + print(args.file, "is not a valid OFF file") + + f.close() + + +Example2: Computing persistence using strong relaxed witness complex +-------------------------------------------------------------------- + +Here is an example of constructing a strong witness complex filtration and computing persistence on it: + +* :download:`euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py <../example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py>` + +Bibliography +************ + +.. bibliography:: bibliography.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py new file mode 100755 index 00000000..adedc7d2 --- /dev/null +++ b/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='AlphaComplex creation from ' + 'points read in a OFF file.', + epilog='Example: ' + 'example/alpha_complex_diagram_persistence_from_off_file_example.py ' + '-f ../data/points/tore3D_300.off -a 0.6' + '- Constructs a alpha complex with the ' + 'points from the given OFF file.') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-a", "--max_alpha_square", type=float, default=0.5) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("AlphaComplex creation from points read in a OFF file") + + message = "AlphaComplex with max_edge_length=" + repr(args.max_alpha_square) + print(message) + + alpha_complex = gudhi.AlphaComplex(off_file=args.file) + simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=args.max_alpha_square) + + message = "Number of simplices=" + repr(simplex_tree.num_simplices()) + print(message) + + diag = simplex_tree.persistence() + + print("betti_numbers()=") + print(simplex_tree.betti_numbers()) + + if args.no_diagram == False: + gudhi.plot_persistence_diagram(diag) + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/alpha_complex_from_points_example.py b/src/cython/example/alpha_complex_from_points_example.py new file mode 100755 index 00000000..688edb65 --- /dev/null +++ b/src/cython/example/alpha_complex_from_points_example.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +from gudhi import AlphaComplex, SimplexTree + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("AlphaComplex creation from points") +alpha_complex = AlphaComplex(points=[[0, 0], [1, 0], [0, 1], [1, 1]]) +simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=60.0) + +if simplex_tree.find([0, 1]): + print("[0, 1] Found !!") +else: + print("[0, 1] Not found...") + +if simplex_tree.find([4]): + print("[4] Found !!") +else: + print("[4] Not found...") + +if simplex_tree.insert([0, 1, 2], filtration=4.0): + print("[0, 1, 2] Inserted !!") +else: + print("[0, 1, 2] Not inserted...") + +if simplex_tree.insert([0, 1, 4], filtration=4.0): + print("[0, 1, 4] Inserted !!") +else: + print("[0, 1, 4] Not inserted...") + +if simplex_tree.find([4]): + print("[4] Found !!") +else: + print("[4] Not found...") + +print("dimension=", simplex_tree.dimension()) +print("filtered_tree=", simplex_tree.get_filtered_tree()) +print("star([0])=", simplex_tree.get_star([0])) +print("coface([0], 1)=", simplex_tree.get_cofaces([0], 1)) + +print("point[0]=", alpha_complex.get_point(0)) +print("point[5]=", alpha_complex.get_point(5)) diff --git a/src/cython/example/alpha_rips_persistence_bottleneck_distance.py b/src/cython/example/alpha_rips_persistence_bottleneck_distance.py new file mode 100755 index 00000000..ab5fc1e9 --- /dev/null +++ b/src/cython/example/alpha_rips_persistence_bottleneck_distance.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +import gudhi +import argparse +import math + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='AlphaComplex and RipsComplex ' + 'persistence creation from points read in ' + 'a OFF file. Bottleneck distance computation' + ' on each dimension', + epilog='Example: ' + 'example/alpha_rips_persistence_bottleneck_distance.py ' + '-f ../data/points/tore3D_1307.off -t 0.15 -d 3') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-t", "--threshold", type=float, default=0.5) +parser.add_argument("-d", "--max_dimension", type=int, default=1) + +args = parser.parse_args() +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("RipsComplex creation from points read in a OFF file") + + message = "RipsComplex with max_edge_length=" + repr(args.threshold) + print(message) + + rips_complex = gudhi.RipsComplex(off_file=args.file, + max_edge_length=args.threshold) + + rips_stree = rips_complex.create_simplex_tree(max_dimension=args.max_dimension) + + message = "Number of simplices=" + repr(rips_stree.num_simplices()) + print(message) + + rips_diag = rips_stree.persistence() + + print("#####################################################################") + print("AlphaComplex creation from points read in a OFF file") + + message = "AlphaComplex with max_edge_length=" + repr(args.threshold) + print(message) + + alpha_complex = gudhi.AlphaComplex(off_file=args.file) + alpha_stree = alpha_complex.create_simplex_tree(max_alpha_square=(args.threshold * args.threshold)) + + message = "Number of simplices=" + repr(alpha_stree.num_simplices()) + print(message) + + alpha_diag = alpha_stree.persistence() + + max_b_distance = 0.0 + for dim in range(args.max_dimension): + # Alpha persistence values needs to be transform because filtration + # values are alpha square values + funcs = [math.sqrt, math.sqrt] + alpha_intervals = [] + for interval in alpha_stree.persistence_intervals_in_dimension(dim): + alpha_intervals.append(map(lambda func,value: func(value), funcs, interval)) + + rips_intervals = rips_stree.persistence_intervals_in_dimension(dim) + bottleneck_distance = gudhi.bottleneck_distance(rips_intervals, alpha_intervals) + message = "In dimension " + repr(dim) + ", bottleneck distance = " + repr(bottleneck_distance) + print(message) + max_b_distance = max(bottleneck_distance, max_b_distance) + + print("================================================================================") + message = "Bottleneck distance is " + repr(max_b_distance) + print(message) + + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/bottleneck_basic_example.py b/src/cython/example/bottleneck_basic_example.py new file mode 100755 index 00000000..31cecb29 --- /dev/null +++ b/src/cython/example/bottleneck_basic_example.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): Francois Godi, 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/>. +""" + +__author__ = "Francois Godi, Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +import gudhi + +diag1 = [[2.7, 3.7],[9.6, 14.],[34.2, 34.974], [3.,float('Inf')]] + +diag2 = [[2.8, 4.45],[9.5, 14.1],[3.2,float('Inf')]] + +message = "diag1=" + repr(diag1) +print(message) + +message = "diag2=" + repr(diag2) +print(message) + +message = "Bottleneck distance approximation=" + repr(gudhi.bottleneck_distance(diag1, diag2, 0.1)) +print(message) + +message = "Bottleneck distance exact value=" + repr(gudhi.bottleneck_distance(diag1, diag2)) +print(message) + diff --git a/src/cython/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py new file mode 100755 index 00000000..2474fc87 --- /dev/null +++ b/src/cython/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='EuclideanStrongWitnessComplex creation from ' + 'points read in a OFF file.', + epilog='Example: ' + 'example/witness_complex_diagram_persistence_from_off_file_example.py ' + '-f ../data/points/tore3D_300.off -a 1.0 -n 20 -d 2' + '- Constructs a strong witness complex with the ' + 'points from the given OFF file.') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-a", "--max_alpha_square", type=float, required=True) +parser.add_argument("-n", "--number_of_landmarks", type=int, required=True) +parser.add_argument("-d", "--limit_dimension", type=int, required=True) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("EuclideanStrongWitnessComplex creation from points read in a OFF file") + + witnesses = gudhi.read_off(off_file=args.file) + landmarks = gudhi.pick_n_random_points(points=witnesses, nb_points=args.number_of_landmarks) + + message = "EuclideanStrongWitnessComplex with max_edge_length=" + repr(args.max_alpha_square) + \ + " - Number of landmarks=" + repr(args.number_of_landmarks) + print(message) + + witness_complex = gudhi.EuclideanStrongWitnessComplex(witnesses=witnesses, landmarks=landmarks) + simplex_tree = witness_complex.create_simplex_tree(max_alpha_square=args.max_alpha_square, + limit_dimension=args.limit_dimension) + + message = "Number of simplices=" + repr(simplex_tree.num_simplices()) + print(message) + + diag = simplex_tree.persistence() + + print("betti_numbers()=") + print(simplex_tree.betti_numbers()) + + if args.no_diagram == False: + gudhi.plot_persistence_diagram(diag) + + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py new file mode 100755 index 00000000..5a75417b --- /dev/null +++ b/src/cython/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='EuclideanWitnessComplex creation from ' + 'points read in a OFF file.', + epilog='Example: ' + 'example/witness_complex_diagram_persistence_from_off_file_example.py ' + '-f ../data/points/tore3D_300.off -a 1.0 -n 20 -d 2' + '- Constructs a weak witness complex with the ' + 'points from the given OFF file.') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-a", "--max_alpha_square", type=float, required=True) +parser.add_argument("-n", "--number_of_landmarks", type=int, required=True) +parser.add_argument("-d", "--limit_dimension", type=int, required=True) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("EuclideanWitnessComplex creation from points read in a OFF file") + + witnesses = gudhi.read_off(off_file=args.file) + landmarks = gudhi.pick_n_random_points(points=witnesses, nb_points=args.number_of_landmarks) + + message = "EuclideanWitnessComplex with max_edge_length=" + repr(args.max_alpha_square) + \ + " - Number of landmarks=" + repr(args.number_of_landmarks) + print(message) + + witness_complex = gudhi.EuclideanWitnessComplex(witnesses=witnesses, landmarks=landmarks) + simplex_tree = witness_complex.create_simplex_tree(max_alpha_square=args.max_alpha_square, + limit_dimension=args.limit_dimension) + + message = "Number of simplices=" + repr(simplex_tree.num_simplices()) + print(message) + + diag = simplex_tree.persistence() + + print("betti_numbers()=") + print(simplex_tree.betti_numbers()) + + if args.no_diagram == False: + gudhi.plot_persistence_diagram(diag) + + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/gudhi_graphical_tools_example.py b/src/cython/example/gudhi_graphical_tools_example.py new file mode 100755 index 00000000..bc3b16ec --- /dev/null +++ b/src/cython/example/gudhi_graphical_tools_example.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): 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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("Show palette colors values for dimension") + +gudhi.show_palette_values() + +print("#####################################################################") +print("Show barcode persistence example") + +persistence = [(2, (1.0, float('inf'))), (1, (1.4142135623730951, float('inf'))), + (1, (1.4142135623730951, float('inf'))), (0, (0.0, float('inf'))), + (0, (0.0, 1.0)), (0, (0.0, 1.0)), (0, (0.0, 1.0))] +gudhi.plot_persistence_barcode(persistence) + +print("#####################################################################") +print("Show diagram persistence example") + +gudhi.plot_persistence_diagram(persistence) diff --git a/src/cython/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py b/src/cython/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py new file mode 100755 index 00000000..db530161 --- /dev/null +++ b/src/cython/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +def is_file_perseus(file): + num_lines = open(file).read().count('\n') + try: + f = open(file) + num_dim = int(f.readline()) + coeff = 1 + for dim in range(0, num_dim): + try: + line = int(f.readline()) + coeff *= abs(line) + except ValueError: + return False + if num_lines == (1 + num_dim + coeff): + return True + else: + return False + except ValueError: + return False + +parser = argparse.ArgumentParser(description='Periodic cubical complex from a ' + 'perseus file style name.', + epilog='Example: ' + './periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py' + ' -f ../data/bitmap/CubicalTwoSphere.txt') + +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument('--no-barcode', default=False, action='store_true' , help='Flag for not to display the barcodes') + +args = parser.parse_args() + +if is_file_perseus(args.file): + print("#####################################################################") + print("PeriodicCubicalComplex creation") + periodic_cubical_complex = gudhi.PeriodicCubicalComplex(perseus_file=args.file) + + print("persistence(homology_coeff_field=3, min_persistence=0)=") + diag = periodic_cubical_complex.persistence(homology_coeff_field=3, min_persistence=0) + print(diag) + + print("betti_numbers()=") + print(periodic_cubical_complex.betti_numbers()) + if args.no_barcode == False: + gudhi.plot_persistence_barcode(diag) +else: + print(args.file, "is not a valid perseus style file") diff --git a/src/cython/example/random_cubical_complex_persistence_example.py b/src/cython/example/random_cubical_complex_persistence_example.py new file mode 100755 index 00000000..1c55f777 --- /dev/null +++ b/src/cython/example/random_cubical_complex_persistence_example.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +import gudhi +import numpy +import argparse +import operator + + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='Random cubical complex.', + epilog='Example: ' + './random_cubical_complex_persistence_example.py' + ' 10 10 10 - Constructs a random cubical ' + 'complex in a dimension [10, 10, 10] (aka. ' + '1000 random top dimensional cells).') +parser.add_argument('dimension', type=int, nargs="*", + help='Cubical complex dimensions') + +args = parser.parse_args() +dimension_multiplication = reduce(operator.mul, args.dimension, 1) + +if dimension_multiplication > 1: + print("#####################################################################") + print("CubicalComplex creation") + cubical_complex = gudhi.CubicalComplex(dimensions=args.dimension, + top_dimensional_cells = numpy.random.rand(dimension_multiplication)) + + print("persistence(homology_coeff_field=2, min_persistence=0)=") + print(cubical_complex.persistence(homology_coeff_field=2, min_persistence=0)) + + print("betti_numbers()=") + print(cubical_complex.betti_numbers())
\ No newline at end of file diff --git a/src/cython/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py b/src/cython/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py new file mode 100755 index 00000000..664eb5c4 --- /dev/null +++ b/src/cython/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='RipsComplex creation from ' + 'a distance matrix read in a OFF file.', + epilog='Example: ' + 'example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py ' + '-f ../data/distance_matrix/lower_triangular_distance_matrix.csv -e 12.0 -d 3' + '- Constructs a Rips complex with the ' + 'points from the given OFF file.') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-e", "--max_edge_length", type=float, default=0.5) +parser.add_argument("-d", "--max_dimension", type=int, default=1) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("RipsComplex creation from distance matrix read in a csv file") + + message = "RipsComplex with max_edge_length=" + repr(args.max_edge_length) + print(message) + + rips_complex = gudhi.RipsComplex(off_file=args.file, max_edge_length=args.max_edge_length) + simplex_tree = rips_complex.create_simplex_tree(max_dimension=args.max_dimension) + + message = "Number of simplices=" + repr(simplex_tree.num_simplices()) + print(message) + + diag = simplex_tree.persistence() + + print("betti_numbers()=") + print(simplex_tree.betti_numbers()) + + if args.no_diagram == False: + gudhi.plot_persistence_diagram(diag) + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/rips_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/rips_complex_diagram_persistence_from_off_file_example.py new file mode 100755 index 00000000..4c21b98e --- /dev/null +++ b/src/cython/example/rips_complex_diagram_persistence_from_off_file_example.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='RipsComplex creation from ' + 'points read in a OFF file.', + epilog='Example: ' + 'example/rips_complex_diagram_persistence_from_off_file_example.py ' + '-f ../data/points/tore3D_300.off -a 0.6' + '- Constructs a Rips complex with the ' + 'points from the given OFF file.') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-e", "--max_edge_length", type=float, default=0.5) +parser.add_argument("-d", "--max_dimension", type=int, default=1) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("RipsComplex creation from points read in a OFF file") + + message = "RipsComplex with max_edge_length=" + repr(args.max_edge_length) + print(message) + + rips_complex = gudhi.RipsComplex(off_file=args.file, max_edge_length=args.max_edge_length) + simplex_tree = rips_complex.create_simplex_tree(max_dimension=args.max_dimension) + + message = "Number of simplices=" + repr(simplex_tree.num_simplices()) + print(message) + + diag = simplex_tree.persistence() + + print("betti_numbers()=") + print(simplex_tree.betti_numbers()) + + if args.no_diagram == False: + gudhi.plot_persistence_diagram(diag) + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/rips_complex_from_points_example.py b/src/cython/example/rips_complex_from_points_example.py new file mode 100755 index 00000000..9b7fc79d --- /dev/null +++ b/src/cython/example/rips_complex_from_points_example.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): 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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("RipsComplex creation from points") +rips = gudhi.RipsComplex(points=[[0, 0], [1, 0], [0, 1], [1, 1]], + max_edge_length=42) + +simplex_tree = rips.create_simplex_tree(max_dimension=1) + +print("filtered_tree=", simplex_tree.get_filtered_tree()) +print("star([0])=", simplex_tree.get_star([0])) +print("coface([0], 1)=", simplex_tree.get_cofaces([0], 1)) diff --git a/src/cython/example/rips_persistence_diagram.py b/src/cython/example/rips_persistence_diagram.py new file mode 100755 index 00000000..4e5cd2c8 --- /dev/null +++ b/src/cython/example/rips_persistence_diagram.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): Marc Glisse + + Copyright (C) 2016 INRIA + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +__author__ = "Marc Glisse" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("RipsComplex creation from points") +rips = gudhi.RipsComplex(points=[[0, 0], [1, 0], [0, 1], [1, 1]], + max_edge_length=42) + +simplex_tree = rips.create_simplex_tree(max_dimension=1) + + +diag = simplex_tree.persistence(homology_coeff_field=2, min_persistence=0) +print("diag=", diag) + +gudhi.plot_persistence_diagram(diag) diff --git a/src/cython/example/simplex_tree_example.py b/src/cython/example/simplex_tree_example.py new file mode 100755 index 00000000..bf5f17a2 --- /dev/null +++ b/src/cython/example/simplex_tree_example.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): 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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("SimplexTree creation from insertion") + +st = gudhi.SimplexTree() + +if st.insert([0, 1]): + print("Inserted !!") +else: + print("Not inserted...") + +if st.find([0, 1]): + print("Found !!") +else: + print("Not found...") + +if st.insert([0, 1, 2], filtration=4.0): + print("Inserted !!") +else: + print("Not inserted...") + +# FIXME: Remove this line +st.set_dimension(3) +print("dimension=", st.dimension()) + +st.set_filtration(4.0) +st.initialize_filtration() +print("filtration=", st.get_filtration()) +print("filtration[1, 2]=", st.filtration([1, 2])) +print("filtration[4, 2]=", st.filtration([4, 2])) + +print("num_simplices=", st.num_simplices()) +print("num_vertices=", st.num_vertices()) + +print("skeleton_tree[2]=", st.get_skeleton_tree(2)) +print("skeleton_tree[1]=", st.get_skeleton_tree(1)) +print("skeleton_tree[0]=", st.get_skeleton_tree(0)) diff --git a/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py new file mode 100755 index 00000000..4845eb47 --- /dev/null +++ b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='TangentialComplex creation from ' + 'points read in a OFF file.', + epilog='Example: ' + 'example/tangential_complex_plain_homology_from_off_file_example.py ' + '-f ../data/points/tore3D_300.off' + '- Constructs a tangential complex with the ' + 'points from the given OFF file') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("TangentialComplex creation from points read in a OFF file") + + tc = gudhi.TangentialComplex(off_file=args.file) + st = tc.create_simplex_tree() + + message = "Number of simplices=" + repr(st.num_simplices()) + print(message) + + diag = st.persistence(persistence_dim_max = True) + + print("betti_numbers()=") + print(st.betti_numbers()) + + if args.no_diagram == False: + gudhi.plot_persistence_diagram(diag) + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/witness_complex_from_nearest_landmark_table.py b/src/cython/example/witness_complex_from_nearest_landmark_table.py new file mode 100755 index 00000000..92ed970b --- /dev/null +++ b/src/cython/example/witness_complex_from_nearest_landmark_table.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +from gudhi import StrongWitnessComplex, SimplexTree + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("WitnessComplex creation from nearest landmark table") +nearest_landmark_table = [[[0, 0], [1, 1], [2, 2], [3, 3], [4, 4]], + [[1, 0], [2, 1], [3, 2], [4, 3], [0, 4]], + [[2, 0], [3, 1], [4, 2], [0, 3], [1, 4]], + [[3, 0], [4, 1], [0, 2], [1, 3], [2, 4]], + [[4, 0], [0, 1], [1, 2], [2, 3], [3, 4]]] + +witness_complex = StrongWitnessComplex(nearest_landmark_table=nearest_landmark_table) +simplex_tree = witness_complex.create_simplex_tree(max_alpha_square=4.1) + +message = "Number of simplices: " + repr(simplex_tree.num_simplices()) +print(message) + +diag = simplex_tree.persistence(min_persistence=-0.1, homology_coeff_field=11) +print(diag) diff --git a/src/cython/gudhi.pyx.in b/src/cython/gudhi.pyx.in new file mode 100644 index 00000000..34d7c3b5 --- /dev/null +++ b/src/cython/gudhi.pyx.in @@ -0,0 +1,39 @@ +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +include "cython/off_reader.pyx" +include "cython/simplex_tree.pyx" +include "cython/rips_complex.pyx" +include "cython/cubical_complex.pyx" +include "cython/periodic_cubical_complex.pyx" +include "cython/persistence_graphical_tools.py" +include "cython/witness_complex.pyx" +include "cython/strong_witness_complex.pyx" +@GUDHI_CYTHON_ALPHA_COMPLEX@ +@GUDHI_CYTHON_EUCLIDEAN_WITNESS_COMPLEX@ +@GUDHI_CYTHON_SUBSAMPLING@ +@GUDHI_CYTHON_TANGENTIAL_COMPLEX@ +@GUDHI_CYTHON_BOTTLENECK_DISTANCE@ diff --git a/src/cython/include/Alpha_complex_interface.h b/src/cython/include/Alpha_complex_interface.h new file mode 100644 index 00000000..d47db71f --- /dev/null +++ b/src/cython/include/Alpha_complex_interface.h @@ -0,0 +1,82 @@ +/* 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 INCLUDE_ALPHA_COMPLEX_INTERFACE_H_ +#define INCLUDE_ALPHA_COMPLEX_INTERFACE_H_ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Alpha_complex.h> +#include <CGAL/Epick_d.h> + +#include "Simplex_tree_interface.h" + +#include <iostream> +#include <vector> +#include <string> + +namespace Gudhi { + +namespace alpha_complex { + +class Alpha_complex_interface { + using Dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; + using Point_d = Dynamic_kernel::Point_d; + + public: + Alpha_complex_interface(const std::vector<std::vector<double>>& points) { + alpha_complex_ = new Alpha_complex<Dynamic_kernel>(points); + } + + Alpha_complex_interface(const std::string& off_file_name, bool from_file = true) { + alpha_complex_ = new Alpha_complex<Dynamic_kernel>(off_file_name); + } + + ~Alpha_complex_interface() { + delete alpha_complex_; + } + + std::vector<double> get_point(int vh) { + std::vector<double> vd; + try { + Point_d ph = alpha_complex_->get_point(vh); + for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++) + vd.push_back(*coord); + } catch (std::out_of_range outofrange) { + // std::out_of_range is thrown in case not found. Other exceptions must be re-thrown + } + return vd; + } + + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square) { + alpha_complex_->create_complex(*simplex_tree, max_alpha_square); + simplex_tree->initialize_filtration(); + } + + private: + Alpha_complex<Dynamic_kernel>* alpha_complex_; +}; + +} // namespace alpha_complex + +} // namespace Gudhi + +#endif // INCLUDE_ALPHA_COMPLEX_INTERFACE_H_ diff --git a/src/cython/include/Bottleneck_distance_interface.h b/src/cython/include/Bottleneck_distance_interface.h new file mode 100644 index 00000000..d5fbf6ea --- /dev/null +++ b/src/cython/include/Bottleneck_distance_interface.h @@ -0,0 +1,53 @@ +/* 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 INCLUDE_BOTTLENECK_DISTANCE_INTERFACE_H_ +#define INCLUDE_BOTTLENECK_DISTANCE_INTERFACE_H_ + +#include <gudhi/Bottleneck.h> + +#include <iostream> +#include <vector> +#include <utility> // for std::pair + +namespace Gudhi { + +namespace persistence_diagram { + + // bottleneck_distance function renamed for the python function can be called bottleneck_dstance + double bottleneck(const std::vector<std::pair<double, double>>& diag1, + const std::vector<std::pair<double, double>>& diag2, + double e) { + return bottleneck_distance(diag1, diag2, e); + } + + double bottleneck(const std::vector<std::pair<double, double>>& diag1, + const std::vector<std::pair<double, double>>& diag2) { + return bottleneck_distance(diag1, diag2); + } + +} // namespace persistence_diagram + +} // namespace Gudhi + + +#endif // INCLUDE_BOTTLENECK_DISTANCE_INTERFACE_H_ diff --git a/src/cython/include/Cubical_complex_interface.h b/src/cython/include/Cubical_complex_interface.h new file mode 100644 index 00000000..7c0148f1 --- /dev/null +++ b/src/cython/include/Cubical_complex_interface.h @@ -0,0 +1,56 @@ +/* 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 INCLUDE_CUBICAL_COMPLEX_INTERFACE_H_ +#define INCLUDE_CUBICAL_COMPLEX_INTERFACE_H_ + +#include <gudhi/Bitmap_cubical_complex.h> +#include <gudhi/Bitmap_cubical_complex_base.h> +#include <gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h> + +#include <iostream> +#include <vector> +#include <string> + +namespace Gudhi { + +namespace cubical_complex { + +template<typename CubicalComplexOptions = Bitmap_cubical_complex_base<double>> +class Cubical_complex_interface : public Bitmap_cubical_complex<CubicalComplexOptions> { + public: + Cubical_complex_interface(const std::vector<unsigned>& dimensions, + const std::vector<double>& top_dimensional_cells) + : Bitmap_cubical_complex<CubicalComplexOptions>(dimensions, top_dimensional_cells) { + } + + Cubical_complex_interface(const std::string& perseus_file) + : Bitmap_cubical_complex<CubicalComplexOptions>(perseus_file.c_str()) { + } +}; + +} // namespace cubical_complex + +} // namespace Gudhi + +#endif // INCLUDE_CUBICAL_COMPLEX_INTERFACE_H_ + diff --git a/src/cython/include/Euclidean_strong_witness_complex_interface.h b/src/cython/include/Euclidean_strong_witness_complex_interface.h new file mode 100644 index 00000000..b9dd8177 --- /dev/null +++ b/src/cython/include/Euclidean_strong_witness_complex_interface.h @@ -0,0 +1,93 @@ +/* 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 INCLUDE_EUCLIDEAN_STRONG_WITNESS_COMPLEX_INTERFACE_H_ +#define INCLUDE_EUCLIDEAN_STRONG_WITNESS_COMPLEX_INTERFACE_H_ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Euclidean_strong_witness_complex.h> + +#include "Simplex_tree_interface.h" + +#include <CGAL/Epick_d.h> + +#include <vector> +#include <utility> // std::pair +#include <iostream> +#include <cstddef> + +namespace Gudhi { + +namespace witness_complex { + + +class Euclidean_strong_witness_complex_interface { + using Dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; + using Point_d = Dynamic_kernel::Point_d; + + typedef typename Simplex_tree<>::Simplex_key Simplex_key; + + public: + Euclidean_strong_witness_complex_interface(const std::vector<std::vector<double>>& landmarks, + const std::vector<std::vector<double>>& witnesses) { + landmarks_.reserve(landmarks.size()); + for (auto& landmark : landmarks) + landmarks_.emplace_back(landmark.begin(), landmark.end()); + witness_complex_ = new Euclidean_strong_witness_complex<Dynamic_kernel>(landmarks_, witnesses); + } + + ~Euclidean_strong_witness_complex_interface() { + delete witness_complex_; + } + + void create_simplex_tree(Gudhi::Simplex_tree<>* simplex_tree, double max_alpha_square, + std::size_t limit_dimension) { + witness_complex_->create_complex(*simplex_tree, max_alpha_square, limit_dimension); + simplex_tree->initialize_filtration(); + } + + void create_simplex_tree(Gudhi::Simplex_tree<>* simplex_tree, double max_alpha_square) { + witness_complex_->create_complex(*simplex_tree, max_alpha_square); + simplex_tree->initialize_filtration(); + } + + std::vector<double> get_point(unsigned vh) { + std::vector<double> vd; + if (vh < landmarks_.size()) { + Point_d ph = witness_complex_->get_point(vh); + for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++) + vd.push_back(*coord); + } + return vd; + } + + private: + std::vector<Point_d> landmarks_; + Euclidean_strong_witness_complex<Dynamic_kernel>* witness_complex_; +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // INCLUDE_EUCLIDEAN_STRONG_WITNESS_COMPLEX_INTERFACE_H_ + diff --git a/src/cython/include/Euclidean_witness_complex_interface.h b/src/cython/include/Euclidean_witness_complex_interface.h new file mode 100644 index 00000000..2a09b3b5 --- /dev/null +++ b/src/cython/include/Euclidean_witness_complex_interface.h @@ -0,0 +1,92 @@ +/* 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 INCLUDE_EUCLIDEAN_WITNESS_COMPLEX_INTERFACE_H_ +#define INCLUDE_EUCLIDEAN_WITNESS_COMPLEX_INTERFACE_H_ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Euclidean_witness_complex.h> + +#include "Simplex_tree_interface.h" + +#include <CGAL/Epick_d.h> + +#include <vector> +#include <utility> // std::pair +#include <iostream> +#include <cstddef> + +namespace Gudhi { + +namespace witness_complex { + + +class Euclidean_witness_complex_interface { + using Dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; + using Point_d = Dynamic_kernel::Point_d; + + typedef typename Simplex_tree<>::Simplex_key Simplex_key; + + public: + Euclidean_witness_complex_interface(const std::vector<std::vector<double>>& landmarks, + const std::vector<std::vector<double>>& witnesses) { + landmarks_.reserve(landmarks.size()); + for (auto& landmark : landmarks) + landmarks_.emplace_back(landmark.begin(), landmark.end()); + witness_complex_ = new Euclidean_witness_complex<Dynamic_kernel>(landmarks_, witnesses); + } + + ~Euclidean_witness_complex_interface() { + delete witness_complex_; + } + + void create_simplex_tree(Gudhi::Simplex_tree<>* simplex_tree, double max_alpha_square, std::size_t limit_dimension) { + witness_complex_->create_complex(*simplex_tree, max_alpha_square, limit_dimension); + simplex_tree->initialize_filtration(); + } + + void create_simplex_tree(Gudhi::Simplex_tree<>* simplex_tree, double max_alpha_square) { + witness_complex_->create_complex(*simplex_tree, max_alpha_square); + simplex_tree->initialize_filtration(); + } + + std::vector<double> get_point(unsigned vh) { + std::vector<double> vd; + if (vh < landmarks_.size()) { + Point_d ph = witness_complex_->get_point(vh); + for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++) + vd.push_back(*coord); + } + return vd; + } + + private: + std::vector<Point_d> landmarks_; + Euclidean_witness_complex<Dynamic_kernel>* witness_complex_; +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // INCLUDE_EUCLIDEAN_WITNESS_COMPLEX_INTERFACE_H_ + diff --git a/src/cython/include/Off_reader_interface.h b/src/cython/include/Off_reader_interface.h new file mode 100644 index 00000000..0ca55500 --- /dev/null +++ b/src/cython/include/Off_reader_interface.h @@ -0,0 +1,42 @@ +/* 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 INCLUDE_OFF_READER_INTERFACE_H_ +#define INCLUDE_OFF_READER_INTERFACE_H_ + +#include <gudhi/Points_off_io.h> + +#include <iostream> +#include <vector> +#include <string> + +namespace Gudhi { + +std::vector<std::vector<double>> read_points_from_OFF_file(const std::string& off_file) { + Gudhi::Points_off_reader<std::vector<double>> off_reader(off_file); + return off_reader.get_point_cloud(); +} + +} // namespace Gudhi + +#endif // INCLUDE_OFF_READER_INTERFACE_H_ + diff --git a/src/cython/include/Persistent_cohomology_interface.h b/src/cython/include/Persistent_cohomology_interface.h new file mode 100644 index 00000000..25c458d2 --- /dev/null +++ b/src/cython/include/Persistent_cohomology_interface.h @@ -0,0 +1,96 @@ +/* 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 INCLUDE_PERSISTENT_COHOMOLOGY_INTERFACE_H_ +#define INCLUDE_PERSISTENT_COHOMOLOGY_INTERFACE_H_ + +#include <gudhi/Persistent_cohomology.h> + +#include <vector> +#include <utility> // for std::pair +#include <algorithm> // for sort + +namespace Gudhi { + +template<class FilteredComplex> +class Persistent_cohomology_interface : public +persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp> { + private: + /* + * Compare two intervals by dimension, then by length. + */ + struct cmp_intervals_by_dim_then_length { + explicit cmp_intervals_by_dim_then_length(FilteredComplex * sc) + : sc_(sc) { } + + template<typename Persistent_interval> + bool operator()(const Persistent_interval & p1, const Persistent_interval & p2) { + if (sc_->dimension(get < 0 > (p1)) == sc_->dimension(get < 0 > (p2))) + return (sc_->filtration(get < 1 > (p1)) - sc_->filtration(get < 0 > (p1)) + > sc_->filtration(get < 1 > (p2)) - sc_->filtration(get < 0 > (p2))); + else + return (sc_->dimension(get < 0 > (p1)) > sc_->dimension(get < 0 > (p2))); + } + FilteredComplex* sc_; + }; + + public: + Persistent_cohomology_interface(FilteredComplex* stptr) + : persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>(*stptr), + stptr_(stptr) { } + + Persistent_cohomology_interface(FilteredComplex* stptr, bool persistence_dim_max) + : persistent_cohomology::Persistent_cohomology<FilteredComplex, + persistent_cohomology::Field_Zp>(*stptr, persistence_dim_max), + stptr_(stptr) { } + + std::vector<std::pair<int, std::pair<double, double>>> get_persistence(int homology_coeff_field, + double min_persistence) { + persistent_cohomology::Persistent_cohomology<FilteredComplex, + persistent_cohomology::Field_Zp>::init_coefficients(homology_coeff_field); + persistent_cohomology::Persistent_cohomology<FilteredComplex, + persistent_cohomology::Field_Zp>::compute_persistent_cohomology(min_persistence); + + // Custom sort and output persistence + cmp_intervals_by_dim_then_length cmp(stptr_); + auto persistent_pairs = persistent_cohomology::Persistent_cohomology<FilteredComplex, + persistent_cohomology::Field_Zp>::get_persistent_pairs(); + std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp); + + std::vector<std::pair<int, std::pair<double, double>>> persistence; + for (auto pair : persistent_pairs) { + persistence.push_back(std::make_pair(stptr_->dimension(get<0>(pair)), + std::make_pair(stptr_->filtration(get<0>(pair)), + stptr_->filtration(get<1>(pair))))); + } + return persistence; + } + + private: + // A copy + FilteredComplex* stptr_; + +}; + +} // namespace Gudhi + +#endif // INCLUDE_PERSISTENT_COHOMOLOGY_INTERFACE_H_ diff --git a/src/cython/include/Rips_complex_interface.h b/src/cython/include/Rips_complex_interface.h new file mode 100644 index 00000000..1879bd74 --- /dev/null +++ b/src/cython/include/Rips_complex_interface.h @@ -0,0 +1,86 @@ +/* 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 INCLUDE_RIPS_COMPLEX_INTERFACE_H_ +#define INCLUDE_RIPS_COMPLEX_INTERFACE_H_ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Rips_complex.h> +#include <gudhi/Points_off_io.h> +#include <gudhi/distance_functions.h> +#include <gudhi/reader_utils.h> + +#include "Simplex_tree_interface.h" + +#include <iostream> +#include <vector> +#include <utility> // std::pair +#include <string> + +namespace Gudhi { + +namespace rips_complex { + +class Rips_complex_interface { + using Point_d = std::vector<double>; + using Distance_matrix = std::vector<std::vector<Simplex_tree_interface<>::Filtration_value>>; + + public: + Rips_complex_interface(const std::vector<std::vector<double>>& values, double threshold, bool euclidean) { + if (euclidean) { + // Rips construction where values is a vector of points + rips_complex_ = new Rips_complex<Simplex_tree_interface<>::Filtration_value>(values, threshold, + Euclidean_distance()); + } else { + // Rips construction where values is a distance matrix + rips_complex_ = new Rips_complex<Simplex_tree_interface<>::Filtration_value>(values, threshold); + } + } + + Rips_complex_interface(const std::string& file_name, double threshold, bool euclidean, bool from_file = true) { + if (euclidean) { + // Rips construction where file_name is an OFF file + Gudhi::Points_off_reader<Point_d> off_reader(file_name); + rips_complex_ = new Rips_complex<Simplex_tree_interface<>::Filtration_value>(off_reader.get_point_cloud(), + threshold, Euclidean_distance()); + } else { + // Rips construction where values is a distance matrix + Distance_matrix distances = + read_lower_triangular_matrix_from_csv_file<Simplex_tree_interface<>::Filtration_value>(file_name); + rips_complex_ = new Rips_complex<Simplex_tree_interface<>::Filtration_value>(distances, threshold); + } + } + + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, int dim_max) { + rips_complex_->create_complex(*simplex_tree, dim_max); + simplex_tree->initialize_filtration(); + } + + private: + Rips_complex<Simplex_tree_interface<>::Filtration_value>* rips_complex_; +}; + +} // namespace rips_complex + +} // namespace Gudhi + +#endif // INCLUDE_RIPS_COMPLEX_INTERFACE_H_ diff --git a/src/cython/include/Simplex_tree_interface.h b/src/cython/include/Simplex_tree_interface.h new file mode 100644 index 00000000..4266b3ef --- /dev/null +++ b/src/cython/include/Simplex_tree_interface.h @@ -0,0 +1,149 @@ +/* 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 INCLUDE_SIMPLEX_TREE_INTERFACE_H_ +#define INCLUDE_SIMPLEX_TREE_INTERFACE_H_ + +#include <gudhi/graph_simplicial_complex.h> +#include <gudhi/distance_functions.h> +#include <gudhi/Simplex_tree.h> +#include <gudhi/Points_off_io.h> + +#include "Persistent_cohomology_interface.h" + +#include <iostream> +#include <vector> +#include <utility> // std::pair + +namespace Gudhi { + +template<typename SimplexTreeOptions = Simplex_tree_options_full_featured> +class Simplex_tree_interface : public Simplex_tree<SimplexTreeOptions> { + public: + using Base = Simplex_tree<SimplexTreeOptions>; + using Filtration_value = typename Base::Filtration_value; + using Vertex_handle = typename Base::Vertex_handle; + using Simplex_handle = typename Base::Simplex_handle; + using Insertion_result = typename std::pair<Simplex_handle, bool>; + using Simplex = std::vector<Vertex_handle>; + using Complex = std::vector<std::pair<Simplex, Filtration_value>>; + + public: + bool find_simplex(const Simplex& vh) { + return (Base::find(vh) != Base::null_simplex()); + } + + bool insert_simplex(const Simplex& simplex, Filtration_value filtration = 0) { + Insertion_result result = Base::insert_simplex(simplex, filtration); + Base::initialize_filtration(); + return (result.second); + } + + bool insert_simplex_and_subfaces(const Simplex& simplex, Filtration_value filtration = 0) { + Insertion_result result = Base::insert_simplex_and_subfaces(simplex, filtration); + Base::initialize_filtration(); + return (result.second); + } + + // Do not interface this function, only used in strong witness interface for complex creation + bool insert_simplex(const std::vector<std::size_t>& complex, Filtration_value filtration = 0) { + Insertion_result result = Base::insert_simplex(complex, filtration); + Base::initialize_filtration(); + return (result.second); + } + + // Do not interface this function, only used in strong witness interface for complex creation + bool insert_simplex_and_subfaces(const std::vector<std::size_t>& complex, Filtration_value filtration = 0) { + Insertion_result result = Base::insert_simplex_and_subfaces(complex, filtration); + Base::initialize_filtration(); + return (result.second); + } + + Filtration_value simplex_filtration(const Simplex& simplex) { + return Base::filtration(Base::find(simplex)); + } + + void remove_maximal_simplex(const Simplex& simplex) { + Base::remove_maximal_simplex(Base::find(simplex)); + Base::initialize_filtration(); + } + + Complex get_filtered_tree() { + Complex filtered_tree; + for (auto f_simplex : Base::filtration_simplex_range()) { + Simplex simplex; + for (auto vertex : Base::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + filtered_tree.push_back(std::make_pair(simplex, Base::filtration(f_simplex))); + } + return filtered_tree; + } + + Complex get_skeleton_tree(int dimension) { + Complex skeleton_tree; + for (auto f_simplex : Base::skeleton_simplex_range(dimension)) { + Simplex simplex; + for (auto vertex : Base::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + skeleton_tree.push_back(std::make_pair(simplex, Base::filtration(f_simplex))); + } + return skeleton_tree; + } + + Complex get_star(const Simplex& simplex) { + Complex star; + for (auto f_simplex : Base::star_simplex_range(Base::find(simplex))) { + Simplex simplex_star; + for (auto vertex : Base::simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + simplex_star.insert(simplex_star.begin(), vertex); + } + std::cout << std::endl; + star.push_back(std::make_pair(simplex_star, Base::filtration(f_simplex))); + } + return star; + } + + Complex get_cofaces(const Simplex& simplex, int dimension) { + Complex cofaces; + for (auto f_simplex : Base::cofaces_simplex_range(Base::find(simplex), dimension)) { + Simplex simplex_coface; + for (auto vertex : Base::simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + simplex_coface.insert(simplex_coface.begin(), vertex); + } + std::cout << std::endl; + cofaces.push_back(std::make_pair(simplex_coface, Base::filtration(f_simplex))); + } + return cofaces; + } + + void create_persistence(Gudhi::Persistent_cohomology_interface<Base>* pcoh) { + pcoh = new Gudhi::Persistent_cohomology_interface<Base>(*this); + } +}; + +} // namespace Gudhi + +#endif // INCLUDE_SIMPLEX_TREE_INTERFACE_H_ diff --git a/src/cython/include/Strong_witness_complex_interface.h b/src/cython/include/Strong_witness_complex_interface.h new file mode 100644 index 00000000..d05eaac5 --- /dev/null +++ b/src/cython/include/Strong_witness_complex_interface.h @@ -0,0 +1,73 @@ +/* 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 INCLUDE_STRONG_WITNESS_COMPLEX_INTERFACE_H_ +#define INCLUDE_STRONG_WITNESS_COMPLEX_INTERFACE_H_ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Strong_witness_complex.h> + +#include "Simplex_tree_interface.h" + +#include <vector> +#include <utility> // std::pair +#include <iostream> +#include <cstddef> + +namespace Gudhi { + +namespace witness_complex { + +class Strong_witness_complex_interface { + using Nearest_landmark_range = std::vector<std::pair<std::size_t, double>>; + using Nearest_landmark_table = std::vector<Nearest_landmark_range>; + + public: + Strong_witness_complex_interface(const Nearest_landmark_table& nlt) { + witness_complex_ = new Strong_witness_complex<Nearest_landmark_table>(nlt); + } + + ~Strong_witness_complex_interface() { + delete witness_complex_; + } + + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, + std::size_t limit_dimension) { + witness_complex_->create_complex(*simplex_tree, max_alpha_square, limit_dimension); + simplex_tree->initialize_filtration(); + } + + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, + double max_alpha_square) { + witness_complex_->create_complex(*simplex_tree, max_alpha_square); + simplex_tree->initialize_filtration(); + } + + private: + Strong_witness_complex<Nearest_landmark_table>* witness_complex_; +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // INCLUDE_STRONG_WITNESS_COMPLEX_INTERFACE_H_ diff --git a/src/cython/include/Subsampling_interface.h b/src/cython/include/Subsampling_interface.h new file mode 100644 index 00000000..1c6032c0 --- /dev/null +++ b/src/cython/include/Subsampling_interface.h @@ -0,0 +1,119 @@ +/* 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 INCLUDE_SUBSAMPLING_INTERFACE_H_ +#define INCLUDE_SUBSAMPLING_INTERFACE_H_ + +#include <gudhi/choose_n_farthest_points.h> +#include <gudhi/pick_n_random_points.h> +#include <gudhi/sparsify_point_set.h> +#include <gudhi/Points_off_io.h> +#include <CGAL/Epick_d.h> + +#include <iostream> +#include <vector> +#include <string> + +namespace Gudhi { + +namespace subsampling { + +using Subsampling_dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; +using Subsampling_point_d = Subsampling_dynamic_kernel::Point_d; +using Subsampling_ft = Subsampling_dynamic_kernel::FT; + +// ------ choose_n_farthest_points ------ +std::vector<std::vector<double>> subsampling_n_farthest_points(const std::vector<std::vector<double>>& points, + unsigned nb_points) { + std::vector<std::vector<double>> landmarks; + Subsampling_dynamic_kernel k; + choose_n_farthest_points(k, points, nb_points, std::back_inserter(landmarks)); + + return landmarks; +} + +std::vector<std::vector<double>> subsampling_n_farthest_points(const std::vector<std::vector<double>>& points, + unsigned nb_points, unsigned starting_point) { + std::vector<std::vector<double>> landmarks; + Subsampling_dynamic_kernel k; + choose_n_farthest_points(k, points, nb_points, starting_point, std::back_inserter(landmarks)); + + return landmarks; +} + +std::vector<std::vector<double>> subsampling_n_farthest_points_from_file(const std::string& off_file, + unsigned nb_points) { + Gudhi::Points_off_reader<std::vector<double>> off_reader(off_file); + std::vector<std::vector<double>> points = off_reader.get_point_cloud(); + return subsampling_n_farthest_points(points, nb_points); +} + +std::vector<std::vector<double>> subsampling_n_farthest_points_from_file(const std::string& off_file, + unsigned nb_points, unsigned starting_point) { + Gudhi::Points_off_reader<std::vector<double>> off_reader(off_file); + std::vector<std::vector<double>> points = off_reader.get_point_cloud(); + return subsampling_n_farthest_points(points, nb_points, starting_point); +} + +// ------ pick_n_random_points ------ +std::vector<std::vector<double>> subsampling_n_random_points(const std::vector<std::vector<double>>& points, + unsigned nb_points) { + std::vector<std::vector<double>> landmarks; + pick_n_random_points(points, nb_points, std::back_inserter(landmarks)); + + return landmarks; +} + +std::vector<std::vector<double>> subsampling_n_random_points_from_file(const std::string& off_file, + unsigned nb_points) { + Gudhi::Points_off_reader<std::vector<double>> off_reader(off_file); + std::vector<std::vector<double>> points = off_reader.get_point_cloud(); + return subsampling_n_random_points(points, nb_points); +} + +// ------ sparsify_point_set ------ +std::vector<std::vector<double>> subsampling_sparsify_points(const std::vector<std::vector<double>>& points, + double min_squared_dist) { + std::vector<Subsampling_point_d> input, output; + for (auto point : points) + input.push_back(Subsampling_point_d(point.size(), point.begin(), point.end())); + Subsampling_dynamic_kernel k; + sparsify_point_set(k, input, min_squared_dist, std::back_inserter(output)); + + std::vector<std::vector<double>> landmarks; + for (auto point : output) + landmarks.push_back(std::vector<double>(point.cartesian_begin(), point.cartesian_end())); + return landmarks; +} + +std::vector<std::vector<double>> subsampling_sparsify_points_from_file(const std::string& off_file, + double min_squared_dist) { + Gudhi::Points_off_reader<std::vector<double>> off_reader(off_file); + std::vector<std::vector<double>> points = off_reader.get_point_cloud(); + return subsampling_sparsify_points(points, min_squared_dist); +} + +} // namespace subsampling + +} // namespace Gudhi + +#endif // INCLUDE_SUBSAMPLING_INTERFACE_H_ diff --git a/src/cython/include/Tangential_complex_interface.h b/src/cython/include/Tangential_complex_interface.h new file mode 100644 index 00000000..5e9dc0e4 --- /dev/null +++ b/src/cython/include/Tangential_complex_interface.h @@ -0,0 +1,123 @@ +/* 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 INCLUDE_TANGENTIAL_COMPLEX_INTERFACE_H_ +#define INCLUDE_TANGENTIAL_COMPLEX_INTERFACE_H_ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Tangential_complex.h> +#include <gudhi/Points_off_io.h> +#include <CGAL/Epick_d.h> + +#include "Simplex_tree_interface.h" + +#include <vector> +#include <utility> // std::pair +#include <iostream> +#include <string> + +namespace Gudhi { + +namespace tangential_complex { + +class Tangential_complex_interface { + using Dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; + using Point_d = Dynamic_kernel::Point_d; + using TC = Tangential_complex<Dynamic_kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag>; + + public: + Tangential_complex_interface(const std::vector<std::vector<double>>& points) { + Dynamic_kernel k; + unsigned intrisic_dim = 0; + if (points.size() > 0) + intrisic_dim = points[0].size() - 1; + + tangential_complex_ = new TC(points, intrisic_dim, k); + tangential_complex_->compute_tangential_complex(); + num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); + } + + Tangential_complex_interface(const std::string& off_file_name, bool from_file = true) { + Gudhi::Points_off_reader<Point_d> off_reader(off_file_name); + Dynamic_kernel k; + unsigned intrisic_dim = 0; + std::vector<Point_d> points = off_reader.get_point_cloud(); + if (points.size() > 0) + intrisic_dim = points[0].size() - 1; + + tangential_complex_ = new TC(points, intrisic_dim, k); + tangential_complex_->compute_tangential_complex(); + num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); + } + + ~Tangential_complex_interface() { + delete tangential_complex_; + } + + std::vector<double> get_point(unsigned vh) { + std::vector<double> vd; + if (vh < tangential_complex_->number_of_vertices()) { + Point_d ph = tangential_complex_->get_point(vh); + for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++) + vd.push_back(*coord); + } + return vd; + } + + unsigned number_of_vertices() { + return tangential_complex_->number_of_vertices(); + } + + unsigned number_of_simplices() { + return num_inconsistencies_.num_simplices; + } + + unsigned number_of_inconsistent_simplices() { + return num_inconsistencies_.num_inconsistent_simplices; + } + + unsigned number_of_inconsistent_stars() { + return num_inconsistencies_.num_inconsistent_stars; + } + + void fix_inconsistencies_using_perturbation(double max_perturb, double time_limit) { + tangential_complex_->fix_inconsistencies_using_perturbation(max_perturb, time_limit); + num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); + } + + void create_simplex_tree(Simplex_tree<>* simplex_tree) { + int max_dim = tangential_complex_->create_complex<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>(*simplex_tree); + // FIXME + simplex_tree->set_dimension(max_dim); + simplex_tree->initialize_filtration(); + } + + private: + TC* tangential_complex_; + TC::Num_inconsistencies num_inconsistencies_; +}; + +} // namespace tangential_complex + +} // namespace Gudhi + +#endif // INCLUDE_TANGENTIAL_COMPLEX_INTERFACE_H_ diff --git a/src/cython/include/Witness_complex_interface.h b/src/cython/include/Witness_complex_interface.h new file mode 100644 index 00000000..6501cc35 --- /dev/null +++ b/src/cython/include/Witness_complex_interface.h @@ -0,0 +1,74 @@ +/* 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 INCLUDE_WITNESS_COMPLEX_INTERFACE_H_ +#define INCLUDE_WITNESS_COMPLEX_INTERFACE_H_ + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Witness_complex.h> + +#include "Simplex_tree_interface.h" + +#include <vector> +#include <utility> // std::pair +#include <iostream> +#include <cstddef> + +namespace Gudhi { + +namespace witness_complex { + +class Witness_complex_interface { + using Nearest_landmark_range = std::vector<std::pair<std::size_t, double>>; + using Nearest_landmark_table = std::vector<Nearest_landmark_range>; + + public: + Witness_complex_interface(const Nearest_landmark_table& nlt) { + witness_complex_ = new Witness_complex<Nearest_landmark_table>(nlt); + } + + ~Witness_complex_interface() { + delete witness_complex_; + } + + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, + std::size_t limit_dimension) { + witness_complex_->create_complex(*simplex_tree, max_alpha_square, limit_dimension); + simplex_tree->initialize_filtration(); + } + + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, + double max_alpha_square) { + witness_complex_->create_complex(*simplex_tree, max_alpha_square); + simplex_tree->initialize_filtration(); + } + + private: + Witness_complex<Nearest_landmark_table>* witness_complex_; +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // INCLUDE_WITNESS_COMPLEX_INTERFACE_H_ + diff --git a/src/cython/test/test_alpha_complex.py b/src/cython/test/test_alpha_complex.py new file mode 100755 index 00000000..2625d529 --- /dev/null +++ b/src/cython/test/test_alpha_complex.py @@ -0,0 +1,86 @@ +from gudhi import AlphaComplex, SimplexTree + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_alpha(): + alpha_complex = AlphaComplex(points=[[0,0]]) + assert alpha_complex.__is_defined() == True + +def test_infinite_alpha(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + alpha_complex = AlphaComplex(points=point_list) + assert alpha_complex.__is_defined() == True + + simplex_tree = alpha_complex.create_simplex_tree() + assert simplex_tree.__is_persistence_defined() == False + + assert simplex_tree.num_simplices() == 11 + assert simplex_tree.num_vertices() == 4 + + assert simplex_tree.get_filtered_tree() == \ + [([0], 0.0), ([1], 0.0), ([2], 0.0), ([3], 0.0), + ([0, 1], 0.25), ([0, 2], 0.25), ([1, 3], 0.25), + ([2, 3], 0.25), ([1, 2], 0.5), ([0, 1, 2], 0.5), + ([1, 2, 3], 0.5)] + assert simplex_tree.get_star([0]) == \ + [([0], 0.0), ([0, 1], 0.25), ([0, 1, 2], 0.5), + ([0, 2], 0.25)] + assert simplex_tree.get_cofaces([0], 1) == \ + [([0, 1], 0.25), ([0, 2], 0.25)] + + assert point_list[0] == alpha_complex.get_point(0) + assert point_list[1] == alpha_complex.get_point(1) + assert point_list[2] == alpha_complex.get_point(2) + assert point_list[3] == alpha_complex.get_point(3) + assert alpha_complex.get_point(4) == [] + assert alpha_complex.get_point(125) == [] + +def test_filtered_alpha(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + filtered_alpha = AlphaComplex(points=point_list) + + simplex_tree = filtered_alpha.create_simplex_tree(max_alpha_square=0.25) + + assert simplex_tree.num_simplices() == 8 + assert simplex_tree.num_vertices() == 4 + + assert point_list[0] == filtered_alpha.get_point(0) + assert point_list[1] == filtered_alpha.get_point(1) + assert point_list[2] == filtered_alpha.get_point(2) + assert point_list[3] == filtered_alpha.get_point(3) + assert filtered_alpha.get_point(4) == [] + assert filtered_alpha.get_point(125) == [] + + assert simplex_tree.get_filtered_tree() == \ + [([0], 0.0), ([1], 0.0), ([2], 0.0), ([3], 0.0), + ([0, 1], 0.25), ([0, 2], 0.25), ([1, 3], 0.25), + ([2, 3], 0.25)] + assert simplex_tree.get_star([0]) == \ + [([0], 0.0), ([0, 1], 0.25), ([0, 2], 0.25)] + assert simplex_tree.get_cofaces([0], 1) == \ + [([0, 1], 0.25), ([0, 2], 0.25)] diff --git a/src/cython/test/test_bottleneck_distance.py b/src/cython/test/test_bottleneck_distance.py new file mode 100755 index 00000000..3d982d34 --- /dev/null +++ b/src/cython/test/test_bottleneck_distance.py @@ -0,0 +1,35 @@ +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): 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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_basic_bottleneck(): + diag1 = [[2.7, 3.7],[9.6, 14.],[34.2, 34.974], [3.,float('Inf')]] + diag2 = [[2.8, 4.45],[9.5, 14.1],[3.2,float('Inf')]] + + assert(gudhi.bottleneck_distance(diag1, diag2, 0.1) == 0.8081763781405569) + assert(gudhi.bottleneck_distance(diag1, diag2) == 0.75) diff --git a/src/cython/test/test_cubical_complex.py b/src/cython/test/test_cubical_complex.py new file mode 100755 index 00000000..c8df8089 --- /dev/null +++ b/src/cython/test/test_cubical_complex.py @@ -0,0 +1,86 @@ +from gudhi import CubicalComplex + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_constructor(): + # Try to create an empty CubicalComplex + cub = CubicalComplex() + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + +def test_non_existing_perseus_file_constructor(): + # Try to open a non existing file + cub = CubicalComplex(perseus_file='pouetpouettralala.toubiloubabdou') + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + +def test_dimension_or_perseus_file_constructor(): + # Create test file + test_file = open('CubicalOneSphere.txt', 'w') + test_file.write('2\n3\n3\n0\n0\n0\n0\n100\n0\n0\n0\n0\n') + test_file.close() + # CubicalComplex can be constructed from dimensions and + # top_dimensional_cells OR from a perseus file style name. + cub = CubicalComplex(dimensions=[3, 3], + top_dimensional_cells = [1,2,3,4,5,6,7,8,9], + perseus_file='CubicalOneSphere.txt') + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + + cub = CubicalComplex(top_dimensional_cells = [1,2,3,4,5,6,7,8,9], + perseus_file='CubicalOneSphere.txt') + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + + cub = CubicalComplex(dimensions=[3, 3], + perseus_file='CubicalOneSphere.txt') + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + +def test_dimension_constructor(): + cub = CubicalComplex(dimensions=[3, 3], + top_dimensional_cells = [1,2,3,4,5,6,7,8,9]) + assert cub.__is_defined() == True + assert cub.__is_persistence_defined() == False + assert cub.persistence() == [(1, (0.0, 100.0)), (0, (0.0, 1.8446744073709552e+19))] + assert cub.__is_persistence_defined() == True + assert cub.betti_numbers() == [1, 0] + assert cub.persistent_betti_numbers(0, 1000) == [0, 0] + +def test_dimension_constructor(): + # Create test file + test_file = open('CubicalOneSphere.txt', 'w') + test_file.write('2\n3\n3\n0\n0\n0\n0\n100\n0\n0\n0\n0\n') + test_file.close() + cub = CubicalComplex(perseus_file='CubicalOneSphere.txt') + assert cub.__is_defined() == True + assert cub.__is_persistence_defined() == False + assert cub.persistence() == [(1, (0.0, 100.0)), (0, (0.0, 1.8446744073709552e+19))] + assert cub.__is_persistence_defined() == True + assert cub.betti_numbers() == [1, 0, 0] + assert cub.persistent_betti_numbers(0, 1000) == [1, 0, 0] diff --git a/src/cython/test/test_euclidean_witness_complex.py b/src/cython/test/test_euclidean_witness_complex.py new file mode 100755 index 00000000..0947cc09 --- /dev/null +++ b/src/cython/test/test_euclidean_witness_complex.py @@ -0,0 +1,71 @@ +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): 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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_euclidean_witness_complex(): + euclidean_witness = gudhi.EuclideanWitnessComplex() + assert euclidean_witness.__is_defined() == False + +def test_witness_complex(): + point_cloud = [[1.0, 1.0], [7.0, 0.0], [4.0, 6.0], [9.0, 6.0], + [0.0, 14.0], [2.0, 19.0], [9.0, 17.0]] + landmarks = [[1.0, 1.0], [7.0, 0.0], [4.0, 6.0]] + euclidean_witness_complex = gudhi.EuclideanWitnessComplex(landmarks=landmarks, witnesses = point_cloud) + simplex_tree = euclidean_witness_complex.create_simplex_tree(max_alpha_square=4.1) + + assert landmarks[0] == euclidean_witness_complex.get_point(0) + assert landmarks[1] == euclidean_witness_complex.get_point(1) + assert landmarks[2] == euclidean_witness_complex.get_point(2) + + assert simplex_tree.get_filtered_tree() == [([0], 0.0), ([1], 0.0), + ([0, 1], 0.0), ([2], 0.0), ([0, 2], 0.0), ([1, 2], 0.0), + ([0, 1, 2], 0.0)] + +def test_empty_euclidean_strong_witness_complex(): + euclidean_strong_witness = gudhi.EuclideanStrongWitnessComplex() + assert euclidean_strong_witness.__is_defined() == False + +def test_strong_witness_complex(): + point_cloud = [[1.0, 1.0], [7.0, 0.0], [4.0, 6.0], [9.0, 6.0], + [0.0, 14.0], [2.0, 19.0], [9.0, 17.0]] + landmarks = [[1.0, 1.0], [7.0, 0.0], [4.0, 6.0]] + euclidean_strong_witness_complex = gudhi.EuclideanStrongWitnessComplex(landmarks=landmarks, witnesses = point_cloud) + simplex_tree = euclidean_strong_witness_complex.create_simplex_tree(max_alpha_square=14.9) + + assert landmarks[0] == euclidean_strong_witness_complex.get_point(0) + assert landmarks[1] == euclidean_strong_witness_complex.get_point(1) + assert landmarks[2] == euclidean_strong_witness_complex.get_point(2) + + assert simplex_tree.get_filtered_tree() == [([0], 0.0), ([1], 0.0), ([2], 0.0)] + + simplex_tree = euclidean_strong_witness_complex.create_simplex_tree(max_alpha_square=100.0) + + assert simplex_tree.get_filtered_tree() == [([0], 0.0), ([1], 0.0), + ([2], 0.0), ([1, 2], 15.0), ([0, 2], 34.0), ([0, 1], 37.0), + ([0, 1, 2], 37.0)] + diff --git a/src/cython/test/test_rips_complex.py b/src/cython/test/test_rips_complex.py new file mode 100755 index 00000000..286a645b --- /dev/null +++ b/src/cython/test/test_rips_complex.py @@ -0,0 +1,111 @@ +from gudhi import RipsComplex +from math import sqrt + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_rips(): + rips_complex = RipsComplex() + assert rips_complex.__is_defined() == True + +def test_rips_from_points(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + rips_complex = RipsComplex(points=point_list, max_edge_length=42) + + simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) + + assert simplex_tree.__is_defined() == True + assert simplex_tree.__is_persistence_defined() == False + + assert simplex_tree.num_simplices() == 10 + assert simplex_tree.num_vertices() == 4 + + assert simplex_tree.get_filtered_tree() == \ + [([0], 0.0), ([1], 0.0), ([2], 0.0), ([3], 0.0), + ([0, 1], 1.0), ([0, 2], 1.0), ([1, 3], 1.0), + ([2, 3], 1.0), ([1, 2], 1.4142135623730951), + ([0, 3], 1.4142135623730951)] + assert simplex_tree.get_star([0]) == \ + [([0], 0.0), ([0, 1], 1.0), ([0, 2], 1.0), + ([0, 3], 1.4142135623730951)] + assert simplex_tree.get_cofaces([0], 1) == \ + [([0, 1], 1.0), ([0, 2], 1.0), + ([0, 3], 1.4142135623730951)] + +def test_filtered_rips_from_points(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + filtered_rips = RipsComplex(points=point_list, max_edge_length=1.0) + + simplex_tree = filtered_rips.create_simplex_tree(max_dimension=1) + + assert simplex_tree.__is_defined() == True + assert simplex_tree.__is_persistence_defined() == False + + assert simplex_tree.num_simplices() == 8 + assert simplex_tree.num_vertices() == 4 + +def test_rips_from_distance_matrix(): + distance_matrix = [[0], + [1, 0], + [1, sqrt(2), 0], + [sqrt(2), 1, 1, 0]] + rips_complex = RipsComplex(distance_matrix=distance_matrix, max_edge_length=42) + + simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) + + assert simplex_tree.__is_defined() == True + assert simplex_tree.__is_persistence_defined() == False + + assert simplex_tree.num_simplices() == 10 + assert simplex_tree.num_vertices() == 4 + + assert simplex_tree.get_filtered_tree() == \ + [([0], 0.0), ([1], 0.0), ([2], 0.0), ([3], 0.0), + ([0, 1], 1.0), ([0, 2], 1.0), ([1, 3], 1.0), + ([2, 3], 1.0), ([1, 2], 1.4142135623730951), + ([0, 3], 1.4142135623730951)] + assert simplex_tree.get_star([0]) == \ + [([0], 0.0), ([0, 1], 1.0), ([0, 2], 1.0), + ([0, 3], 1.4142135623730951)] + assert simplex_tree.get_cofaces([0], 1) == \ + [([0, 1], 1.0), ([0, 2], 1.0), + ([0, 3], 1.4142135623730951)] + +def test_filtered_rips_from_distance_matrix(): + distance_matrix = [[0], + [1, 0], + [1, sqrt(2), 0], + [sqrt(2), 1, 1, 0]] + filtered_rips = RipsComplex(distance_matrix=distance_matrix, max_edge_length=1.0) + + simplex_tree = filtered_rips.create_simplex_tree(max_dimension=1) + + assert simplex_tree.__is_defined() == True + assert simplex_tree.__is_persistence_defined() == False + + assert simplex_tree.num_simplices() == 8 + assert simplex_tree.num_vertices() == 4 diff --git a/src/cython/test/test_simplex_tree.py b/src/cython/test/test_simplex_tree.py new file mode 100755 index 00000000..af5b639a --- /dev/null +++ b/src/cython/test/test_simplex_tree.py @@ -0,0 +1,133 @@ +from gudhi import SimplexTree + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_insertion(): + st = SimplexTree() + assert st.__is_defined() == True + assert st.__is_persistence_defined() == False + + # insert test + assert st.insert_simplex([0, 1]) == True + assert st.insert_simplex_and_subfaces([0, 1, 2], filtration=4.0) == True + # FIXME: Remove this line + st.set_dimension(2) + assert st.num_simplices() == 7 + assert st.num_vertices() == 3 + + # find test + assert st.find([0, 1, 2]) == True + assert st.find([0, 1]) == True + assert st.find([0, 2]) == True + assert st.find([0]) == True + assert st.find([1]) == True + assert st.find([2]) == True + assert st.find([3]) == False + assert st.find([0, 3]) == False + assert st.find([1, 3]) == False + assert st.find([2, 3]) == False + + # filtration test + st.set_filtration(5.0) + st.initialize_filtration() + assert st.get_filtration() == 5.0 + assert st.filtration([0, 1, 2]) == 4.0 + assert st.filtration([0, 2]) == 4.0 + assert st.filtration([1, 2]) == 4.0 + assert st.filtration([2]) == 4.0 + assert st.filtration([0, 1]) == 0.0 + assert st.filtration([0]) == 0.0 + assert st.filtration([1]) == 4.0 + + # skeleton_tree test + assert st.get_skeleton_tree(2) == \ + [([0, 1, 2], 4.0), ([0, 1], 0.0), ([0, 2], 4.0), + ([0], 0.0), ([1, 2], 4.0), ([1], 4.0), ([2], 4.0)] + assert st.get_skeleton_tree(1) == \ + [([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), + ([1, 2], 4.0), ([1], 4.0), ([2], 4.0)] + assert st.get_skeleton_tree(0) == \ + [([0], 0.0), ([1], 4.0), ([2], 4.0)] + + # remove_maximal_simplex test + assert st.get_cofaces([0, 1, 2], 1) == [] + st.remove_maximal_simplex([0, 1, 2]) + assert st.get_skeleton_tree(2) == \ + [([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), + ([1, 2], 4.0), ([1], 4.0), ([2], 4.0)] + assert st.find([0, 1, 2]) == False + assert st.find([0, 1]) == True + assert st.find([0, 2]) == True + assert st.find([0]) == True + assert st.find([1]) == True + assert st.find([2]) == True + + st.initialize_filtration() + assert st.persistence() == [(1, (4.0, float('inf'))), (0, (0.0, float('inf')))] + assert st.__is_persistence_defined() == True + assert st.betti_numbers() == [1, 1] + assert st.persistent_betti_numbers(-0.1, 10000.0) == [0, 0] + assert st.persistent_betti_numbers(0.0, 10000.0) == [1, 0] + assert st.persistent_betti_numbers(3.9, 10000.0) == [1, 0] + assert st.persistent_betti_numbers(4.0, 10000.0) == [1, 1] + assert st.persistent_betti_numbers(9999.0, 10000.0) == [1, 1] + +def test_expansion(): + st = SimplexTree() + assert st.__is_defined() == True + assert st.__is_persistence_defined() == False + + # insert test + assert st.insert_simplex_and_subfaces([3, 2], 0.1) == True + assert st.insert_simplex_and_subfaces([2, 0], 0.2) == True + assert st.insert_simplex_and_subfaces([1, 0], 0.3) == True + assert st.insert_simplex_and_subfaces([3, 1], 0.4) == True + assert st.insert_simplex_and_subfaces([2, 1], 0.5) == True + assert st.insert_simplex_and_subfaces([6, 5], 0.6) == True + assert st.insert_simplex_and_subfaces([4, 2], 0.7) == True + assert st.insert_simplex_and_subfaces([3, 0], 0.8) == True + assert st.insert_simplex_and_subfaces([6, 4], 0.9) == True + assert st.insert_simplex_and_subfaces([6, 3], 1.0) == True + + assert st.num_vertices() == 7 + assert st.num_simplices() == 17 + assert st.get_filtered_tree() == [([2], 0.1), ([3], 0.1), ([2, 3], 0.1), + ([0], 0.2), ([0, 2], 0.2), ([1], 0.3), ([0, 1], 0.3), ([1, 3], 0.4), + ([1, 2], 0.5), ([5], 0.6), ([6], 0.6), ([5, 6], 0.6), ([4], 0.7), + ([2, 4], 0.7), ([0, 3], 0.8), ([4, 6], 0.9), ([3, 6], 1.0)] + + st.expansion(3) + assert st.num_vertices() == 7 + assert st.num_simplices() == 22 + st.initialize_filtration() + + assert st.get_filtered_tree() == [([2], 0.1), ([3], 0.1), ([2, 3], 0.1), + ([0], 0.2), ([0, 2], 0.2), ([1], 0.3), ([0, 1], 0.3), ([1, 3], 0.4), + ([1, 2], 0.5), ([0, 1, 2], 0.5), ([1, 2, 3], 0.5), ([5], 0.6), ([6], 0.6), + ([5, 6], 0.6), ([4], 0.7), ([2, 4], 0.7), ([0, 3], 0.8), ([0, 1, 3], 0.8), + ([0, 2, 3], 0.8), ([0, 1, 2, 3], 0.8), ([4, 6], 0.9), ([3, 6], 1.0)] diff --git a/src/cython/test/test_subsampling.py b/src/cython/test/test_subsampling.py new file mode 100755 index 00000000..2caf4ddb --- /dev/null +++ b/src/cython/test/test_subsampling.py @@ -0,0 +1,133 @@ +import gudhi + +"""This file is part of the Gudhi Library. The Gudhi library + (Geometric Understanding in Higher Dimensions) is a generic C++ + library for computational topology. + + Author(s): 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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_write_off_file_for_tests(): + file = open("subsample.off", "w") + file.write("nOFF\n") + file.write("2 7 0 0\n") + file.write("1.0 1.0\n") + file.write("7.0 0.0\n") + file.write("4.0 6.0\n") + file.write("9.0 6.0\n") + file.write("0.0 14.0\n") + file.write("2.0 19.0\n") + file.write("9.0 17.0\n") + file.close() + +def test_simple_choose_n_farthest_points_with_a_starting_point(): + point_set = [[0,1], [0,0], [1,0], [1,1]] + i = 0 + for point in point_set: + # The iteration starts with the given starting point + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 1, starting_point = i) + assert sub_set[0] == point_set[i] + i = i + 1 + + # The iteration finds then the farthest + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 2, starting_point = 1) + assert sub_set[1] == point_set[3] + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 2, starting_point = 3) + assert sub_set[1] == point_set[1] + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 2, starting_point = 0) + assert sub_set[1] == point_set[2] + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 2, starting_point = 2) + assert sub_set[1] == point_set[0] + + # Test the limits + assert gudhi.choose_n_farthest_points(points = [], nb_points = 0, starting_point = 0) == [] + assert gudhi.choose_n_farthest_points(points = [], nb_points = 1, starting_point = 0) == [] + assert gudhi.choose_n_farthest_points(points = [], nb_points = 0, starting_point = 1) == [] + assert gudhi.choose_n_farthest_points(points = [], nb_points = 1, starting_point = 1) == [] + + # From off file test + for i in range (0, 7): + assert len(gudhi.choose_n_farthest_points(off_file = 'subsample.off', nb_points = i, starting_point = i)) == i + +def test_simple_choose_n_farthest_points_randomed(): + point_set = [[0,1], [0,0], [1,0], [1,1]] + # Test the limits + assert gudhi.choose_n_farthest_points(points = [], nb_points = 0) == [] + assert gudhi.choose_n_farthest_points(points = [], nb_points = 1) == [] + assert gudhi.choose_n_farthest_points(points = point_set, nb_points = 0) == [] + + # Go furter than point set on purpose + for iter in range(1,10): + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = iter) + for sub in sub_set: + found = False + for point in point_set: + if point == sub: + found = True + # Check each sub set point is existing in the point set + assert found == True + + # From off file test + for i in range (0, 7): + assert len(gudhi.choose_n_farthest_points(off_file = 'subsample.off', nb_points = i)) == i + +def test_simple_pick_n_random_points(): + point_set = [[0,1], [0,0], [1,0], [1,1]] + # Test the limits + assert gudhi.pick_n_random_points(points = [], nb_points = 0) == [] + assert gudhi.pick_n_random_points(points = [], nb_points = 1) == [] + assert gudhi.pick_n_random_points(points = point_set, nb_points = 0) == [] + + # Go furter than point set on purpose + for iter in range(1,10): + sub_set = gudhi.pick_n_random_points(points = point_set, nb_points = iter) + print(5) + for sub in sub_set: + found = False + for point in point_set: + if point == sub: + found = True + # Check each sub set point is existing in the point set + assert found == True + + # From off file test + for i in range (0, 7): + assert len(gudhi.pick_n_random_points(off_file = 'subsample.off', nb_points = i)) == i + +def test_simple_sparsify_points(): + point_set = [[0,1], [0,0], [1,0], [1,1]] + # Test the limits + # assert gudhi.sparsify_point_set(points = [], min_squared_dist = 0.0) == [] + # assert gudhi.sparsify_point_set(points = [], min_squared_dist = 10.0) == [] + assert gudhi.sparsify_point_set(points = point_set, min_squared_dist = 0.0) == point_set + assert gudhi.sparsify_point_set(points = point_set, min_squared_dist = 1.0) == point_set + assert gudhi.sparsify_point_set(points = point_set, min_squared_dist = 2.0) == [[0,1], [1,0]] + assert gudhi.sparsify_point_set(points = point_set, min_squared_dist = 2.01) == [[0,1]] + + assert len(gudhi.sparsify_point_set(off_file = 'subsample.off', min_squared_dist = 0.0)) == 7 + assert len(gudhi.sparsify_point_set(off_file = 'subsample.off', min_squared_dist = 30.0)) == 5 + assert len(gudhi.sparsify_point_set(off_file = 'subsample.off', min_squared_dist = 40.0)) == 4 + assert len(gudhi.sparsify_point_set(off_file = 'subsample.off', min_squared_dist = 90.0)) == 3 + assert len(gudhi.sparsify_point_set(off_file = 'subsample.off', min_squared_dist = 100.0)) == 2 + assert len(gudhi.sparsify_point_set(off_file = 'subsample.off', min_squared_dist = 325.0)) == 2 + assert len(gudhi.sparsify_point_set(off_file = 'subsample.off', min_squared_dist = 325.01)) == 1 diff --git a/src/cython/test/test_tangential_complex.py b/src/cython/test/test_tangential_complex.py new file mode 100755 index 00000000..c191baa4 --- /dev/null +++ b/src/cython/test/test_tangential_complex.py @@ -0,0 +1,52 @@ +from gudhi import TangentialComplex, SimplexTree + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_tangential(): + point_list = [[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]] + tc = TangentialComplex(points=point_list) + assert tc.__is_defined() == True + assert tc.num_vertices() == 4 + + st = tc.create_simplex_tree() + assert st.__is_defined() == True + assert st.__is_persistence_defined() == False + + assert st.num_simplices() == 6 + assert st.num_vertices() == 4 + + assert st.get_filtered_tree() == \ + [([0], 0.0), ([1], 0.0), ([2], 0.0), ([0, 2], 0.0), ([3], 0.0), ([1, 3], 0.0)] + assert st.get_cofaces([0], 1) == [([0, 2], 0.0)] + + assert point_list[0] == tc.get_point(0) + assert point_list[1] == tc.get_point(1) + assert point_list[2] == tc.get_point(2) + assert point_list[3] == tc.get_point(3) + assert tc.get_point(4) == [] + assert tc.get_point(125) == [] diff --git a/src/cython/test/test_witness_complex.py b/src/cython/test/test_witness_complex.py new file mode 100755 index 00000000..7d1fb6be --- /dev/null +++ b/src/cython/test/test_witness_complex.py @@ -0,0 +1,62 @@ +from gudhi import WitnessComplex, StrongWitnessComplex, SimplexTree + +"""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/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_witness_complex(): + witness = WitnessComplex() + assert witness.__is_defined() == False + +def test_witness_complex(): + nearest_landmark_table = [[[0, 0], [1, 1], [2, 2], [3, 3], [4, 4]], + [[1, 0], [2, 1], [3, 2], [4, 3], [0, 4]], + [[2, 0], [3, 1], [4, 2], [0, 3], [1, 4]], + [[3, 0], [4, 1], [0, 2], [1, 3], [2, 4]], + [[4, 0], [0, 1], [1, 2], [2, 3], [3, 4]]] + + witness_complex = WitnessComplex(nearest_landmark_table=nearest_landmark_table) + simplex_tree = witness_complex.create_simplex_tree(max_alpha_square=4.1) + assert simplex_tree.num_vertices() == 5 + assert simplex_tree.num_simplices() == 31 + simplex_tree = witness_complex.create_simplex_tree(max_alpha_square=4.1, limit_dimension=2) + assert simplex_tree.num_vertices() == 5 + assert simplex_tree.num_simplices() == 25 + +def test_strong_witness_complex(): + nearest_landmark_table = [[[0, 0], [1, 1], [2, 2], [3, 3], [4, 4]], + [[1, 0], [2, 1], [3, 2], [4, 3], [0, 4]], + [[2, 0], [3, 1], [4, 2], [0, 3], [1, 4]], + [[3, 0], [4, 1], [0, 2], [1, 3], [2, 4]], + [[4, 0], [0, 1], [1, 2], [2, 3], [3, 4]]] + + strong_witness_complex = StrongWitnessComplex(nearest_landmark_table=nearest_landmark_table) + simplex_tree = strong_witness_complex.create_simplex_tree(max_alpha_square=4.1) + assert simplex_tree.num_vertices() == 5 + assert simplex_tree.num_simplices() == 31 + simplex_tree = strong_witness_complex.create_simplex_tree(max_alpha_square=4.1, limit_dimension=2) + assert simplex_tree.num_vertices() == 5 + assert simplex_tree.num_simplices() == 25 diff --git a/src/debian/changelog b/src/debian/changelog deleted file mode 100644 index 32b3f6f9..00000000 --- a/src/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -gudhi (1.3.0-1) unstable; urgency=low - - * Initial release. - - -- Marc Glisse <marc.glisse@inria.fr> Sat, 26 Mar 2016 10:51:01 +0100 diff --git a/src/debian/compat b/src/debian/compat deleted file mode 100644 index ec635144..00000000 --- a/src/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/src/debian/control b/src/debian/control deleted file mode 100644 index 838234a9..00000000 --- a/src/debian/control +++ /dev/null @@ -1,26 +0,0 @@ -Source: gudhi -Priority: optional -Maintainer: Marc Glisse <marc.glisse@normalesup.org> -Build-Depends: debhelper (>= 9), cmake, libboost-dev -Standards-Version: 3.9.6 -Section: libs -Homepage: http://gudhi.gforge.inria.fr/ -#Vcs-Git: git://anonscm.debian.org/collab-maint/gudhi.git -#Vcs-Browser: https://anonscm.debian.org/gitweb/?p=collab-maint/gudhi.git;a=summary - -Package: libgudhi-dev -Section: libdevel -Architecture: all -Depends: libboost-dev, ${misc:Depends} -Recommends: libcgal-dev -Description: Gudhi library for topological data analysis - The Gudhi library (Geometric Understanding in Higher Dimensions) is a generic - open source C++ library for Computational Topology and Topological Data - Analysis (TDA). - . - The current release of the GUDHI library includes: - * Data structures to represent, construct and manipulate simplicial and - cubical complexes, including alpha-complex, witness complex, Rips complex. - * Algorithms to compute persistent homology and multi-field persistent - homology. - * Simplication of simplicial complexes by edge contraction. diff --git a/src/debian/copyright b/src/debian/copyright deleted file mode 100644 index 2e1f88cd..00000000 --- a/src/debian/copyright +++ /dev/null @@ -1,28 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: gudhi -Upstream-Contact: gudhi-users@lists.gforge.inria.fr -Source: <url://http://gudhi.gforge.inria.fr/> - -Files: * -Copyright: 2014-2016 Inria Sophia Antipolis-Méditerranée - 2014-2016 Inria Saclay - Ile de France - 2014-2016 Université Nice Sophia Antipolis -License: GPL-3.0+ - -License: GPL-3.0+ - 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 package 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 <https://www.gnu.org/licenses/>. - . - On Debian systems, the complete text of the GNU General - Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". - diff --git a/src/debian/docs b/src/debian/docs deleted file mode 100644 index 878a2ba1..00000000 --- a/src/debian/docs +++ /dev/null @@ -1,2 +0,0 @@ -Conventions.txt -README diff --git a/src/debian/rules b/src/debian/rules deleted file mode 100755 index c9b049af..00000000 --- a/src/debian/rules +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/make -f -# See debhelper(7) (uncomment to enable) -# output every command that modifies files on the build system. -#export DH_VERBOSE = 1 - -# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/* -DPKG_EXPORT_BUILDFLAGS = 1 -include /usr/share/dpkg/default.mk - -# see FEATURE AREAS in dpkg-buildflags(1) -#export DEB_BUILD_MAINT_OPTIONS = hardening=+all - -# see ENVIRONMENT in dpkg-buildflags(1) -# package maintainers to append CFLAGS -#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic -# package maintainers to append LDFLAGS -#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed - - -# main packaging script based on dh7 syntax -%: - dh $@ - -# dh_make generated override targets -# This is example for Cmake (See https://bugs.debian.org/641051 ) -#override_dh_auto_configure: -# dh_auto_configure -- \ -# -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) diff --git a/src/debian/source/format b/src/debian/source/format deleted file mode 100644 index 163aaf8d..00000000 --- a/src/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) |