boostorg / graph

Boost.org graph module
http://boost.org/libs/graph
320 stars 206 forks source link

Bug in `undirected_dfs` causing incorrect callbacks to `finish_edge` of `dfs_visitor` #389

Open danielyxyang opened 6 days ago

danielyxyang commented 6 days ago

Minimal working example

Code ```c++ #include #include #include using Graph = boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, boost::property>; using Vertex = boost::graph_traits::vertex_descriptor; using Edge = boost::graph_traits::edge_descriptor; struct DFSVisitorLogger : boost::default_dfs_visitor { void log_vertex(const Vertex v, const std::string &event) { std::cout << "vertex " << v << " " << event << "\n"; } void log_edge(const Edge e, const std::string &event, const Graph &g) { std::cout << "edge (" << boost::source(e, g) << "," << boost::target(e, g) << ") " << event << "\n"; } void discover_vertex(Vertex v, const Graph &g) { log_vertex(v, "discovered"); } void finish_vertex(Vertex v, const Graph &g) { log_vertex(v, "finished"); } void examine_edge(Edge e, const Graph &g) { log_edge(e, "examined", g); } void tree_edge(Edge e, const Graph &g) { log_edge(e, "tree", g); } void back_edge(Edge e, const Graph &g) { log_edge(e, "back", g); } void forward_or_cross_edge(Edge e, const Graph &g) { log_edge(e, "forward_cross", g); } void finish_edge(Edge e, const Graph &g) { log_edge(e, "finished", g); } }; int main() { Graph g(3); boost::add_edge(0, 1, g); boost::add_edge(1, 2, g); DFSVisitorLogger dfs_visitor_logger; boost::undirected_dfs(g, boost::visitor(dfs_visitor_logger) .edge_color_map(boost::get(boost::edge_color, g))); } ```

Example Graph

0 (start) -- 1 -- 2

Actual output:

vertex 0 discovered
edge (0,1) examined
edge (0,1) tree
vertex 1 discovered
edge (1,0) examined
edge (1,0) finished
edge (1,2) examined
edge (1,2) tree
vertex 2 discovered
edge (2,1) examined
edge (2,1) finished
vertex 2 finished
edge (1,2) finished
vertex 1 finished
edge (1,2) finished   <-- should be "edge (0, 1) finished"
vertex 0 finished
edge (0,1) finished   <-- should not appear

Expected output:

vertex 0 discovered
edge (0,1) examined
edge (0,1) tree
vertex 1 discovered
edge (1,0) examined
edge (1,0) finished
edge (1,2) examined
edge (1,2) tree
vertex 2 discovered
edge (2,1) examined
edge (2,1) finished
vertex 2 finished
edge (1,2) finished
vertex 1 finished
edge (0,1) finished
vertex 0 finished

Problem

The problem is that in undirected_dfs.hpp:61 the following invariant for the entries VertexInfo& back = (u, (src_e, out_e)) in the stack is established:

Solution

See pull request #390

Related issues

Issue related to #222 and pull request #129, but the solution proposed there does not properly establish the described invariant.

jeremy-murphy commented 5 days ago

Thanks for the detailed explanation, proposed solution and references to existing issues/PRs. An exemplary issue!

Now if you can just codify your example here (without all the strings) as a unit test, the proposed solution will be perfect. :)

Thanks!