//======================================================================= // Copyright 2009 Trustees of Indiana University. // Authors: Michael Hansen, Andrew Lumsdaine // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= #include #include #include #include #include #include #include #include #include #include #include using namespace boost; typedef adjacency_list VectorGraph; typedef adjacency_list > ListGraph; template void test_graph(const Graph& graph) { typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename graph_traits::vertices_size_type vertices_size_type; typedef typename property_map::type IndexPropertyMap; typedef std::map RankMap; typedef associative_property_map RankPropertyMap; typedef std::vector ParentMap; typedef iterator_property_map IndexParentMap; RankMap rank_map; RankPropertyMap rank_property_map(rank_map); ParentMap parent_map(num_vertices(graph)); IndexParentMap index_parent_map(parent_map.begin()); // Create disjoint sets of vertices from the graph disjoint_sets vertex_sets(rank_property_map, index_parent_map); initialize_incremental_components(graph, vertex_sets); incremental_components(graph, vertex_sets); // Build component index from the graph's vertices, its index map, // and the disjoint sets. typedef component_index Components; Components vertex_components(parent_map.begin(), parent_map.end(), get(boost::vertex_index, graph)); // Create a reverse-lookup map for vertex indices std::vector reverse_index_map(num_vertices(graph)); BOOST_FOREACH(vertex_descriptor vertex, vertices(graph)) { reverse_index_map[get(get(boost::vertex_index, graph), vertex)] = vertex; } // Verify that components are really connected BOOST_FOREACH(vertices_size_type component_index, vertex_components) { std::set component_vertices; BOOST_FOREACH(vertices_size_type child_index, vertex_components[component_index]) { vertex_descriptor child_vertex = reverse_index_map[child_index]; component_vertices.insert(child_vertex); } // foreach child_index // Verify that children are connected to each other in some // manner, but not to vertices outside their component. BOOST_FOREACH(vertex_descriptor child_vertex, component_vertices) { // Skip orphan vertices if (out_degree(child_vertex, graph) == 0) { continue; } // Make sure at least one edge exists between [child_vertex] and // another vertex in the component. bool edge_exists = false; BOOST_FOREACH(edge_descriptor child_edge, out_edges(child_vertex, graph)) { if (component_vertices.count(target(child_edge, graph)) > 0) { edge_exists = true; break; } } // foreach child_edge BOOST_REQUIRE(edge_exists); } // foreach child_vertex } // foreach component_index } // test_graph int test_main(int argc, char* argv[]) { std::size_t vertices_to_generate = 100, edges_to_generate = 50, random_seed = time(0); // Parse command-line arguments if (argc > 1) { vertices_to_generate = lexical_cast(argv[1]); } if (argc > 2) { edges_to_generate = lexical_cast(argv[2]); } if (argc > 3) { random_seed = lexical_cast(argv[3]); } minstd_rand generator(random_seed); // Generate random vector and list graphs VectorGraph vector_graph; generate_random_graph(vector_graph, vertices_to_generate, edges_to_generate, generator, false); test_graph(vector_graph); ListGraph list_graph; generate_random_graph(list_graph, vertices_to_generate, edges_to_generate, generator, false); // Assign indices to list_graph's vertices graph_traits::vertices_size_type index = 0; BOOST_FOREACH(graph_traits::vertex_descriptor vertex, vertices(list_graph)) { put(get(boost::vertex_index, list_graph), vertex, index++); } test_graph(list_graph); return 0; }