// Copyright (C) 2004-2008 The Trustees of Indiana University. // Use, modification and distribution is subject to 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) // Authors: Nick Edmonds // Douglas Gregor // Andrew Lumsdaine // SCC won't work with CSR currently due to the way the reverse graph // is constructed in the SCC algorithm #include // #define CSR #ifdef CSR # include #else # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_NO_EXCEPTIONS void boost::throw_exception(std::exception const& ex) { std::cout << ex.what() << std::endl; abort(); } #endif typedef double time_type; inline time_type get_time() { return MPI_Wtime(); } std::string print_time(time_type t) { std::ostringstream out; out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t; return out.str(); } using namespace boost; using boost::graph::distributed::mpi_process_group; void test_distributed_strong_components(int n, double _p, bool verify, bool emit_dot_file, int seed) { #ifdef CSR typedef compressed_sparse_row_graph > Graph; #else typedef adjacency_list, bidirectionalS > Graph; #endif minstd_rand gen; gen.seed(seed); mpi_process_group pg; parallel::variant_distribution distrib = parallel::block(pg, n); #ifdef CSR Graph g(sorted_erdos_renyi_iterator(gen, n, _p/2), sorted_erdos_renyi_iterator(), n, pg, distrib); #else Graph g(erdos_renyi_iterator(gen, n, _p/2), erdos_renyi_iterator(), n, pg, distrib); #endif synchronize(g); std::vector local_components_vec(num_vertices(g)); typedef iterator_property_map::iterator, property_map::type> ComponentMap; ComponentMap component(local_components_vec.begin(), get(vertex_index, g)); int num_components = 0; time_type start = get_time(); num_components = strong_components(g, component); time_type end = get_time(); if (process_id(g.process_group()) == 0) std::cerr << "Erdos-Reyni graph:\n" << n << " Vertices " << _p << " Edge probability " << num_processes(pg) << " Processors\n" << "Strong Components time = " << print_time(end - start) << " seconds.\n" << num_components << " components identified\n"; if ( verify ) { if ( process_id(g.process_group()) == 0 ) { for (int i = 0; i < n; ++i) get(component, vertex(i, g)); synchronize(component); // Check against the sequential version typedef adjacency_list Graph2; gen.seed(seed); Graph2 g2(erdos_renyi_iterator(gen, n, _p/2), erdos_renyi_iterator(), n); std::vector component2(n); int seq_num_components = strong_components(g2, make_iterator_property_map(component2.begin(), get(vertex_index, g2))); assert(num_components == seq_num_components); // Make sure components and component2 match std::map c2c; int i; for ( i = 0; i < n; i++ ) if ( c2c.find( get(component, vertex(i, g)) ) == c2c.end() ) c2c[get(component, vertex(i, g))] = component2[i]; else if ( c2c[get(component, vertex(i, g))] != component2[i] ) break; if ( i < n ) std::cerr << "Unable to verify SCC result...\n"; else std::cerr << "Passed verification... " << seq_num_components << " strong components\n"; } else { synchronize(component); } if ( emit_dot_file ) write_graphviz("scc.dot", g, paint_by_number(component)); } } int test_main(int argc, char* argv[]) { mpi::environment env(argc, argv); if (argc == 1) test_distributed_strong_components(10000, 0.0005, true, false, 1); else if ( argc < 5 ) std::cerr << "usage: test_distributed_strong_components [seed]\n"; else test_distributed_strong_components (atoi(argv[1]), atof(argv[2]), argv[3]==std::string("true"), argv[4]==std::string("true"), argc == 5? 1 : atoi(argv[5])); return 0; }