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