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