distributed_csr_algorithm_test.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. // Copyright (C) 2006 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Nick Edmonds
  6. // Andrew Lumsdaine
  7. // A test of the distributed compressed sparse row graph type
  8. #include <boost/graph/use_mpi.hpp>
  9. #include <boost/config.hpp>
  10. #include <boost/throw_exception.hpp>
  11. #include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
  12. #include <boost/graph/distributed/mpi_process_group.hpp>
  13. #include <boost/graph/distributed/concepts.hpp>
  14. #include <boost/graph/erdos_renyi_generator.hpp>
  15. #include <boost/graph/small_world_generator.hpp>
  16. #include <boost/graph/rmat_graph_generator.hpp>
  17. #include <boost/graph/breadth_first_search.hpp>
  18. #include <boost/graph/depth_first_search.hpp>
  19. #include <boost/graph/distributed/delta_stepping_shortest_paths.hpp>
  20. #include <boost/graph/dijkstra_shortest_paths.hpp>
  21. #include <boost/graph/distributed/page_rank.hpp>
  22. #include <boost/graph/distributed/boman_et_al_graph_coloring.hpp>
  23. #include <boost/graph/connected_components.hpp>
  24. #include <boost/graph/strong_components.hpp>
  25. #include <boost/graph/distributed/betweenness_centrality.hpp>
  26. #include <boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp>
  27. #include <boost/graph/distributed/st_connected.hpp>
  28. #if 0 // Contains internal AdjList types not present in CSR graph
  29. # include <boost/graph/distributed/connected_components_parallel_search.hpp>
  30. #endif
  31. #include <boost/graph/distributed/vertex_list_adaptor.hpp> // Needed for MST
  32. #include <boost/random/linear_congruential.hpp>
  33. #include <boost/graph/graphviz.hpp>
  34. #include <boost/property_map/vector_property_map.hpp>
  35. #include <boost/test/minimal.hpp>
  36. #ifdef BOOST_NO_EXCEPTIONS
  37. void
  38. boost::throw_exception(std::exception const& ex)
  39. {
  40. std::cout << ex.what() << std::endl;
  41. abort();
  42. }
  43. #endif
  44. /****************************************************************************
  45. * Edge weight generator iterator *
  46. ****************************************************************************/
  47. template<typename F, typename RandomGenerator>
  48. class generator_iterator
  49. {
  50. public:
  51. typedef std::input_iterator_tag iterator_category;
  52. typedef typename F::result_type value_type;
  53. typedef const value_type& reference;
  54. typedef const value_type* pointer;
  55. typedef void difference_type;
  56. explicit
  57. generator_iterator(RandomGenerator& gen, const F& f = F())
  58. : f(f), gen(&gen)
  59. {
  60. value = this->f(gen);
  61. }
  62. reference operator*() const { return value; }
  63. pointer operator->() const { return &value; }
  64. generator_iterator& operator++()
  65. {
  66. value = f(*gen);
  67. return *this;
  68. }
  69. generator_iterator operator++(int)
  70. {
  71. generator_iterator temp(*this);
  72. ++(*this);
  73. return temp;
  74. }
  75. bool operator==(const generator_iterator& other) const
  76. { return f == other.f; }
  77. bool operator!=(const generator_iterator& other) const
  78. { return !(*this == other); }
  79. private:
  80. F f;
  81. RandomGenerator* gen;
  82. value_type value;
  83. };
  84. template<typename F, typename RandomGenerator>
  85. inline generator_iterator<F, RandomGenerator>
  86. make_generator_iterator( RandomGenerator& gen, const F& f)
  87. { return generator_iterator<F, RandomGenerator>(gen, f); }
  88. /****************************************************************************
  89. * Printing DFS Visitor *
  90. ****************************************************************************/
  91. struct printing_dfs_visitor
  92. {
  93. template<typename Vertex, typename Graph>
  94. void initialize_vertex(Vertex v, const Graph& g)
  95. {
  96. vertex_event("initialize_vertex", v, g);
  97. }
  98. template<typename Vertex, typename Graph>
  99. void start_vertex(Vertex v, const Graph& g)
  100. {
  101. vertex_event("start_vertex", v, g);
  102. }
  103. template<typename Vertex, typename Graph>
  104. void discover_vertex(Vertex v, const Graph& g)
  105. {
  106. vertex_event("discover_vertex", v, g);
  107. }
  108. template<typename Edge, typename Graph>
  109. void examine_edge(Edge e, const Graph& g)
  110. {
  111. edge_event("examine_edge", e, g);
  112. }
  113. template<typename Edge, typename Graph>
  114. void tree_edge(Edge e, const Graph& g)
  115. {
  116. edge_event("tree_edge", e, g);
  117. }
  118. template<typename Edge, typename Graph>
  119. void back_edge(Edge e, const Graph& g)
  120. {
  121. edge_event("back_edge", e, g);
  122. }
  123. template<typename Edge, typename Graph>
  124. void forward_or_cross_edge(Edge e, const Graph& g)
  125. {
  126. edge_event("forward_or_cross_edge", e, g);
  127. }
  128. template<typename Vertex, typename Graph>
  129. void finish_vertex(Vertex v, const Graph& g)
  130. {
  131. vertex_event("finish_vertex", v, g);
  132. }
  133. private:
  134. template<typename Vertex, typename Graph>
  135. void vertex_event(const char* name, Vertex v, const Graph& g)
  136. {
  137. std::cerr << "#" << process_id(g.process_group()) << ": " << name << "("
  138. << get_vertex_name(v, g) << ": " << local(v) << "@" << owner(v)
  139. << ")\n";
  140. }
  141. template<typename Edge, typename Graph>
  142. void edge_event(const char* name, Edge e, const Graph& g)
  143. {
  144. std::cerr << "#" << process_id(g.process_group()) << ": " << name << "("
  145. << get_vertex_name(source(e, g), g) << ": "
  146. << local(source(e, g)) << "@" << owner(source(e, g)) << ", "
  147. << get_vertex_name(target(e, g), g) << ": "
  148. << local(target(e, g)) << "@" << owner(target(e, g)) << ")\n";
  149. }
  150. };
  151. using namespace boost;
  152. using boost::graph::distributed::mpi_process_group;
  153. typedef int weight_type;
  154. struct WeightedEdge {
  155. WeightedEdge(weight_type weight = 0) : weight(weight) { }
  156. weight_type weight;
  157. template<typename Archiver>
  158. void serialize(Archiver& ar, const unsigned int /*version*/)
  159. {
  160. ar & weight;
  161. }
  162. };
  163. struct VertexProperties {
  164. VertexProperties(int d = 0)
  165. : distance(d) { }
  166. int distance;
  167. template<typename Archiver>
  168. void serialize(Archiver& ar, const unsigned int /*version*/)
  169. {
  170. ar & distance;
  171. }
  172. };
  173. int test_main(int argc, char* argv[])
  174. {
  175. mpi::environment env(argc, argv);
  176. typedef compressed_sparse_row_graph<directedS, VertexProperties, WeightedEdge,
  177. no_property, distributedS<mpi_process_group> >
  178. Digraph;
  179. // Make sure we can build graphs using common graph generators
  180. typedef sorted_erdos_renyi_iterator<minstd_rand, Digraph> ERIter;
  181. typedef small_world_iterator<minstd_rand, Digraph> SWIter;
  182. typedef sorted_rmat_iterator<minstd_rand, Digraph> RMATIter;
  183. typedef graph_traits<Digraph>::edge_descriptor edge_descriptor;
  184. int n = 40;
  185. int k = 3;
  186. double prob = 0.1;
  187. int C = 10;
  188. double a = 0.5, b = 0.1, c = 0.25, d = 0.15;
  189. int iterations = 50;
  190. int num_colors = n / 10;
  191. int lookahead = C / 10;
  192. minstd_rand gen;
  193. // Directed Graphs
  194. Digraph g(ERIter(gen, n, prob), ERIter(),
  195. make_generator_iterator(gen, uniform_int<int>(0, C)),
  196. n);
  197. Digraph g2(SWIter(gen, n, k, prob), SWIter(), n);
  198. Digraph g3(RMATIter(gen, n, size_t(n*n*prob), a, b, c, d), RMATIter(), n);
  199. // Test BFS
  200. breadth_first_search(g, vertex(0, g), visitor(bfs_visitor<>()));
  201. // Test SSSP Algorithms
  202. graph::distributed::delta_stepping_shortest_paths(g,
  203. vertex(0, g),
  204. dummy_property_map(),
  205. get(&VertexProperties::distance, g),
  206. get(&WeightedEdge::weight, g));
  207. dijkstra_shortest_paths(g, vertex(0, g),
  208. distance_map(get(&VertexProperties::distance, g)).
  209. weight_map(get(&WeightedEdge::weight, g)));
  210. dijkstra_shortest_paths(g, vertex(0, g),
  211. distance_map(get(&VertexProperties::distance, g)).
  212. weight_map(get(&WeightedEdge::weight, g)).
  213. lookahead(lookahead));
  214. // Test PageRank
  215. using boost::graph::n_iterations;
  216. std::vector<double> ranks(num_vertices(g));
  217. page_rank(g,
  218. make_iterator_property_map(ranks.begin(),
  219. get(boost::vertex_index, g)),
  220. n_iterations(iterations), 0.85, vertex(0, g));
  221. // Test Graph Coloring
  222. typedef property_map<Digraph, vertex_index_t>::type vertex_index_map;
  223. std::vector<int> colors_vec(num_vertices(g));
  224. iterator_property_map<int*, vertex_index_map> color(&colors_vec[0],
  225. get(vertex_index, g));
  226. graph::boman_et_al_graph_coloring(g, color, num_colors);
  227. // Test DFS
  228. //
  229. // DFS requires an undirected graph, currently CSR graphs must be directed
  230. #if 0
  231. std::vector<vertex_descriptor> parent(num_vertices(g));
  232. std::vector<vertex_descriptor> explore(num_vertices(g));
  233. boost::graph::tsin_depth_first_visit
  234. (g,
  235. vertex(0, g),
  236. printing_dfs_visitor(),
  237. color,
  238. make_iterator_property_map(parent.begin(), get(vertex_index, g)),
  239. make_iterator_property_map(explore.begin(), get(vertex_index, g)),
  240. get(vertex_index, g));
  241. #endif
  242. // Test S-T Connected
  243. st_connected(g, vertex(0, g), vertex(1, g), color, get(vertex_owner, g));
  244. // Test Connected Components
  245. //
  246. // CC requires an undirected graph, currently CSR graphs must be directed
  247. #if 0
  248. std::vector<int> local_components_vec(num_vertices(g));
  249. typedef iterator_property_map<std::vector<int>::iterator,
  250. vertex_index_map> ComponentMap;
  251. ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
  252. assert(connected_components(g, component) ==
  253. connected_components_ps(g, component));
  254. #endif
  255. // Test Betweenness Centrality
  256. //
  257. // Betweenness Centrality is broken at the moment
  258. typedef iterator_property_map<std::vector<int>::iterator, vertex_index_map>
  259. CentralityMap;
  260. std::vector<int> centralityS(num_vertices(g), 0);
  261. CentralityMap centrality(centralityS.begin(), get(vertex_index, g));
  262. brandes_betweenness_centrality(g, centrality);
  263. //
  264. // Test MST
  265. //
  266. std::vector<edge_descriptor> mst_edges;
  267. dense_boruvka_minimum_spanning_tree(make_vertex_list_adaptor(g),
  268. get(&WeightedEdge::weight, g),
  269. std::back_inserter(mst_edges));
  270. mst_edges.clear();
  271. merge_local_minimum_spanning_trees(make_vertex_list_adaptor(g),
  272. get(&WeightedEdge::weight, g),
  273. std::back_inserter(mst_edges));
  274. mst_edges.clear();
  275. boruvka_then_merge(make_vertex_list_adaptor(g),
  276. get(&WeightedEdge::weight, g),
  277. std::back_inserter(mst_edges));
  278. mst_edges.clear();
  279. boruvka_mixed_merge(make_vertex_list_adaptor(g),
  280. get(&WeightedEdge::weight, g),
  281. std::back_inserter(mst_edges));
  282. // Test Strong Components
  283. //
  284. // Can't build reverse graph of a CSR graph
  285. #if 0
  286. std::vector<int> local_components_vec(num_vertices(g));
  287. typedef iterator_property_map<std::vector<int>::iterator,
  288. vertex_index_map> ComponentMap;
  289. ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
  290. int num_components = strong_components(g, component);
  291. #endif
  292. std::ofstream out("dcsr.dot");
  293. write_graphviz(out, g);
  294. return 0;
  295. }