Opened 18 years ago
Closed 18 years ago
#268 closed Bugs (Invalid)
incomplete connected components with disjoint_sets
Reported by: | nobody | Owned by: | Douglas Gregor |
---|---|---|---|
Milestone: | Component: | graph | |
Version: | None | Severity: | |
Keywords: | Cc: |
Description
I am trying to understand why the order in which I add edges to an adjacency_list graph has some effect on the connected components I get using incremental_components. Using the listing below, with Boost release 1.30.0 (also 1.31.0) with g++ 2.95 (cygwin) I get the following: > g++ -I./boost_1_31_0 -o ok -ftemplate-depth-40 incremental-components-eg-bug.cpp > ./ok rank[0] = 0 rank[1] = 0 rank[2] = 0 rank[3] = 1 rank[4] = 0 parent[0] = 3 parent[1] = 3 parent[2] = 3 parent[3] = 3 parent[4] = 3 component 0 contains: 4 3 2 1 0 This is what I expect. If I change the order in which I add edges to the graph, I get a different answer: > g++ -I./boost_1_31_0 -DSHOWBUG -o bug -ftemplate- depth-40 incremental-components-eg-bug.cpp > ./bug rank[0] = 0 rank[1] = 0 rank[2] = 1 rank[3] = 2 rank[4] = 0 parent[0] = 3 parent[1] = 2 parent[2] = 3 parent[3] = 3 parent[4] = 3 component 0 contains: 4 3 2 0 This is not what I expect. The single connected component has lost a vertex. But it should be the same graph, the only difference being the order in which I called add_edge(). Is this a bug or a misunderstanding on my part? Any advice would be appreciated... Jeff #include <iostream> #include <vector> #include <algorithm> #include <utility> #include <boost/graph/adjacency_list.hpp> #include <boost/pending/disjoint_sets.hpp> #include <boost/graph/incremental_components.hpp> int main(int, char *[]) { using namespace boost; // Create a graph typedef adjacency_list < vecS, vecS, undirectedS > Graph; typedef graph_traits < Graph >::vertex_descriptor Vertex; const int N = 5; Graph G(N); add_edge(0, 3, G); add_edge(0, 4, G); #ifndef SHOWBUG add_edge(1, 4, G); add_edge(1, 2, G); #else add_edge(1, 2, G); add_edge(1, 4, G); #endif // create the disjoint-sets object, which requires rank and parent vertex properties std::vector < Vertex > rank(num_vertices(G)); std::vector < Vertex > parent(num_vertices(G)); typedef graph_traits<Graph>::vertices_size_type* Rank; typedef Vertex* Parent; disjoint_sets < Rank, Parent > ds(&rank[0], &parent [0]); // determine the connected components, storing the results in the disjoint-sets object initialize_incremental_components(G, ds); incremental_components(G, ds); for (unsigned int i = 0; i < rank.size(); ++i) { std::cout << "rank[" << i << "] = " << rank[i] << std::endl; } for (unsigned int i = 0; i < parent.size(); ++i) { std::cout << "parent[" << i << "] = " << parent[i] << std::endl; } typedef component_index < unsigned int >Components; Components components(parent.begin(), parent.end()); for (Components::size_type i = 0; i < components.size (); ++i) { std::cout << "component " << i << " contains: "; for (Components::value_type::iterator j = components [i].begin(); j != components[i].end(); ++j) std::cout << *j << " "; std::cout << std::endl; } return EXIT_SUCCESS; }
Change History (2)
comment:2 by , 18 years ago
Status: | assigned → closed |
---|
Logged In: YES user_id=249098 This is actually not a bug. The problem is that, before using component_index to figure out what components exist, one needs to perform a "find_set" on each vertex to compress the representation. For instance, the example code does this: graph_traits<Graph>::vertex_iterator i,end; for (boost::tie(i, end) = vertices(G); i != end; ++i) cout << "representative[" << *i << "] = " << ds.find_set(*i) << endl;; cout << endl; Alternatively, one can use the "compress_sets" function in the disjoint sets data structure to do this more easily, e.g., ds.compress_sets(vertices(g).first, vertices(g).second); There is arguably a problem with the interface to incremental components because this is a subtle issue, but we should address that separately.
Note:
See TracTickets
for help on using tickets.