1 // Copyright 2004 The Trustees of Indiana University.
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // Authors: Nick Edmonds
10 // #define PBGL_ACCOUNTING
12 #include <boost/graph/use_mpi.hpp>
14 #include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
15 #include <boost/graph/distributed/adjacency_list.hpp>
17 #include <boost/graph/distributed/mpi_process_group.hpp>
19 #include <boost/test/minimal.hpp>
20 #include <boost/random.hpp>
21 #include <boost/property_map/parallel/distributed_property_map.hpp>
22 #include <boost/graph/distributed/graphviz.hpp>
23 #include <boost/graph/iteration_macros.hpp>
24 #include <boost/graph/properties.hpp>
26 #include <boost/graph/rmat_graph_generator.hpp>
27 #include <boost/graph/small_world_generator.hpp>
28 #include <boost/graph/erdos_renyi_generator.hpp>
30 #include <boost/graph/distributed/connected_components.hpp>
31 #include <boost/graph/distributed/connected_components_parallel_search.hpp>
32 #include <boost/graph/distributed/betweenness_centrality.hpp>
33 #include <boost/graph/distributed/delta_stepping_shortest_paths.hpp>
43 // Edge distribution tags select a generator
44 struct rmat_edge_distribution_tag
{ };
45 struct rmat_unique_edge_distribution_tag
{ };
47 using namespace boost
;
48 using boost::graph::distributed::mpi_process_group
;
50 /****************************************************************************
52 ****************************************************************************/
53 #ifndef PBGL_ACCOUNTING
55 typedef double time_type
;
57 inline time_type
get_time()
61 return tp
.tv_sec
+ tp
.tv_usec
/ 1000000.0;
64 std::string
print_time(time_type t
)
66 std::ostringstream out
;
67 out
<< std::setiosflags(std::ios::fixed
) << std::setprecision(2) << t
;
71 #endif // PBGL_ACCOUNTING
73 /****************************************************************************
74 * Edge weight generator iterator *
75 ****************************************************************************/
76 template<typename F
, typename RandomGenerator
>
77 class generator_iterator
80 typedef std::input_iterator_tag iterator_category
;
81 typedef typename
F::result_type value_type
;
82 typedef const value_type
& reference
;
83 typedef const value_type
* pointer
;
84 typedef void difference_type
;
87 generator_iterator(RandomGenerator
& gen
, const F
& f
= F())
93 reference
operator*() const { return value
; }
94 pointer
operator->() const { return &value
; }
96 generator_iterator
& operator++()
102 generator_iterator
operator++(int)
104 generator_iterator
temp(*this);
109 bool operator==(const generator_iterator
& other
) const
110 { return f
== other
.f
; }
112 bool operator!=(const generator_iterator
& other
) const
113 { return !(*this == other
); }
117 RandomGenerator
* gen
;
121 template<typename F
, typename RandomGenerator
>
122 inline generator_iterator
<F
, RandomGenerator
>
123 make_generator_iterator( RandomGenerator
& gen
, const F
& f
)
124 { return generator_iterator
<F
, RandomGenerator
>(gen
, f
); }
126 /****************************************************************************
128 ****************************************************************************/
129 typedef int weight_type
;
131 struct WeightedEdge
{
132 WeightedEdge(weight_type weight
= 0) : weight(weight
) { }
136 template<typename Archiver
>
137 void serialize(Archiver
& ar
, const unsigned int /*version*/)
143 /****************************************************************************
145 ****************************************************************************/
146 template <typename Graph
>
147 void test_directed_sequential_algorithms(const Graph
& g
)
150 template <typename Graph
>
151 void test_undirected_sequential_algorithms(const Graph
& g
)
153 std::vector
<unsigned int> componentS(num_vertices(g
));
154 typedef iterator_property_map
<
155 std::vector
<unsigned int>::iterator
,
156 typename property_map
<Graph
, vertex_index_t
>::type
>
158 ComponentMap
component(componentS
.begin(), get(vertex_index
, g
));
160 time_type start
= get_time();
161 unsigned int num_components
= connected_components(g
, component
);
162 time_type end
= get_time();
164 std::cerr
<< " Sequential connected Components time = "
165 << print_time(end
- start
) << " seconds.\n"
166 << " " << num_components
<< " components identified\n";
169 template <typename Graph
, typename EdgeWeightMap
>
170 void test_directed_csr_only_algorithms(const Graph
& g
, EdgeWeightMap weight
,
171 typename graph_traits
<Graph
>::vertices_size_type num_sources
,
172 typename property_traits
<EdgeWeightMap
>::value_type C
)
174 typedef typename graph_traits
<Graph
>::vertex_descriptor vertex_descriptor
;
175 typedef typename graph_traits
<Graph
>::vertex_iterator vertex_iterator
;
176 typedef typename graph_traits
<Graph
>::vertices_size_type vertices_size_type
;
177 typedef typename graph_traits
<Graph
>::edges_size_type edges_size_type
;
179 typedef typename
boost::graph::parallel::process_group_type
<Graph
>::type
182 process_group_type pg
= process_group(g
);
183 typename
process_group_type::process_id_type id
= process_id(pg
);
184 typename
process_group_type::process_size_type p
= num_processes(pg
);
186 vertices_size_type n
= num_vertices(g
);
187 n
= boost::parallel::all_reduce(pg
, n
, std::plus
<vertices_size_type
>());
189 edges_size_type m
= num_edges(g
);
190 m
= boost::parallel::all_reduce(pg
, m
, std::plus
<edges_size_type
>());
193 // Betweenness Centrality (Approximate)
195 queue
<vertex_descriptor
> delta_stepping_vertices
;
198 // Distributed Centrality Map
199 typedef typename property_map
<Graph
, vertex_index_t
>::const_type IndexMap
;
200 typedef iterator_property_map
<std::vector
<int>::iterator
, IndexMap
> CentralityMap
;
202 std::vector
<int> centralityS(num_vertices(g
), 0);
203 CentralityMap
centrality(centralityS
.begin(), get(vertex_index
, g
));
205 // Calculate number of vertices of degree 0
206 vertices_size_type n0
= 0;
207 BGL_FORALL_VERTICES_T(v
, g
, Graph
) {
208 if (out_degree(v
, g
) == 0) n0
++;
210 n0
= boost::parallel::all_reduce(pg
, n0
, std::plus
<vertices_size_type
>());
212 queue
<vertex_descriptor
> sources
;
215 assert(num_sources
>= p
); // Don't feel like adding a special case for num_sources < p
218 uniform_int
<vertices_size_type
> rand_vertex(0, num_vertices(g
) - 1);
219 std::vector
<vertex_descriptor
> all_sources
, local_sources
;
220 vertices_size_type local_vertices
= vertices_size_type(floor((double)num_sources
/ p
));
221 local_vertices
+= (id
< (num_sources
- (p
* local_vertices
)) ? 1 : 0);
223 while (local_vertices
> 0) {
224 vertex_iterator iter
= vertices(g
).first
;
225 std::advance(iter
, rand_vertex(gen
));
227 if (out_degree(*iter
, g
) != 0
228 && std::find(local_sources
.begin(), local_sources
.end(), *iter
) == local_sources
.end()) {
229 local_sources
.push_back(*iter
);
233 all_gather(pg
, local_sources
.begin(), local_sources
.end(), all_sources
);
234 std::sort(all_sources
.begin(), all_sources
.end());
235 for (typename
std::vector
<vertex_descriptor
>::iterator iter
= all_sources
.begin();
236 iter
!= all_sources
.end(); ++iter
) {
238 delta_stepping_vertices
.push(*iter
);
242 // NOTE: The delta below assumes uniform edge weight distribution
243 time_type start
= get_time();
244 brandes_betweenness_centrality(g
, buffer(sources
).weight_map(weight
).
245 centrality_map(centrality
).lookahead((m
/ n
) * (C
/ 2)));
246 time_type end
= get_time();
248 edges_size_type exactTEPs
= edges_size_type(floor(7 * n
* (n
- n0
) / (end
- start
)));
251 std::cerr
<< " Betweenness Centrality Approximate (" << num_sources
<< " sources) = "
252 << print_time(end
- start
) << " (" << exactTEPs
<< " TEPs)\n";
256 // Delta stepping performance (to compare to SSSP inside BC
259 typedef typename property_map
<Graph
, vertex_index_t
>::const_type IndexMap
;
260 typedef iterator_property_map
<std::vector
<int>::iterator
, IndexMap
> DistanceMap
;
262 std::vector
<int> distanceS(num_vertices(g
), 0);
263 DistanceMap
distance(distanceS
.begin(), get(vertex_index
, g
));
265 while(!delta_stepping_vertices
.empty()) {
267 time_type start
= get_time();
268 delta_stepping_shortest_paths(g
, delta_stepping_vertices
.top(), dummy_property_map(),
270 time_type end
= get_time();
272 delta_stepping_vertices
.pop();
276 std::cerr
<< " Delta-stepping shortest paths = " << print_time(end
- start
)
283 template <typename Graph
>
284 void test_directed_algorithms(const Graph
& g
)
288 template <typename Graph
>
289 void test_undirected_algorithms(const Graph
& g
)
291 typedef typename
boost::graph::parallel::process_group_type
<Graph
>::type
294 process_group_type pg
= process_group(g
);
295 typename
process_group_type::process_id_type id
= process_id(pg
);
296 typename
process_group_type::process_size_type p
= num_processes(pg
);
299 // Connected Components
300 std::vector
<unsigned int> local_components_vec(num_vertices(g
));
301 typedef iterator_property_map
<
302 std::vector
<unsigned int>::iterator
,
303 typename property_map
<Graph
, vertex_index_t
>::type
>
305 ComponentMap
component(local_components_vec
.begin(), get(vertex_index
, g
));
309 time_type start
= get_time();
310 num_components
= connected_components(g
, component
);
311 time_type end
= get_time();
313 std::cerr
<< " Connected Components time = " << print_time(end
- start
)
315 << " " << num_components
<< " components identified\n";
318 num_components
= boost::graph::distributed::connected_components_ps(g
, component
);
321 std::cerr
<< " Connected Components (parallel search) time = "
322 << print_time(end
- start
) << " seconds.\n"
323 << " " << num_components
<< " components identified\n";
326 /****************************************************************************
328 ****************************************************************************/
330 // TODO: Re-seed PRNG before sequential tests to get the same graph as the
334 // Compressed Sparse Row
338 template <typename ProcessGroup
, typename RandomGenerator
, typename Distribution
>
339 void test_csr(const ProcessGroup
& pg
, RandomGenerator
& gen
, Distribution
& distrib
,
340 bool sequential_tests
, size_t N
, size_t M
, size_t C
,
341 double a
, double b
, double c
, double d
, size_t num_sources
,
342 rmat_edge_distribution_tag
)
344 if (process_id(pg
) == 0)
345 std::cerr
<< " R-MAT\n";
347 typedef compressed_sparse_row_graph
<directedS
, no_property
, WeightedEdge
, no_property
,
348 distributedS
<mpi_process_group
> > Graph
;
350 Graph
g(sorted_rmat_iterator
<RandomGenerator
, Graph
>(gen
, N
, M
, a
, b
, c
, d
),
351 sorted_rmat_iterator
<RandomGenerator
, Graph
>(),
352 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
355 test_directed_algorithms(g
);
356 test_directed_csr_only_algorithms(g
, get(&WeightedEdge::weight
, g
), num_sources
, C
);
358 if (sequential_tests
&& process_id(pg
) == 0) {
359 typedef compressed_sparse_row_graph
<directedS
, no_property
, WeightedEdge
>
362 seqGraph
sg(edges_are_sorted
,
363 sorted_rmat_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, M
, a
, b
, c
, d
),
364 sorted_rmat_iterator
<RandomGenerator
, seqGraph
>(),
365 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
368 test_directed_sequential_algorithms(sg
);
372 // R-MAT with unique edges
373 template <typename ProcessGroup
, typename RandomGenerator
, typename Distribution
>
374 void test_csr(const ProcessGroup
& pg
, RandomGenerator
& gen
, Distribution
& distrib
,
375 bool sequential_tests
, size_t N
, size_t M
, size_t C
,
376 double a
, double b
, double c
, double d
, size_t num_sources
,
377 rmat_unique_edge_distribution_tag
)
379 if (process_id(pg
) == 0)
380 std::cerr
<< " R-MAT - unique\n";
382 typedef compressed_sparse_row_graph
<directedS
, no_property
, WeightedEdge
, no_property
,
383 distributedS
<mpi_process_group
> > Graph
;
385 // Last boolean parameter makes R-MAT bidirectional
386 Graph
g(sorted_unique_rmat_iterator
<RandomGenerator
, Graph
>(gen
, N
, M
, a
, b
, c
, d
),
387 sorted_unique_rmat_iterator
<RandomGenerator
, Graph
>(),
388 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
391 test_directed_algorithms(g
);
392 test_directed_csr_only_algorithms(g
, get(&WeightedEdge::weight
, g
), num_sources
, C
);
394 if (sequential_tests
&& process_id(pg
) == 0) {
395 typedef compressed_sparse_row_graph
<directedS
, no_property
, WeightedEdge
>
398 seqGraph
sg(edges_are_sorted
,
399 sorted_unique_rmat_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, M
, a
, b
, c
, d
),
400 sorted_unique_rmat_iterator
<RandomGenerator
, seqGraph
>(),
401 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
404 test_directed_sequential_algorithms(sg
);
409 template <typename ProcessGroup
, typename RandomGenerator
, typename Distribution
>
410 void test_csr(const ProcessGroup
& pg
, RandomGenerator
& gen
, Distribution
& distrib
,
411 bool sequential_tests
, size_t N
, size_t M
, size_t C
, size_t num_sources
)
413 if (process_id(pg
) == 0)
414 std::cerr
<< " Erdos-Renyi\n";
416 double _p
= static_cast<double>(M
) / (N
*N
);
418 typedef compressed_sparse_row_graph
<directedS
, no_property
, WeightedEdge
, no_property
,
419 distributedS
<mpi_process_group
> > Graph
;
421 Graph
g(sorted_erdos_renyi_iterator
<RandomGenerator
, Graph
>(gen
, N
, _p
/2),
422 sorted_erdos_renyi_iterator
<RandomGenerator
, Graph
>(),
423 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
426 test_directed_algorithms(g
);
427 test_directed_csr_only_algorithms(g
, get(&WeightedEdge::weight
, g
), num_sources
, C
);
429 if (sequential_tests
&& process_id(pg
) == 0) {
430 typedef compressed_sparse_row_graph
<directedS
, no_property
, WeightedEdge
>
433 seqGraph
sg(edges_are_sorted
,
434 sorted_erdos_renyi_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, _p
/2),
435 sorted_erdos_renyi_iterator
<RandomGenerator
, seqGraph
>(),
436 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
439 test_directed_sequential_algorithms(sg
);
444 template <typename ProcessGroup
, typename RandomGenerator
, typename Distribution
>
445 void test_csr(const ProcessGroup
& pg
, RandomGenerator
& gen
, Distribution
& distrib
,
446 bool sequential_tests
, size_t N
, size_t M
, size_t C
, double p
,
449 if (process_id(pg
) == 0)
450 std::cerr
<< " Small-World\n";
454 typedef compressed_sparse_row_graph
<directedS
, no_property
, WeightedEdge
, no_property
,
455 distributedS
<mpi_process_group
> > Graph
;
457 Graph
g(small_world_iterator
<RandomGenerator
, Graph
>(gen
, N
, k
, p
),
458 small_world_iterator
<RandomGenerator
, Graph
>(),
459 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
462 test_directed_algorithms(g
);
463 test_directed_csr_only_algorithms(g
, get(&WeightedEdge::weight
, g
), num_sources
, C
);
465 if (sequential_tests
&& process_id(pg
) == 0) {
466 typedef compressed_sparse_row_graph
<directedS
, no_property
, WeightedEdge
>
469 seqGraph
sg(edges_are_sorted
,
470 small_world_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, k
, p
),
471 small_world_iterator
<RandomGenerator
, seqGraph
>(),
472 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
475 test_directed_sequential_algorithms(sg
);
484 template <typename ProcessGroup
, typename RandomGenerator
, typename Distribution
>
485 void test_adjacency_list(const ProcessGroup
& pg
, RandomGenerator
& gen
, Distribution
& distrib
,
486 bool sequential_tests
, size_t N
, size_t M
, size_t C
,
487 double a
, double b
, double c
, double d
,
488 rmat_edge_distribution_tag
)
490 if (process_id(pg
) == 0)
491 std::cerr
<< "R-MAT\n";
494 typedef adjacency_list
<vecS
, distributedS
<mpi_process_group
, vecS
>,
495 directedS
, no_property
, WeightedEdge
> Graph
;
497 Graph
g(rmat_iterator
<RandomGenerator
, Graph
>(gen
, N
, M
, a
, b
, c
, d
),
498 rmat_iterator
<RandomGenerator
, Graph
>(),
499 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
502 test_directed_algorithms(g
);
506 typedef adjacency_list
<vecS
, distributedS
<mpi_process_group
, vecS
>,
507 undirectedS
, no_property
, WeightedEdge
> Graph
;
509 Graph
g(rmat_iterator
<RandomGenerator
, Graph
>(gen
, N
, M
, a
, b
, c
, d
),
510 rmat_iterator
<RandomGenerator
, Graph
>(),
511 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
514 test_undirected_algorithms(g
);
517 if (sequential_tests
&& process_id(pg
) == 0) {
519 typedef adjacency_list
<vecS
, vecS
, directedS
, no_property
, property
<edge_weight_t
, int> >
522 seqGraph
sg(rmat_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, M
, a
, b
, c
, d
),
523 rmat_iterator
<RandomGenerator
, seqGraph
>(),
524 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
527 test_directed_sequential_algorithms(sg
);
531 typedef adjacency_list
<vecS
, vecS
, undirectedS
, no_property
, property
<edge_weight_t
, int> >
534 seqGraph
sg(rmat_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, M
, a
, b
, c
, d
),
535 rmat_iterator
<RandomGenerator
, seqGraph
>(),
536 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
539 test_undirected_sequential_algorithms(sg
);
544 // R-MAT with unique edges
545 template <typename ProcessGroup
, typename RandomGenerator
, typename Distribution
>
546 void test_adjacency_list(const ProcessGroup
& pg
, RandomGenerator
& gen
, Distribution
& distrib
,
547 bool sequential_tests
, size_t N
, size_t M
, size_t C
,
548 double a
, double b
, double c
, double d
,
549 rmat_unique_edge_distribution_tag
)
551 if (process_id(pg
) == 0)
552 std::cerr
<< " R-MAT - unique\n";
555 typedef adjacency_list
<vecS
, distributedS
<mpi_process_group
, vecS
>,
556 directedS
, no_property
, WeightedEdge
> Graph
;
558 Graph
g(sorted_unique_rmat_iterator
<RandomGenerator
, Graph
>(gen
, N
, M
, a
, b
, c
, d
),
559 sorted_unique_rmat_iterator
<RandomGenerator
, Graph
>(),
560 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
563 test_directed_algorithms(g
);
567 typedef adjacency_list
<vecS
, distributedS
<mpi_process_group
, vecS
>,
568 undirectedS
, no_property
, WeightedEdge
> Graph
;
570 Graph
g(sorted_unique_rmat_iterator
<RandomGenerator
, Graph
>(gen
, N
, M
, a
, b
, c
, d
),
571 sorted_unique_rmat_iterator
<RandomGenerator
, Graph
>(),
572 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
575 test_undirected_algorithms(g
);
578 if (sequential_tests
&& process_id(pg
) == 0) {
580 typedef adjacency_list
<vecS
, vecS
, directedS
, no_property
, property
<edge_weight_t
, int> >
583 seqGraph
sg(sorted_unique_rmat_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, M
, a
, b
, c
, d
),
584 sorted_unique_rmat_iterator
<RandomGenerator
, seqGraph
>(),
585 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
588 test_directed_sequential_algorithms(sg
);
592 typedef adjacency_list
<vecS
, vecS
, undirectedS
, no_property
, property
<edge_weight_t
, int> >
595 seqGraph
sg(sorted_unique_rmat_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, M
, a
, b
, c
, d
),
596 sorted_unique_rmat_iterator
<RandomGenerator
, seqGraph
>(),
597 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
600 test_undirected_sequential_algorithms(sg
);
606 template <typename ProcessGroup
, typename RandomGenerator
, typename Distribution
>
607 void test_adjacency_list(const ProcessGroup
& pg
, RandomGenerator
& gen
, Distribution
& distrib
,
608 bool sequential_tests
, size_t N
, size_t M
, size_t C
)
610 if (process_id(pg
) == 0)
611 std::cerr
<< " Erdos-Renyi\n";
613 double _p
= static_cast<double>(M
) / N
*N
;
616 typedef adjacency_list
<vecS
, distributedS
<mpi_process_group
, vecS
>,
617 directedS
, no_property
, WeightedEdge
> Graph
;
619 Graph
g(erdos_renyi_iterator
<RandomGenerator
, Graph
>(gen
, N
, _p
/2),
620 erdos_renyi_iterator
<RandomGenerator
, Graph
>(),
621 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
624 test_directed_algorithms(g
);
628 typedef adjacency_list
<vecS
, distributedS
<mpi_process_group
, vecS
>,
629 undirectedS
, no_property
, WeightedEdge
> Graph
;
631 Graph
g(erdos_renyi_iterator
<RandomGenerator
, Graph
>(gen
, N
, _p
/2),
632 erdos_renyi_iterator
<RandomGenerator
, Graph
>(),
633 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
636 test_undirected_algorithms(g
);
639 if (sequential_tests
&& process_id(pg
) == 0) {
641 typedef adjacency_list
<vecS
, vecS
, directedS
, no_property
, property
<edge_weight_t
, int> >
644 seqGraph
sg(erdos_renyi_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, _p
/2),
645 erdos_renyi_iterator
<RandomGenerator
, seqGraph
>(),
646 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
649 test_directed_sequential_algorithms(sg
);
653 typedef adjacency_list
<vecS
, vecS
, undirectedS
, no_property
, property
<edge_weight_t
, int> >
656 seqGraph
sg(erdos_renyi_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, _p
/2),
657 erdos_renyi_iterator
<RandomGenerator
, seqGraph
>(),
658 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
661 test_undirected_sequential_algorithms(sg
);
667 template <typename ProcessGroup
, typename RandomGenerator
, typename Distribution
>
668 void test_adjacency_list(const ProcessGroup
& pg
, RandomGenerator
& gen
, Distribution
& distrib
,
669 bool sequential_tests
, size_t N
, size_t M
, size_t C
, double p
)
671 if (process_id(pg
) == 0)
672 std::cerr
<< " Small-World\n";
677 typedef adjacency_list
<vecS
, distributedS
<mpi_process_group
, vecS
>,
678 directedS
, no_property
, WeightedEdge
> Graph
;
680 Graph
g(small_world_iterator
<RandomGenerator
, Graph
>(gen
, N
, k
, p
),
681 small_world_iterator
<RandomGenerator
, Graph
>(),
682 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
685 test_directed_algorithms(g
);
689 typedef adjacency_list
<vecS
, distributedS
<mpi_process_group
, vecS
>,
690 undirectedS
, no_property
, WeightedEdge
> Graph
;
692 Graph
g(small_world_iterator
<RandomGenerator
, Graph
>(gen
, N
, k
, p
),
693 small_world_iterator
<RandomGenerator
, Graph
>(),
694 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
697 test_undirected_algorithms(g
);
700 if (sequential_tests
&& process_id(pg
) == 0) {
702 typedef adjacency_list
<vecS
, vecS
, directedS
, no_property
, property
<edge_weight_t
, int> >
705 seqGraph
sg(small_world_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, k
, p
),
706 small_world_iterator
<RandomGenerator
, seqGraph
>(),
707 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
710 test_directed_sequential_algorithms(sg
);
714 typedef adjacency_list
<vecS
, vecS
, undirectedS
, no_property
, property
<edge_weight_t
, int> >
717 seqGraph
sg(small_world_iterator
<RandomGenerator
, seqGraph
>(gen
, N
, k
, p
),
718 small_world_iterator
<RandomGenerator
, seqGraph
>(),
719 make_generator_iterator(gen
, uniform_int
<int>(1, C
)),
722 test_undirected_sequential_algorithms(sg
);
729 std::cerr
<< "Algorithm Performance Test\n"
730 << "Usage : algorithm_performance [options]\n\n"
732 << "\t--vertices v\t\t\tNumber of vertices in the graph\n"
733 << "\t--edges v\t\t\tNumber of edges in the graph\n"
734 << "\t--seed s\t\t\tSeed for synchronized random number generator\n"
735 << "\t--max-weight miw\t\tMaximum integer edge weight\n"
736 << "\t--rewire-probability\t\tRewire-probabitility (p) for small-world graphs\n"
737 << "\t--dot\t\t\t\tEmit a dot file containing the graph\n"
738 << "\t--verify\t\t\tVerify result\n"
739 << "\t--degree-dist\t\t\tOutput degree distribution of graph\n"
740 << "\t--sequential-graph\t\tRun sequential graph tests\n"
741 << "\t--erdos-renyi\t\t\tRun tests on Erdos-Renyi graphs\n"
742 << "\t--small-world\t\t\tRun tests on Small World graphs\n"
743 << "\t--rmat\t\t\t\tRun tests on R-MAT graphs\n"
744 << "\t--rmat-unique\t\t\tRun tests on R-MAT graphs with no duplicate edges\n"
745 << "\t--csr <bool>\t\t\tRun tests using CSR graphs\n"
746 << "\t--adjacency-list <bool>\t\tRun tests using Adjacency List graphs\n";
750 int test_main(int argc
, char* argv
[])
752 mpi::environment
env(argc
, argv
);
761 num_headers
= 16 * 1024,
762 batch_buffer_size
= 1024 * 1024;
764 bool emit_dot_file
= false,
766 sequential_graph
= false,
767 show_degree_dist
= false,
781 for (int i
= 1; i
< argc
; ++i
) {
782 std::string arg
= argv
[i
];
784 if (arg
== "--vertices")
785 n
= boost::lexical_cast
<size_t>( argv
[i
+1] );
788 seed
= boost::lexical_cast
<uint64_t>( argv
[i
+1] );
790 if (arg
== "--edges")
791 m
= boost::lexical_cast
<size_t>( argv
[i
+1] );
793 if (arg
== "--max-weight")
794 c
= boost::lexical_cast
<int>( argv
[i
+1] );
796 if (arg
== "--batch-buffer-size") {
797 batch_buffer_size
= boost::lexical_cast
<size_t>( argv
[i
+1] );
798 num_headers
= batch_buffer_size
/ 16;
799 num_headers
= num_headers
> 0 ? num_headers
: 1;
802 if (arg
== "--rewire-probability")
803 p
= boost::lexical_cast
<double>( argv
[i
+1] );
805 if (arg
== "--num-sources")
806 num_sources
= boost::lexical_cast
<size_t>( argv
[i
+ 1] );
808 if (arg
== "--erdos-renyi")
811 if (arg
== "--small-world")
817 if (arg
== "--rmat-unique")
821 emit_dot_file
= true;
823 if (arg
== "--verify")
826 if (arg
== "--degree-dist")
827 show_degree_dist
= true;
829 if (arg
== "--sequential-graph")
830 sequential_graph
= true;
833 csr
= std::string(argv
[i
+1]) == "true";
835 if (arg
== "--adjacency-list")
836 adj_list
= std::string(argv
[i
+1]) == "true";
839 mpi_process_group
pg(num_headers
, batch_buffer_size
);
842 if (process_id(pg
) == 0)
849 parallel::variant_distribution
<mpi_process_group
> distrib
850 = parallel::block(pg
, n
);
853 if (process_id(pg
) == 0)
854 std::cerr
<< "CSR Graph Tests\n";
857 test_csr(pg
, gen
, distrib
, sequential_graph
, n
, m
, c
, num_sources
);
859 test_csr(pg
, gen
, distrib
, sequential_graph
, n
, m
, c
, p
, num_sources
);
861 test_csr(pg
, gen
, distrib
, sequential_graph
, n
, m
, c
,
862 rmat_a
, rmat_b
, rmat_c
, rmat_d
, num_sources
, rmat_edge_distribution_tag());
864 test_csr(pg
, gen
, distrib
, sequential_graph
, n
, m
, c
,
865 rmat_a
, rmat_b
, rmat_c
, rmat_d
, num_sources
, rmat_unique_edge_distribution_tag());
868 gen
.seed(seed
); // DEBUG
871 if (process_id(pg
) == 0)
872 std::cerr
<< "Adjacency List Graph Tests\n";
875 test_adjacency_list(pg
, gen
, distrib
, sequential_graph
, n
, m
, c
);
877 test_adjacency_list(pg
, gen
, distrib
, sequential_graph
, n
, m
, c
, p
);
879 test_adjacency_list(pg
, gen
, distrib
, sequential_graph
, n
, m
, c
,
880 rmat_a
, rmat_b
, rmat_c
, rmat_d
, rmat_edge_distribution_tag());
882 test_adjacency_list(pg
, gen
, distrib
, sequential_graph
, n
, m
, c
,
883 rmat_a
, rmat_b
, rmat_c
, rmat_d
, rmat_unique_edge_distribution_tag());