11#include <boost/graph/breadth_first_search.hpp>
12#include <boost/graph/depth_first_search.hpp>
28 template <
typename... Args>
29 void examine_vertex(Args&&...) {}
31 template <
typename... Args>
32 void tree_edge(Args&&...) {}
34 template <
typename... Args>
35 void back_edge(Args&&...) {}
41template <
typename GraphWrapper,
typename Edge>
44 using NodeID =
typename GraphWrapper::NodeType;
46 GenericBfsEdgeVisitor(std::vector<std::pair<NodeID, NodeID>>& edges,
const GraphWrapper& graph_wrapper)
47 : tree_edges(edges), graph_wrapper(graph_wrapper) {}
50 void tree_edge(Edge e,
const G& g) {
51 NodeID u = graph_wrapper.get_node_id(boost::source(e, g));
52 NodeID v = graph_wrapper.get_node_id(boost::target(e, g));
53 tree_edges.emplace_back(u, v);
56 std::vector<std::pair<NodeID, NodeID>>& tree_edges;
57 const GraphWrapper& graph_wrapper;
60template <
typename GraphWrapper>
68[[deprecated(
"Use G.bfs_edges(start) instead.")]]
69auto bfs_edges(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start) {
70 return G.bfs_edges(start);
73template <
typename GraphWrapper>
81[[deprecated(
"Use G.bfs_tree(start) instead.")]]
82auto bfs_tree(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start) {
83 return G.bfs_tree(start);
86template <
typename GraphWrapper>
94[[deprecated(
"Use G.bfs_successors(start) instead.")]]
95auto bfs_successors(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start) {
96 return G.bfs_successors(start);
99template <
typename GraphWrapper,
typename Edge,
typename OnVertex,
typename OnTreeEdge>
102 using NodeID =
typename GraphWrapper::NodeType;
105 : graph_wrapper(graph_wrapper), on_vertex(on_vertex), on_tree_edge(on_tree_edge) {}
107 template <
typename G>
108 void examine_vertex(
typename boost::graph_traits<G>::vertex_descriptor u,
const G&)
const {
109 on_vertex(graph_wrapper.get_node_id(u));
112 template <
typename G>
113 void tree_edge(Edge e,
const G& g)
const {
114 on_tree_edge(graph_wrapper.get_node_id(boost::source(e, g)), graph_wrapper.get_node_id(boost::target(e, g)));
118 const GraphWrapper& graph_wrapper;
120 OnTreeEdge& on_tree_edge;
123template <
typename Visitor,
typename NodeID,
typename GraphWrapper>
124void bfs_dispatch_examine_vertex(Visitor&
visitor,
const NodeID& u,
const GraphWrapper& G) {
125 if constexpr (
requires {
visitor.examine_vertex(u, G); }) {
126 visitor.examine_vertex(u, G);
130template <
typename Visitor,
typename NodeID,
typename GraphWrapper>
131void bfs_dispatch_tree_edge(Visitor& visitor,
const NodeID& u,
const NodeID& v,
const GraphWrapper& G) {
132 if constexpr (
requires { visitor.tree_edge(u, v, G); }) {
133 visitor.tree_edge(u, v, G);
137template <
typename NodeID,
typename Edge,
typename GraphWrapper,
typename Visitor>
143 template <
typename G>
144 void examine_vertex(
typename boost::graph_traits<G>::vertex_descriptor u,
const G&)
const {
145 bfs_dispatch_examine_vertex(
visitor, graph_wrapper.get_node_id(u), graph_wrapper);
148 template <
typename G>
149 void tree_edge(Edge e,
const G& g)
const {
150 bfs_dispatch_tree_edge(
152 graph_wrapper.get_node_id(boost::source(e, g)),
153 graph_wrapper.get_node_id(boost::target(e, g)),
159 const GraphWrapper& graph_wrapper;
163template <
typename GraphWrapper,
typename Visitor>
171[[deprecated(
"Use G.breadth_first_search(start, visitor) instead.")]]
173 G.breadth_first_search(start,
visitor);
176template <
typename GraphWrapper,
typename OnVertex,
typename OnTreeEdge>
185[[deprecated(
"Use G.bfs_visit(start, on_vertex, on_tree_edge) instead.")]]
186void bfs_visit(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start, OnVertex&& on_vertex, OnTreeEdge&& on_tree_edge) {
187 G.bfs_visit(start, std::forward<OnVertex>(on_vertex), std::forward<OnTreeEdge>(on_tree_edge));
190template <
typename GraphWrapper,
typename Edge>
193 using NodeID =
typename GraphWrapper::NodeType;
195 GenericDfsEdgeVisitor(std::vector<std::pair<NodeID, NodeID>>& edges,
const GraphWrapper& graph_wrapper)
196 : tree_edges(edges), graph_wrapper(graph_wrapper) {}
198 template <
typename G>
199 void tree_edge(Edge e,
const G& g) {
200 NodeID u = graph_wrapper.get_node_id(boost::source(e, g));
201 NodeID v = graph_wrapper.get_node_id(boost::target(e, g));
202 tree_edges.emplace_back(u, v);
205 std::vector<std::pair<NodeID, NodeID>>& tree_edges;
206 const GraphWrapper& graph_wrapper;
209template <
typename GraphWrapper>
217[[deprecated(
"Use G.dfs_edges(start) instead.")]]
218auto dfs_edges(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start) {
219 return G.dfs_edges(start);
222template <
typename GraphWrapper>
230[[deprecated(
"Use G.dfs_tree(start) instead.")]]
231auto dfs_tree(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start) {
232 return G.dfs_tree(start);
235template <
typename GraphWrapper>
243[[deprecated(
"Use G.dfs_predecessors(start) instead.")]]
244auto dfs_predecessors(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start) {
245 return G.dfs_predecessors(start);
248template <
typename GraphWrapper>
256[[deprecated(
"Use G.dfs_successors(start) instead.")]]
257auto dfs_successors(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start) {
258 return G.dfs_successors(start);
261template <
typename GraphWrapper,
typename Edge,
typename OnTreeEdge,
typename OnBackEdge>
264 GenericDfsVisitVisitor(
const GraphWrapper& graph_wrapper, OnTreeEdge& on_tree_edge, OnBackEdge& on_back_edge)
265 : graph_wrapper(graph_wrapper), on_tree_edge(on_tree_edge), on_back_edge(on_back_edge) {}
267 template <
typename G>
268 void tree_edge(Edge e,
const G& g)
const {
269 on_tree_edge(graph_wrapper.get_node_id(boost::source(e, g)), graph_wrapper.get_node_id(boost::target(e, g)));
272 template <
typename G>
273 void back_edge(Edge e,
const G& g)
const {
274 on_back_edge(graph_wrapper.get_node_id(boost::source(e, g)), graph_wrapper.get_node_id(boost::target(e, g)));
278 const GraphWrapper& graph_wrapper;
279 OnTreeEdge& on_tree_edge;
280 OnBackEdge& on_back_edge;
283template <
typename Visitor,
typename NodeID,
typename GraphWrapper>
284void dfs_dispatch_tree_edge(Visitor&
visitor,
const NodeID& u,
const NodeID& v,
const GraphWrapper& G) {
285 if constexpr (
requires {
visitor.tree_edge(u, v, G); }) {
286 visitor.tree_edge(u, v, G);
290template <
typename Visitor,
typename NodeID,
typename GraphWrapper>
291void dfs_dispatch_back_edge(Visitor& visitor,
const NodeID& u,
const NodeID& v,
const GraphWrapper& G) {
292 if constexpr (
requires { visitor.back_edge(u, v, G); }) {
293 visitor.back_edge(u, v, G);
297template <
typename NodeID,
typename Edge,
typename GraphWrapper,
typename Visitor>
303 template <
typename G>
304 void tree_edge(Edge e,
const G& g)
const {
305 dfs_dispatch_tree_edge(
307 graph_wrapper.get_node_id(boost::source(e, g)),
308 graph_wrapper.get_node_id(boost::target(e, g)),
313 template <
typename G>
314 void back_edge(Edge e,
const G& g)
const {
315 dfs_dispatch_back_edge(
317 graph_wrapper.get_node_id(boost::source(e, g)),
318 graph_wrapper.get_node_id(boost::target(e, g)),
324 const GraphWrapper& graph_wrapper;
328template <
typename GraphWrapper,
typename Visitor>
336[[deprecated(
"Use G.depth_first_search(start, visitor) instead.")]]
338 G.depth_first_search(start,
visitor);
341template <
typename GraphWrapper,
typename OnTreeEdge,
typename OnBackEdge>
350[[deprecated(
"Use G.dfs_visit(start, on_tree_edge, on_back_edge) instead.")]]
351void dfs_visit(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& start, OnTreeEdge&& on_tree_edge, OnBackEdge&& on_back_edge) {
352 G.dfs_visit(start, std::forward<OnTreeEdge>(on_tree_edge), std::forward<OnBackEdge>(on_back_edge));
355template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
357 std::vector<std::pair<NodeID, NodeID>> edges;
358 using EdgeType =
typename boost::graph_traits<GraphType>::edge_descriptor;
360 if (!has_node(start)) {
361 throw std::runtime_error(
"Traversal failed: start node not found.");
364 const auto start_bgl = get_id_to_bgl_map().at(start);
366 boost::breadth_first_search(get_impl(), start_bgl, boost::visitor(vis));
370template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
374 if (!has_node(start)) {
375 throw std::runtime_error(
"Traversal failed: start node not found.");
379 for (
const auto& [u, v] :
bfs_edges(start)) {
385template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
387 if (!has_node(start))
throw std::runtime_error(
"Traversal failed: start node not found.");
388 std::vector<std::optional<std::vector<NodeID>>> successors(boost::num_vertices(g));
389 for (
const auto& [u, v] :
bfs_edges(start)) {
390 const auto parent_index = get_vertex_index(get_id_to_bgl_map().at(u));
391 if (!successors[parent_index].has_value()) {
392 successors[parent_index] = std::vector<NodeID>{};
394 successors[parent_index]->push_back(v);
396 return build_sparse_node_indexed_result<std::vector<NodeID>>(successors);
399template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
400template <
typename Visitor>
402 using EdgeType =
typename boost::graph_traits<GraphType>::edge_descriptor;
403 if (!has_node(start))
throw std::runtime_error(
"Traversal failed: start node not found.");
404 const auto start_bgl = get_id_to_bgl_map().at(start);
405 std::vector<boost::default_color_type> color(boost::num_vertices(g));
406 GenericBfsObjectVisitor<NodeID, EdgeType, Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>, Visitor> vis(*
this,
visitor);
407 boost::breadth_first_search(
410 boost::visitor(vis).color_map(boost::make_iterator_property_map(color.begin(), vertex_index_map))
414template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
415template <
typename OnVertex,
typename OnTreeEdge>
417 struct callback_visitor {
419 OnTreeEdge& on_tree_edge;
420 void examine_vertex(
const NodeID& u,
const Graph&) { on_vertex(u); }
421 void tree_edge(
const NodeID& u,
const NodeID& v,
const Graph&) { on_tree_edge(u, v); }
423 auto on_vertex_fn = std::forward<OnVertex>(on_vertex);
424 auto on_tree_edge_fn = std::forward<OnTreeEdge>(on_tree_edge);
425 callback_visitor
visitor{on_vertex_fn, on_tree_edge_fn};
429template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
431 std::vector<std::pair<NodeID, NodeID>> edges;
432 using EdgeType =
typename boost::graph_traits<GraphType>::edge_descriptor;
434 if (!has_node(start)) {
435 throw std::runtime_error(
"Traversal failed: start node not found.");
438 const auto start_bgl = get_id_to_bgl_map().at(start);
440 std::vector<boost::default_color_type> color(boost::num_vertices(g));
441 boost::depth_first_search(
443 boost::root_vertex(start_bgl)
445 .color_map(boost::make_iterator_property_map(color.begin(), vertex_index_map))
450template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
454 if (!has_node(start)) {
455 throw std::runtime_error(
"Traversal failed: start node not found.");
459 for (
const auto& [u, v] :
dfs_edges(start)) {
465template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
467 if (!has_node(start))
throw std::runtime_error(
"Traversal failed: start node not found.");
468 std::vector<std::optional<NodeID>> predecessors(boost::num_vertices(g));
469 for (
const auto& [u, v] :
dfs_edges(start)) {
470 predecessors[get_vertex_index(get_id_to_bgl_map().at(v))] = u;
472 return build_sparse_node_indexed_result<NodeID>(predecessors);
475template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
477 if (!has_node(start))
throw std::runtime_error(
"Traversal failed: start node not found.");
478 std::vector<std::optional<std::vector<NodeID>>> successors(boost::num_vertices(g));
479 for (
const auto& [u, v] :
dfs_edges(start)) {
480 const auto parent_index = get_vertex_index(get_id_to_bgl_map().at(u));
481 if (!successors[parent_index].has_value()) {
482 successors[parent_index] = std::vector<NodeID>{};
484 successors[parent_index]->push_back(v);
486 return build_sparse_node_indexed_result<std::vector<NodeID>>(successors);
489template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
490template <
typename Visitor>
492 using EdgeType =
typename boost::graph_traits<GraphType>::edge_descriptor;
493 if (!has_node(start))
throw std::runtime_error(
"Traversal failed: start node not found.");
494 const auto start_bgl = get_id_to_bgl_map().at(start);
495 std::vector<boost::default_color_type> color(boost::num_vertices(g));
496 GenericDfsObjectVisitor<NodeID, EdgeType, Graph<NodeID, EdgeWeight, Directed, Multi, Weighted, OutEdgeSelector, VertexSelector>, Visitor> vis(*
this,
visitor);
497 boost::depth_first_search(
499 boost::root_vertex(start_bgl)
501 .color_map(boost::make_iterator_property_map(color.begin(), vertex_index_map))
505template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
506template <
typename OnTreeEdge,
typename OnBackEdge>
508 struct callback_visitor {
509 OnTreeEdge& on_tree_edge;
510 OnBackEdge& on_back_edge;
511 void tree_edge(
const NodeID& u,
const NodeID& v,
const Graph&) { on_tree_edge(u, v); }
512 void back_edge(
const NodeID& u,
const NodeID& v,
const Graph&) { on_back_edge(u, v); }
514 auto on_tree_edge_fn = std::forward<OnTreeEdge>(on_tree_edge);
515 auto on_back_edge_fn = std::forward<OnBackEdge>(on_back_edge);
516 callback_visitor
visitor{on_tree_edge_fn, on_back_edge_fn};
Definition traversal.hpp:42
Definition traversal.hpp:138
Definition traversal.hpp:100
Definition traversal.hpp:191
Definition traversal.hpp:298
Definition traversal.hpp:262
Graph wrapper around Boost Graph Library with Python-inspired helpers.
Definition graph.hpp:272
auto dfs_predecessors(const NodeID &start) const
Returns the DFS predecessor assigned to each discovered node.
Definition traversal.hpp:466
auto bfs_tree(const NodeID &start) const
Materializes the breadth-first-search tree rooted at start.
Definition traversal.hpp:371
void bfs_visit(const NodeID &start, OnVertex &&on_vertex, OnTreeEdge &&on_tree_edge) const
Runs breadth-first search with lightweight callback hooks.
Definition traversal.hpp:416
void dfs_visit(const NodeID &start, OnTreeEdge &&on_tree_edge, OnBackEdge &&on_back_edge) const
Runs depth-first search with lightweight callback hooks.
Definition traversal.hpp:507
auto dfs_successors(const NodeID &start) const
Groups DFS tree children by their discovered parent.
Definition traversal.hpp:476
auto bfs_edges(const NodeID &start) const
Returns the tree edges discovered by breadth-first search.
Definition traversal.hpp:356
void depth_first_search(const NodeID &start, Visitor &visitor) const
Runs depth-first search with an object-style visitor.
Definition traversal.hpp:491
void add_node(const NodeID &id)
Ensures that a node with the given ID exists in the graph.
Definition graph.hpp:507
void breadth_first_search(const NodeID &start, Visitor &visitor) const
Runs breadth-first search with an object-style visitor.
Definition traversal.hpp:401
auto dfs_edges(const NodeID &start) const
Returns the tree edges discovered by depth-first search.
Definition traversal.hpp:430
auto bfs_successors(const NodeID &start) const
Groups BFS tree children by their discovered parent.
Definition traversal.hpp:386
auto dfs_tree(const NodeID &start) const
Materializes the depth-first-search tree rooted at start.
Definition traversal.hpp:451
Minimal visitor interface for wrapper-level traversal callbacks.
Definition traversal.hpp:26
Core graph wrapper, proxy surface, and public alias presets.
auto bfs_successors(const GraphWrapper &G, const typename GraphWrapper::NodeType &start)
Deprecated free-function alias for G.bfs_successors(start).
Definition traversal.hpp:95
void depth_first_search(const GraphWrapper &G, const typename GraphWrapper::NodeType &start, Visitor &visitor)
Deprecated free-function alias for G.depth_first_search(start, visitor).
Definition traversal.hpp:337
void dfs_visit(const GraphWrapper &G, const typename GraphWrapper::NodeType &start, OnTreeEdge &&on_tree_edge, OnBackEdge &&on_back_edge)
Deprecated free-function alias for G.dfs_visit(start, on_tree_edge, on_back_edge).
Definition traversal.hpp:351
auto dfs_successors(const GraphWrapper &G, const typename GraphWrapper::NodeType &start)
Deprecated free-function alias for G.dfs_successors(start).
Definition traversal.hpp:257
void breadth_first_search(const GraphWrapper &G, const typename GraphWrapper::NodeType &start, Visitor &visitor)
Deprecated free-function alias for G.breadth_first_search(start, visitor).
Definition traversal.hpp:172
auto dfs_tree(const GraphWrapper &G, const typename GraphWrapper::NodeType &start)
Deprecated free-function alias for G.dfs_tree(start).
Definition traversal.hpp:231
auto bfs_edges(const GraphWrapper &G, const typename GraphWrapper::NodeType &start)
Deprecated free-function alias for G.bfs_edges(start).
Definition traversal.hpp:69
auto dfs_predecessors(const GraphWrapper &G, const typename GraphWrapper::NodeType &start)
Deprecated free-function alias for G.dfs_predecessors(start).
Definition traversal.hpp:244
auto bfs_tree(const GraphWrapper &G, const typename GraphWrapper::NodeType &start)
Deprecated free-function alias for G.bfs_tree(start).
Definition traversal.hpp:82
auto dfs_edges(const GraphWrapper &G, const typename GraphWrapper::NodeType &start)
Deprecated free-function alias for G.dfs_edges(start).
Definition traversal.hpp:218
void bfs_visit(const GraphWrapper &G, const typename GraphWrapper::NodeType &start, OnVertex &&on_vertex, OnTreeEdge &&on_tree_edge)
Deprecated free-function alias for G.bfs_visit(start, on_vertex, on_tree_edge).
Definition traversal.hpp:186