diff options
Diffstat (limited to 'src/Simplex_tree/example')
-rw-r--r-- | src/Simplex_tree/example/CMakeLists.txt | 48 | ||||
-rw-r--r-- | src/Simplex_tree/example/README | 73 | ||||
-rw-r--r-- | src/Simplex_tree/example/cech_complex_cgal_mini_sphere_3d.cpp | 209 | ||||
-rw-r--r-- | src/Simplex_tree/example/example_alpha_shapes_3_simplex_tree_from_off_file.cpp | 264 | ||||
-rw-r--r-- | src/Simplex_tree/example/graph_expansion_with_blocker.cpp | 65 | ||||
-rw-r--r-- | src/Simplex_tree/example/mini_simplex_tree.cpp | 54 | ||||
-rw-r--r-- | src/Simplex_tree/example/simple_simplex_tree.cpp | 256 | ||||
-rw-r--r-- | src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp | 109 |
8 files changed, 1078 insertions, 0 deletions
diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt new file mode 100644 index 00000000..f99b164c --- /dev/null +++ b/src/Simplex_tree/example/CMakeLists.txt @@ -0,0 +1,48 @@ +project(Simplex_tree_examples) + +add_executable ( Simplex_tree_example_from_cliques_of_graph simplex_tree_from_cliques_of_graph.cpp ) +if (TBB_FOUND) + target_link_libraries(Simplex_tree_example_from_cliques_of_graph ${TBB_LIBRARIES}) +endif() +add_test(NAME Simplex_tree_example_from_cliques_of_graph_2 COMMAND $<TARGET_FILE:Simplex_tree_example_from_cliques_of_graph> + "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/Klein_bottle_complex.fsc" "2") +add_test(NAME Simplex_tree_example_from_cliques_of_graph_3 COMMAND $<TARGET_FILE:Simplex_tree_example_from_cliques_of_graph> + "${CMAKE_SOURCE_DIR}/data/filtered_simplicial_complex/Klein_bottle_complex.fsc" "3") + +add_executable ( Simplex_tree_example_simple_simplex_tree simple_simplex_tree.cpp ) +if (TBB_FOUND) + target_link_libraries(Simplex_tree_example_simple_simplex_tree ${TBB_LIBRARIES}) +endif() +add_test(NAME Simplex_tree_example_simple_simplex_tree COMMAND $<TARGET_FILE:Simplex_tree_example_simple_simplex_tree>) + +add_executable ( Simplex_tree_example_mini_simplex_tree mini_simplex_tree.cpp ) +add_test(NAME Simplex_tree_example_mini_simplex_tree COMMAND $<TARGET_FILE:Simplex_tree_example_mini_simplex_tree>) + +# An example with Simplex-tree using CGAL alpha_shapes_3 +if(GMP_FOUND AND NOT CGAL_VERSION VERSION_LESS 4.11.0) + add_executable ( Simplex_tree_example_alpha_shapes_3_from_off example_alpha_shapes_3_simplex_tree_from_off_file.cpp ) + target_link_libraries(Simplex_tree_example_alpha_shapes_3_from_off ${GMP_LIBRARIES} ${CGAL_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(Simplex_tree_example_alpha_shapes_3_from_off ${TBB_LIBRARIES}) + endif() + add_test(NAME Simplex_tree_example_alpha_shapes_3_from_off COMMAND $<TARGET_FILE:Simplex_tree_example_alpha_shapes_3_from_off> + "${CMAKE_SOURCE_DIR}/data/points/bunny_5000.off") + +endif() + +if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + add_executable ( Simplex_tree_example_cech_complex_cgal_mini_sphere_3d cech_complex_cgal_mini_sphere_3d.cpp ) + target_link_libraries(Simplex_tree_example_cech_complex_cgal_mini_sphere_3d ${Boost_PROGRAM_OPTIONS_LIBRARY} ${CGAL_LIBRARY}) + if (TBB_FOUND) + target_link_libraries(Simplex_tree_example_cech_complex_cgal_mini_sphere_3d ${TBB_LIBRARIES}) + endif() + add_test(NAME Simplex_tree_example_cech_complex_cgal_mini_sphere_3d COMMAND $<TARGET_FILE:Simplex_tree_example_cech_complex_cgal_mini_sphere_3d> + "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" -r 0.3 -d 3) +endif () + +add_executable ( Simplex_tree_example_graph_expansion_with_blocker graph_expansion_with_blocker.cpp ) +if (TBB_FOUND) + target_link_libraries(Simplex_tree_example_graph_expansion_with_blocker ${TBB_LIBRARIES}) +endif() + +add_test(NAME Simplex_tree_example_graph_expansion_with_blocker COMMAND $<TARGET_FILE:Simplex_tree_example_graph_expansion_with_blocker>) diff --git a/src/Simplex_tree/example/README b/src/Simplex_tree/example/README new file mode 100644 index 00000000..a9498173 --- /dev/null +++ b/src/Simplex_tree/example/README @@ -0,0 +1,73 @@ +To build the example, run in a Terminal: + +cd /path-to-gudhi/ +cmake . +cd /path-to-example/ +make + + +Example of use : + +*** Simple simplex tree construction + +./Simplex_tree_example_simple_simplex_tree + +******************************************************************** +EXAMPLE OF SIMPLE INSERTION + * INSERT 0 + + 0 INSERTED + * INSERT 1 + + 1 INSERTED + * INSERT (0,1) + + (0,1) INSERTED + * INSERT 2 + + 2 INSERTED + * INSERT (2,0) + + (2,0) INSERTED + * INSERT (2,1) + + (2,1) INSERTED + * INSERT (2,1,0) + + (2,1,0) INSERTED + * INSERT 3 + + 3 INSERTED + * INSERT (3,0) + + (3,0) INSERTED + * INSERT 0 (already inserted) + - 0 NOT INSERTED + * INSERT (2,1,0) (already inserted) + - (2,1,0) NOT INSERTED +******************************************************************** +* The complex contains 9 simplices + - dimension 2 - filtration 0.4 +* Iterator on Simplices in the filtration, with [filtration value]: + [0.1] 0 + [0.1] 1 + [0.1] 2 + [0.1] 3 + [0.2] 1 0 + [0.2] 2 0 + [0.2] 2 1 + [0.2] 3 0 + [0.3] 2 1 0 + +*** Simplex tree construction with Z/2Z coefficients on weighted graph Klein bottle file: + +./Simplex_tree_example_from_cliques_of_graph ../../../data/points/Klein_bottle_complex.txt 2 +Insert the 1-skeleton in the simplex tree in 0 s. +Expand the simplex tree in 0 s. +Information of the Simplex Tree: + Number of vertices = 10 Number of simplices = 82 + +with Z/3Z coefficients: + +./Simplex_tree_example_from_cliques_of_graph ../../../data/points/Klein_bottle_complex.txt 3 + +Insert the 1-skeleton in the simplex tree in 0 s. +Expand the simplex tree in 0 s. +Information of the Simplex Tree: + Number of vertices = 10 Number of simplices = 106 + +*** Simplex_tree computed and displayed from a 3D alpha complex: + [ Requires CGAL, GMP and GMPXX to be installed] + +./Simplex_tree_example_alpha_shapes_3_from_off ../../../data/points/bunny_5000 diff --git a/src/Simplex_tree/example/cech_complex_cgal_mini_sphere_3d.cpp b/src/Simplex_tree/example/cech_complex_cgal_mini_sphere_3d.cpp new file mode 100644 index 00000000..d716fb1f --- /dev/null +++ b/src/Simplex_tree/example/cech_complex_cgal_mini_sphere_3d.cpp @@ -0,0 +1,209 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2017 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include <gudhi/graph_simplicial_complex.h> +#include <gudhi/distance_functions.h> +#include <gudhi/Simplex_tree.h> +#include <gudhi/Points_off_io.h> + +#include <CGAL/Epick_d.h> +#include <CGAL/Min_sphere_of_spheres_d.h> +#include <CGAL/Min_sphere_of_points_d_traits_d.h> + +#include <boost/program_options.hpp> + +#include <string> +#include <vector> +#include <limits> // infinity +#include <utility> // for pair +#include <map> + +// ------------------------------------------------------------------------------- +// cech_complex_cgal_mini_sphere_3d is an example of each step that is required to +// build a Cech over a Simplex_tree. Please refer to cech_persistence to see +// how to do the same thing with the Cech_complex wrapper for less detailed +// steps. +// ------------------------------------------------------------------------------- + +// Types definition +using Simplex_tree = Gudhi::Simplex_tree<>; +using Vertex_handle = Simplex_tree::Vertex_handle; +using Simplex_handle = Simplex_tree::Simplex_handle; +using Filtration_value = Simplex_tree::Filtration_value; +using Siblings = Simplex_tree::Siblings; +using Graph_t = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, + boost::property<Gudhi::vertex_filtration_t, Filtration_value>, + boost::property<Gudhi::edge_filtration_t, Filtration_value> >; +using Edge_t = std::pair<Vertex_handle, Vertex_handle>; + +using Kernel = CGAL::Epick_d<CGAL::Dimension_tag<3> >; +using Point = Kernel::Point_d; +using Traits = CGAL::Min_sphere_of_points_d_traits_d<Kernel, Filtration_value, 3>; +using Min_sphere = CGAL::Min_sphere_of_spheres_d<Traits>; + +using Points_off_reader = Gudhi::Points_off_reader<Point>; + +class Cech_blocker { + public: + bool operator()(Simplex_handle sh) { + std::vector<Point> points; +#if DEBUG_TRACES + std::cout << "Cech_blocker on ["; +#endif // DEBUG_TRACES + for (auto vertex : simplex_tree_.simplex_vertex_range(sh)) { + points.push_back(point_cloud_[vertex]); +#if DEBUG_TRACES + std::cout << vertex << ", "; +#endif // DEBUG_TRACES + } + Min_sphere ms(points.begin(), points.end()); + Filtration_value radius = ms.radius(); +#if DEBUG_TRACES + std::cout << "] - radius = " << radius << " - returns " << (radius > threshold_) << std::endl; +#endif // DEBUG_TRACES + simplex_tree_.assign_filtration(sh, radius); + return (radius > threshold_); + } + Cech_blocker(Simplex_tree& simplex_tree, Filtration_value threshold, const std::vector<Point>& point_cloud) + : simplex_tree_(simplex_tree), threshold_(threshold), point_cloud_(point_cloud) {} + + private: + Simplex_tree simplex_tree_; + Filtration_value threshold_; + std::vector<Point> point_cloud_; +}; + +template <typename InputPointRange> +Graph_t compute_proximity_graph(InputPointRange& points, Filtration_value threshold); + +void program_options(int argc, char* argv[], std::string& off_file_points, Filtration_value& threshold, int& dim_max); + +int main(int argc, char* argv[]) { + std::string off_file_points; + Filtration_value threshold; + int dim_max; + + program_options(argc, argv, off_file_points, threshold, dim_max); + + // Extract the points from the file filepoints + Points_off_reader off_reader(off_file_points); + + // Compute the proximity graph of the points + Graph_t prox_graph = compute_proximity_graph(off_reader.get_point_cloud(), threshold); + + // Min_sphere sph1(off_reader.get_point_cloud()[0], off_reader.get_point_cloud()[1], off_reader.get_point_cloud()[2]); + // Construct the Rips complex in a Simplex Tree + Simplex_tree st; + // insert the proximity graph in the simplex tree + st.insert_graph(prox_graph); + // expand the graph until dimension dim_max + st.expansion_with_blockers(dim_max, Cech_blocker(st, threshold, off_reader.get_point_cloud())); + + std::cout << "The complex contains " << st.num_simplices() << " simplices \n"; + std::cout << " and has dimension " << st.dimension() << " \n"; + + // Sort the simplices in the order of the filtration + st.initialize_filtration(); + +#if DEBUG_TRACES + std::cout << "********************************************************************\n"; + // Display the Simplex_tree - Can not be done in the middle of 2 inserts + std::cout << "* The complex contains " << st.num_simplices() << " simplices - dimension=" << st.dimension() << "\n"; + std::cout << "* Iterator on Simplices in the filtration, with [filtration value]:\n"; + for (auto f_simplex : st.filtration_simplex_range()) { + std::cout << " " + << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << static_cast<int>(vertex) << " "; + } + std::cout << std::endl; + } +#endif // DEBUG_TRACES + return 0; +} + +void program_options(int argc, char* argv[], std::string& off_file_points, Filtration_value& threshold, int& dim_max) { + namespace po = boost::program_options; + po::options_description hidden("Hidden options"); + hidden.add_options()("input-file", po::value<std::string>(&off_file_points), + "Name of an OFF file containing a 3d point set.\n"); + + po::options_description visible("Allowed options", 100); + visible.add_options()("help,h", "produce help message")( + "max-edge-length,r", + po::value<Filtration_value>(&threshold)->default_value(std::numeric_limits<Filtration_value>::infinity()), + "Maximal length of an edge for the Cech complex construction.")( + "cpx-dimension,d", po::value<int>(&dim_max)->default_value(1), + "Maximal dimension of the Cech 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 << "Construct a Cech complex defined on a set of input points.\n \n"; + + std::cout << "Usage: " << argv[0] << " [options] input-file" << std::endl << std::endl; + std::cout << visible << std::endl; + exit(-1); + } +} + +/** Output the proximity graph of the points. + * + * If points contains n elements, the proximity graph is the graph + * with n vertices, and an edge [u,v] iff the distance function between + * points u and v is smaller than threshold. + * + * The type PointCloud furnishes .begin() and .end() methods, that return + * iterators with value_type Point. + */ +template <typename InputPointRange> +Graph_t compute_proximity_graph(InputPointRange& points, Filtration_value threshold) { + std::vector<Edge_t> edges; + std::vector<Filtration_value> edges_fil; + + Kernel k; + Vertex_handle idx_u, idx_v; + Filtration_value fil; + idx_u = 0; + for (auto it_u = points.begin(); it_u != points.end(); ++it_u) { + idx_v = idx_u + 1; + for (auto it_v = it_u + 1; it_v != points.end(); ++it_v, ++idx_v) { + fil = k.squared_distance_d_object()(*it_u, *it_v); + // For Cech Complex, threshold is a radius (distance /2) + fil = std::sqrt(fil) / 2.; + if (fil <= threshold) { + edges.emplace_back(idx_u, idx_v); + edges_fil.push_back(fil); + } + } + ++idx_u; + } + + Graph_t skel_graph(edges.begin(), edges.end(), edges_fil.begin(), + idx_u); // number of points labeled from 0 to idx_u-1 + + auto vertex_prop = boost::get(Gudhi::vertex_filtration_t(), skel_graph); + + boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end; + for (std::tie(vi, vi_end) = boost::vertices(skel_graph); vi != vi_end; ++vi) { + boost::put(vertex_prop, *vi, 0.); + } + + return skel_graph; +} diff --git a/src/Simplex_tree/example/example_alpha_shapes_3_simplex_tree_from_off_file.cpp b/src/Simplex_tree/example/example_alpha_shapes_3_simplex_tree_from_off_file.cpp new file mode 100644 index 00000000..e455c426 --- /dev/null +++ b/src/Simplex_tree/example/example_alpha_shapes_3_simplex_tree_from_off_file.cpp @@ -0,0 +1,264 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2014 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include <gudhi/Simplex_tree.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/Alpha_shape_vertex_base_3.h> +#include <CGAL/Alpha_shape_cell_base_3.h> +#include <CGAL/iterator.h> + +#include <fstream> +#include <cmath> +#include <string> +#include <tuple> // for tuple<> +#include <map> +#include <utility> // for pair<> +#include <list> +#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; + +// From file type definition +typedef Kernel::Point_3 Point; + +// 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; +typedef std::list<Alpha_shape_3::Vertex_handle> Vertex_list; + +// gudhi type definition +typedef Gudhi::Simplex_tree<> Simplex_tree; +typedef Simplex_tree::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; + +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& 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; +} + +int main(int argc, char * const argv[]) { + // program args management + if (argc != 2) { + std::cerr << "Usage: " << argv[0] + << " path_to_off_file \n"; + return 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> off_reader(offInputFile); + // Check the read operation was correct + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << argv[1] << std::endl; + return 0; + } + // Retrieve the triangulation + std::vector<Point> 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; + Simplex_tree 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(); + 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); + count_cells++; + } else if (const Facet * facet = CGAL::object_cast<Facet>(&object_iterator)) { + vertex_list = from(*facet); + count_facets++; + } else if (const Edge * edge = CGAL::object_cast<Edge>(&object_iterator)) { + vertex_list = from(*edge); + count_edges++; + } 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); + } + // 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_simplex " << vertex << "\n"; +#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 +#ifdef DEBUG_TRACES + std::cout << "filtration = " << *the_alpha_value_iterator << std::endl; +#endif // DEBUG_TRACES + simplex_tree.insert_simplex(the_simplex_tree, std::sqrt(*the_alpha_value_iterator)); + if (the_alpha_value_iterator != the_alpha_values.end()) + ++the_alpha_value_iterator; + else + std::cerr << "This shall not happen" << std::endl; + } +#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:\n"; + std::cout << " Number of vertices = " << simplex_tree.num_vertices() << " "; + std::cout << " Number of simplices = " << simplex_tree.num_simplices() << std::endl << std::endl; +#endif // DEBUG_TRACES + +#ifdef DEBUG_TRACES + std::cout << "Iterator on vertices: \n"; + for (auto vertex : simplex_tree.complex_vertex_range()) { + std::cout << vertex << " "; + } +#endif // DEBUG_TRACES + + std::cout << simplex_tree << std::endl; + +#ifdef DEBUG_TRACES + std::cout << std::endl << std::endl << "Iterator on simplices:\n"; + for (auto simplex : simplex_tree.complex_simplex_range()) { + std::cout << " "; + for (auto vertex : simplex_tree.simplex_vertex_range(simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + } +#endif // DEBUG_TRACES +#ifdef DEBUG_TRACES + std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, with [filtration value]:\n"; + for (auto f_simplex : simplex_tree.filtration_simplex_range()) { + std::cout << " " << "[" << simplex_tree.filtration(f_simplex) << "] "; + for (auto vertex : simplex_tree.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + } +#endif // DEBUG_TRACES +#ifdef DEBUG_TRACES + std::cout << std::endl << std::endl << "Iterator on Simplices in the filtration, and their boundary simplices:\n"; + for (auto f_simplex : simplex_tree.filtration_simplex_range()) { + std::cout << " " << "[" << simplex_tree.filtration(f_simplex) << "] "; + for (auto vertex : simplex_tree.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + + for (auto b_simplex : simplex_tree.boundary_simplex_range(f_simplex)) { + std::cout << " " << "[" << simplex_tree.filtration(b_simplex) << "] "; + for (auto vertex : simplex_tree.simplex_vertex_range(b_simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + } + } +#endif // DEBUG_TRACES + + return 0; +} diff --git a/src/Simplex_tree/example/graph_expansion_with_blocker.cpp b/src/Simplex_tree/example/graph_expansion_with_blocker.cpp new file mode 100644 index 00000000..494f8b1d --- /dev/null +++ b/src/Simplex_tree/example/graph_expansion_with_blocker.cpp @@ -0,0 +1,65 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2014 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include <gudhi/Simplex_tree.h> + +#include <iostream> + +using Simplex_tree = Gudhi::Simplex_tree<>; +using Simplex_handle = Simplex_tree::Simplex_handle; + +int main(int argc, char* const argv[]) { + // Construct the Simplex Tree with a 1-skeleton graph example + Simplex_tree stree; + + stree.insert_simplex({0, 1}, 0.); + stree.insert_simplex({0, 2}, 1.); + stree.insert_simplex({0, 3}, 2.); + stree.insert_simplex({1, 2}, 3.); + stree.insert_simplex({1, 3}, 4.); + stree.insert_simplex({2, 3}, 5.); + stree.insert_simplex({2, 4}, 6.); + stree.insert_simplex({3, 6}, 7.); + stree.insert_simplex({4, 5}, 8.); + stree.insert_simplex({4, 6}, 9.); + stree.insert_simplex({5, 6}, 10.); + stree.insert_simplex({6}, 10.); + + stree.expansion_with_blockers(3, [&](Simplex_handle sh) { + bool result = false; + std::cout << "Blocker on ["; + // User can loop on the vertices from the given simplex_handle i.e. + for (auto vertex : stree.simplex_vertex_range(sh)) { + // We block the expansion, if the vertex '6' is in the given list of vertices + if (vertex == 6) result = true; + std::cout << vertex << ", "; + } + std::cout << "] ( " << stree.filtration(sh); + // User can re-assign a new filtration value directly in the blocker (default is the maximal value of boudaries) + stree.assign_filtration(sh, stree.filtration(sh) + 1.); + + std::cout << " + 1. ) = " << result << std::endl; + + return result; + }); + + std::cout << "********************************************************************\n"; + std::cout << "* The complex contains " << stree.num_simplices() << " simplices"; + std::cout << " - dimension " << stree.dimension() << "\n"; + std::cout << "* Iterator on Simplices in the filtration, with [filtration value]:\n"; + for (auto f_simplex : stree.filtration_simplex_range()) { + std::cout << " " + << "[" << stree.filtration(f_simplex) << "] "; + for (auto vertex : stree.simplex_vertex_range(f_simplex)) std::cout << "(" << vertex << ")"; + std::cout << std::endl; + } + + return 0; +} diff --git a/src/Simplex_tree/example/mini_simplex_tree.cpp b/src/Simplex_tree/example/mini_simplex_tree.cpp new file mode 100644 index 00000000..bbc582c7 --- /dev/null +++ b/src/Simplex_tree/example/mini_simplex_tree.cpp @@ -0,0 +1,54 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Marc Glisse + * + * Copyright (C) 2015 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include <gudhi/Simplex_tree.h> +#include <iostream> +#include <initializer_list> + +struct MyOptions : Gudhi::Simplex_tree_options_full_featured { + // Not doing persistence, so we don't need those + static const bool store_key = false; + static const bool store_filtration = false; + // I have few vertices + typedef short Vertex_handle; +}; + +using ST = Gudhi::Simplex_tree<MyOptions>; + +// Dictionary should be private, but for now this is the easiest way. +static_assert(sizeof(ST::Dictionary::value_type) < sizeof(Gudhi::Simplex_tree<>::Dictionary::value_type), + "Not storing the filtration and key should save some space"); + +int main() { + ST st; + + /* Complex to build. */ + /* 1 */ + /* o */ + /* /X\ */ + /* o---o---o */ + /* 2 0 3 */ + + auto triangle012 = {0, 1, 2}; + auto edge03 = {0, 3}; + st.insert_simplex_and_subfaces(triangle012); + st.insert_simplex_and_subfaces(edge03); + + auto edge02 = {0, 2}; + ST::Simplex_handle e = st.find(edge02); + // We are not using filtrations so everything has value 0 + assert(st.filtration(e) == 0); + for (ST::Simplex_handle t : st.cofaces_simplex_range(e, 1)) { + // Only coface is 012 + for (ST::Vertex_handle v : st.simplex_vertex_range(t)) // v in { 0, 1, 2 } + std::cout << v; + std::cout << '\n'; + } +} diff --git a/src/Simplex_tree/example/simple_simplex_tree.cpp b/src/Simplex_tree/example/simple_simplex_tree.cpp new file mode 100644 index 00000000..4353939f --- /dev/null +++ b/src/Simplex_tree/example/simple_simplex_tree.cpp @@ -0,0 +1,256 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2014 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include <gudhi/graph_simplicial_complex.h> +#include <gudhi/Simplex_tree.h> + +#include <iostream> +#include <utility> // for pair +#include <vector> + +using Simplex_tree = Gudhi::Simplex_tree<>; +using Vertex_handle = Simplex_tree::Vertex_handle; +using Filtration_value = Simplex_tree::Filtration_value; +using typeVectorVertex = std::vector<Vertex_handle>; +using typePairSimplexBool = std::pair<Simplex_tree::Simplex_handle, bool>; + +int main(int argc, char* const argv[]) { + const Filtration_value FIRST_FILTRATION_VALUE = 0.1; + const Filtration_value SECOND_FILTRATION_VALUE = 0.2; + const Filtration_value THIRD_FILTRATION_VALUE = 0.3; + const Filtration_value FOURTH_FILTRATION_VALUE = 0.4; + + // TEST OF INSERTION + std::cout << "********************************************************************" << std::endl; + std::cout << "EXAMPLE OF SIMPLE INSERTION" << std::endl; + // Construct the Simplex Tree + Simplex_tree simplexTree; + + /* Simplex to be inserted: */ + /* 1 */ + /* o */ + /* /X\ */ + /* o---o---o */ + /* 2 0 3 */ + + // ++ FIRST + std::cout << " * INSERT 0" << std::endl; + typeVectorVertex firstSimplexVector = {0}; + typePairSimplexBool returnValue = + simplexTree.insert_simplex(firstSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + 0 INSERTED" << std::endl; + } else { + std::cout << " - 0 NOT INSERTED" << std::endl; + } + + // ++ SECOND + std::cout << " * INSERT 1" << std::endl; + typeVectorVertex secondSimplexVector = {1}; + returnValue = simplexTree.insert_simplex(secondSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + 1 INSERTED" << std::endl; + } else { + std::cout << " - 1 NOT INSERTED" << std::endl; + } + + // ++ THIRD + std::cout << " * INSERT (0,1)" << std::endl; + typeVectorVertex thirdSimplexVector = {0, 1}; + returnValue = simplexTree.insert_simplex(thirdSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + (0,1) INSERTED" << std::endl; + } else { + std::cout << " - (0,1) NOT INSERTED" << std::endl; + } + + // ++ FOURTH + std::cout << " * INSERT 2" << std::endl; + typeVectorVertex fourthSimplexVector = {2}; + returnValue = simplexTree.insert_simplex(fourthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + 2 INSERTED" << std::endl; + } else { + std::cout << " - 2 NOT INSERTED" << std::endl; + } + + // ++ FIFTH + std::cout << " * INSERT (2,0)" << std::endl; + typeVectorVertex fifthSimplexVector = {2, 0}; + returnValue = simplexTree.insert_simplex(fifthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + (2,0) INSERTED" << std::endl; + } else { + std::cout << " - (2,0) NOT INSERTED" << std::endl; + } + + // ++ SIXTH + std::cout << " * INSERT (2,1)" << std::endl; + typeVectorVertex sixthSimplexVector = {2, 1}; + returnValue = simplexTree.insert_simplex(sixthSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + (2,1) INSERTED" << std::endl; + } else { + std::cout << " - (2,1) NOT INSERTED" << std::endl; + } + + // ++ SEVENTH + std::cout << " * INSERT (2,1,0)" << std::endl; + typeVectorVertex seventhSimplexVector = {2, 1, 0}; + returnValue = simplexTree.insert_simplex(seventhSimplexVector, Filtration_value(THIRD_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + (2,1,0) INSERTED" << std::endl; + } else { + std::cout << " - (2,1,0) NOT INSERTED" << std::endl; + } + + // ++ EIGHTH + std::cout << " * INSERT 3" << std::endl; + typeVectorVertex eighthSimplexVector = {3}; + returnValue = simplexTree.insert_simplex(eighthSimplexVector, Filtration_value(FIRST_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + 3 INSERTED" << std::endl; + } else { + std::cout << " - 3 NOT INSERTED" << std::endl; + } + + // ++ NINETH + std::cout << " * INSERT (3,0)" << std::endl; + typeVectorVertex ninethSimplexVector = {3, 0}; + returnValue = simplexTree.insert_simplex(ninethSimplexVector, Filtration_value(SECOND_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + (3,0) INSERTED" << std::endl; + } else { + std::cout << " - (3,0) NOT INSERTED" << std::endl; + } + + // ++ TENTH + std::cout << " * INSERT 0 (already inserted)" << std::endl; + typeVectorVertex tenthSimplexVector = {0}; + // With a different filtration value + returnValue = simplexTree.insert_simplex(tenthSimplexVector, Filtration_value(FOURTH_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + 0 INSERTED" << std::endl; + } else { + std::cout << " - 0 NOT INSERTED" << std::endl; + } + + // ++ ELEVENTH + std::cout << " * INSERT (2,1,0) (already inserted)" << std::endl; + typeVectorVertex eleventhSimplexVector = {2, 1, 0}; + returnValue = simplexTree.insert_simplex(eleventhSimplexVector, Filtration_value(FOURTH_FILTRATION_VALUE)); + + if (returnValue.second == true) { + std::cout << " + (2,1,0) INSERTED" << std::endl; + } else { + std::cout << " - (2,1,0) NOT INSERTED" << std::endl; + } + + // ++ GENERAL VARIABLE SET + + std::cout << "********************************************************************\n"; + // Display the Simplex_tree - Can not be done in the middle of 2 inserts + std::cout << "* The complex contains " << simplexTree.num_simplices() << " simplices\n"; + std::cout << " - dimension " << simplexTree.dimension() << "\n"; + std::cout << "* Iterator on Simplices in the filtration, with [filtration value]:\n"; + for (auto f_simplex : simplexTree.filtration_simplex_range()) { + std::cout << " " + << "[" << simplexTree.filtration(f_simplex) << "] "; + for (auto vertex : simplexTree.simplex_vertex_range(f_simplex)) std::cout << "(" << vertex << ")"; + std::cout << std::endl; + } + // [0.1] 0 + // [0.1] 1 + // [0.1] 2 + // [0.1] 3 + // [0.2] 1 0 + // [0.2] 2 0 + // [0.2] 2 1 + // [0.2] 3 0 + // [0.3] 2 1 0 + + // ------------------------------------------------------------------------------------------------------------------ + // Find in the simplex_tree + // ------------------------------------------------------------------------------------------------------------------ + Simplex_tree::Simplex_handle simplexFound = simplexTree.find(secondSimplexVector); + std::cout << "**************IS THE SIMPLEX {1} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != simplexTree.null_simplex()) + std::cout << "***+ YES IT IS!\n"; + else + std::cout << "***- NO IT ISN'T\n"; + + typeVectorVertex unknownSimplexVector = {15}; + simplexFound = simplexTree.find(unknownSimplexVector); + std::cout << "**************IS THE SIMPLEX {15} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != simplexTree.null_simplex()) + std::cout << "***+ YES IT IS!\n"; + else + std::cout << "***- NO IT ISN'T\n"; + + simplexFound = simplexTree.find(fifthSimplexVector); + std::cout << "**************IS THE SIMPLEX {2,0} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != simplexTree.null_simplex()) + std::cout << "***+ YES IT IS!\n"; + else + std::cout << "***- NO IT ISN'T\n"; + + typeVectorVertex otherSimplexVector = {1, 15}; + simplexFound = simplexTree.find(otherSimplexVector); + std::cout << "**************IS THE SIMPLEX {15,1} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != simplexTree.null_simplex()) + std::cout << "***+ YES IT IS!\n"; + else + std::cout << "***- NO IT ISN'T\n"; + + typeVectorVertex invSimplexVector = {1, 2, 0}; + simplexFound = simplexTree.find(invSimplexVector); + std::cout << "**************IS THE SIMPLEX {1,2,0} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != simplexTree.null_simplex()) + std::cout << "***+ YES IT IS!\n"; + else + std::cout << "***- NO IT ISN'T\n"; + + simplexFound = simplexTree.find({0, 1}); + std::cout << "**************IS THE SIMPLEX {0,1} IN THE SIMPLEX TREE ?\n"; + if (simplexFound != simplexTree.null_simplex()) + std::cout << "***+ YES IT IS!\n"; + else + std::cout << "***- NO IT ISN'T\n"; + + std::cout << "**************COFACES OF {0,1} IN CODIMENSION 1 ARE\n"; + for (auto& simplex : simplexTree.cofaces_simplex_range(simplexTree.find({0, 1}), 1)) { + for (auto vertex : simplexTree.simplex_vertex_range(simplex)) std::cout << "(" << vertex << ")"; + std::cout << std::endl; + } + + std::cout << "**************STARS OF {0,1} ARE\n"; + for (auto& simplex : simplexTree.star_simplex_range(simplexTree.find({0, 1}))) { + for (auto vertex : simplexTree.simplex_vertex_range(simplex)) std::cout << "(" << vertex << ")"; + std::cout << std::endl; + } + + std::cout << "**************BOUNDARIES OF {0,1,2} ARE\n"; + for (auto& simplex : simplexTree.boundary_simplex_range(simplexTree.find({0, 1, 2}))) { + for (auto vertex : simplexTree.simplex_vertex_range(simplex)) std::cout << "(" << vertex << ")"; + std::cout << std::endl; + } + + return 0; +} diff --git a/src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp b/src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp new file mode 100644 index 00000000..f6dfa53c --- /dev/null +++ b/src/Simplex_tree/example/simplex_tree_from_cliques_of_graph.cpp @@ -0,0 +1,109 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Clément Maria + * + * Copyright (C) 2014 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include <gudhi/reader_utils.h> +#include <gudhi/Simplex_tree.h> + +#include <iostream> +#include <ctime> +#include <string> +#include <utility> // for std::pair + +using namespace Gudhi; + +typedef int Vertex_handle; +typedef double Filtration_value; +typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, + boost::property < vertex_filtration_t, Filtration_value >, + boost::property < edge_filtration_t, Filtration_value > > Graph_t; + +int main(int argc, char * const argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] + << " path_to_file_graph max_dim \n"; + return 0; + } + std::string filegraph = argv[1]; + int max_dim = atoi(argv[2]); + + clock_t start, end; + // Construct the Simplex Tree + Simplex_tree<> st; + + start = clock(); + auto g = read_graph<Graph_t, Filtration_value, Vertex_handle>(filegraph); + // insert the graph in the simplex tree as 1-skeleton + st.insert_graph(g); + end = clock(); + std::cout << "Insert the 1-skeleton in the simplex tree in " + << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s. \n"; + + start = clock(); + // expand the 1-skeleton until dimension max_dim + st.expansion(max_dim); + end = clock(); + std::cout << "max_dim = " << max_dim << "\n"; + std::cout << "Expand the simplex tree in " + << static_cast<double>(end - start) / CLOCKS_PER_SEC << " s. \n"; + + std::cout << "Information of the Simplex Tree: " << std::endl; + std::cout << " Number of vertices = " << st.num_vertices() << " "; + std::cout << " Number of simplices = " << st.num_simplices() << std::endl; + std::cout << std::endl << std::endl; + + std::cout << "Iterator on vertices: "; + for (auto vertex : st.complex_vertex_range()) { + std::cout << vertex << " "; + } + + std::cout << std::endl; + + std::cout << std::endl << std::endl; + + std::cout << "Iterator on simplices: " << std::endl; + for (auto simplex : st.complex_simplex_range()) { + std::cout << " "; + for (auto vertex : st.simplex_vertex_range(simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + } + + std::cout << std::endl << std::endl; + + std::cout << "Iterator on Simplices in the filtration, with [filtration value]:" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + std::cout << " " << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + } + + std::cout << std::endl << std::endl; + + std::cout << "Iterator on Simplices in the filtration, and their boundary simplices:" << std::endl; + for (auto f_simplex : st.filtration_simplex_range()) { + std::cout << " " << "[" << st.filtration(f_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(f_simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + + for (auto b_simplex : st.boundary_simplex_range(f_simplex)) { + std::cout << " " << "[" << st.filtration(b_simplex) << "] "; + for (auto vertex : st.simplex_vertex_range(b_simplex)) { + std::cout << vertex << " "; + } + std::cout << std::endl; + } + } + return 0; +} |