Chris@16
|
1 // Copyright (C) 2004-2008 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_DISTRIBUTED_DFS_HPP
|
Chris@16
|
10 #define BOOST_GRAPH_DISTRIBUTED_DFS_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/property_map/property_map.hpp>
|
Chris@16
|
18 #include <boost/graph/overloading.hpp>
|
Chris@16
|
19 #include <boost/graph/properties.hpp>
|
Chris@16
|
20 #include <boost/graph/distributed/concepts.hpp>
|
Chris@16
|
21 #include <boost/static_assert.hpp>
|
Chris@16
|
22 #include <boost/assert.hpp>
|
Chris@16
|
23 #include <boost/graph/parallel/process_group.hpp>
|
Chris@16
|
24 #include <boost/graph/parallel/container_traits.hpp>
|
Chris@16
|
25
|
Chris@16
|
26 namespace boost {
|
Chris@16
|
27 namespace graph { namespace distributed { namespace detail {
|
Chris@16
|
28 template<typename DistributedGraph, typename ColorMap, typename ParentMap,
|
Chris@16
|
29 typename ExploreMap, typename VertexIndexMap, typename DFSVisitor>
|
Chris@16
|
30 class parallel_dfs
|
Chris@16
|
31 {
|
Chris@16
|
32 typedef typename graph_traits<DistributedGraph>::vertex_iterator
|
Chris@16
|
33 vertex_iterator;
|
Chris@16
|
34 typedef typename graph_traits<DistributedGraph>::vertex_descriptor
|
Chris@16
|
35 vertex_descriptor;
|
Chris@16
|
36 typedef typename graph_traits<DistributedGraph>::out_edge_iterator
|
Chris@16
|
37 out_edge_iterator;
|
Chris@16
|
38
|
Chris@16
|
39 typedef typename boost::graph::parallel::process_group_type<DistributedGraph>
|
Chris@16
|
40 ::type process_group_type;
|
Chris@16
|
41 typedef typename process_group_type::process_id_type process_id_type;
|
Chris@16
|
42
|
Chris@16
|
43 /**
|
Chris@16
|
44 * The first vertex in the pair is the local node (i) and the
|
Chris@16
|
45 * second vertex in the pair is the (possibly remote) node (j).
|
Chris@16
|
46 */
|
Chris@16
|
47 typedef boost::parallel::detail::untracked_pair<vertex_descriptor, vertex_descriptor> vertex_pair;
|
Chris@16
|
48
|
Chris@16
|
49 typedef typename property_traits<ColorMap>::value_type color_type;
|
Chris@16
|
50 typedef color_traits<color_type> Color;
|
Chris@16
|
51
|
Chris@16
|
52 // Message types
|
Chris@16
|
53 enum { discover_msg = 10, return_msg = 50, visited_msg = 100 , done_msg = 150};
|
Chris@16
|
54
|
Chris@16
|
55
|
Chris@16
|
56 public:
|
Chris@16
|
57 parallel_dfs(const DistributedGraph& g, ColorMap color,
|
Chris@16
|
58 ParentMap parent, ExploreMap explore,
|
Chris@16
|
59 VertexIndexMap index_map, DFSVisitor vis)
|
Chris@16
|
60 : g(g), color(color), parent(parent), explore(explore),
|
Chris@16
|
61 index_map(index_map), vis(vis), pg(process_group(g)),
|
Chris@16
|
62 owner(get(vertex_owner, g)), next_out_edge(num_vertices(g))
|
Chris@16
|
63 { }
|
Chris@16
|
64
|
Chris@16
|
65 void run(vertex_descriptor s)
|
Chris@16
|
66 {
|
Chris@16
|
67 vertex_iterator vi, vi_end;
|
Chris@16
|
68 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
|
Chris@16
|
69 put(color, *vi, Color::white());
|
Chris@16
|
70 put(parent, *vi, *vi);
|
Chris@16
|
71 put(explore, *vi, *vi);
|
Chris@16
|
72 next_out_edge[get(index_map, *vi)] = out_edges(*vi, g).first;
|
Chris@16
|
73 vis.initialize_vertex(*vi, g);
|
Chris@16
|
74 }
|
Chris@16
|
75
|
Chris@16
|
76 vis.start_vertex(s, g);
|
Chris@16
|
77
|
Chris@16
|
78 if (get(owner, s) == process_id(pg)) {
|
Chris@16
|
79 send_oob(pg, get(owner, s), discover_msg, vertex_pair(s, s));
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 bool done = false;
|
Chris@16
|
83 while (!done) {
|
Chris@16
|
84 std::pair<process_id_type, int> msg = *pg.poll(true);
|
Chris@16
|
85
|
Chris@16
|
86 switch (msg.second) {
|
Chris@16
|
87 case discover_msg:
|
Chris@16
|
88 {
|
Chris@16
|
89 vertex_pair p;
|
Chris@16
|
90 receive_oob(pg, msg.first, msg.second, p);
|
Chris@16
|
91
|
Chris@16
|
92 if (p.first != p.second) {
|
Chris@16
|
93 // delete j from nomessage(j)
|
Chris@16
|
94 if (get(color, p.second) != Color::black())
|
Chris@16
|
95 local_put(color, p.second, Color::gray());
|
Chris@16
|
96
|
Chris@16
|
97 if (recover(p)) break;
|
Chris@16
|
98 }
|
Chris@16
|
99
|
Chris@16
|
100 if (get(color, p.first) == Color::white()) {
|
Chris@16
|
101 put(color, p.first, Color::gray());
|
Chris@16
|
102 put(parent, p.first, p.second);
|
Chris@16
|
103
|
Chris@16
|
104 vis.discover_vertex(p.first, g);
|
Chris@16
|
105
|
Chris@16
|
106 if (shift_center_of_activity(p.first)) break;
|
Chris@16
|
107
|
Chris@16
|
108 out_edge_iterator ei, ei_end;
|
Chris@16
|
109 for (boost::tie(ei,ei_end) = out_edges(p.first, g); ei != ei_end; ++ei)
|
Chris@16
|
110 {
|
Chris@16
|
111 // Notify everyone who may not know that the source
|
Chris@16
|
112 // vertex has been visited. They can then mark the
|
Chris@16
|
113 // corresponding color map entry gray.
|
Chris@16
|
114 if (get(parent, p.first) != target(*ei, g)
|
Chris@16
|
115 && get(explore, p.first) != target(*ei, g)) {
|
Chris@16
|
116 vertex_pair visit(target(*ei, g), p.first);
|
Chris@16
|
117
|
Chris@16
|
118 send_oob(pg, get(owner, target(*ei, g)), visited_msg, visit);
|
Chris@16
|
119 }
|
Chris@16
|
120 }
|
Chris@16
|
121 }
|
Chris@16
|
122 }
|
Chris@16
|
123 break;
|
Chris@16
|
124
|
Chris@16
|
125 case visited_msg:
|
Chris@16
|
126 {
|
Chris@16
|
127 vertex_pair p;
|
Chris@16
|
128 receive_oob(pg, msg.first, msg.second, p);
|
Chris@16
|
129
|
Chris@16
|
130 // delete j from nomessage(j)
|
Chris@16
|
131 if (get(color, p.second) != Color::black())
|
Chris@16
|
132 local_put(color, p.second, Color::gray());
|
Chris@16
|
133
|
Chris@16
|
134 recover(p);
|
Chris@16
|
135 }
|
Chris@16
|
136 break;
|
Chris@16
|
137
|
Chris@16
|
138 case return_msg:
|
Chris@16
|
139 {
|
Chris@16
|
140 vertex_pair p;
|
Chris@16
|
141 receive_oob(pg, msg.first, msg.second, p);
|
Chris@16
|
142
|
Chris@16
|
143 // delete j from nomessage(i)
|
Chris@16
|
144 local_put(color, p.second, Color::black());
|
Chris@16
|
145
|
Chris@16
|
146 shift_center_of_activity(p.first);
|
Chris@16
|
147 }
|
Chris@16
|
148 break;
|
Chris@16
|
149
|
Chris@16
|
150 case done_msg:
|
Chris@16
|
151 {
|
Chris@16
|
152 receive_oob(pg, msg.first, msg.second, done);
|
Chris@16
|
153
|
Chris@16
|
154 // Propagate done message downward in tree
|
Chris@16
|
155 done = true;
|
Chris@16
|
156 process_id_type id = process_id(pg);
|
Chris@16
|
157 process_id_type left = 2*id + 1;
|
Chris@16
|
158 process_id_type right = left + 1;
|
Chris@16
|
159 if (left < num_processes(pg))
|
Chris@16
|
160 send_oob(pg, left, done_msg, done);
|
Chris@16
|
161 if (right < num_processes(pg))
|
Chris@16
|
162 send_oob(pg, right, done_msg, done);
|
Chris@16
|
163 }
|
Chris@16
|
164 break;
|
Chris@16
|
165
|
Chris@16
|
166 default:
|
Chris@16
|
167 BOOST_ASSERT(false);
|
Chris@16
|
168 }
|
Chris@16
|
169 }
|
Chris@16
|
170 }
|
Chris@16
|
171
|
Chris@16
|
172 private:
|
Chris@16
|
173 bool recover(const vertex_pair& p)
|
Chris@16
|
174 {
|
Chris@16
|
175 if (get(explore, p.first) == p.second) {
|
Chris@16
|
176 return shift_center_of_activity(p.first);
|
Chris@16
|
177 }
|
Chris@16
|
178 else
|
Chris@16
|
179 return false;
|
Chris@16
|
180 }
|
Chris@16
|
181
|
Chris@16
|
182 bool shift_center_of_activity(vertex_descriptor i)
|
Chris@16
|
183 {
|
Chris@16
|
184 for (out_edge_iterator ei = next_out_edge[get(index_map, i)],
|
Chris@16
|
185 ei_end = out_edges(i, g).second;
|
Chris@16
|
186 ei != ei_end; ++ei) {
|
Chris@16
|
187 vis.examine_edge(*ei, g);
|
Chris@16
|
188
|
Chris@16
|
189 vertex_descriptor k = target(*ei, g);
|
Chris@16
|
190 color_type target_color = get(color, k);
|
Chris@16
|
191 if (target_color == Color::black()) vis.forward_or_cross_edge(*ei, g);
|
Chris@16
|
192 else if (target_color == Color::gray()) vis.back_edge(*ei, g);
|
Chris@16
|
193 else {
|
Chris@16
|
194 put(explore, i, k);
|
Chris@16
|
195 vis.tree_edge(*ei, g);
|
Chris@16
|
196 vertex_pair p(k, i);
|
Chris@16
|
197 send_oob(pg, get(owner, k), discover_msg, p);
|
Chris@16
|
198 next_out_edge[get(index_map, i)] = ++ei;
|
Chris@16
|
199 return false;
|
Chris@16
|
200 }
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 next_out_edge[get(index_map, i)] = out_edges(i, g).second;
|
Chris@16
|
204 put(explore, i, i);
|
Chris@16
|
205 put(color, i, Color::black());
|
Chris@16
|
206 vis.finish_vertex(i, g);
|
Chris@16
|
207
|
Chris@16
|
208 if (get(parent, i) == i) {
|
Chris@16
|
209 send_oob(pg, 0, done_msg, true);
|
Chris@16
|
210 return true;
|
Chris@16
|
211 }
|
Chris@16
|
212 else {
|
Chris@16
|
213 vertex_pair ret(get(parent, i), i);
|
Chris@16
|
214 send_oob(pg, get(owner, ret.first), return_msg, ret);
|
Chris@16
|
215 }
|
Chris@16
|
216 return false;
|
Chris@16
|
217 }
|
Chris@16
|
218
|
Chris@16
|
219 const DistributedGraph& g;
|
Chris@16
|
220 ColorMap color;
|
Chris@16
|
221 ParentMap parent;
|
Chris@16
|
222 ExploreMap explore;
|
Chris@16
|
223 VertexIndexMap index_map;
|
Chris@16
|
224 DFSVisitor vis;
|
Chris@16
|
225 process_group_type pg;
|
Chris@16
|
226 typename property_map<DistributedGraph, vertex_owner_t>::const_type owner;
|
Chris@16
|
227 std::vector<out_edge_iterator> next_out_edge;
|
Chris@16
|
228 };
|
Chris@16
|
229 } // end namespace detail
|
Chris@16
|
230
|
Chris@16
|
231 template<typename DistributedGraph, typename ColorMap, typename ParentMap,
|
Chris@16
|
232 typename ExploreMap, typename VertexIndexMap, typename DFSVisitor>
|
Chris@16
|
233 void
|
Chris@16
|
234 tsin_depth_first_visit
|
Chris@16
|
235 (const DistributedGraph& g,
|
Chris@16
|
236 typename graph_traits<DistributedGraph>::vertex_descriptor s,
|
Chris@16
|
237 DFSVisitor vis, ColorMap color, ParentMap parent, ExploreMap explore,
|
Chris@16
|
238 VertexIndexMap index_map)
|
Chris@16
|
239 {
|
Chris@16
|
240 typedef typename graph_traits<DistributedGraph>::directed_category
|
Chris@16
|
241 directed_category;
|
Chris@16
|
242 BOOST_STATIC_ASSERT(
|
Chris@16
|
243 (is_convertible<directed_category, undirected_tag>::value));
|
Chris@16
|
244
|
Chris@16
|
245 set_property_map_role(vertex_color, color);
|
Chris@16
|
246 graph::distributed::detail::parallel_dfs
|
Chris@16
|
247 <DistributedGraph, ColorMap, ParentMap, ExploreMap, VertexIndexMap,
|
Chris@16
|
248 DFSVisitor> do_dfs(g, color, parent, explore, index_map, vis);
|
Chris@16
|
249 do_dfs.run(s);
|
Chris@16
|
250
|
Chris@16
|
251 using boost::graph::parallel::process_group;
|
Chris@16
|
252 synchronize(process_group(g));
|
Chris@16
|
253 }
|
Chris@16
|
254
|
Chris@16
|
255 template<typename DistributedGraph, typename DFSVisitor,
|
Chris@16
|
256 typename VertexIndexMap>
|
Chris@16
|
257 void
|
Chris@16
|
258 tsin_depth_first_visit
|
Chris@16
|
259 (const DistributedGraph& g,
|
Chris@16
|
260 typename graph_traits<DistributedGraph>::vertex_descriptor s,
|
Chris@16
|
261 DFSVisitor vis,
|
Chris@16
|
262 VertexIndexMap index_map)
|
Chris@16
|
263 {
|
Chris@16
|
264 typedef typename graph_traits<DistributedGraph>::vertex_descriptor
|
Chris@16
|
265 vertex_descriptor;
|
Chris@16
|
266
|
Chris@16
|
267 std::vector<default_color_type> colors(num_vertices(g));
|
Chris@16
|
268 std::vector<vertex_descriptor> parent(num_vertices(g));
|
Chris@16
|
269 std::vector<vertex_descriptor> explore(num_vertices(g));
|
Chris@16
|
270 tsin_depth_first_visit
|
Chris@16
|
271 (g, s,
|
Chris@16
|
272 vis,
|
Chris@16
|
273 make_iterator_property_map(colors.begin(), index_map),
|
Chris@16
|
274 make_iterator_property_map(parent.begin(), index_map),
|
Chris@16
|
275 make_iterator_property_map(explore.begin(), index_map),
|
Chris@16
|
276 index_map);
|
Chris@16
|
277 }
|
Chris@16
|
278
|
Chris@16
|
279 template<typename DistributedGraph, typename DFSVisitor,
|
Chris@16
|
280 typename VertexIndexMap>
|
Chris@16
|
281 void
|
Chris@16
|
282 tsin_depth_first_visit
|
Chris@16
|
283 (const DistributedGraph& g,
|
Chris@16
|
284 typename graph_traits<DistributedGraph>::vertex_descriptor s,
|
Chris@16
|
285 DFSVisitor vis)
|
Chris@16
|
286 {
|
Chris@16
|
287 tsin_depth_first_visit(g, s, vis, get(vertex_index, g));
|
Chris@16
|
288 }
|
Chris@16
|
289 } // end namespace distributed
|
Chris@16
|
290
|
Chris@16
|
291 using distributed::tsin_depth_first_visit;
|
Chris@16
|
292
|
Chris@16
|
293 } // end namespace graph
|
Chris@16
|
294
|
Chris@16
|
295 template<typename DistributedGraph, typename DFSVisitor>
|
Chris@16
|
296 void
|
Chris@16
|
297 depth_first_visit
|
Chris@16
|
298 (const DistributedGraph& g,
|
Chris@16
|
299 typename graph_traits<DistributedGraph>::vertex_descriptor s,
|
Chris@16
|
300 DFSVisitor vis)
|
Chris@16
|
301 {
|
Chris@16
|
302 graph::tsin_depth_first_visit(g, s, vis, get(vertex_index, g));
|
Chris@16
|
303 }
|
Chris@16
|
304
|
Chris@16
|
305 } // end namespace boost
|
Chris@16
|
306
|
Chris@16
|
307 #endif // BOOST_GRAPH_DISTRIBUTED_DFS_HPP
|