]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | { | |
35 | explicit graph_id_writer(const Graph& g) : g(g) { } | |
36 | ||
37 | 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 | { | |
49 | explicit paint_by_number_writer(NumberMap number) : number(number) { } | |
50 | ||
51 | template<typename Descriptor> | |
52 | 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> | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 |