graphviz.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // Copyright (C) 2004-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: Douglas Gregor
  6. // Andrew Lumsdaine
  7. #ifndef BOOST_GRAPH_PARALLEL_GRAPHVIZ_HPP
  8. #define BOOST_GRAPH_PARALLEL_GRAPHVIZ_HPP
  9. #ifndef BOOST_GRAPH_USE_MPI
  10. #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
  11. #endif
  12. #include <boost/graph/graph_traits.hpp>
  13. #include <boost/graph/distributed/concepts.hpp>
  14. #include <boost/property_map/property_map.hpp>
  15. #include <boost/property_map/parallel/parallel_property_maps.hpp>
  16. #include <boost/graph/graphviz.hpp>
  17. #include <boost/type_traits/is_base_and_derived.hpp>
  18. #include <boost/type_traits/is_same.hpp>
  19. #include <fstream>
  20. #include <sstream>
  21. #include <iostream>
  22. #include <string>
  23. #include <boost/graph/parallel/container_traits.hpp>
  24. #include <boost/graph/parallel/process_group.hpp>
  25. #include <boost/property_map/parallel/global_index_map.hpp>
  26. namespace boost {
  27. template<typename Graph>
  28. struct graph_id_writer
  29. {
  30. explicit graph_id_writer(const Graph& g) : g(g) { }
  31. void operator()(std::ostream& out)
  32. {
  33. out << " label=\"p" << process_id(g.process_group()) << "\";\n";
  34. }
  35. private:
  36. const Graph& g;
  37. };
  38. template<typename NumberMap>
  39. struct paint_by_number_writer
  40. {
  41. explicit paint_by_number_writer(NumberMap number) : number(number) { }
  42. template<typename Descriptor>
  43. void operator()(std::ostream& out, Descriptor k)
  44. {
  45. static const char* color_names[] = {
  46. "blue",
  47. "brown",
  48. "cyan",
  49. "darkgreen",
  50. "darkorchid",
  51. "darksalmon",
  52. "darkviolet",
  53. "deeppink",
  54. "gold3",
  55. "green",
  56. "magenta",
  57. "navy",
  58. "red",
  59. "yellow",
  60. "palegreen",
  61. "gray65",
  62. "gray21",
  63. "bisque2",
  64. "greenyellow",
  65. "indianred4",
  66. "lightblue2",
  67. "mediumspringgreen",
  68. "orangered",
  69. "orange"
  70. };
  71. const int colors = sizeof(color_names) / sizeof(color_names[0]);
  72. if (get(number, k) < colors) {
  73. out << " [ style=\"filled\", fillcolor=\"" << color_names[get(number, k)]
  74. << "\" ]";
  75. } else {
  76. out << " [ label=\"(" << get(number, k) << ")\" ]";
  77. }
  78. }
  79. private:
  80. NumberMap number;
  81. };
  82. template<typename NumberMap>
  83. inline paint_by_number_writer<NumberMap>
  84. paint_by_number(NumberMap number)
  85. { return paint_by_number_writer<NumberMap>(number); }
  86. template<typename Graph, typename VertexPropertiesWriter,
  87. typename EdgePropertiesWriter, typename GraphPropertiesWriter>
  88. void
  89. write_graphviz(std::ostream& out,
  90. const Graph& g,
  91. VertexPropertiesWriter vpw,
  92. EdgePropertiesWriter epw,
  93. GraphPropertiesWriter gpw
  94. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  95. {
  96. typedef typename graph_traits<Graph>::directed_category directed_category;
  97. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  98. process_group_type;
  99. typedef typename property_map<Graph, vertex_index_t>::const_type
  100. VertexIndexMap;
  101. typedef typename property_map<Graph, vertex_global_t>::const_type
  102. VertexGlobalMap;
  103. static const bool is_undirected
  104. = (is_base_and_derived<undirected_tag, directed_category>::value
  105. || is_same<undirected_tag, directed_category>::value);
  106. static const char* graph_kind = is_undirected? "graph" : "digraph";
  107. static const char* edge_kind = is_undirected? "--" : "->";
  108. using boost::graph::parallel::process_group;
  109. process_group_type pg = process_group(g);
  110. parallel::global_index_map<VertexIndexMap, VertexGlobalMap>
  111. global_index(pg, num_vertices(g), get(vertex_index, g),
  112. get(vertex_global, g));
  113. std::ostringstream local_graph_out;
  114. local_graph_out << " subgraph cluster_" << process_id(pg) << " {\n";
  115. gpw(local_graph_out);
  116. typename graph_traits<Graph>::vertex_iterator vi, vi_end;
  117. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
  118. int global_idx = get(global_index, *vi);
  119. local_graph_out << " n" << global_idx;
  120. vpw(local_graph_out, *vi);
  121. local_graph_out << ";\n";
  122. }
  123. local_graph_out << " }\n\n";
  124. typename graph_traits<Graph>::edge_iterator ei, ei_end;
  125. for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
  126. int source_idx = get(global_index, source(*ei, g));
  127. int target_idx = get(global_index, target(*ei, g));
  128. local_graph_out << " n" << source_idx << " " << edge_kind << " n"
  129. << target_idx;
  130. epw(local_graph_out, *ei);
  131. local_graph_out << ";\n";
  132. }
  133. if (process_id(pg) == 0) {
  134. out << graph_kind << " g {\n";
  135. out << local_graph_out.str();
  136. synchronize(pg);
  137. for (int i = 1; i < num_processes(pg); ++i) {
  138. int len;
  139. receive(pg, i, 0, len);
  140. char* data = new char [len+1];
  141. data[len] = 0;
  142. receive(pg, i, 1, data, len);
  143. out << std::endl << data;
  144. delete [] data;
  145. }
  146. out << "}\n";
  147. } else {
  148. std::string result_str = local_graph_out.str();
  149. const char* data = result_str.c_str();
  150. int len = result_str.length();
  151. send(pg, 0, 0, len);
  152. send(pg, 0, 1, data, len);
  153. synchronize(pg);
  154. }
  155. synchronize(pg);
  156. synchronize(pg);
  157. synchronize(pg);
  158. }
  159. template<typename Graph, typename VertexPropertiesWriter,
  160. typename EdgePropertiesWriter>
  161. inline void
  162. write_graphviz(std::ostream& out,
  163. const Graph& g,
  164. VertexPropertiesWriter vpw,
  165. EdgePropertiesWriter epw
  166. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  167. {
  168. write_graphviz(out, g, vpw, epw, graph_id_writer<Graph>(g));
  169. }
  170. template<typename Graph, typename VertexPropertiesWriter>
  171. inline void
  172. write_graphviz(std::ostream& out,
  173. const Graph& g,
  174. VertexPropertiesWriter vpw
  175. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  176. {
  177. write_graphviz(out, g, vpw, default_writer());
  178. }
  179. template<typename Graph>
  180. inline void
  181. write_graphviz(std::ostream& out, const Graph& g
  182. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  183. {
  184. write_graphviz(out, g, default_writer());
  185. }
  186. template<typename Graph, typename VertexPropertiesWriter,
  187. typename EdgePropertiesWriter, typename GraphPropertiesWriter>
  188. void
  189. write_graphviz(const std::string& filename,
  190. const Graph& g,
  191. VertexPropertiesWriter vpw,
  192. EdgePropertiesWriter epw,
  193. GraphPropertiesWriter gpw
  194. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  195. {
  196. if (process_id(g.process_group()) == 0) {
  197. std::ofstream out(filename.c_str());
  198. write_graphviz(out, g, vpw, epw, gpw);
  199. } else {
  200. write_graphviz(std::cout, g, vpw, epw, gpw);
  201. }
  202. }
  203. template<typename Graph, typename VertexPropertiesWriter,
  204. typename EdgePropertiesWriter>
  205. void
  206. write_graphviz(const std::string& filename,
  207. const Graph& g,
  208. VertexPropertiesWriter vpw,
  209. EdgePropertiesWriter epw
  210. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  211. {
  212. if (process_id(g.process_group()) == 0) {
  213. std::ofstream out(filename.c_str());
  214. write_graphviz(out, g, vpw, epw);
  215. } else {
  216. write_graphviz(std::cout, g, vpw, epw);
  217. }
  218. }
  219. template<typename Graph, typename VertexPropertiesWriter>
  220. void
  221. write_graphviz(const std::string& filename,
  222. const Graph& g,
  223. VertexPropertiesWriter vpw
  224. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  225. {
  226. if (process_id(g.process_group()) == 0) {
  227. std::ofstream out(filename.c_str());
  228. write_graphviz(out, g, vpw);
  229. } else {
  230. write_graphviz(std::cout, g, vpw);
  231. }
  232. }
  233. template<typename Graph>
  234. void
  235. write_graphviz(const std::string& filename, const Graph& g
  236. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  237. {
  238. if (process_id(g.process_group()) == 0) {
  239. std::ofstream out(filename.c_str());
  240. write_graphviz(out, g);
  241. } else {
  242. write_graphviz(std::cout, g);
  243. }
  244. }
  245. template<typename Graph>
  246. void
  247. write_graphviz(std::ostream& out, const Graph& g,
  248. const dynamic_properties& dp,
  249. const std::string& node_id = "node_id"
  250. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag))
  251. {
  252. write_graphviz
  253. (out, g,
  254. /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id),
  255. /*edge_writer=*/dynamic_properties_writer(dp));
  256. }
  257. } // end namespace boost
  258. #endif // BOOST_GRAPH_PARALLEL_GRAPHVIZ_HPP