graphviz.hpp 8.5 KB

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