From 20bee15a2e7dc68deb3141ebab7a30a3edcfb401 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 17 Apr 2021 16:54:38 +0200 Subject: Introduce a custom graph type --- .../include/gudhi/Sparse_rips_complex.h | 76 ++++++++++++++++++---- 1 file changed, 63 insertions(+), 13 deletions(-) (limited to 'src/Rips_complex/include/gudhi/Sparse_rips_complex.h') diff --git a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h index d7669dad..30afb1d0 100644 --- a/src/Rips_complex/include/gudhi/Sparse_rips_complex.h +++ b/src/Rips_complex/include/gudhi/Sparse_rips_complex.h @@ -17,9 +17,68 @@ #include #include +#include #include +namespace Gudhi { +namespace rips_complex { +// A custom graph class, because boost::adjacency_list does not conveniently allow to choose vertex descriptors +template +struct Graph { + typedef std::vector VList; + typedef std::vector> EList; + typedef typename VList::const_iterator vertex_iterator; + typedef boost::counting_iterator edge_iterator; + VList vlist; + EList elist; +}; +template +void add_vertex(Vertex_handle v, Graph&g) { g.vlist.push_back(v); } +template +void add_edge(Vertex_handle u, Vertex_handle v, Filtration_value f, Graph&g) { g.elist.emplace_back(u, v, f); } +template +std::size_t num_vertices(Graph const&g) { return g.vlist.size(); } +template +std::size_t num_edges(Graph const&g) { return g.elist.size(); } +template ::vertex_iterator> +std::pair +vertices(Graph const&g) { + return { g.vlist.begin(), g.vlist.end() }; +} +template +std::pair, boost::counting_iterator> +edges(Graph const&g) { + typedef boost::counting_iterator I; + return { I(0), I(g.elist.size()) }; +} +template +std::size_t source(std::size_t e, Graph const&g) { return std::get<0>(g.elist[e]); } +template +std::size_t target(std::size_t e, Graph const&g) { return std::get<1>(g.elist[e]); } +template +Filtration_value get(vertex_filtration_t, Graph const&, Vertex_handle) { return 0; } +template +Filtration_value get(edge_filtration_t, Graph const&g, std::size_t e) { return std::get<2>(g.elist[e]); } +} // namespace rips_complex +} // namespace Gudhi +namespace boost { +template +struct graph_traits> { + typedef Gudhi::rips_complex::Graph G; + struct traversal_category : vertex_list_graph_tag, edge_list_graph_tag {}; + typedef Vertex_handle vertex_descriptor; + typedef typename G::vertex_iterator vertex_iterator; + typedef std::size_t vertices_size_type; + typedef std::size_t edge_descriptor; + typedef typename G::edge_iterator edge_iterator; + typedef std::size_t edges_size_type; + typedef directed_tag directed_category; + typedef disallow_parallel_edge_tag edge_parallel_category; +}; +// Etc, since we don't expose this graph to the world, we know we are not going to query property_traits. +} + namespace Gudhi { namespace rips_complex { @@ -45,13 +104,8 @@ template class Sparse_rips_complex { private: // TODO(MG): use a different graph where we know we can safely insert in parallel. - // Use a graph that lets us skip some vertices, for `mini` or redundant points. - typedef typename boost::adjacency_list, - boost::property> - Graph; - typedef int Vertex_handle; + typedef rips_complex::Graph Graph; public: /** \brief Sparse_rips_complex constructor from a list of points. @@ -137,13 +191,9 @@ class Sparse_rips_complex { const int n = boost::size(points); double cst = epsilon * (1 - epsilon) / 2; graph_.~Graph(); - new (&graph_) Graph(n); - // for(auto v : vertices(g)) // doesn't work :-( - typename boost::graph_traits::vertex_iterator v_i, v_e; - for (std::tie(v_i, v_e) = vertices(graph_); v_i != v_e; ++v_i) { - auto v = *v_i; - // This whole loop might not be necessary, leave it until someone investigates if it is safe to remove. - put(vertex_filtration_t(), graph_, v, 0); + new (&graph_) Graph(); + for (int i = 0; i < n; ++i) { + add_vertex(i, graph_); } // TODO(MG): -- cgit v1.2.3