175 lines
5.3 KiB
C++
175 lines
5.3 KiB
C++
//=======================================================================
|
|
// 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 <iostream>
|
|
#include <map>
|
|
#include <set>
|
|
#include <ctime>
|
|
|
|
#include <boost/foreach.hpp>
|
|
#include <boost/graph/adjacency_list.hpp>
|
|
#include <boost/graph/incremental_components.hpp>
|
|
#include <boost/graph/random.hpp>
|
|
#include <boost/lexical_cast.hpp>
|
|
#include <boost/property_map/property_map.hpp>
|
|
#include <boost/random.hpp>
|
|
#include <boost/core/lightweight_test.hpp>
|
|
|
|
using namespace boost;
|
|
|
|
typedef adjacency_list< vecS, vecS, undirectedS > VectorGraph;
|
|
|
|
typedef adjacency_list< listS, listS, undirectedS,
|
|
property< vertex_index_t, unsigned int > >
|
|
ListGraph;
|
|
|
|
template < typename Graph > void test_graph(const Graph& graph)
|
|
{
|
|
typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
|
|
typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor;
|
|
typedef
|
|
typename graph_traits< Graph >::vertices_size_type vertices_size_type;
|
|
|
|
typedef
|
|
typename property_map< Graph, vertex_index_t >::type IndexPropertyMap;
|
|
|
|
typedef std::map< vertex_descriptor, vertices_size_type > RankMap;
|
|
typedef associative_property_map< RankMap > RankPropertyMap;
|
|
|
|
typedef std::vector< vertex_descriptor > ParentMap;
|
|
typedef iterator_property_map< typename ParentMap::iterator,
|
|
IndexPropertyMap, vertex_descriptor, vertex_descriptor& >
|
|
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< RankPropertyMap, IndexParentMap > 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< vertices_size_type > 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< vertex_descriptor > 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< vertex_descriptor > 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_TEST(edge_exists);
|
|
|
|
} // foreach child_vertex
|
|
|
|
} // foreach component_index
|
|
|
|
} // test_graph
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
std::size_t vertices_to_generate = 100, edges_to_generate = 50,
|
|
random_seed = std::time(0);
|
|
|
|
// Parse command-line arguments
|
|
|
|
if (argc > 1)
|
|
{
|
|
vertices_to_generate = lexical_cast< std::size_t >(argv[1]);
|
|
}
|
|
|
|
if (argc > 2)
|
|
{
|
|
edges_to_generate = lexical_cast< std::size_t >(argv[2]);
|
|
}
|
|
|
|
if (argc > 3)
|
|
{
|
|
random_seed = lexical_cast< std::size_t >(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< ListGraph >::vertices_size_type index = 0;
|
|
BOOST_FOREACH (graph_traits< ListGraph >::vertex_descriptor vertex,
|
|
vertices(list_graph))
|
|
{
|
|
put(get(boost::vertex_index, list_graph), vertex, index++);
|
|
}
|
|
|
|
test_graph(list_graph);
|
|
|
|
return boost::report_errors();
|
|
}
|