Chris@16
|
1 // Copyright (C) 2004-2006 The Trustees of Indiana University.
|
Chris@16
|
2 // Copyright (C) 2007 Douglas Gregor
|
Chris@16
|
3
|
Chris@16
|
4 // Use, modification and distribution is subject to the Boost Software
|
Chris@16
|
5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7
|
Chris@16
|
8 // Authors: Douglas Gregor
|
Chris@16
|
9 // Andrew Lumsdaine
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
|
Chris@16
|
12 #define BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
|
Chris@16
|
13
|
Chris@16
|
14 #ifndef BOOST_GRAPH_USE_MPI
|
Chris@16
|
15 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
|
Chris@16
|
16 #endif
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/graph/adjacency_list.hpp>
|
Chris@16
|
19 #include <boost/graph/properties.hpp>
|
Chris@16
|
20 #include <boost/graph/graph_traits.hpp>
|
Chris@16
|
21 #include <boost/graph/iteration_macros.hpp>
|
Chris@16
|
22 #include <boost/graph/distributed/concepts.hpp>
|
Chris@16
|
23 #include <boost/iterator/transform_iterator.hpp>
|
Chris@16
|
24 #include <boost/property_map/property_map.hpp>
|
Chris@16
|
25 #include <boost/graph/adjacency_iterator.hpp>
|
Chris@16
|
26 #include <boost/property_map/parallel/distributed_property_map.hpp>
|
Chris@16
|
27 #include <boost/property_map/parallel/local_property_map.hpp>
|
Chris@16
|
28 #include <boost/graph/parallel/detail/property_holders.hpp>
|
Chris@16
|
29 #include <boost/mpl/if.hpp>
|
Chris@16
|
30 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
31 #include <boost/assert.hpp>
|
Chris@16
|
32 #include <list>
|
Chris@16
|
33 #include <algorithm>
|
Chris@16
|
34 #include <boost/limits.hpp>
|
Chris@16
|
35 #include <boost/graph/parallel/properties.hpp>
|
Chris@16
|
36 #include <boost/graph/parallel/distribution.hpp>
|
Chris@16
|
37 #include <boost/graph/parallel/algorithm.hpp>
|
Chris@16
|
38 #include <boost/graph/distributed/selector.hpp>
|
Chris@16
|
39 #include <boost/graph/parallel/process_group.hpp>
|
Chris@16
|
40 #include <boost/pending/container_traits.hpp>
|
Chris@16
|
41
|
Chris@16
|
42 // Callbacks
|
Chris@16
|
43 #include <boost/function/function2.hpp>
|
Chris@16
|
44
|
Chris@16
|
45 // Serialization
|
Chris@16
|
46 #include <boost/serialization/base_object.hpp>
|
Chris@16
|
47 #include <boost/mpi/datatype.hpp>
|
Chris@16
|
48 #include <boost/pending/property_serialize.hpp>
|
Chris@16
|
49 #include <boost/graph/distributed/unsafe_serialize.hpp>
|
Chris@16
|
50
|
Chris@16
|
51 // Named vertices
|
Chris@16
|
52 #include <boost/graph/distributed/named_graph.hpp>
|
Chris@16
|
53
|
Chris@16
|
54 #include <boost/graph/distributed/shuffled_distribution.hpp>
|
Chris@16
|
55
|
Chris@16
|
56 namespace boost {
|
Chris@16
|
57
|
Chris@16
|
58 /// The type used to store an identifier that uniquely names a processor.
|
Chris@16
|
59 // NGE: I doubt we'll be running on more than 32768 procs for the time being
|
Chris@16
|
60 typedef /*int*/ short processor_id_type;
|
Chris@16
|
61
|
Chris@16
|
62 // Tell which processor the target of an edge resides on (for
|
Chris@16
|
63 // directed graphs) or which processor the other end point of the
|
Chris@16
|
64 // edge resides on (for undirected graphs).
|
Chris@16
|
65 enum edge_target_processor_id_t { edge_target_processor_id };
|
Chris@16
|
66 BOOST_INSTALL_PROPERTY(edge, target_processor_id);
|
Chris@16
|
67
|
Chris@16
|
68 // For undirected graphs, tells whether the edge is locally owned.
|
Chris@16
|
69 enum edge_locally_owned_t { edge_locally_owned };
|
Chris@16
|
70 BOOST_INSTALL_PROPERTY(edge, locally_owned);
|
Chris@16
|
71
|
Chris@16
|
72 // For bidirectional graphs, stores the incoming edges.
|
Chris@16
|
73 enum vertex_in_edges_t { vertex_in_edges };
|
Chris@16
|
74 BOOST_INSTALL_PROPERTY(vertex, in_edges);
|
Chris@16
|
75
|
Chris@16
|
76 /// Tag class for directed, distributed adjacency list
|
Chris@16
|
77 struct directed_distributed_adj_list_tag
|
Chris@16
|
78 : public virtual distributed_graph_tag,
|
Chris@16
|
79 public virtual distributed_vertex_list_graph_tag,
|
Chris@16
|
80 public virtual distributed_edge_list_graph_tag,
|
Chris@16
|
81 public virtual incidence_graph_tag,
|
Chris@16
|
82 public virtual adjacency_graph_tag {};
|
Chris@16
|
83
|
Chris@16
|
84 /// Tag class for bidirectional, distributed adjacency list
|
Chris@16
|
85 struct bidirectional_distributed_adj_list_tag
|
Chris@16
|
86 : public virtual distributed_graph_tag,
|
Chris@16
|
87 public virtual distributed_vertex_list_graph_tag,
|
Chris@16
|
88 public virtual distributed_edge_list_graph_tag,
|
Chris@16
|
89 public virtual incidence_graph_tag,
|
Chris@16
|
90 public virtual adjacency_graph_tag,
|
Chris@16
|
91 public virtual bidirectional_graph_tag {};
|
Chris@16
|
92
|
Chris@16
|
93 /// Tag class for undirected, distributed adjacency list
|
Chris@16
|
94 struct undirected_distributed_adj_list_tag
|
Chris@16
|
95 : public virtual distributed_graph_tag,
|
Chris@16
|
96 public virtual distributed_vertex_list_graph_tag,
|
Chris@16
|
97 public virtual distributed_edge_list_graph_tag,
|
Chris@16
|
98 public virtual incidence_graph_tag,
|
Chris@16
|
99 public virtual adjacency_graph_tag,
|
Chris@16
|
100 public virtual bidirectional_graph_tag {};
|
Chris@16
|
101
|
Chris@16
|
102 namespace detail {
|
Chris@16
|
103 template<typename Archiver, typename Directed, typename Vertex>
|
Chris@16
|
104 void
|
Chris@16
|
105 serialize(Archiver& ar, edge_base<Directed, Vertex>& e,
|
Chris@16
|
106 const unsigned int /*version*/)
|
Chris@16
|
107 {
|
Chris@16
|
108 ar & unsafe_serialize(e.m_source)
|
Chris@16
|
109 & unsafe_serialize(e.m_target);
|
Chris@16
|
110 }
|
Chris@16
|
111
|
Chris@16
|
112 template<typename Archiver, typename Directed, typename Vertex>
|
Chris@16
|
113 void
|
Chris@16
|
114 serialize(Archiver& ar, edge_desc_impl<Directed, Vertex>& e,
|
Chris@16
|
115 const unsigned int /*version*/)
|
Chris@16
|
116 {
|
Chris@16
|
117 ar & boost::serialization::base_object<edge_base<Directed, Vertex> >(e)
|
Chris@16
|
118 & unsafe_serialize(e.m_eproperty);
|
Chris@16
|
119 }
|
Chris@16
|
120 }
|
Chris@16
|
121
|
Chris@16
|
122 namespace detail { namespace parallel {
|
Chris@16
|
123
|
Chris@16
|
124 /**
|
Chris@16
|
125 * A distributed vertex descriptor. These descriptors contain both
|
Chris@16
|
126 * the ID of the processor that owns the vertex and a local vertex
|
Chris@16
|
127 * descriptor that identifies the particular vertex for that
|
Chris@16
|
128 * processor.
|
Chris@16
|
129 */
|
Chris@16
|
130 template<typename LocalDescriptor>
|
Chris@16
|
131 struct global_descriptor
|
Chris@16
|
132 {
|
Chris@16
|
133 typedef LocalDescriptor local_descriptor_type;
|
Chris@16
|
134
|
Chris@16
|
135 global_descriptor() : owner(), local() { }
|
Chris@16
|
136
|
Chris@16
|
137 global_descriptor(processor_id_type owner, LocalDescriptor local)
|
Chris@16
|
138 : owner(owner), local(local) { }
|
Chris@16
|
139
|
Chris@16
|
140 processor_id_type owner;
|
Chris@16
|
141 LocalDescriptor local;
|
Chris@16
|
142
|
Chris@16
|
143 /**
|
Chris@16
|
144 * A function object that, given a processor ID, generates
|
Chris@16
|
145 * distributed vertex descriptors from local vertex
|
Chris@16
|
146 * descriptors. This function object is used by the
|
Chris@16
|
147 * vertex_iterator of the distributed adjacency list.
|
Chris@16
|
148 */
|
Chris@16
|
149 struct generator
|
Chris@16
|
150 {
|
Chris@16
|
151 typedef global_descriptor<LocalDescriptor> result_type;
|
Chris@16
|
152 typedef LocalDescriptor argument_type;
|
Chris@16
|
153
|
Chris@16
|
154 generator() {}
|
Chris@16
|
155 generator(processor_id_type owner) : owner(owner) {}
|
Chris@16
|
156
|
Chris@16
|
157 result_type operator()(argument_type v) const
|
Chris@16
|
158 { return result_type(owner, v); }
|
Chris@16
|
159
|
Chris@16
|
160 private:
|
Chris@16
|
161 processor_id_type owner;
|
Chris@16
|
162 };
|
Chris@16
|
163
|
Chris@16
|
164 template<typename Archiver>
|
Chris@16
|
165 void serialize(Archiver& ar, const unsigned int /*version*/)
|
Chris@16
|
166 {
|
Chris@16
|
167 ar & owner & unsafe_serialize(local);
|
Chris@16
|
168 }
|
Chris@16
|
169 };
|
Chris@16
|
170
|
Chris@16
|
171 /// Determine the process that owns the given descriptor
|
Chris@16
|
172 template<typename LocalDescriptor>
|
Chris@16
|
173 inline processor_id_type owner(const global_descriptor<LocalDescriptor>& v)
|
Chris@16
|
174 { return v.owner; }
|
Chris@16
|
175
|
Chris@16
|
176 /// Determine the local portion of the given descriptor
|
Chris@16
|
177 template<typename LocalDescriptor>
|
Chris@16
|
178 inline LocalDescriptor local(const global_descriptor<LocalDescriptor>& v)
|
Chris@16
|
179 { return v.local; }
|
Chris@16
|
180
|
Chris@16
|
181 /// Compare distributed vertex descriptors for equality
|
Chris@16
|
182 template<typename LocalDescriptor>
|
Chris@16
|
183 inline bool
|
Chris@16
|
184 operator==(const global_descriptor<LocalDescriptor>& u,
|
Chris@16
|
185 const global_descriptor<LocalDescriptor>& v)
|
Chris@16
|
186 {
|
Chris@16
|
187 return u.owner == v.owner && u.local == v.local;
|
Chris@16
|
188 }
|
Chris@16
|
189
|
Chris@16
|
190 /// Compare distributed vertex descriptors for inequality
|
Chris@16
|
191 template<typename LocalDescriptor>
|
Chris@16
|
192 inline bool
|
Chris@16
|
193 operator!=(const global_descriptor<LocalDescriptor>& u,
|
Chris@16
|
194 const global_descriptor<LocalDescriptor>& v)
|
Chris@16
|
195 { return !(u == v); }
|
Chris@16
|
196
|
Chris@16
|
197 template<typename LocalDescriptor>
|
Chris@16
|
198 inline bool
|
Chris@16
|
199 operator<(const global_descriptor<LocalDescriptor>& u,
|
Chris@16
|
200 const global_descriptor<LocalDescriptor>& v)
|
Chris@16
|
201 {
|
Chris@16
|
202 return (u.owner) < v.owner || (u.owner == v.owner && (u.local) < v.local);
|
Chris@16
|
203 }
|
Chris@16
|
204
|
Chris@16
|
205 template<typename LocalDescriptor>
|
Chris@16
|
206 inline bool
|
Chris@16
|
207 operator<=(const global_descriptor<LocalDescriptor>& u,
|
Chris@16
|
208 const global_descriptor<LocalDescriptor>& v)
|
Chris@16
|
209 {
|
Chris@16
|
210 return u.owner <= v.owner || (u.owner == v.owner && u.local <= v.local);
|
Chris@16
|
211 }
|
Chris@16
|
212
|
Chris@16
|
213 template<typename LocalDescriptor>
|
Chris@16
|
214 inline bool
|
Chris@16
|
215 operator>(const global_descriptor<LocalDescriptor>& u,
|
Chris@16
|
216 const global_descriptor<LocalDescriptor>& v)
|
Chris@16
|
217 {
|
Chris@16
|
218 return v < u;
|
Chris@16
|
219 }
|
Chris@16
|
220
|
Chris@16
|
221 template<typename LocalDescriptor>
|
Chris@16
|
222 inline bool
|
Chris@16
|
223 operator>=(const global_descriptor<LocalDescriptor>& u,
|
Chris@16
|
224 const global_descriptor<LocalDescriptor>& v)
|
Chris@16
|
225 {
|
Chris@16
|
226 return v <= u;
|
Chris@16
|
227 }
|
Chris@16
|
228
|
Chris@16
|
229 // DPG TBD: Add <, <=, >=, > for global descriptors
|
Chris@16
|
230
|
Chris@16
|
231 /**
|
Chris@16
|
232 * A Readable Property Map that extracts a global descriptor pair
|
Chris@16
|
233 * from a global_descriptor.
|
Chris@16
|
234 */
|
Chris@16
|
235 template<typename LocalDescriptor>
|
Chris@16
|
236 struct global_descriptor_property_map
|
Chris@16
|
237 {
|
Chris@16
|
238 typedef std::pair<processor_id_type, LocalDescriptor> value_type;
|
Chris@16
|
239 typedef value_type reference;
|
Chris@16
|
240 typedef global_descriptor<LocalDescriptor> key_type;
|
Chris@16
|
241 typedef readable_property_map_tag category;
|
Chris@16
|
242 };
|
Chris@16
|
243
|
Chris@16
|
244 template<typename LocalDescriptor>
|
Chris@16
|
245 inline std::pair<processor_id_type, LocalDescriptor>
|
Chris@16
|
246 get(global_descriptor_property_map<LocalDescriptor>,
|
Chris@16
|
247 global_descriptor<LocalDescriptor> x)
|
Chris@16
|
248 {
|
Chris@16
|
249 return std::pair<processor_id_type, LocalDescriptor>(x.owner, x.local);
|
Chris@16
|
250 }
|
Chris@16
|
251
|
Chris@16
|
252 /**
|
Chris@16
|
253 * A Readable Property Map that extracts the owner of a global
|
Chris@16
|
254 * descriptor.
|
Chris@16
|
255 */
|
Chris@16
|
256 template<typename LocalDescriptor>
|
Chris@16
|
257 struct owner_property_map
|
Chris@16
|
258 {
|
Chris@16
|
259 typedef processor_id_type value_type;
|
Chris@16
|
260 typedef value_type reference;
|
Chris@16
|
261 typedef global_descriptor<LocalDescriptor> key_type;
|
Chris@16
|
262 typedef readable_property_map_tag category;
|
Chris@16
|
263 };
|
Chris@16
|
264
|
Chris@16
|
265 template<typename LocalDescriptor>
|
Chris@16
|
266 inline processor_id_type
|
Chris@16
|
267 get(owner_property_map<LocalDescriptor>,
|
Chris@16
|
268 global_descriptor<LocalDescriptor> x)
|
Chris@16
|
269 {
|
Chris@16
|
270 return x.owner;
|
Chris@16
|
271 }
|
Chris@16
|
272
|
Chris@16
|
273 /**
|
Chris@16
|
274 * A Readable Property Map that extracts the local descriptor from
|
Chris@16
|
275 * a global descriptor.
|
Chris@16
|
276 */
|
Chris@16
|
277 template<typename LocalDescriptor>
|
Chris@16
|
278 struct local_descriptor_property_map
|
Chris@16
|
279 {
|
Chris@16
|
280 typedef LocalDescriptor value_type;
|
Chris@16
|
281 typedef value_type reference;
|
Chris@16
|
282 typedef global_descriptor<LocalDescriptor> key_type;
|
Chris@16
|
283 typedef readable_property_map_tag category;
|
Chris@16
|
284 };
|
Chris@16
|
285
|
Chris@16
|
286 template<typename LocalDescriptor>
|
Chris@16
|
287 inline LocalDescriptor
|
Chris@16
|
288 get(local_descriptor_property_map<LocalDescriptor>,
|
Chris@16
|
289 global_descriptor<LocalDescriptor> x)
|
Chris@16
|
290 {
|
Chris@16
|
291 return x.local;
|
Chris@16
|
292 }
|
Chris@16
|
293
|
Chris@16
|
294 /**
|
Chris@16
|
295 * Stores an incoming edge for a bidirectional distributed
|
Chris@16
|
296 * adjacency list. The user does not see this type directly,
|
Chris@16
|
297 * because it is just an implementation detail.
|
Chris@16
|
298 */
|
Chris@16
|
299 template<typename Edge>
|
Chris@16
|
300 struct stored_in_edge
|
Chris@16
|
301 {
|
Chris@16
|
302 stored_in_edge(processor_id_type sp, Edge e)
|
Chris@16
|
303 : source_processor(sp), e(e) {}
|
Chris@16
|
304
|
Chris@16
|
305 processor_id_type source_processor;
|
Chris@16
|
306 Edge e;
|
Chris@16
|
307 };
|
Chris@16
|
308
|
Chris@16
|
309 /**
|
Chris@16
|
310 * A distributed edge descriptor. These descriptors contain the
|
Chris@16
|
311 * underlying edge descriptor, the processor IDs for both the
|
Chris@16
|
312 * source and the target of the edge, and a boolean flag that
|
Chris@16
|
313 * indicates which of the processors actually owns the edge.
|
Chris@16
|
314 */
|
Chris@16
|
315 template<typename Edge>
|
Chris@16
|
316 struct edge_descriptor
|
Chris@16
|
317 {
|
Chris@16
|
318 edge_descriptor(processor_id_type sp = processor_id_type(),
|
Chris@16
|
319 processor_id_type tp = processor_id_type(),
|
Chris@16
|
320 bool owns = false, Edge ld = Edge())
|
Chris@16
|
321 : source_processor(sp), target_processor(tp),
|
Chris@16
|
322 source_owns_edge(owns), local(ld) {}
|
Chris@16
|
323
|
Chris@16
|
324 processor_id_type owner() const
|
Chris@16
|
325 {
|
Chris@16
|
326 return source_owns_edge? source_processor : target_processor;
|
Chris@16
|
327 }
|
Chris@16
|
328
|
Chris@16
|
329 /// The processor that the source vertex resides on
|
Chris@16
|
330 processor_id_type source_processor;
|
Chris@16
|
331
|
Chris@16
|
332 /// The processor that the target vertex resides on
|
Chris@16
|
333 processor_id_type target_processor;
|
Chris@16
|
334
|
Chris@16
|
335 /// True when the source processor owns the edge, false when the
|
Chris@16
|
336 /// target processor owns the edge.
|
Chris@16
|
337 bool source_owns_edge;
|
Chris@16
|
338
|
Chris@16
|
339 /// The local edge descriptor.
|
Chris@16
|
340 Edge local;
|
Chris@16
|
341
|
Chris@16
|
342 /**
|
Chris@16
|
343 * Function object that generates edge descriptors for the
|
Chris@16
|
344 * out_edge_iterator of the given distributed adjacency list
|
Chris@16
|
345 * from the edge descriptors of the underlying adjacency list.
|
Chris@16
|
346 */
|
Chris@16
|
347 template<typename Graph>
|
Chris@16
|
348 class out_generator
|
Chris@16
|
349 {
|
Chris@16
|
350 typedef typename Graph::directed_selector directed_selector;
|
Chris@16
|
351
|
Chris@16
|
352 public:
|
Chris@16
|
353 typedef edge_descriptor<Edge> result_type;
|
Chris@16
|
354 typedef Edge argument_type;
|
Chris@16
|
355
|
Chris@16
|
356 out_generator() : g(0) {}
|
Chris@16
|
357 explicit out_generator(const Graph& g) : g(&g) {}
|
Chris@16
|
358
|
Chris@16
|
359 result_type operator()(argument_type e) const
|
Chris@16
|
360 { return map(e, directed_selector()); }
|
Chris@16
|
361
|
Chris@16
|
362 private:
|
Chris@16
|
363 result_type map(argument_type e, directedS) const
|
Chris@16
|
364 {
|
Chris@16
|
365 return result_type(g->processor(),
|
Chris@16
|
366 get(edge_target_processor_id, g->base(), e),
|
Chris@16
|
367 true, e);
|
Chris@16
|
368 }
|
Chris@16
|
369
|
Chris@16
|
370 result_type map(argument_type e, bidirectionalS) const
|
Chris@16
|
371 {
|
Chris@16
|
372 return result_type(g->processor(),
|
Chris@16
|
373 get(edge_target_processor_id, g->base(), e),
|
Chris@16
|
374 true, e);
|
Chris@16
|
375 }
|
Chris@16
|
376
|
Chris@16
|
377 result_type map(argument_type e, undirectedS) const
|
Chris@16
|
378 {
|
Chris@16
|
379 return result_type(g->processor(),
|
Chris@16
|
380 get(edge_target_processor_id, g->base(), e),
|
Chris@16
|
381 get(edge_locally_owned, g->base(), e),
|
Chris@16
|
382 e);
|
Chris@16
|
383 }
|
Chris@16
|
384
|
Chris@16
|
385 const Graph* g;
|
Chris@16
|
386 };
|
Chris@16
|
387
|
Chris@16
|
388 /**
|
Chris@16
|
389 * Function object that generates edge descriptors for the
|
Chris@16
|
390 * in_edge_iterator of the given distributed adjacency list
|
Chris@16
|
391 * from the edge descriptors of the underlying adjacency list.
|
Chris@16
|
392 */
|
Chris@16
|
393 template<typename Graph>
|
Chris@16
|
394 class in_generator
|
Chris@16
|
395 {
|
Chris@16
|
396 typedef typename Graph::directed_selector DirectedS;
|
Chris@16
|
397
|
Chris@16
|
398 public:
|
Chris@16
|
399 typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
|
Chris@16
|
400 stored_in_edge<Edge>,
|
Chris@16
|
401 Edge>::type argument_type;
|
Chris@16
|
402 typedef edge_descriptor<Edge> result_type;
|
Chris@16
|
403
|
Chris@16
|
404 in_generator() : g(0) {}
|
Chris@16
|
405 explicit in_generator(const Graph& g) : g(&g) {}
|
Chris@16
|
406
|
Chris@16
|
407 result_type operator()(argument_type e) const
|
Chris@16
|
408 { return map(e, DirectedS()); }
|
Chris@16
|
409
|
Chris@16
|
410 private:
|
Chris@16
|
411 /**
|
Chris@16
|
412 * For a bidirectional graph, we just generate the appropriate
|
Chris@16
|
413 * edge. No tricks.
|
Chris@16
|
414 */
|
Chris@16
|
415 result_type map(argument_type e, bidirectionalS) const
|
Chris@16
|
416 {
|
Chris@16
|
417 return result_type(e.source_processor,
|
Chris@16
|
418 g->processor(),
|
Chris@16
|
419 true,
|
Chris@16
|
420 e.e);
|
Chris@16
|
421 }
|
Chris@16
|
422
|
Chris@16
|
423 /**
|
Chris@16
|
424 * For an undirected graph, we generate descriptors for the
|
Chris@16
|
425 * incoming edges by swapping the source/target of the
|
Chris@16
|
426 * underlying edge descriptor (a hack). The target processor
|
Chris@16
|
427 * ID on the edge is actually the source processor for this
|
Chris@16
|
428 * edge, and our processor is the target processor. If the
|
Chris@16
|
429 * edge is locally owned, then it is owned by the target (us);
|
Chris@16
|
430 * otherwise it is owned by the source.
|
Chris@16
|
431 */
|
Chris@16
|
432 result_type map(argument_type e, undirectedS) const
|
Chris@16
|
433 {
|
Chris@16
|
434 typename Graph::local_edge_descriptor local_edge(e);
|
Chris@16
|
435 // TBD: This is a very, VERY lame hack that takes advantage
|
Chris@16
|
436 // of our knowledge of the internals of the BGL
|
Chris@16
|
437 // adjacency_list. There should be a cleaner way to handle
|
Chris@16
|
438 // this...
|
Chris@16
|
439 using std::swap;
|
Chris@16
|
440 swap(local_edge.m_source, local_edge.m_target);
|
Chris@16
|
441 return result_type(get(edge_target_processor_id, g->base(), e),
|
Chris@16
|
442 g->processor(),
|
Chris@16
|
443 !get(edge_locally_owned, g->base(), e),
|
Chris@16
|
444 local_edge);
|
Chris@16
|
445 }
|
Chris@16
|
446
|
Chris@16
|
447 const Graph* g;
|
Chris@16
|
448 };
|
Chris@16
|
449
|
Chris@16
|
450 private:
|
Chris@16
|
451 friend class boost::serialization::access;
|
Chris@16
|
452
|
Chris@16
|
453 template<typename Archiver>
|
Chris@16
|
454 void serialize(Archiver& ar, const unsigned int /*version*/)
|
Chris@16
|
455 {
|
Chris@16
|
456 ar
|
Chris@16
|
457 & source_processor
|
Chris@16
|
458 & target_processor
|
Chris@16
|
459 & source_owns_edge
|
Chris@16
|
460 & local;
|
Chris@16
|
461 }
|
Chris@16
|
462 };
|
Chris@16
|
463
|
Chris@16
|
464 /// Determine the process that owns this edge
|
Chris@16
|
465 template<typename Edge>
|
Chris@16
|
466 inline processor_id_type
|
Chris@16
|
467 owner(const edge_descriptor<Edge>& e)
|
Chris@16
|
468 { return e.source_owns_edge? e.source_processor : e.target_processor; }
|
Chris@16
|
469
|
Chris@16
|
470 /// Determine the local descriptor for this edge.
|
Chris@16
|
471 template<typename Edge>
|
Chris@16
|
472 inline Edge
|
Chris@16
|
473 local(const edge_descriptor<Edge>& e)
|
Chris@16
|
474 { return e.local; }
|
Chris@16
|
475
|
Chris@16
|
476 /**
|
Chris@16
|
477 * A Readable Property Map that extracts the owner and local
|
Chris@16
|
478 * descriptor of an edge descriptor.
|
Chris@16
|
479 */
|
Chris@16
|
480 template<typename Edge>
|
Chris@16
|
481 struct edge_global_property_map
|
Chris@16
|
482 {
|
Chris@16
|
483 typedef std::pair<processor_id_type, Edge> value_type;
|
Chris@16
|
484 typedef value_type reference;
|
Chris@16
|
485 typedef edge_descriptor<Edge> key_type;
|
Chris@16
|
486 typedef readable_property_map_tag category;
|
Chris@16
|
487 };
|
Chris@16
|
488
|
Chris@16
|
489 template<typename Edge>
|
Chris@16
|
490 inline std::pair<processor_id_type, Edge>
|
Chris@16
|
491 get(edge_global_property_map<Edge>, const edge_descriptor<Edge>& e)
|
Chris@16
|
492 {
|
Chris@16
|
493 typedef std::pair<processor_id_type, Edge> result_type;
|
Chris@16
|
494 return result_type(e.source_owns_edge? e.source_processor
|
Chris@16
|
495 /* target owns edge*/: e.target_processor,
|
Chris@16
|
496 e.local);
|
Chris@16
|
497 }
|
Chris@16
|
498
|
Chris@16
|
499 /**
|
Chris@16
|
500 * A Readable Property Map that extracts the owner of an edge
|
Chris@16
|
501 * descriptor.
|
Chris@16
|
502 */
|
Chris@16
|
503 template<typename Edge>
|
Chris@16
|
504 struct edge_owner_property_map
|
Chris@16
|
505 {
|
Chris@16
|
506 typedef processor_id_type value_type;
|
Chris@16
|
507 typedef value_type reference;
|
Chris@16
|
508 typedef edge_descriptor<Edge> key_type;
|
Chris@16
|
509 typedef readable_property_map_tag category;
|
Chris@16
|
510 };
|
Chris@16
|
511
|
Chris@16
|
512 template<typename Edge>
|
Chris@16
|
513 inline processor_id_type
|
Chris@16
|
514 get(edge_owner_property_map<Edge>, const edge_descriptor<Edge>& e)
|
Chris@16
|
515 {
|
Chris@16
|
516 return e.source_owns_edge? e.source_processor : e.target_processor;
|
Chris@16
|
517 }
|
Chris@16
|
518
|
Chris@16
|
519 /**
|
Chris@16
|
520 * A Readable Property Map that extracts the local descriptor from
|
Chris@16
|
521 * an edge descriptor.
|
Chris@16
|
522 */
|
Chris@16
|
523 template<typename Edge>
|
Chris@16
|
524 struct edge_local_property_map
|
Chris@16
|
525 {
|
Chris@16
|
526 typedef Edge value_type;
|
Chris@16
|
527 typedef value_type reference;
|
Chris@16
|
528 typedef edge_descriptor<Edge> key_type;
|
Chris@16
|
529 typedef readable_property_map_tag category;
|
Chris@16
|
530 };
|
Chris@16
|
531
|
Chris@16
|
532 template<typename Edge>
|
Chris@16
|
533 inline Edge
|
Chris@16
|
534 get(edge_local_property_map<Edge>,
|
Chris@16
|
535 const edge_descriptor<Edge>& e)
|
Chris@16
|
536 {
|
Chris@16
|
537 return e.local;
|
Chris@16
|
538 }
|
Chris@16
|
539
|
Chris@16
|
540 /** Compare distributed edge descriptors for equality.
|
Chris@16
|
541 *
|
Chris@16
|
542 * \todo need edge_descriptor to know if it is undirected so we
|
Chris@16
|
543 * can compare both ways.
|
Chris@16
|
544 */
|
Chris@16
|
545 template<typename Edge>
|
Chris@16
|
546 inline bool
|
Chris@16
|
547 operator==(const edge_descriptor<Edge>& e1,
|
Chris@16
|
548 const edge_descriptor<Edge>& e2)
|
Chris@16
|
549 {
|
Chris@16
|
550 return (e1.source_processor == e2.source_processor
|
Chris@16
|
551 && e1.target_processor == e2.target_processor
|
Chris@16
|
552 && e1.local == e2.local);
|
Chris@16
|
553 }
|
Chris@16
|
554
|
Chris@16
|
555 /// Compare distributed edge descriptors for inequality.
|
Chris@16
|
556 template<typename Edge>
|
Chris@16
|
557 inline bool
|
Chris@16
|
558 operator!=(const edge_descriptor<Edge>& e1,
|
Chris@16
|
559 const edge_descriptor<Edge>& e2)
|
Chris@16
|
560 { return !(e1 == e2); }
|
Chris@16
|
561
|
Chris@16
|
562 /**
|
Chris@16
|
563 * Configuration for the distributed adjacency list. We use this
|
Chris@16
|
564 * parameter to store all of the configuration details for the
|
Chris@16
|
565 * implementation of the distributed adjacency list, which allows us to
|
Chris@16
|
566 * get at the distribution type in the maybe_named_graph.
|
Chris@16
|
567 */
|
Chris@16
|
568 template<typename OutEdgeListS, typename ProcessGroup,
|
Chris@16
|
569 typename InVertexListS, typename InDistribution,
|
Chris@16
|
570 typename DirectedS, typename VertexProperty,
|
Chris@16
|
571 typename EdgeProperty, typename GraphProperty,
|
Chris@16
|
572 typename EdgeListS>
|
Chris@16
|
573 struct adjacency_list_config
|
Chris@16
|
574 {
|
Chris@16
|
575 typedef typename mpl::if_<is_same<InVertexListS, defaultS>,
|
Chris@16
|
576 vecS, InVertexListS>::type
|
Chris@16
|
577 VertexListS;
|
Chris@16
|
578
|
Chris@16
|
579 /// Introduce the target processor ID property for each edge
|
Chris@16
|
580 typedef property<edge_target_processor_id_t, processor_id_type,
|
Chris@16
|
581 EdgeProperty> edge_property_with_id;
|
Chris@16
|
582
|
Chris@16
|
583 /// For undirected graphs, introduce the locally-owned property for edges
|
Chris@16
|
584 typedef typename boost::mpl::if_<is_same<DirectedS, undirectedS>,
|
Chris@16
|
585 property<edge_locally_owned_t, bool,
|
Chris@16
|
586 edge_property_with_id>,
|
Chris@16
|
587 edge_property_with_id>::type
|
Chris@16
|
588 base_edge_property_type;
|
Chris@16
|
589
|
Chris@16
|
590 /// The edge descriptor type for the local subgraph
|
Chris@16
|
591 typedef typename adjacency_list_traits<OutEdgeListS,
|
Chris@16
|
592 VertexListS,
|
Chris@16
|
593 directedS>::edge_descriptor
|
Chris@16
|
594 local_edge_descriptor;
|
Chris@16
|
595
|
Chris@16
|
596 /// For bidirectional graphs, the type of an incoming stored edge
|
Chris@16
|
597 typedef stored_in_edge<local_edge_descriptor> bidir_stored_edge;
|
Chris@16
|
598
|
Chris@16
|
599 /// The container type that will store incoming edges for a
|
Chris@16
|
600 /// bidirectional graph.
|
Chris@16
|
601 typedef typename container_gen<EdgeListS, bidir_stored_edge>::type
|
Chris@16
|
602 in_edge_list_type;
|
Chris@16
|
603
|
Chris@16
|
604 // Bidirectional graphs have an extra vertex property to store
|
Chris@16
|
605 // the incoming edges.
|
Chris@16
|
606 typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
|
Chris@16
|
607 property<vertex_in_edges_t, in_edge_list_type,
|
Chris@16
|
608 VertexProperty>,
|
Chris@16
|
609 VertexProperty>::type
|
Chris@16
|
610 base_vertex_property_type;
|
Chris@16
|
611
|
Chris@16
|
612 // The type of the distributed adjacency list
|
Chris@16
|
613 typedef adjacency_list<OutEdgeListS,
|
Chris@16
|
614 distributedS<ProcessGroup,
|
Chris@16
|
615 VertexListS,
|
Chris@16
|
616 InDistribution>,
|
Chris@16
|
617 DirectedS, VertexProperty, EdgeProperty,
|
Chris@16
|
618 GraphProperty, EdgeListS>
|
Chris@16
|
619 graph_type;
|
Chris@16
|
620
|
Chris@16
|
621 // The type of the underlying adjacency list implementation
|
Chris@16
|
622 typedef adjacency_list<OutEdgeListS, VertexListS, directedS,
|
Chris@16
|
623 base_vertex_property_type,
|
Chris@16
|
624 base_edge_property_type,
|
Chris@16
|
625 GraphProperty,
|
Chris@16
|
626 EdgeListS>
|
Chris@16
|
627 inherited;
|
Chris@16
|
628
|
Chris@16
|
629 typedef InDistribution in_distribution_type;
|
Chris@16
|
630 typedef typename inherited::vertices_size_type vertices_size_type;
|
Chris@16
|
631
|
Chris@16
|
632 typedef typename ::boost::graph::distributed::select_distribution<
|
Chris@16
|
633 in_distribution_type, VertexProperty, vertices_size_type,
|
Chris@16
|
634 ProcessGroup>::type
|
Chris@16
|
635 base_distribution_type;
|
Chris@16
|
636
|
Chris@16
|
637 typedef ::boost::graph::distributed::shuffled_distribution<
|
Chris@16
|
638 base_distribution_type> distribution_type;
|
Chris@16
|
639
|
Chris@16
|
640 typedef VertexProperty vertex_property_type;
|
Chris@16
|
641 typedef EdgeProperty edge_property_type;
|
Chris@16
|
642 typedef ProcessGroup process_group_type;
|
Chris@16
|
643
|
Chris@16
|
644 typedef VertexListS vertex_list_selector;
|
Chris@16
|
645 typedef OutEdgeListS out_edge_list_selector;
|
Chris@16
|
646 typedef DirectedS directed_selector;
|
Chris@16
|
647 typedef GraphProperty graph_property_type;
|
Chris@16
|
648 typedef EdgeListS edge_list_selector;
|
Chris@16
|
649 };
|
Chris@16
|
650
|
Chris@16
|
651 // Maybe initialize the indices of each vertex
|
Chris@16
|
652 template<typename IteratorPair, typename VertexIndexMap>
|
Chris@16
|
653 void
|
Chris@16
|
654 maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index,
|
Chris@16
|
655 read_write_property_map_tag)
|
Chris@16
|
656 {
|
Chris@16
|
657 typedef typename property_traits<VertexIndexMap>::value_type index_t;
|
Chris@16
|
658 index_t next_index = 0;
|
Chris@16
|
659 while (p.first != p.second)
|
Chris@16
|
660 put(to_index, *p.first++, next_index++);
|
Chris@16
|
661 }
|
Chris@16
|
662
|
Chris@16
|
663 template<typename IteratorPair, typename VertexIndexMap>
|
Chris@16
|
664 inline void
|
Chris@16
|
665 maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index,
|
Chris@16
|
666 readable_property_map_tag)
|
Chris@16
|
667 {
|
Chris@16
|
668 // Do nothing
|
Chris@16
|
669 }
|
Chris@16
|
670
|
Chris@16
|
671 template<typename IteratorPair, typename VertexIndexMap>
|
Chris@16
|
672 inline void
|
Chris@16
|
673 maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index)
|
Chris@16
|
674 {
|
Chris@16
|
675 typedef typename property_traits<VertexIndexMap>::category category;
|
Chris@16
|
676 maybe_initialize_vertex_indices(p, to_index, category());
|
Chris@16
|
677 }
|
Chris@16
|
678
|
Chris@16
|
679 template<typename IteratorPair>
|
Chris@16
|
680 inline void
|
Chris@16
|
681 maybe_initialize_vertex_indices(IteratorPair p,
|
Chris@16
|
682 ::boost::detail::error_property_not_found)
|
Chris@16
|
683 { }
|
Chris@16
|
684
|
Chris@16
|
685 /***********************************************************************
|
Chris@16
|
686 * Message Payloads *
|
Chris@16
|
687 ***********************************************************************/
|
Chris@16
|
688
|
Chris@16
|
689 /**
|
Chris@16
|
690 * Data stored with a msg_add_edge message, which requests the
|
Chris@16
|
691 * remote addition of an edge.
|
Chris@16
|
692 */
|
Chris@16
|
693 template<typename Vertex, typename LocalVertex>
|
Chris@16
|
694 struct msg_add_edge_data
|
Chris@16
|
695 {
|
Chris@16
|
696 msg_add_edge_data() { }
|
Chris@16
|
697
|
Chris@16
|
698 msg_add_edge_data(Vertex source, Vertex target)
|
Chris@16
|
699 : source(source.local), target(target) { }
|
Chris@16
|
700
|
Chris@16
|
701 /// The source of the edge; the processor will be the
|
Chris@16
|
702 /// receiving processor.
|
Chris@16
|
703 LocalVertex source;
|
Chris@16
|
704
|
Chris@16
|
705 /// The target of the edge.
|
Chris@16
|
706 Vertex target;
|
Chris@16
|
707
|
Chris@16
|
708 template<typename Archiver>
|
Chris@16
|
709 void serialize(Archiver& ar, const unsigned int /*version*/)
|
Chris@16
|
710 {
|
Chris@16
|
711 ar & unsafe_serialize(source) & target;
|
Chris@16
|
712 }
|
Chris@16
|
713 };
|
Chris@16
|
714
|
Chris@16
|
715 /**
|
Chris@16
|
716 * Like @c msg_add_edge_data, but also includes a user-specified
|
Chris@16
|
717 * property value to be attached to the edge.
|
Chris@16
|
718 */
|
Chris@16
|
719 template<typename Vertex, typename LocalVertex, typename EdgeProperty>
|
Chris@16
|
720 struct msg_add_edge_with_property_data
|
Chris@16
|
721 : msg_add_edge_data<Vertex, LocalVertex>,
|
Chris@16
|
722 maybe_store_property<EdgeProperty>
|
Chris@16
|
723 {
|
Chris@16
|
724 private:
|
Chris@16
|
725 typedef msg_add_edge_data<Vertex, LocalVertex> inherited_data;
|
Chris@16
|
726 typedef maybe_store_property<EdgeProperty> inherited_property;
|
Chris@16
|
727
|
Chris@16
|
728 public:
|
Chris@16
|
729 msg_add_edge_with_property_data() { }
|
Chris@16
|
730
|
Chris@16
|
731 msg_add_edge_with_property_data(Vertex source,
|
Chris@16
|
732 Vertex target,
|
Chris@16
|
733 const EdgeProperty& property)
|
Chris@16
|
734 : inherited_data(source, target),
|
Chris@16
|
735 inherited_property(property) { }
|
Chris@16
|
736
|
Chris@16
|
737 template<typename Archiver>
|
Chris@16
|
738 void serialize(Archiver& ar, const unsigned int /*version*/)
|
Chris@16
|
739 {
|
Chris@16
|
740 ar & boost::serialization::base_object<inherited_data>(*this)
|
Chris@16
|
741 & boost::serialization::base_object<inherited_property>(*this);
|
Chris@16
|
742 }
|
Chris@16
|
743 };
|
Chris@16
|
744
|
Chris@16
|
745 //------------------------------------------------------------------------
|
Chris@16
|
746 // Distributed adjacency list property map details
|
Chris@16
|
747 /**
|
Chris@16
|
748 * Metafunction that extracts the given property from the given
|
Chris@16
|
749 * distributed adjacency list type. This could be implemented much
|
Chris@16
|
750 * more cleanly, but even newer versions of GCC (e.g., 3.2.3)
|
Chris@16
|
751 * cannot properly handle partial specializations involving
|
Chris@16
|
752 * enumerator types.
|
Chris@16
|
753 */
|
Chris@16
|
754 template<typename Property>
|
Chris@16
|
755 struct get_adj_list_pmap
|
Chris@16
|
756 {
|
Chris@16
|
757 template<typename Graph>
|
Chris@16
|
758 struct apply
|
Chris@16
|
759 {
|
Chris@16
|
760 typedef Graph graph_type;
|
Chris@16
|
761 typedef typename graph_type::process_group_type process_group_type;
|
Chris@16
|
762 typedef typename graph_type::inherited base_graph_type;
|
Chris@16
|
763 typedef typename property_map<base_graph_type, Property>::type
|
Chris@16
|
764 local_pmap;
|
Chris@16
|
765 typedef typename property_map<base_graph_type, Property>::const_type
|
Chris@16
|
766 local_const_pmap;
|
Chris@16
|
767
|
Chris@16
|
768 typedef graph_traits<graph_type> traits;
|
Chris@16
|
769 typedef typename graph_type::local_vertex_descriptor local_vertex;
|
Chris@16
|
770 typedef typename property_traits<local_pmap>::key_type local_key_type;
|
Chris@16
|
771
|
Chris@16
|
772 typedef typename property_traits<local_pmap>::value_type value_type;
|
Chris@16
|
773
|
Chris@16
|
774 typedef typename property_map<Graph, vertex_global_t>::const_type
|
Chris@16
|
775 vertex_global_map;
|
Chris@16
|
776 typedef typename property_map<Graph, edge_global_t>::const_type
|
Chris@16
|
777 edge_global_map;
|
Chris@16
|
778
|
Chris@16
|
779 typedef typename mpl::if_c<(is_same<local_key_type,
|
Chris@16
|
780 local_vertex>::value),
|
Chris@16
|
781 vertex_global_map, edge_global_map>::type
|
Chris@16
|
782 global_map;
|
Chris@16
|
783
|
Chris@16
|
784 public:
|
Chris@16
|
785 typedef ::boost::parallel::distributed_property_map<
|
Chris@16
|
786 process_group_type, global_map, local_pmap> type;
|
Chris@16
|
787
|
Chris@16
|
788 typedef ::boost::parallel::distributed_property_map<
|
Chris@16
|
789 process_group_type, global_map, local_const_pmap> const_type;
|
Chris@16
|
790 };
|
Chris@16
|
791 };
|
Chris@16
|
792
|
Chris@16
|
793 /**
|
Chris@16
|
794 * The local vertex index property map is actually a mapping from
|
Chris@16
|
795 * the local vertex descriptors to vertex indices.
|
Chris@16
|
796 */
|
Chris@16
|
797 template<>
|
Chris@16
|
798 struct get_adj_list_pmap<vertex_local_index_t>
|
Chris@16
|
799 {
|
Chris@16
|
800 template<typename Graph>
|
Chris@16
|
801 struct apply
|
Chris@16
|
802 : ::boost::property_map<typename Graph::inherited, vertex_index_t>
|
Chris@16
|
803 { };
|
Chris@16
|
804 };
|
Chris@16
|
805
|
Chris@16
|
806 /**
|
Chris@16
|
807 * The vertex index property map maps from global descriptors
|
Chris@16
|
808 * (e.g., the vertex descriptor of a distributed adjacency list)
|
Chris@16
|
809 * to the underlying local index. It is not valid to use this
|
Chris@16
|
810 * property map with nonlocal descriptors.
|
Chris@16
|
811 */
|
Chris@16
|
812 template<>
|
Chris@16
|
813 struct get_adj_list_pmap<vertex_index_t>
|
Chris@16
|
814 {
|
Chris@16
|
815 template<typename Graph>
|
Chris@16
|
816 struct apply
|
Chris@16
|
817 {
|
Chris@16
|
818 private:
|
Chris@16
|
819 typedef typename property_map<Graph, vertex_global_t>::const_type
|
Chris@16
|
820 global_map;
|
Chris@16
|
821
|
Chris@16
|
822 typedef property_map<typename Graph::inherited, vertex_index_t> local;
|
Chris@16
|
823
|
Chris@16
|
824 public:
|
Chris@16
|
825 typedef local_property_map<typename Graph::process_group_type,
|
Chris@16
|
826 global_map,
|
Chris@16
|
827 typename local::type> type;
|
Chris@16
|
828 typedef local_property_map<typename Graph::process_group_type,
|
Chris@16
|
829 global_map,
|
Chris@16
|
830 typename local::const_type> const_type;
|
Chris@16
|
831 };
|
Chris@16
|
832 };
|
Chris@16
|
833
|
Chris@16
|
834 /**
|
Chris@16
|
835 * The vertex owner property map maps from vertex descriptors to
|
Chris@16
|
836 * the processor that owns the vertex.
|
Chris@16
|
837 */
|
Chris@16
|
838 template<>
|
Chris@16
|
839 struct get_adj_list_pmap<vertex_global_t>
|
Chris@16
|
840 {
|
Chris@16
|
841 template<typename Graph>
|
Chris@16
|
842 struct apply
|
Chris@16
|
843 {
|
Chris@16
|
844 private:
|
Chris@16
|
845 typedef typename Graph::local_vertex_descriptor
|
Chris@16
|
846 local_vertex_descriptor;
|
Chris@16
|
847 public:
|
Chris@16
|
848 typedef global_descriptor_property_map<local_vertex_descriptor> type;
|
Chris@16
|
849 typedef type const_type;
|
Chris@16
|
850 };
|
Chris@16
|
851 };
|
Chris@16
|
852
|
Chris@16
|
853 /**
|
Chris@16
|
854 * The vertex owner property map maps from vertex descriptors to
|
Chris@16
|
855 * the processor that owns the vertex.
|
Chris@16
|
856 */
|
Chris@16
|
857 template<>
|
Chris@16
|
858 struct get_adj_list_pmap<vertex_owner_t>
|
Chris@16
|
859 {
|
Chris@16
|
860 template<typename Graph>
|
Chris@16
|
861 struct apply
|
Chris@16
|
862 {
|
Chris@16
|
863 private:
|
Chris@16
|
864 typedef typename Graph::local_vertex_descriptor
|
Chris@16
|
865 local_vertex_descriptor;
|
Chris@16
|
866 public:
|
Chris@16
|
867 typedef owner_property_map<local_vertex_descriptor> type;
|
Chris@16
|
868 typedef type const_type;
|
Chris@16
|
869 };
|
Chris@16
|
870 };
|
Chris@16
|
871
|
Chris@16
|
872 /**
|
Chris@16
|
873 * The vertex local property map maps from vertex descriptors to
|
Chris@16
|
874 * the local descriptor for that vertex.
|
Chris@16
|
875 */
|
Chris@16
|
876 template<>
|
Chris@16
|
877 struct get_adj_list_pmap<vertex_local_t>
|
Chris@16
|
878 {
|
Chris@16
|
879 template<typename Graph>
|
Chris@16
|
880 struct apply
|
Chris@16
|
881 {
|
Chris@16
|
882 private:
|
Chris@16
|
883 typedef typename Graph::local_vertex_descriptor
|
Chris@16
|
884 local_vertex_descriptor;
|
Chris@16
|
885 public:
|
Chris@16
|
886 typedef local_descriptor_property_map<local_vertex_descriptor> type;
|
Chris@16
|
887 typedef type const_type;
|
Chris@16
|
888 };
|
Chris@16
|
889 };
|
Chris@16
|
890
|
Chris@16
|
891 /**
|
Chris@16
|
892 * The edge global property map maps from edge descriptors to
|
Chris@16
|
893 * a pair of the owning processor and local descriptor.
|
Chris@16
|
894 */
|
Chris@16
|
895 template<>
|
Chris@16
|
896 struct get_adj_list_pmap<edge_global_t>
|
Chris@16
|
897 {
|
Chris@16
|
898 template<typename Graph>
|
Chris@16
|
899 struct apply
|
Chris@16
|
900 {
|
Chris@16
|
901 private:
|
Chris@16
|
902 typedef typename Graph::local_edge_descriptor
|
Chris@16
|
903 local_edge_descriptor;
|
Chris@16
|
904 public:
|
Chris@16
|
905 typedef edge_global_property_map<local_edge_descriptor> type;
|
Chris@16
|
906 typedef type const_type;
|
Chris@16
|
907 };
|
Chris@16
|
908 };
|
Chris@16
|
909
|
Chris@16
|
910 /**
|
Chris@16
|
911 * The edge owner property map maps from edge descriptors to
|
Chris@16
|
912 * the processor that owns the edge.
|
Chris@16
|
913 */
|
Chris@16
|
914 template<>
|
Chris@16
|
915 struct get_adj_list_pmap<edge_owner_t>
|
Chris@16
|
916 {
|
Chris@16
|
917 template<typename Graph>
|
Chris@16
|
918 struct apply
|
Chris@16
|
919 {
|
Chris@16
|
920 private:
|
Chris@16
|
921 typedef typename Graph::local_edge_descriptor
|
Chris@16
|
922 local_edge_descriptor;
|
Chris@16
|
923 public:
|
Chris@16
|
924 typedef edge_owner_property_map<local_edge_descriptor> type;
|
Chris@16
|
925 typedef type const_type;
|
Chris@16
|
926 };
|
Chris@16
|
927 };
|
Chris@16
|
928
|
Chris@16
|
929 /**
|
Chris@16
|
930 * The edge local property map maps from edge descriptors to
|
Chris@16
|
931 * the local descriptor for that edge.
|
Chris@16
|
932 */
|
Chris@16
|
933 template<>
|
Chris@16
|
934 struct get_adj_list_pmap<edge_local_t>
|
Chris@16
|
935 {
|
Chris@16
|
936 template<typename Graph>
|
Chris@16
|
937 struct apply
|
Chris@16
|
938 {
|
Chris@16
|
939 private:
|
Chris@16
|
940 typedef typename Graph::local_edge_descriptor
|
Chris@16
|
941 local_edge_descriptor;
|
Chris@16
|
942 public:
|
Chris@16
|
943 typedef edge_local_property_map<local_edge_descriptor> type;
|
Chris@16
|
944 typedef type const_type;
|
Chris@16
|
945 };
|
Chris@16
|
946 };
|
Chris@16
|
947 //------------------------------------------------------------------------
|
Chris@16
|
948
|
Chris@16
|
949 // Directed graphs do not have in edges, so this is a no-op
|
Chris@16
|
950 template<typename Graph>
|
Chris@16
|
951 inline void
|
Chris@16
|
952 remove_in_edge(typename Graph::edge_descriptor, Graph&, directedS)
|
Chris@16
|
953 { }
|
Chris@16
|
954
|
Chris@16
|
955 // Bidirectional graphs have in edges stored in the
|
Chris@16
|
956 // vertex_in_edges property.
|
Chris@16
|
957 template<typename Graph>
|
Chris@16
|
958 inline void
|
Chris@16
|
959 remove_in_edge(typename Graph::edge_descriptor e, Graph& g, bidirectionalS)
|
Chris@16
|
960 {
|
Chris@16
|
961 typedef typename Graph::in_edge_list_type in_edge_list_type;
|
Chris@16
|
962 in_edge_list_type& in_edges =
|
Chris@16
|
963 get(vertex_in_edges, g.base())[target(e, g).local];
|
Chris@16
|
964 typename in_edge_list_type::iterator i = in_edges.begin();
|
Chris@16
|
965 while (i != in_edges.end()
|
Chris@16
|
966 && !(i->source_processor == source(e, g).owner)
|
Chris@16
|
967 && i->e == e.local)
|
Chris@16
|
968 ++i;
|
Chris@16
|
969
|
Chris@16
|
970 BOOST_ASSERT(i != in_edges.end());
|
Chris@16
|
971 in_edges.erase(i);
|
Chris@16
|
972 }
|
Chris@16
|
973
|
Chris@16
|
974 // Undirected graphs have in edges stored as normal edges.
|
Chris@16
|
975 template<typename Graph>
|
Chris@16
|
976 inline void
|
Chris@16
|
977 remove_in_edge(typename Graph::edge_descriptor e, Graph& g, undirectedS)
|
Chris@16
|
978 {
|
Chris@16
|
979 typedef typename Graph::inherited base_type;
|
Chris@16
|
980 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
Chris@16
|
981
|
Chris@16
|
982 // TBD: can we make this more efficient?
|
Chris@16
|
983 // Removing edge (v, u). v is local
|
Chris@16
|
984 base_type& bg = g.base();
|
Chris@16
|
985 vertex_descriptor u = source(e, g);
|
Chris@16
|
986 vertex_descriptor v = target(e, g);
|
Chris@16
|
987 if (v.owner != process_id(g.process_group())) {
|
Chris@16
|
988 using std::swap;
|
Chris@16
|
989 swap(u, v);
|
Chris@16
|
990 }
|
Chris@16
|
991
|
Chris@16
|
992 typename graph_traits<base_type>::out_edge_iterator ei, ei_end;
|
Chris@16
|
993 for (boost::tie(ei, ei_end) = out_edges(v.local, bg); ei != ei_end; ++ei)
|
Chris@16
|
994 {
|
Chris@16
|
995 if (target(*ei, g.base()) == u.local
|
Chris@16
|
996 // TBD: deal with parallel edges properly && *ei == e
|
Chris@16
|
997 && get(edge_target_processor_id, bg, *ei) == u.owner) {
|
Chris@16
|
998 remove_edge(ei, bg);
|
Chris@16
|
999 return;
|
Chris@16
|
1000 }
|
Chris@16
|
1001 }
|
Chris@16
|
1002
|
Chris@16
|
1003 if (v.owner == process_id(g.process_group())) {
|
Chris@16
|
1004
|
Chris@16
|
1005 }
|
Chris@16
|
1006 }
|
Chris@16
|
1007
|
Chris@16
|
1008 //------------------------------------------------------------------------
|
Chris@16
|
1009 // Lazy addition of edges
|
Chris@16
|
1010
|
Chris@16
|
1011 // Work around the fact that an adjacency_list with vecS vertex
|
Chris@16
|
1012 // storage automatically adds edges when the descriptor is
|
Chris@16
|
1013 // out-of-range.
|
Chris@16
|
1014 template <class Graph, class Config, class Base>
|
Chris@16
|
1015 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
1016 add_local_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
1017 typename Config::vertex_descriptor v,
|
Chris@16
|
1018 const typename Config::edge_property_type& p,
|
Chris@16
|
1019 vec_adj_list_impl<Graph, Config, Base>& g_)
|
Chris@16
|
1020 {
|
Chris@16
|
1021 adj_list_helper<Config, Base>& g = g_;
|
Chris@16
|
1022 return add_edge(u, v, p, g);
|
Chris@16
|
1023 }
|
Chris@16
|
1024
|
Chris@16
|
1025 template <class Graph, class Config, class Base>
|
Chris@16
|
1026 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
1027 add_local_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
1028 typename Config::vertex_descriptor v,
|
Chris@16
|
1029 const typename Config::edge_property_type& p,
|
Chris@16
|
1030 boost::adj_list_impl<Graph, Config, Base>& g)
|
Chris@16
|
1031 {
|
Chris@16
|
1032 return add_edge(u, v, p, g);
|
Chris@16
|
1033 }
|
Chris@16
|
1034
|
Chris@16
|
1035 template <class EdgeProperty,class EdgeDescriptor>
|
Chris@16
|
1036 struct msg_nonlocal_edge_data
|
Chris@16
|
1037 : public detail::parallel::maybe_store_property<EdgeProperty>
|
Chris@16
|
1038 {
|
Chris@16
|
1039 typedef EdgeProperty edge_property_type;
|
Chris@16
|
1040 typedef EdgeDescriptor local_edge_descriptor;
|
Chris@16
|
1041 typedef detail::parallel::maybe_store_property<edge_property_type>
|
Chris@16
|
1042 inherited;
|
Chris@16
|
1043
|
Chris@16
|
1044 msg_nonlocal_edge_data() {}
|
Chris@16
|
1045 msg_nonlocal_edge_data(local_edge_descriptor e,
|
Chris@16
|
1046 const edge_property_type& p)
|
Chris@16
|
1047 : inherited(p), e(e) { }
|
Chris@16
|
1048
|
Chris@16
|
1049 local_edge_descriptor e;
|
Chris@16
|
1050
|
Chris@16
|
1051 template<typename Archiver>
|
Chris@16
|
1052 void serialize(Archiver& ar, const unsigned int /*version*/)
|
Chris@16
|
1053 {
|
Chris@16
|
1054 ar & boost::serialization::base_object<inherited>(*this) & e;
|
Chris@16
|
1055 }
|
Chris@16
|
1056 };
|
Chris@16
|
1057
|
Chris@16
|
1058 template <class EdgeDescriptor>
|
Chris@16
|
1059 struct msg_remove_edge_data
|
Chris@16
|
1060 {
|
Chris@16
|
1061 typedef EdgeDescriptor edge_descriptor;
|
Chris@16
|
1062 msg_remove_edge_data() {}
|
Chris@16
|
1063 explicit msg_remove_edge_data(edge_descriptor e) : e(e) {}
|
Chris@16
|
1064
|
Chris@16
|
1065 edge_descriptor e;
|
Chris@16
|
1066
|
Chris@16
|
1067 template<typename Archiver>
|
Chris@16
|
1068 void serialize(Archiver& ar, const unsigned int /*version*/)
|
Chris@16
|
1069 {
|
Chris@16
|
1070 ar & e;
|
Chris@16
|
1071 }
|
Chris@16
|
1072 };
|
Chris@16
|
1073
|
Chris@16
|
1074 } } // end namespace detail::parallel
|
Chris@16
|
1075
|
Chris@16
|
1076 /**
|
Chris@16
|
1077 * Adjacency list traits for a distributed adjacency list. Contains
|
Chris@16
|
1078 * the vertex and edge descriptors, the directed-ness, and the
|
Chris@16
|
1079 * parallel edges typedefs.
|
Chris@16
|
1080 */
|
Chris@16
|
1081 template<typename OutEdgeListS, typename ProcessGroup,
|
Chris@16
|
1082 typename InVertexListS, typename InDistribution, typename DirectedS>
|
Chris@16
|
1083 struct adjacency_list_traits<OutEdgeListS,
|
Chris@16
|
1084 distributedS<ProcessGroup,
|
Chris@16
|
1085 InVertexListS,
|
Chris@16
|
1086 InDistribution>,
|
Chris@16
|
1087 DirectedS>
|
Chris@16
|
1088 {
|
Chris@16
|
1089 private:
|
Chris@16
|
1090 typedef typename mpl::if_<is_same<InVertexListS, defaultS>,
|
Chris@16
|
1091 vecS,
|
Chris@16
|
1092 InVertexListS>::type VertexListS;
|
Chris@16
|
1093
|
Chris@16
|
1094 typedef adjacency_list_traits<OutEdgeListS, VertexListS, directedS>
|
Chris@16
|
1095 base_type;
|
Chris@16
|
1096
|
Chris@16
|
1097 public:
|
Chris@16
|
1098 typedef typename base_type::vertex_descriptor local_vertex_descriptor;
|
Chris@16
|
1099 typedef typename base_type::edge_descriptor local_edge_descriptor;
|
Chris@16
|
1100
|
Chris@16
|
1101 typedef typename boost::mpl::if_<typename DirectedS::is_bidir_t,
|
Chris@16
|
1102 bidirectional_tag,
|
Chris@16
|
1103 typename boost::mpl::if_<typename DirectedS::is_directed_t,
|
Chris@16
|
1104 directed_tag, undirected_tag
|
Chris@16
|
1105 >::type
|
Chris@16
|
1106 >::type directed_category;
|
Chris@16
|
1107
|
Chris@16
|
1108 typedef typename parallel_edge_traits<OutEdgeListS>::type
|
Chris@16
|
1109 edge_parallel_category;
|
Chris@16
|
1110
|
Chris@16
|
1111 typedef detail::parallel::global_descriptor<local_vertex_descriptor>
|
Chris@16
|
1112 vertex_descriptor;
|
Chris@16
|
1113
|
Chris@16
|
1114 typedef detail::parallel::edge_descriptor<local_edge_descriptor>
|
Chris@16
|
1115 edge_descriptor;
|
Chris@16
|
1116 };
|
Chris@16
|
1117
|
Chris@16
|
1118 #define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS \
|
Chris@16
|
1119 typename OutEdgeListS, typename ProcessGroup, typename InVertexListS, \
|
Chris@16
|
1120 typename InDistribution, typename DirectedS, typename VertexProperty, \
|
Chris@16
|
1121 typename EdgeProperty, typename GraphProperty, typename EdgeListS
|
Chris@16
|
1122
|
Chris@16
|
1123 #define PBGL_DISTRIB_ADJLIST_TYPE \
|
Chris@16
|
1124 adjacency_list<OutEdgeListS, \
|
Chris@16
|
1125 distributedS<ProcessGroup, InVertexListS, InDistribution>, \
|
Chris@16
|
1126 DirectedS, VertexProperty, EdgeProperty, GraphProperty, \
|
Chris@16
|
1127 EdgeListS>
|
Chris@16
|
1128
|
Chris@16
|
1129 #define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG \
|
Chris@16
|
1130 typename OutEdgeListS, typename ProcessGroup, typename InVertexListS, \
|
Chris@16
|
1131 typename InDistribution, typename VertexProperty, \
|
Chris@16
|
1132 typename EdgeProperty, typename GraphProperty, typename EdgeListS
|
Chris@16
|
1133
|
Chris@16
|
1134 #define PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directed) \
|
Chris@16
|
1135 adjacency_list<OutEdgeListS, \
|
Chris@16
|
1136 distributedS<ProcessGroup, InVertexListS, InDistribution>, \
|
Chris@16
|
1137 directed, VertexProperty, EdgeProperty, GraphProperty, \
|
Chris@16
|
1138 EdgeListS>
|
Chris@16
|
1139
|
Chris@16
|
1140 /** A distributed adjacency list.
|
Chris@16
|
1141 *
|
Chris@16
|
1142 * This class template partial specialization defines a distributed
|
Chris@16
|
1143 * (or "partitioned") adjacency list graph. The distributed
|
Chris@16
|
1144 * adjacency list is similar to the standard Boost Graph Library
|
Chris@16
|
1145 * adjacency list, which stores a list of vertices and for each
|
Chris@16
|
1146 * verted the list of edges outgoing from the vertex (and, in some
|
Chris@16
|
1147 * cases, also the edges incoming to the vertex). The distributed
|
Chris@16
|
1148 * adjacency list differs in that it partitions the graph into
|
Chris@16
|
1149 * several subgraphs that are then divided among different
|
Chris@16
|
1150 * processors (or nodes within a cluster). The distributed adjacency
|
Chris@16
|
1151 * list attempts to maintain a high degree of compatibility with the
|
Chris@16
|
1152 * standard, non-distributed adjacency list.
|
Chris@16
|
1153 *
|
Chris@16
|
1154 * The graph is partitioned by vertex, with each processor storing
|
Chris@16
|
1155 * all of the required information for a particular subset of the
|
Chris@16
|
1156 * vertices, including vertex properties, outgoing edges, and (for
|
Chris@16
|
1157 * bidirectional graphs) incoming edges. This information is
|
Chris@16
|
1158 * accessible only on the processor that owns the vertex: for
|
Chris@16
|
1159 * instance, if processor 0 owns vertex @c v, no other processor can
|
Chris@16
|
1160 * directly access the properties of @c v or enumerate its outgoing
|
Chris@16
|
1161 * edges.
|
Chris@16
|
1162 *
|
Chris@16
|
1163 * Edges in a graph may be entirely local (connecting two local
|
Chris@16
|
1164 * vertices), but more often it is the case that edges are
|
Chris@16
|
1165 * non-local, meaning that the two vertices they connect reside in
|
Chris@16
|
1166 * different processes. Edge properties are stored with the
|
Chris@16
|
1167 * originating vertex for directed and bidirectional graphs, and are
|
Chris@16
|
1168 * therefore only accessible from the processor that owns the
|
Chris@16
|
1169 * originating vertex. Other processors may query the source and
|
Chris@16
|
1170 * target of the edge, but cannot access its properties. This is
|
Chris@16
|
1171 * particularly interesting when accessing the incoming edges of a
|
Chris@16
|
1172 * bidirectional graph, which are not guaranteed to be stored on the
|
Chris@16
|
1173 * processor that is able to perform the iteration. For undirected
|
Chris@16
|
1174 * graphs the situation is more complicated, since no vertex clearly
|
Chris@16
|
1175 * owns the edges: the list of edges incident to a vertex may
|
Chris@16
|
1176 * contain a mix of local and non-local edges.
|
Chris@16
|
1177 *
|
Chris@16
|
1178 * The distributed adjacency list is able to model several of the
|
Chris@16
|
1179 * existing Graph concepts. It models the Graph concept because it
|
Chris@16
|
1180 * exposes vertex and edge descriptors in the normal way; these
|
Chris@16
|
1181 * descriptors model the GlobalDescriptor concept (because they have
|
Chris@16
|
1182 * an owner and a local descriptor), and as such the distributed
|
Chris@16
|
1183 * adjacency list models the DistributedGraph concept. The adjacency
|
Chris@16
|
1184 * list also models the IncidenceGraph and AdjacencyGraph concepts,
|
Chris@16
|
1185 * although this is only true so long as the domain of the valid
|
Chris@16
|
1186 * expression arguments are restricted to vertices and edges stored
|
Chris@16
|
1187 * locally. Likewise, bidirectional and undirected distributed
|
Chris@16
|
1188 * adjacency lists model the BidirectionalGraph concept (vertex and
|
Chris@16
|
1189 * edge domains must be respectived) and the distributed adjacency
|
Chris@16
|
1190 * list models the MutableGraph concept (vertices and edges can only
|
Chris@16
|
1191 * be added or removed locally). T he distributed adjacency list
|
Chris@16
|
1192 * does not, however, model the VertexListGraph or EdgeListGraph
|
Chris@16
|
1193 * concepts, because we can not efficiently enumerate all vertices
|
Chris@16
|
1194 * or edges in the graph. Instead, the local subsets of vertices and
|
Chris@16
|
1195 * edges can be enumerated (with the same syntax): the distributed
|
Chris@16
|
1196 * adjacency list therefore models the DistributedVertexListGraph
|
Chris@16
|
1197 * and DistributedEdgeListGraph concepts, because concurrent
|
Chris@16
|
1198 * iteration over all of the vertices or edges stored on each
|
Chris@16
|
1199 * processor will visit each vertex or edge.
|
Chris@16
|
1200 *
|
Chris@16
|
1201 * The distributed adjacency list is distinguished from the
|
Chris@16
|
1202 * non-distributed version by the vertex list descriptor, which will
|
Chris@16
|
1203 * be @c distributedS<ProcessGroup,VertexListS>. Here,
|
Chris@16
|
1204 * the VertexListS type plays the same role as the VertexListS type
|
Chris@16
|
1205 * in the non-distributed adjacency list: it allows one to select
|
Chris@16
|
1206 * the data structure that will be used to store the local
|
Chris@16
|
1207 * vertices. The ProcessGroup type, on the other hand, is unique to
|
Chris@16
|
1208 * distributed data structures: it is the type that abstracts a
|
Chris@16
|
1209 * group of cooperating processes, and it used for process
|
Chris@16
|
1210 * identification, communication, and synchronization, among other
|
Chris@16
|
1211 * things. Different process group types represent different
|
Chris@16
|
1212 * communication mediums (e.g., MPI, PVM, TCP) or different models
|
Chris@16
|
1213 * of communication (LogP, CGM, BSP, synchronous, etc.). This
|
Chris@16
|
1214 * distributed adjacency list assumes a model based on non-blocking
|
Chris@16
|
1215 * sends.
|
Chris@16
|
1216 *
|
Chris@16
|
1217 * Distribution of vertices across different processors is
|
Chris@16
|
1218 * accomplished in two different ways. When initially constructing
|
Chris@16
|
1219 * the graph, the user may provide a distribution object (that
|
Chris@16
|
1220 * models the Distribution concept), which will determine the
|
Chris@16
|
1221 * distribution of vertices to each process. Additionally, the @c
|
Chris@16
|
1222 * add_vertex and @c add_edge operations add vertices or edges
|
Chris@16
|
1223 * stored on the local processor. For @c add_edge, this is
|
Chris@16
|
1224 * accomplished by requiring that the source vertex of the new edge
|
Chris@16
|
1225 * be local to the process executing @c add_edge.
|
Chris@16
|
1226 *
|
Chris@16
|
1227 * Internal properties of a distributed adjacency list are
|
Chris@16
|
1228 * accessible in the same manner as internal properties for a
|
Chris@16
|
1229 * non-distributed adjacency list for local vertices or
|
Chris@16
|
1230 * edges. Access to properties for remote vertices or edges occurs
|
Chris@16
|
1231 * with the same syntax, but involve communication with the owner of
|
Chris@16
|
1232 * the information: for more information, refer to class template
|
Chris@16
|
1233 * @ref distributed_property_map, which manages distributed
|
Chris@16
|
1234 * property maps. Note that the distributed property maps created
|
Chris@16
|
1235 * for internal properties determine their reduction operation via
|
Chris@16
|
1236 * the metafunction @ref property_reduce, which for the vast
|
Chris@16
|
1237 * majority of uses is correct behavior.
|
Chris@16
|
1238 *
|
Chris@16
|
1239 * Communication among the processes coordinating on a particular
|
Chris@16
|
1240 * distributed graph relies on non-blocking message passing along
|
Chris@16
|
1241 * with synchronization. Local portions of the distributed graph may
|
Chris@16
|
1242 * be modified concurrently, including the introduction of non-local
|
Chris@16
|
1243 * edges, but prior to accessing the graph it is recommended that
|
Chris@16
|
1244 * the @c synchronize free function be invoked on the graph to clear
|
Chris@16
|
1245 * up any pending interprocess communication and modifications. All
|
Chris@16
|
1246 * processes will then be released from the synchronization barrier
|
Chris@16
|
1247 * concurrently.
|
Chris@16
|
1248 *
|
Chris@16
|
1249 * \todo Determine precisely what we should do with nonlocal edges
|
Chris@16
|
1250 * in undirected graphs. Our parallelization of certain algorithms
|
Chris@16
|
1251 * relies on the ability to access edge property maps immediately
|
Chris@16
|
1252 * (e.g., edge_weight_t), so it may be necessary to duplicate the
|
Chris@16
|
1253 * edge properties in both processes (but then we need some form of
|
Chris@16
|
1254 * coherence protocol).
|
Chris@16
|
1255 *
|
Chris@16
|
1256 * \todo What does the user do if @c property_reduce doesn't do the
|
Chris@16
|
1257 * right thing?
|
Chris@16
|
1258 */
|
Chris@16
|
1259 template<typename OutEdgeListS, typename ProcessGroup,
|
Chris@16
|
1260 typename InVertexListS, typename InDistribution, typename DirectedS,
|
Chris@16
|
1261 typename VertexProperty, typename EdgeProperty,
|
Chris@16
|
1262 typename GraphProperty, typename EdgeListS>
|
Chris@16
|
1263 class adjacency_list<OutEdgeListS,
|
Chris@16
|
1264 distributedS<ProcessGroup,
|
Chris@16
|
1265 InVertexListS,
|
Chris@16
|
1266 InDistribution>,
|
Chris@16
|
1267 DirectedS, VertexProperty,
|
Chris@16
|
1268 EdgeProperty, GraphProperty, EdgeListS>
|
Chris@16
|
1269 : // Support for named vertices
|
Chris@16
|
1270 public graph::distributed::maybe_named_graph<
|
Chris@16
|
1271 adjacency_list<OutEdgeListS,
|
Chris@16
|
1272 distributedS<ProcessGroup,
|
Chris@16
|
1273 InVertexListS,
|
Chris@16
|
1274 InDistribution>,
|
Chris@16
|
1275 DirectedS, VertexProperty,
|
Chris@16
|
1276 EdgeProperty, GraphProperty, EdgeListS>,
|
Chris@16
|
1277 typename adjacency_list_traits<OutEdgeListS,
|
Chris@16
|
1278 distributedS<ProcessGroup,
|
Chris@16
|
1279 InVertexListS,
|
Chris@16
|
1280 InDistribution>,
|
Chris@16
|
1281 DirectedS>::vertex_descriptor,
|
Chris@16
|
1282 typename adjacency_list_traits<OutEdgeListS,
|
Chris@16
|
1283 distributedS<ProcessGroup,
|
Chris@16
|
1284 InVertexListS,
|
Chris@16
|
1285 InDistribution>,
|
Chris@16
|
1286 DirectedS>::edge_descriptor,
|
Chris@16
|
1287 detail::parallel::adjacency_list_config<OutEdgeListS, ProcessGroup,
|
Chris@16
|
1288 InVertexListS, InDistribution,
|
Chris@16
|
1289 DirectedS, VertexProperty,
|
Chris@16
|
1290 EdgeProperty, GraphProperty,
|
Chris@16
|
1291 EdgeListS> >
|
Chris@16
|
1292 {
|
Chris@16
|
1293 typedef detail::parallel::adjacency_list_config<OutEdgeListS, ProcessGroup,
|
Chris@16
|
1294 InVertexListS, InDistribution,
|
Chris@16
|
1295 DirectedS, VertexProperty,
|
Chris@16
|
1296 EdgeProperty, GraphProperty,
|
Chris@16
|
1297 EdgeListS>
|
Chris@16
|
1298 config_type;
|
Chris@16
|
1299
|
Chris@16
|
1300 typedef adjacency_list_traits<OutEdgeListS,
|
Chris@16
|
1301 distributedS<ProcessGroup,
|
Chris@16
|
1302 InVertexListS,
|
Chris@16
|
1303 InDistribution>,
|
Chris@16
|
1304 DirectedS>
|
Chris@16
|
1305 traits_type;
|
Chris@16
|
1306
|
Chris@16
|
1307 typedef typename DirectedS::is_directed_t is_directed;
|
Chris@16
|
1308
|
Chris@16
|
1309 typedef EdgeListS edge_list_selector;
|
Chris@16
|
1310
|
Chris@16
|
1311 public:
|
Chris@16
|
1312 /// The container type that will store incoming edges for a
|
Chris@16
|
1313 /// bidirectional graph.
|
Chris@16
|
1314 typedef typename config_type::in_edge_list_type in_edge_list_type;
|
Chris@16
|
1315 // typedef typename inherited::edge_descriptor edge_descriptor;
|
Chris@16
|
1316
|
Chris@16
|
1317 /// The type of the underlying adjacency list implementation
|
Chris@16
|
1318 typedef typename config_type::inherited inherited;
|
Chris@16
|
1319
|
Chris@16
|
1320 /// The type of properties stored in the local subgraph
|
Chris@16
|
1321 /// Bidirectional graphs have an extra vertex property to store
|
Chris@16
|
1322 /// the incoming edges.
|
Chris@16
|
1323 typedef typename inherited::vertex_property_type
|
Chris@16
|
1324 base_vertex_property_type;
|
Chris@16
|
1325
|
Chris@16
|
1326 /// The type of the distributed adjacency list (this type)
|
Chris@16
|
1327 typedef typename config_type::graph_type graph_type;
|
Chris@16
|
1328
|
Chris@16
|
1329 /// Expose graph components and graph category
|
Chris@16
|
1330 typedef typename traits_type::local_vertex_descriptor
|
Chris@16
|
1331 local_vertex_descriptor;
|
Chris@16
|
1332 typedef typename traits_type::local_edge_descriptor
|
Chris@16
|
1333 local_edge_descriptor;
|
Chris@16
|
1334 typedef typename traits_type::vertex_descriptor vertex_descriptor;
|
Chris@16
|
1335 typedef typename traits_type::edge_descriptor edge_descriptor;
|
Chris@16
|
1336
|
Chris@16
|
1337 typedef typename traits_type::directed_category directed_category;
|
Chris@16
|
1338 typedef typename inherited::edge_parallel_category
|
Chris@16
|
1339 edge_parallel_category;
|
Chris@16
|
1340 typedef typename inherited::graph_tag graph_tag;
|
Chris@16
|
1341
|
Chris@16
|
1342 // Current implementation requires the ability to have parallel
|
Chris@16
|
1343 // edges in the underlying adjacency_list. Which processor each
|
Chris@16
|
1344 // edge refers to is attached as an internal property. TBD:
|
Chris@16
|
1345 // remove this restriction, which may require some rewriting.
|
Chris@16
|
1346 BOOST_STATIC_ASSERT((is_same<edge_parallel_category,
|
Chris@16
|
1347 allow_parallel_edge_tag>::value));
|
Chris@16
|
1348
|
Chris@16
|
1349 /** Determine the graph traversal category.
|
Chris@16
|
1350 *
|
Chris@16
|
1351 * A directed distributed adjacency list models the Distributed
|
Chris@16
|
1352 * Graph, Incidence Graph, and Adjacency Graph
|
Chris@16
|
1353 * concepts. Bidirectional and undirected graphs also model the
|
Chris@16
|
1354 * Bidirectional Graph concept. Note that when modeling these
|
Chris@16
|
1355 * concepts the domains of certain operations (e.g., in_edges)
|
Chris@16
|
1356 * are restricted; see the distributed adjacency_list
|
Chris@16
|
1357 * documentation.
|
Chris@16
|
1358 */
|
Chris@16
|
1359 typedef typename boost::mpl::if_<
|
Chris@16
|
1360 is_same<DirectedS, directedS>,
|
Chris@16
|
1361 directed_distributed_adj_list_tag,
|
Chris@16
|
1362 typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
|
Chris@16
|
1363 bidirectional_distributed_adj_list_tag,
|
Chris@16
|
1364 undirected_distributed_adj_list_tag>::type>
|
Chris@16
|
1365 ::type traversal_category;
|
Chris@16
|
1366
|
Chris@16
|
1367 typedef typename inherited::degree_size_type degree_size_type;
|
Chris@16
|
1368 typedef typename inherited::vertices_size_type vertices_size_type;
|
Chris@16
|
1369 typedef typename inherited::edges_size_type edges_size_type;
|
Chris@16
|
1370 typedef VertexProperty vertex_property_type;
|
Chris@16
|
1371 typedef EdgeProperty edge_property_type;
|
Chris@16
|
1372 typedef typename inherited::graph_property_type graph_property_type;
|
Chris@16
|
1373 typedef typename inherited::vertex_bundled vertex_bundled;
|
Chris@16
|
1374 typedef typename inherited::edge_bundled edge_bundled;
|
Chris@16
|
1375 typedef typename inherited::graph_bundled graph_bundled;
|
Chris@16
|
1376
|
Chris@16
|
1377 typedef typename container_gen<edge_list_selector, edge_descriptor>::type
|
Chris@16
|
1378 local_edge_list_type;
|
Chris@16
|
1379
|
Chris@16
|
1380 private:
|
Chris@16
|
1381 typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
|
Chris@16
|
1382 typename in_edge_list_type::const_iterator,
|
Chris@16
|
1383 typename inherited::out_edge_iterator>::type
|
Chris@16
|
1384 base_in_edge_iterator;
|
Chris@16
|
1385
|
Chris@16
|
1386 typedef typename inherited::out_edge_iterator base_out_edge_iterator;
|
Chris@16
|
1387 typedef typename graph_traits<inherited>::edge_iterator
|
Chris@16
|
1388 base_edge_iterator;
|
Chris@16
|
1389 typedef typename inherited::edge_property_type base_edge_property_type;
|
Chris@16
|
1390
|
Chris@16
|
1391 typedef typename local_edge_list_type::const_iterator
|
Chris@16
|
1392 undirected_edge_iterator;
|
Chris@16
|
1393
|
Chris@16
|
1394 typedef InDistribution in_distribution_type;
|
Chris@16
|
1395
|
Chris@16
|
1396 typedef parallel::trigger_receive_context trigger_receive_context;
|
Chris@16
|
1397
|
Chris@16
|
1398 public:
|
Chris@16
|
1399 /// Iterator over the (local) vertices of the graph
|
Chris@16
|
1400 typedef transform_iterator<typename vertex_descriptor::generator,
|
Chris@16
|
1401 typename inherited::vertex_iterator>
|
Chris@16
|
1402 vertex_iterator;
|
Chris@16
|
1403
|
Chris@16
|
1404 /// Helper for out_edge_iterator
|
Chris@16
|
1405 typedef typename edge_descriptor::template out_generator<adjacency_list>
|
Chris@16
|
1406 out_edge_generator;
|
Chris@16
|
1407
|
Chris@16
|
1408 /// Iterator over the outgoing edges of a vertex
|
Chris@16
|
1409 typedef transform_iterator<out_edge_generator,
|
Chris@16
|
1410 typename inherited::out_edge_iterator>
|
Chris@16
|
1411 out_edge_iterator;
|
Chris@16
|
1412
|
Chris@16
|
1413 /// Helper for in_edge_iterator
|
Chris@16
|
1414 typedef typename edge_descriptor::template in_generator<adjacency_list>
|
Chris@16
|
1415 in_edge_generator;
|
Chris@16
|
1416
|
Chris@16
|
1417 /// Iterator over the incoming edges of a vertex
|
Chris@16
|
1418 typedef transform_iterator<in_edge_generator, base_in_edge_iterator>
|
Chris@16
|
1419 in_edge_iterator;
|
Chris@16
|
1420
|
Chris@16
|
1421 /// Iterator over the neighbors of a vertex
|
Chris@16
|
1422 typedef boost::adjacency_iterator<
|
Chris@16
|
1423 adjacency_list, vertex_descriptor, out_edge_iterator,
|
Chris@16
|
1424 typename detail::iterator_traits<base_out_edge_iterator>
|
Chris@16
|
1425 ::difference_type>
|
Chris@16
|
1426 adjacency_iterator;
|
Chris@16
|
1427
|
Chris@16
|
1428 /// Iterator over the (local) edges in a graph
|
Chris@16
|
1429 typedef typename boost::mpl::if_<is_same<DirectedS, undirectedS>,
|
Chris@16
|
1430 undirected_edge_iterator,
|
Chris@16
|
1431 transform_iterator<out_edge_generator,
|
Chris@16
|
1432 base_edge_iterator>
|
Chris@16
|
1433 >::type
|
Chris@16
|
1434 edge_iterator;
|
Chris@16
|
1435
|
Chris@16
|
1436 public:
|
Chris@16
|
1437 /// The type of the mixin for named vertices
|
Chris@16
|
1438 typedef graph::distributed::maybe_named_graph<graph_type,
|
Chris@16
|
1439 vertex_descriptor,
|
Chris@16
|
1440 edge_descriptor,
|
Chris@16
|
1441 config_type>
|
Chris@16
|
1442 named_graph_mixin;
|
Chris@16
|
1443
|
Chris@16
|
1444 /// Process group used for communication
|
Chris@16
|
1445 typedef ProcessGroup process_group_type;
|
Chris@16
|
1446
|
Chris@16
|
1447 /// How to refer to a process
|
Chris@16
|
1448 typedef typename process_group_type::process_id_type process_id_type;
|
Chris@16
|
1449
|
Chris@16
|
1450 /// Whether this graph is directed, undirected, or bidirectional
|
Chris@16
|
1451 typedef DirectedS directed_selector;
|
Chris@16
|
1452
|
Chris@16
|
1453 // Structure used for the lazy addition of vertices
|
Chris@16
|
1454 struct lazy_add_vertex_with_property;
|
Chris@16
|
1455 friend struct lazy_add_vertex_with_property;
|
Chris@16
|
1456
|
Chris@16
|
1457 // Structure used for the lazy addition of edges
|
Chris@16
|
1458 struct lazy_add_edge;
|
Chris@16
|
1459 friend struct lazy_add_edge;
|
Chris@16
|
1460
|
Chris@16
|
1461 // Structure used for the lazy addition of edges with properties
|
Chris@16
|
1462 struct lazy_add_edge_with_property;
|
Chris@16
|
1463 friend struct lazy_add_edge_with_property;
|
Chris@16
|
1464
|
Chris@16
|
1465 /// default_distribution_type is the type of the distribution used if the
|
Chris@16
|
1466 /// user didn't specify an explicit one
|
Chris@16
|
1467 typedef typename graph::distributed::select_distribution<
|
Chris@16
|
1468 InDistribution, VertexProperty, vertices_size_type,
|
Chris@16
|
1469 ProcessGroup>::default_type
|
Chris@16
|
1470 default_distribution_type;
|
Chris@16
|
1471
|
Chris@16
|
1472 /// distribution_type is the type of the distribution instance stored in
|
Chris@16
|
1473 /// the maybe_named_graph base class
|
Chris@16
|
1474 typedef typename graph::distributed::select_distribution<
|
Chris@16
|
1475 InDistribution, VertexProperty, vertices_size_type,
|
Chris@16
|
1476 ProcessGroup>::type
|
Chris@16
|
1477 base_distribution_type;
|
Chris@16
|
1478
|
Chris@16
|
1479 typedef graph::distributed::shuffled_distribution<
|
Chris@16
|
1480 base_distribution_type> distribution_type;
|
Chris@16
|
1481
|
Chris@16
|
1482 private:
|
Chris@16
|
1483 // FIXME: the original adjacency_list contained this comment:
|
Chris@16
|
1484 // Default copy constructor and copy assignment operators OK??? TBD
|
Chris@16
|
1485 // but the adj_list_impl contained these declarations:
|
Chris@16
|
1486 adjacency_list(const adjacency_list& other);
|
Chris@16
|
1487 adjacency_list& operator=(const adjacency_list& other);
|
Chris@16
|
1488
|
Chris@16
|
1489 public:
|
Chris@16
|
1490 adjacency_list(const ProcessGroup& pg = ProcessGroup())
|
Chris@16
|
1491 : named_graph_mixin(pg, default_distribution_type(pg, 0)),
|
Chris@16
|
1492 m_local_graph(GraphProperty()),
|
Chris@101
|
1493 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1494 {
|
Chris@16
|
1495 setup_triggers();
|
Chris@16
|
1496 }
|
Chris@16
|
1497
|
Chris@16
|
1498 adjacency_list(const ProcessGroup& pg,
|
Chris@16
|
1499 const base_distribution_type& distribution)
|
Chris@16
|
1500 : named_graph_mixin(pg, distribution),
|
Chris@16
|
1501 m_local_graph(GraphProperty()),
|
Chris@101
|
1502 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1503 {
|
Chris@16
|
1504 setup_triggers();
|
Chris@16
|
1505 }
|
Chris@16
|
1506
|
Chris@16
|
1507 adjacency_list(const GraphProperty& g,
|
Chris@16
|
1508 const ProcessGroup& pg = ProcessGroup())
|
Chris@16
|
1509 : named_graph_mixin(pg, default_distribution_type(pg, 0)),
|
Chris@16
|
1510 m_local_graph(g),
|
Chris@101
|
1511 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1512 {
|
Chris@16
|
1513 setup_triggers();
|
Chris@16
|
1514 }
|
Chris@16
|
1515
|
Chris@16
|
1516 adjacency_list(vertices_size_type n,
|
Chris@16
|
1517 const GraphProperty& p,
|
Chris@16
|
1518 const ProcessGroup& pg,
|
Chris@16
|
1519 const base_distribution_type& distribution)
|
Chris@16
|
1520 : named_graph_mixin(pg, distribution),
|
Chris@16
|
1521 m_local_graph(distribution.block_size(process_id(pg), n), p),
|
Chris@101
|
1522 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1523 {
|
Chris@16
|
1524 setup_triggers();
|
Chris@16
|
1525
|
Chris@16
|
1526 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
|
Chris@16
|
1527 get(vertex_index, base()));
|
Chris@16
|
1528 }
|
Chris@16
|
1529
|
Chris@16
|
1530 adjacency_list(vertices_size_type n,
|
Chris@16
|
1531 const ProcessGroup& pg,
|
Chris@16
|
1532 const base_distribution_type& distribution)
|
Chris@16
|
1533 : named_graph_mixin(pg, distribution),
|
Chris@16
|
1534 m_local_graph(distribution.block_size(process_id(pg), n), GraphProperty()),
|
Chris@101
|
1535 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1536 {
|
Chris@16
|
1537 setup_triggers();
|
Chris@16
|
1538
|
Chris@16
|
1539 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
|
Chris@16
|
1540 get(vertex_index, base()));
|
Chris@16
|
1541 }
|
Chris@16
|
1542
|
Chris@16
|
1543 adjacency_list(vertices_size_type n,
|
Chris@16
|
1544 const GraphProperty& p,
|
Chris@16
|
1545 const ProcessGroup& pg = ProcessGroup())
|
Chris@16
|
1546 : named_graph_mixin(pg, default_distribution_type(pg, n)),
|
Chris@16
|
1547 m_local_graph(this->distribution().block_size(process_id(pg), n), p),
|
Chris@101
|
1548 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1549 {
|
Chris@16
|
1550 setup_triggers();
|
Chris@16
|
1551
|
Chris@16
|
1552 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
|
Chris@16
|
1553 get(vertex_index, base()));
|
Chris@16
|
1554 }
|
Chris@16
|
1555
|
Chris@16
|
1556 adjacency_list(vertices_size_type n,
|
Chris@16
|
1557 const ProcessGroup& pg = ProcessGroup())
|
Chris@16
|
1558 : named_graph_mixin(pg, default_distribution_type(pg, n)),
|
Chris@16
|
1559 m_local_graph(this->distribution().block_size(process_id(pg), n),
|
Chris@16
|
1560 GraphProperty()),
|
Chris@101
|
1561 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1562 {
|
Chris@16
|
1563 setup_triggers();
|
Chris@16
|
1564
|
Chris@16
|
1565 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
|
Chris@16
|
1566 get(vertex_index, base()));
|
Chris@16
|
1567 }
|
Chris@16
|
1568
|
Chris@16
|
1569 /*
|
Chris@16
|
1570 * We assume that every processor sees the same list of edges, so
|
Chris@16
|
1571 * they skip over any that don't originate from themselves. This
|
Chris@16
|
1572 * means that programs switching between a local and a distributed
|
Chris@16
|
1573 * graph will keep the same semantics.
|
Chris@16
|
1574 */
|
Chris@16
|
1575 template <class EdgeIterator>
|
Chris@16
|
1576 adjacency_list(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1577 vertices_size_type n,
|
Chris@16
|
1578 const ProcessGroup& pg = ProcessGroup(),
|
Chris@16
|
1579 const GraphProperty& p = GraphProperty())
|
Chris@16
|
1580 : named_graph_mixin(pg, default_distribution_type(pg, n)),
|
Chris@16
|
1581 m_local_graph(this->distribution().block_size(process_id(pg), n), p),
|
Chris@101
|
1582 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1583 {
|
Chris@16
|
1584 setup_triggers();
|
Chris@16
|
1585
|
Chris@16
|
1586 typedef typename config_type::VertexListS vertex_list_selector;
|
Chris@16
|
1587 initialize(first, last, n, this->distribution(), vertex_list_selector());
|
Chris@16
|
1588 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
|
Chris@16
|
1589 get(vertex_index, base()));
|
Chris@16
|
1590
|
Chris@16
|
1591 }
|
Chris@16
|
1592
|
Chris@16
|
1593 template <class EdgeIterator, class EdgePropertyIterator>
|
Chris@16
|
1594 adjacency_list(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1595 EdgePropertyIterator ep_iter,
|
Chris@16
|
1596 vertices_size_type n,
|
Chris@16
|
1597 const ProcessGroup& pg = ProcessGroup(),
|
Chris@16
|
1598 const GraphProperty& p = GraphProperty())
|
Chris@16
|
1599 : named_graph_mixin(pg, default_distribution_type(pg, n)),
|
Chris@16
|
1600 m_local_graph(this->distribution().block_size(process_id(pg), n), p),
|
Chris@101
|
1601 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1602 {
|
Chris@16
|
1603 setup_triggers();
|
Chris@16
|
1604
|
Chris@16
|
1605 typedef typename config_type::VertexListS vertex_list_selector;
|
Chris@16
|
1606 initialize(first, last, ep_iter, n, this->distribution(),
|
Chris@16
|
1607 vertex_list_selector());
|
Chris@16
|
1608 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
|
Chris@16
|
1609 get(vertex_index, base()));
|
Chris@16
|
1610
|
Chris@16
|
1611 }
|
Chris@16
|
1612
|
Chris@16
|
1613 template <class EdgeIterator>
|
Chris@16
|
1614 adjacency_list(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1615 vertices_size_type n,
|
Chris@16
|
1616 const ProcessGroup& pg,
|
Chris@16
|
1617 const base_distribution_type& distribution,
|
Chris@16
|
1618 const GraphProperty& p = GraphProperty())
|
Chris@16
|
1619 : named_graph_mixin(pg, distribution),
|
Chris@16
|
1620 m_local_graph(distribution.block_size(process_id(pg), n), p),
|
Chris@101
|
1621 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1622 {
|
Chris@16
|
1623 setup_triggers();
|
Chris@16
|
1624
|
Chris@16
|
1625 typedef typename config_type::VertexListS vertex_list_selector;
|
Chris@16
|
1626 initialize(first, last, n, this->distribution(), vertex_list_selector());
|
Chris@16
|
1627 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
|
Chris@16
|
1628 get(vertex_index, base()));
|
Chris@16
|
1629
|
Chris@16
|
1630 }
|
Chris@16
|
1631
|
Chris@16
|
1632 template <class EdgeIterator, class EdgePropertyIterator>
|
Chris@16
|
1633 adjacency_list(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1634 EdgePropertyIterator ep_iter,
|
Chris@16
|
1635 vertices_size_type n,
|
Chris@16
|
1636 const ProcessGroup& pg,
|
Chris@16
|
1637 const base_distribution_type& distribution,
|
Chris@16
|
1638 const GraphProperty& p = GraphProperty())
|
Chris@16
|
1639 : named_graph_mixin(pg, distribution),
|
Chris@16
|
1640 m_local_graph(this->distribution().block_size(process_id(pg), n), p),
|
Chris@101
|
1641 process_group_(pg, boost::parallel::attach_distributed_object())
|
Chris@16
|
1642 {
|
Chris@16
|
1643 setup_triggers();
|
Chris@16
|
1644
|
Chris@16
|
1645 typedef typename config_type::VertexListS vertex_list_selector;
|
Chris@16
|
1646 initialize(first, last, ep_iter, n, distribution,
|
Chris@16
|
1647 vertex_list_selector());
|
Chris@16
|
1648 detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
|
Chris@16
|
1649 get(vertex_index, base()));
|
Chris@16
|
1650
|
Chris@16
|
1651 }
|
Chris@16
|
1652
|
Chris@16
|
1653 ~adjacency_list()
|
Chris@16
|
1654 {
|
Chris@16
|
1655 synchronize(process_group_);
|
Chris@16
|
1656 }
|
Chris@16
|
1657
|
Chris@16
|
1658 void clear()
|
Chris@16
|
1659 {
|
Chris@16
|
1660 base().clear();
|
Chris@16
|
1661 local_edges_.clear();
|
Chris@16
|
1662 named_graph_mixin::clearing_graph();
|
Chris@16
|
1663 }
|
Chris@16
|
1664
|
Chris@16
|
1665 void swap(adjacency_list& other)
|
Chris@16
|
1666 {
|
Chris@16
|
1667 using std::swap;
|
Chris@16
|
1668
|
Chris@16
|
1669 base().swap(other);
|
Chris@16
|
1670 swap(process_group_, other.process_group_);
|
Chris@16
|
1671 }
|
Chris@16
|
1672
|
Chris@16
|
1673 static vertex_descriptor null_vertex()
|
Chris@16
|
1674 {
|
Chris@16
|
1675 return vertex_descriptor(processor_id_type(0),
|
Chris@16
|
1676 inherited::null_vertex());
|
Chris@16
|
1677 }
|
Chris@16
|
1678
|
Chris@16
|
1679 inherited& base() { return m_local_graph; }
|
Chris@16
|
1680 const inherited& base() const { return m_local_graph; }
|
Chris@16
|
1681
|
Chris@16
|
1682 processor_id_type processor() const { return process_id(process_group_); }
|
Chris@16
|
1683 process_group_type process_group() const { return process_group_.base(); }
|
Chris@16
|
1684
|
Chris@16
|
1685 local_edge_list_type& local_edges() { return local_edges_; }
|
Chris@16
|
1686 const local_edge_list_type& local_edges() const { return local_edges_; }
|
Chris@16
|
1687
|
Chris@16
|
1688 // Redistribute the vertices of the graph by placing each vertex
|
Chris@16
|
1689 // v on the processor get(vertex_to_processor, v).
|
Chris@16
|
1690 template<typename VertexProcessorMap>
|
Chris@16
|
1691 void redistribute(VertexProcessorMap vertex_to_processor);
|
Chris@16
|
1692
|
Chris@16
|
1693 // Directly access a vertex or edge bundle
|
Chris@16
|
1694 vertex_bundled& operator[](vertex_descriptor v)
|
Chris@16
|
1695 {
|
Chris@16
|
1696 BOOST_ASSERT(v.owner == processor());
|
Chris@16
|
1697 return base()[v.local];
|
Chris@16
|
1698 }
|
Chris@16
|
1699
|
Chris@16
|
1700 const vertex_bundled& operator[](vertex_descriptor v) const
|
Chris@16
|
1701 {
|
Chris@16
|
1702 BOOST_ASSERT(v.owner == processor());
|
Chris@16
|
1703 return base()[v.local];
|
Chris@16
|
1704 }
|
Chris@16
|
1705
|
Chris@16
|
1706 edge_bundled& operator[](edge_descriptor e)
|
Chris@16
|
1707 {
|
Chris@16
|
1708 BOOST_ASSERT(e.owner() == processor());
|
Chris@16
|
1709 return base()[e.local];
|
Chris@16
|
1710 }
|
Chris@16
|
1711
|
Chris@16
|
1712 const edge_bundled& operator[](edge_descriptor e) const
|
Chris@16
|
1713 {
|
Chris@16
|
1714 BOOST_ASSERT(e.owner() == processor());
|
Chris@16
|
1715 return base()[e.local];
|
Chris@16
|
1716 }
|
Chris@16
|
1717
|
Chris@16
|
1718 graph_bundled& operator[](graph_bundle_t)
|
Chris@16
|
1719 { return get_property(*this); }
|
Chris@16
|
1720
|
Chris@16
|
1721 graph_bundled const& operator[](graph_bundle_t) const
|
Chris@16
|
1722 { return get_property(*this); }
|
Chris@16
|
1723
|
Chris@16
|
1724 template<typename OStreamConstructibleArchive>
|
Chris@16
|
1725 void save(std::string const& filename) const;
|
Chris@16
|
1726
|
Chris@16
|
1727 template<typename IStreamConstructibleArchive>
|
Chris@16
|
1728 void load(std::string const& filename);
|
Chris@16
|
1729
|
Chris@16
|
1730 // Callback that will be invoked whenever a new vertex is added locally
|
Chris@16
|
1731 boost::function<void(vertex_descriptor, adjacency_list&)> on_add_vertex;
|
Chris@16
|
1732
|
Chris@16
|
1733 // Callback that will be invoked whenever a new edge is added locally
|
Chris@16
|
1734 boost::function<void(edge_descriptor, adjacency_list&)> on_add_edge;
|
Chris@16
|
1735
|
Chris@16
|
1736 private:
|
Chris@16
|
1737 // Request vertex->processor mapping for neighbors <does nothing>
|
Chris@16
|
1738 template<typename VertexProcessorMap>
|
Chris@16
|
1739 void
|
Chris@16
|
1740 request_in_neighbors(vertex_descriptor,
|
Chris@16
|
1741 VertexProcessorMap,
|
Chris@16
|
1742 directedS) { }
|
Chris@16
|
1743
|
Chris@16
|
1744 // Request vertex->processor mapping for neighbors <does nothing>
|
Chris@16
|
1745 template<typename VertexProcessorMap>
|
Chris@16
|
1746 void
|
Chris@16
|
1747 request_in_neighbors(vertex_descriptor,
|
Chris@16
|
1748 VertexProcessorMap,
|
Chris@16
|
1749 undirectedS) { }
|
Chris@16
|
1750
|
Chris@16
|
1751 // Request vertex->processor mapping for neighbors
|
Chris@16
|
1752 template<typename VertexProcessorMap>
|
Chris@16
|
1753 void
|
Chris@16
|
1754 request_in_neighbors(vertex_descriptor v,
|
Chris@16
|
1755 VertexProcessorMap vertex_to_processor,
|
Chris@16
|
1756 bidirectionalS);
|
Chris@16
|
1757
|
Chris@16
|
1758 // Clear the list of in-edges, but don't tell the remote processor
|
Chris@16
|
1759 void clear_in_edges_local(vertex_descriptor v, directedS) {}
|
Chris@16
|
1760 void clear_in_edges_local(vertex_descriptor v, undirectedS) {}
|
Chris@16
|
1761
|
Chris@16
|
1762 void clear_in_edges_local(vertex_descriptor v, bidirectionalS)
|
Chris@16
|
1763 { get(vertex_in_edges, base())[v.local].clear(); }
|
Chris@16
|
1764
|
Chris@16
|
1765 // Remove in-edges that have migrated <does nothing>
|
Chris@16
|
1766 template<typename VertexProcessorMap>
|
Chris@16
|
1767 void
|
Chris@16
|
1768 remove_migrated_in_edges(vertex_descriptor,
|
Chris@16
|
1769 VertexProcessorMap,
|
Chris@16
|
1770 directedS) { }
|
Chris@16
|
1771
|
Chris@16
|
1772 // Remove in-edges that have migrated <does nothing>
|
Chris@16
|
1773 template<typename VertexProcessorMap>
|
Chris@16
|
1774 void
|
Chris@16
|
1775 remove_migrated_in_edges(vertex_descriptor,
|
Chris@16
|
1776 VertexProcessorMap,
|
Chris@16
|
1777 undirectedS) { }
|
Chris@16
|
1778
|
Chris@16
|
1779 // Remove in-edges that have migrated
|
Chris@16
|
1780 template<typename VertexProcessorMap>
|
Chris@16
|
1781 void
|
Chris@16
|
1782 remove_migrated_in_edges(vertex_descriptor v,
|
Chris@16
|
1783 VertexProcessorMap vertex_to_processor,
|
Chris@16
|
1784 bidirectionalS);
|
Chris@16
|
1785
|
Chris@16
|
1786 // Initialize the graph with the given edge list and vertex
|
Chris@16
|
1787 // distribution. This variation works only when
|
Chris@16
|
1788 // VertexListS=vecS, and we know how to create remote vertex
|
Chris@16
|
1789 // descriptors based solely on the distribution.
|
Chris@16
|
1790 template<typename EdgeIterator>
|
Chris@16
|
1791 void
|
Chris@16
|
1792 initialize(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1793 vertices_size_type, const base_distribution_type& distribution,
|
Chris@16
|
1794 vecS);
|
Chris@16
|
1795
|
Chris@16
|
1796 // Initialize the graph with the given edge list, edge
|
Chris@16
|
1797 // properties, and vertex distribution. This variation works
|
Chris@16
|
1798 // only when VertexListS=vecS, and we know how to create remote
|
Chris@16
|
1799 // vertex descriptors based solely on the distribution.
|
Chris@16
|
1800 template<typename EdgeIterator, typename EdgePropertyIterator>
|
Chris@16
|
1801 void
|
Chris@16
|
1802 initialize(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1803 EdgePropertyIterator ep_iter,
|
Chris@16
|
1804 vertices_size_type, const base_distribution_type& distribution,
|
Chris@16
|
1805 vecS);
|
Chris@16
|
1806
|
Chris@16
|
1807 // Initialize the graph with the given edge list, edge
|
Chris@16
|
1808 // properties, and vertex distribution.
|
Chris@16
|
1809 template<typename EdgeIterator, typename EdgePropertyIterator,
|
Chris@16
|
1810 typename VertexListS>
|
Chris@16
|
1811 void
|
Chris@16
|
1812 initialize(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1813 EdgePropertyIterator ep_iter,
|
Chris@16
|
1814 vertices_size_type n,
|
Chris@16
|
1815 const base_distribution_type& distribution,
|
Chris@16
|
1816 VertexListS);
|
Chris@16
|
1817
|
Chris@16
|
1818 // Initialize the graph with the given edge list and vertex
|
Chris@16
|
1819 // distribution. This is nearly identical to the one below it,
|
Chris@16
|
1820 // for which I should be flogged. However, this version does use
|
Chris@16
|
1821 // slightly less memory than the version that accepts an edge
|
Chris@16
|
1822 // property iterator.
|
Chris@16
|
1823 template<typename EdgeIterator, typename VertexListS>
|
Chris@16
|
1824 void
|
Chris@16
|
1825 initialize(EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1826 vertices_size_type n,
|
Chris@16
|
1827 const base_distribution_type& distribution,
|
Chris@16
|
1828 VertexListS);
|
Chris@16
|
1829
|
Chris@16
|
1830 public:
|
Chris@16
|
1831 //---------------------------------------------------------------------
|
Chris@16
|
1832 // Build a vertex property instance for the underlying adjacency
|
Chris@16
|
1833 // list from the given property instance of the type exposed to
|
Chris@16
|
1834 // the user.
|
Chris@16
|
1835 base_vertex_property_type
|
Chris@16
|
1836 build_vertex_property(const vertex_property_type& p)
|
Chris@16
|
1837 { return build_vertex_property(p, directed_selector()); }
|
Chris@16
|
1838
|
Chris@16
|
1839 base_vertex_property_type
|
Chris@16
|
1840 build_vertex_property(const vertex_property_type& p, directedS)
|
Chris@16
|
1841 {
|
Chris@16
|
1842 return base_vertex_property_type(p);
|
Chris@16
|
1843 }
|
Chris@16
|
1844
|
Chris@16
|
1845 base_vertex_property_type
|
Chris@16
|
1846 build_vertex_property(const vertex_property_type& p, bidirectionalS)
|
Chris@16
|
1847 {
|
Chris@16
|
1848 return base_vertex_property_type(in_edge_list_type(), p);
|
Chris@16
|
1849 }
|
Chris@16
|
1850
|
Chris@16
|
1851 base_vertex_property_type
|
Chris@16
|
1852 build_vertex_property(const vertex_property_type& p, undirectedS)
|
Chris@16
|
1853 {
|
Chris@16
|
1854 return base_vertex_property_type(p);
|
Chris@16
|
1855 }
|
Chris@16
|
1856 //---------------------------------------------------------------------
|
Chris@16
|
1857
|
Chris@16
|
1858 //---------------------------------------------------------------------
|
Chris@16
|
1859 // Build an edge property instance for the underlying adjacency
|
Chris@16
|
1860 // list from the given property instance of the type exposed to
|
Chris@16
|
1861 // the user.
|
Chris@16
|
1862 base_edge_property_type build_edge_property(const edge_property_type& p)
|
Chris@16
|
1863 { return build_edge_property(p, directed_selector()); }
|
Chris@16
|
1864
|
Chris@16
|
1865 base_edge_property_type
|
Chris@16
|
1866 build_edge_property(const edge_property_type& p, directedS)
|
Chris@16
|
1867 {
|
Chris@16
|
1868 return base_edge_property_type(0, p);
|
Chris@16
|
1869 }
|
Chris@16
|
1870
|
Chris@16
|
1871 base_edge_property_type
|
Chris@16
|
1872 build_edge_property(const edge_property_type& p, bidirectionalS)
|
Chris@16
|
1873 {
|
Chris@16
|
1874 return base_edge_property_type(0, p);
|
Chris@16
|
1875 }
|
Chris@16
|
1876
|
Chris@16
|
1877 base_edge_property_type
|
Chris@16
|
1878 build_edge_property(const edge_property_type& p, undirectedS)
|
Chris@16
|
1879 {
|
Chris@16
|
1880 typedef typename base_edge_property_type::next_type
|
Chris@16
|
1881 edge_property_with_id;
|
Chris@16
|
1882 return base_edge_property_type(true, edge_property_with_id(0, p));
|
Chris@16
|
1883 }
|
Chris@16
|
1884 //---------------------------------------------------------------------
|
Chris@16
|
1885
|
Chris@16
|
1886 //---------------------------------------------------------------------
|
Chris@16
|
1887 // Opposite of above.
|
Chris@16
|
1888 edge_property_type split_edge_property(const base_edge_property_type& p)
|
Chris@16
|
1889 { return split_edge_property(p, directed_selector()); }
|
Chris@16
|
1890
|
Chris@16
|
1891 edge_property_type
|
Chris@16
|
1892 split_edge_property(const base_edge_property_type& p, directedS)
|
Chris@16
|
1893 {
|
Chris@16
|
1894 return p.m_base;
|
Chris@16
|
1895 }
|
Chris@16
|
1896
|
Chris@16
|
1897 edge_property_type
|
Chris@16
|
1898 split_edge_property(const base_edge_property_type& p, bidirectionalS)
|
Chris@16
|
1899 {
|
Chris@16
|
1900 return p.m_base;
|
Chris@16
|
1901 }
|
Chris@16
|
1902
|
Chris@16
|
1903 edge_property_type
|
Chris@16
|
1904 split_edge_property(const base_edge_property_type& p, undirectedS)
|
Chris@16
|
1905 {
|
Chris@16
|
1906 return p.m_base.m_base;
|
Chris@16
|
1907 }
|
Chris@16
|
1908 //---------------------------------------------------------------------
|
Chris@16
|
1909
|
Chris@16
|
1910 /** The set of messages that can be transmitted and received by
|
Chris@16
|
1911 * a distributed adjacency list. This list will eventually be
|
Chris@16
|
1912 * exhaustive, but is currently quite limited.
|
Chris@16
|
1913 */
|
Chris@16
|
1914 enum {
|
Chris@16
|
1915 /**
|
Chris@16
|
1916 * Request to add or find a vertex with the given vertex
|
Chris@16
|
1917 * property. The data will be a vertex_property_type
|
Chris@16
|
1918 * structure.
|
Chris@16
|
1919 */
|
Chris@16
|
1920 msg_add_vertex_with_property = 0,
|
Chris@16
|
1921
|
Chris@16
|
1922 /**
|
Chris@16
|
1923 * Request to add or find a vertex with the given vertex
|
Chris@16
|
1924 * property, and request that the remote processor return the
|
Chris@16
|
1925 * descriptor for the added/found edge. The data will be a
|
Chris@16
|
1926 * vertex_property_type structure.
|
Chris@16
|
1927 */
|
Chris@16
|
1928 msg_add_vertex_with_property_and_reply,
|
Chris@16
|
1929
|
Chris@16
|
1930 /**
|
Chris@16
|
1931 * Reply to a msg_add_vertex_* message, containing the local
|
Chris@16
|
1932 * vertex descriptor that was added or found.
|
Chris@16
|
1933 */
|
Chris@16
|
1934 msg_add_vertex_reply,
|
Chris@16
|
1935
|
Chris@16
|
1936 /**
|
Chris@16
|
1937 * Request to add an edge remotely. The data will be a
|
Chris@16
|
1938 * msg_add_edge_data structure.
|
Chris@16
|
1939 */
|
Chris@16
|
1940 msg_add_edge,
|
Chris@16
|
1941
|
Chris@16
|
1942 /**
|
Chris@16
|
1943 * Request to add an edge remotely. The data will be a
|
Chris@16
|
1944 * msg_add_edge_with_property_data structure.
|
Chris@16
|
1945 */
|
Chris@16
|
1946 msg_add_edge_with_property,
|
Chris@16
|
1947
|
Chris@16
|
1948 /**
|
Chris@16
|
1949 * Request to add an edge remotely and reply back with the
|
Chris@16
|
1950 * edge descriptor. The data will be a
|
Chris@16
|
1951 * msg_add_edge_data structure.
|
Chris@16
|
1952 */
|
Chris@16
|
1953 msg_add_edge_with_reply,
|
Chris@16
|
1954
|
Chris@16
|
1955 /**
|
Chris@16
|
1956 * Request to add an edge remotely and reply back with the
|
Chris@16
|
1957 * edge descriptor. The data will be a
|
Chris@16
|
1958 * msg_add_edge_with_property_data structure.
|
Chris@16
|
1959 */
|
Chris@16
|
1960 msg_add_edge_with_property_and_reply,
|
Chris@16
|
1961
|
Chris@16
|
1962 /**
|
Chris@16
|
1963 * Reply message responding to an @c msg_add_edge_with_reply
|
Chris@16
|
1964 * or @c msg_add_edge_with_property_and_reply messages. The
|
Chris@16
|
1965 * data will be a std::pair<edge_descriptor, bool>.
|
Chris@16
|
1966 */
|
Chris@16
|
1967 msg_add_edge_reply,
|
Chris@16
|
1968
|
Chris@16
|
1969 /**
|
Chris@16
|
1970 * Indicates that a nonlocal edge has been created that should
|
Chris@16
|
1971 * be added locally. Only valid for bidirectional and
|
Chris@16
|
1972 * undirected graphs. The message carries a
|
Chris@16
|
1973 * msg_nonlocal_edge_data structure.
|
Chris@16
|
1974 */
|
Chris@16
|
1975 msg_nonlocal_edge,
|
Chris@16
|
1976
|
Chris@16
|
1977 /**
|
Chris@16
|
1978 * Indicates that a remote edge should be removed. This
|
Chris@16
|
1979 * message does not exist for directedS graphs but may refer
|
Chris@16
|
1980 * to either in-edges or out-edges for undirectedS graphs.
|
Chris@16
|
1981 */
|
Chris@16
|
1982 msg_remove_edge,
|
Chris@16
|
1983
|
Chris@16
|
1984 /**
|
Chris@16
|
1985 * Indicates the number of vertices and edges that will be
|
Chris@16
|
1986 * relocated from the source processor to the target
|
Chris@16
|
1987 * processor. The data will be a pair<vertices_size_type,
|
Chris@16
|
1988 * edges_size_type>.
|
Chris@16
|
1989 */
|
Chris@16
|
1990 msg_num_relocated
|
Chris@16
|
1991 };
|
Chris@16
|
1992
|
Chris@16
|
1993 typedef detail::parallel::msg_add_edge_data<vertex_descriptor,
|
Chris@16
|
1994 local_vertex_descriptor>
|
Chris@16
|
1995 msg_add_edge_data;
|
Chris@16
|
1996
|
Chris@16
|
1997 typedef detail::parallel::msg_add_edge_with_property_data
|
Chris@16
|
1998 <vertex_descriptor, local_vertex_descriptor,
|
Chris@16
|
1999 edge_property_type> msg_add_edge_with_property_data;
|
Chris@16
|
2000
|
Chris@16
|
2001 typedef boost::detail::parallel::msg_nonlocal_edge_data<
|
Chris@16
|
2002 edge_property_type,local_edge_descriptor> msg_nonlocal_edge_data;
|
Chris@16
|
2003
|
Chris@16
|
2004 typedef boost::detail::parallel::msg_remove_edge_data<edge_descriptor>
|
Chris@16
|
2005 msg_remove_edge_data;
|
Chris@16
|
2006
|
Chris@16
|
2007 void send_remove_edge_request(edge_descriptor e)
|
Chris@16
|
2008 {
|
Chris@16
|
2009 process_id_type dest = e.target_processor;
|
Chris@16
|
2010 if (e.target_processor == process_id(process_group_))
|
Chris@16
|
2011 dest = e.source_processor;
|
Chris@16
|
2012 send(process_group_, dest, msg_remove_edge, msg_remove_edge_data(e));
|
Chris@16
|
2013 }
|
Chris@16
|
2014
|
Chris@16
|
2015 /// Process incoming messages.
|
Chris@16
|
2016 void setup_triggers();
|
Chris@16
|
2017
|
Chris@16
|
2018 void
|
Chris@16
|
2019 handle_add_vertex_with_property(int source, int tag,
|
Chris@16
|
2020 const vertex_property_type&,
|
Chris@16
|
2021 trigger_receive_context);
|
Chris@16
|
2022
|
Chris@16
|
2023 local_vertex_descriptor
|
Chris@16
|
2024 handle_add_vertex_with_property_and_reply(int source, int tag,
|
Chris@16
|
2025 const vertex_property_type&,
|
Chris@16
|
2026 trigger_receive_context);
|
Chris@16
|
2027
|
Chris@16
|
2028 void
|
Chris@16
|
2029 handle_add_edge(int source, int tag, const msg_add_edge_data& data,
|
Chris@16
|
2030 trigger_receive_context);
|
Chris@16
|
2031
|
Chris@16
|
2032 boost::parallel::detail::untracked_pair<edge_descriptor, bool>
|
Chris@16
|
2033 handle_add_edge_with_reply(int source, int tag,
|
Chris@16
|
2034 const msg_add_edge_data& data,
|
Chris@16
|
2035 trigger_receive_context);
|
Chris@16
|
2036
|
Chris@16
|
2037 void
|
Chris@16
|
2038 handle_add_edge_with_property(int source, int tag,
|
Chris@16
|
2039 const msg_add_edge_with_property_data&,
|
Chris@16
|
2040 trigger_receive_context);
|
Chris@16
|
2041
|
Chris@16
|
2042 boost::parallel::detail::untracked_pair<edge_descriptor, bool>
|
Chris@16
|
2043 handle_add_edge_with_property_and_reply
|
Chris@16
|
2044 (int source, int tag, const msg_add_edge_with_property_data&,
|
Chris@16
|
2045 trigger_receive_context);
|
Chris@16
|
2046
|
Chris@16
|
2047 void
|
Chris@16
|
2048 handle_nonlocal_edge(int source, int tag,
|
Chris@16
|
2049 const msg_nonlocal_edge_data& data,
|
Chris@16
|
2050 trigger_receive_context);
|
Chris@16
|
2051
|
Chris@16
|
2052 void
|
Chris@16
|
2053 handle_remove_edge(int source, int tag,
|
Chris@16
|
2054 const msg_remove_edge_data& data,
|
Chris@16
|
2055 trigger_receive_context);
|
Chris@16
|
2056
|
Chris@16
|
2057 protected:
|
Chris@16
|
2058 /** Add an edge (locally) that was received from another
|
Chris@16
|
2059 * processor. This operation is a no-op for directed graphs,
|
Chris@16
|
2060 * because all edges reside on the local processor. For
|
Chris@16
|
2061 * bidirectional graphs, this routine places the edge onto the
|
Chris@16
|
2062 * list of incoming edges for the target vertex. For undirected
|
Chris@16
|
2063 * graphs, the edge is placed along with all of the other edges
|
Chris@16
|
2064 * for the target vertex, but it is marked as a non-local edge
|
Chris@16
|
2065 * descriptor.
|
Chris@16
|
2066 *
|
Chris@16
|
2067 * \todo There is a potential problem here, where we could
|
Chris@16
|
2068 * unintentionally allow duplicate edges in undirected graphs
|
Chris@16
|
2069 * because the same edge is added on two different processors
|
Chris@16
|
2070 * simultaneously. It's not an issue now, because we require
|
Chris@16
|
2071 * that the graph allow parallel edges. Once we do support
|
Chris@16
|
2072 * containers such as setS or hash_setS that disallow parallel
|
Chris@16
|
2073 * edges we will need to deal with this.
|
Chris@16
|
2074 */
|
Chris@16
|
2075 void
|
Chris@16
|
2076 add_remote_edge(const msg_nonlocal_edge_data&,
|
Chris@16
|
2077 processor_id_type, directedS)
|
Chris@16
|
2078 { }
|
Chris@16
|
2079
|
Chris@16
|
2080
|
Chris@16
|
2081 /**
|
Chris@16
|
2082 * \overload
|
Chris@16
|
2083 */
|
Chris@16
|
2084 void
|
Chris@16
|
2085 add_remote_edge(const msg_nonlocal_edge_data& data,
|
Chris@16
|
2086 processor_id_type other_proc, bidirectionalS)
|
Chris@16
|
2087 {
|
Chris@16
|
2088 typedef detail::parallel::stored_in_edge<local_edge_descriptor> stored_edge;
|
Chris@16
|
2089
|
Chris@16
|
2090 stored_edge edge(other_proc, data.e);
|
Chris@16
|
2091 local_vertex_descriptor v = target(data.e, base());
|
Chris@16
|
2092 boost::graph_detail::push(get(vertex_in_edges, base())[v], edge);
|
Chris@16
|
2093 }
|
Chris@16
|
2094
|
Chris@16
|
2095 /**
|
Chris@16
|
2096 * \overload
|
Chris@16
|
2097 */
|
Chris@16
|
2098 void
|
Chris@16
|
2099 add_remote_edge(const msg_nonlocal_edge_data& data,
|
Chris@16
|
2100 processor_id_type other_proc, undirectedS)
|
Chris@16
|
2101 {
|
Chris@16
|
2102 std::pair<local_edge_descriptor, bool> edge =
|
Chris@16
|
2103 detail::parallel::add_local_edge(target(data.e, base()),
|
Chris@16
|
2104 source(data.e, base()),
|
Chris@16
|
2105 build_edge_property(data.get_property()), base());
|
Chris@16
|
2106 BOOST_ASSERT(edge.second);
|
Chris@16
|
2107 put(edge_target_processor_id, base(), edge.first, other_proc);
|
Chris@16
|
2108
|
Chris@16
|
2109 if (edge.second && on_add_edge)
|
Chris@16
|
2110 on_add_edge(edge_descriptor(processor(), other_proc, false,
|
Chris@16
|
2111 edge.first),
|
Chris@16
|
2112 *this);
|
Chris@16
|
2113 }
|
Chris@16
|
2114
|
Chris@16
|
2115 void
|
Chris@16
|
2116 remove_local_edge(const msg_remove_edge_data&, processor_id_type,
|
Chris@16
|
2117 directedS)
|
Chris@16
|
2118 { }
|
Chris@16
|
2119
|
Chris@16
|
2120 void
|
Chris@16
|
2121 remove_local_edge(const msg_remove_edge_data& data,
|
Chris@16
|
2122 processor_id_type other_proc, bidirectionalS)
|
Chris@16
|
2123 {
|
Chris@16
|
2124 /* When the source is local, we first check if the edge still
|
Chris@16
|
2125 * exists (it may have been deleted locally) and, if so,
|
Chris@16
|
2126 * remove it locally.
|
Chris@16
|
2127 */
|
Chris@16
|
2128 vertex_descriptor src = source(data.e, *this);
|
Chris@16
|
2129 vertex_descriptor tgt = target(data.e, *this);
|
Chris@16
|
2130
|
Chris@16
|
2131 if (src.owner == process_id(process_group_)) {
|
Chris@16
|
2132 base_out_edge_iterator ei, ei_end;
|
Chris@16
|
2133 for (boost::tie(ei, ei_end) = out_edges(src.local, base());
|
Chris@16
|
2134 ei != ei_end; ++ei) {
|
Chris@16
|
2135 // TBD: can't check the descriptor here, because it could
|
Chris@16
|
2136 // have changed if we're allowing the removal of
|
Chris@16
|
2137 // edges. Egads!
|
Chris@16
|
2138 if (tgt.local == target(*ei, base())
|
Chris@16
|
2139 && get(edge_target_processor_id, base(), *ei) == other_proc)
|
Chris@16
|
2140 break;
|
Chris@16
|
2141 }
|
Chris@16
|
2142
|
Chris@16
|
2143 if (ei != ei_end) boost::remove_edge(ei, base());
|
Chris@16
|
2144
|
Chris@16
|
2145 remove_local_edge_from_list(src, tgt, undirectedS());
|
Chris@16
|
2146 } else {
|
Chris@16
|
2147 BOOST_ASSERT(tgt.owner == process_id(process_group_));
|
Chris@16
|
2148 in_edge_list_type& in_edges =
|
Chris@16
|
2149 get(vertex_in_edges, base())[tgt.local];
|
Chris@16
|
2150 typename in_edge_list_type::iterator ei;
|
Chris@16
|
2151 for (ei = in_edges.begin(); ei != in_edges.end(); ++ei) {
|
Chris@16
|
2152 if (src.local == source(ei->e, base())
|
Chris@16
|
2153 && src.owner == ei->source_processor)
|
Chris@16
|
2154 break;
|
Chris@16
|
2155 }
|
Chris@16
|
2156
|
Chris@16
|
2157 if (ei != in_edges.end()) in_edges.erase(ei);
|
Chris@16
|
2158 }
|
Chris@16
|
2159 }
|
Chris@16
|
2160
|
Chris@16
|
2161 void
|
Chris@16
|
2162 remove_local_edge(const msg_remove_edge_data& data,
|
Chris@16
|
2163 processor_id_type other_proc, undirectedS)
|
Chris@16
|
2164 {
|
Chris@16
|
2165 vertex_descriptor local_vertex = source(data.e, *this);
|
Chris@16
|
2166 vertex_descriptor remote_vertex = target(data.e, *this);
|
Chris@16
|
2167 if (remote_vertex.owner == process_id(process_group_)) {
|
Chris@16
|
2168 using std::swap;
|
Chris@16
|
2169 swap(local_vertex, remote_vertex);
|
Chris@16
|
2170 }
|
Chris@16
|
2171
|
Chris@16
|
2172 // Remove the edge from the out-edge list, if it is there
|
Chris@16
|
2173 {
|
Chris@16
|
2174 base_out_edge_iterator ei, ei_end;
|
Chris@16
|
2175 for (boost::tie(ei, ei_end) = out_edges(local_vertex.local, base());
|
Chris@16
|
2176 ei != ei_end; ++ei) {
|
Chris@16
|
2177 // TBD: can't check the descriptor here, because it could
|
Chris@16
|
2178 // have changed if we're allowing the removal of
|
Chris@16
|
2179 // edges. Egads!
|
Chris@16
|
2180 if (remote_vertex.local == target(*ei, base())
|
Chris@16
|
2181 && get(edge_target_processor_id, base(), *ei) == other_proc)
|
Chris@16
|
2182 break;
|
Chris@16
|
2183 }
|
Chris@16
|
2184
|
Chris@16
|
2185 if (ei != ei_end) boost::remove_edge(ei, base());
|
Chris@16
|
2186 }
|
Chris@16
|
2187
|
Chris@16
|
2188 remove_local_edge_from_list(local_vertex, remote_vertex, undirectedS());
|
Chris@16
|
2189 }
|
Chris@16
|
2190
|
Chris@16
|
2191 public:
|
Chris@16
|
2192 void
|
Chris@16
|
2193 remove_local_edge_from_list(vertex_descriptor, vertex_descriptor,
|
Chris@16
|
2194 directedS)
|
Chris@16
|
2195 {
|
Chris@16
|
2196 }
|
Chris@16
|
2197
|
Chris@16
|
2198 void
|
Chris@16
|
2199 remove_local_edge_from_list(vertex_descriptor, vertex_descriptor,
|
Chris@16
|
2200 bidirectionalS)
|
Chris@16
|
2201 {
|
Chris@16
|
2202 }
|
Chris@16
|
2203
|
Chris@16
|
2204 void
|
Chris@16
|
2205 remove_local_edge_from_list(vertex_descriptor src, vertex_descriptor tgt,
|
Chris@16
|
2206 undirectedS)
|
Chris@16
|
2207 {
|
Chris@16
|
2208 // TBD: At some point we'll be able to improve the speed here
|
Chris@16
|
2209 // because we'll know when the edge can't be in the local
|
Chris@16
|
2210 // list.
|
Chris@16
|
2211 {
|
Chris@16
|
2212 typename local_edge_list_type::iterator ei;
|
Chris@16
|
2213 for (ei = local_edges_.begin(); ei != local_edges_.end(); ++ei) {
|
Chris@16
|
2214 if ((source(*ei, *this) == src
|
Chris@16
|
2215 && target(*ei, *this) == tgt)
|
Chris@16
|
2216 || (source(*ei, *this) == tgt
|
Chris@16
|
2217 && target(*ei, *this) == src))
|
Chris@16
|
2218 break;
|
Chris@16
|
2219 }
|
Chris@16
|
2220
|
Chris@16
|
2221 if (ei != local_edges_.end()) local_edges_.erase(ei);
|
Chris@16
|
2222 }
|
Chris@16
|
2223
|
Chris@16
|
2224 }
|
Chris@16
|
2225
|
Chris@16
|
2226 private:
|
Chris@16
|
2227 /// The local subgraph
|
Chris@16
|
2228 inherited m_local_graph;
|
Chris@16
|
2229
|
Chris@16
|
2230 /// The process group through which this distributed graph
|
Chris@16
|
2231 /// communicates.
|
Chris@16
|
2232 process_group_type process_group_;
|
Chris@16
|
2233
|
Chris@16
|
2234 // TBD: should only be available for undirected graphs, but for
|
Chris@16
|
2235 // now it'll just be empty for directed and bidirectional
|
Chris@16
|
2236 // graphs.
|
Chris@16
|
2237 local_edge_list_type local_edges_;
|
Chris@16
|
2238 };
|
Chris@16
|
2239
|
Chris@16
|
2240 //------------------------------------------------------------------------
|
Chris@16
|
2241 // Lazy addition of vertices
|
Chris@16
|
2242 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2243 struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property
|
Chris@16
|
2244 {
|
Chris@16
|
2245 /// Construct a lazy request to add a vertex
|
Chris@16
|
2246 lazy_add_vertex_with_property(adjacency_list& self,
|
Chris@16
|
2247 const vertex_property_type& property)
|
Chris@16
|
2248 : self(self), property(property), committed(false) { }
|
Chris@16
|
2249
|
Chris@16
|
2250 /// Copying a lazy_add_vertex_with_property transfers the
|
Chris@16
|
2251 /// responsibility for adding the vertex to the newly-constructed
|
Chris@16
|
2252 /// object.
|
Chris@16
|
2253 lazy_add_vertex_with_property(const lazy_add_vertex_with_property& other)
|
Chris@16
|
2254 : self(other.self), property(other.property),
|
Chris@16
|
2255 committed(other.committed)
|
Chris@16
|
2256 {
|
Chris@16
|
2257 other.committed = true;
|
Chris@16
|
2258 }
|
Chris@16
|
2259
|
Chris@16
|
2260 /// If the vertex has not yet been added, add the vertex but don't
|
Chris@16
|
2261 /// wait for a reply.
|
Chris@16
|
2262 ~lazy_add_vertex_with_property();
|
Chris@16
|
2263
|
Chris@16
|
2264 /// Returns commit().
|
Chris@16
|
2265 operator vertex_descriptor() const { return commit(); }
|
Chris@16
|
2266
|
Chris@16
|
2267 // Add the vertex. This operation will block if the vertex is
|
Chris@16
|
2268 // being added remotely.
|
Chris@16
|
2269 vertex_descriptor commit() const;
|
Chris@16
|
2270
|
Chris@16
|
2271 protected:
|
Chris@16
|
2272 adjacency_list& self;
|
Chris@16
|
2273 vertex_property_type property;
|
Chris@16
|
2274 mutable bool committed;
|
Chris@16
|
2275
|
Chris@16
|
2276 private:
|
Chris@16
|
2277 // No copy-assignment semantics
|
Chris@16
|
2278 void operator=(lazy_add_vertex_with_property&);
|
Chris@16
|
2279 };
|
Chris@16
|
2280
|
Chris@16
|
2281 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2282 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property::
|
Chris@16
|
2283 ~lazy_add_vertex_with_property()
|
Chris@16
|
2284 {
|
Chris@16
|
2285 /// If this vertex has already been created or will be created by
|
Chris@16
|
2286 /// someone else, or if someone threw an exception, we will not
|
Chris@16
|
2287 /// create the vertex now.
|
Chris@16
|
2288 if (committed || std::uncaught_exception())
|
Chris@16
|
2289 return;
|
Chris@16
|
2290
|
Chris@16
|
2291 committed = true;
|
Chris@16
|
2292
|
Chris@16
|
2293 process_id_type owner
|
Chris@16
|
2294 = static_cast<graph_type&>(self).owner_by_property(property);
|
Chris@16
|
2295 if (owner == self.processor()) {
|
Chris@16
|
2296 /// Add the vertex locally.
|
Chris@16
|
2297 vertex_descriptor v(owner,
|
Chris@16
|
2298 add_vertex(self.build_vertex_property(property),
|
Chris@16
|
2299 self.base()));
|
Chris@16
|
2300 if (self.on_add_vertex)
|
Chris@16
|
2301 self.on_add_vertex(v, self);
|
Chris@16
|
2302 }
|
Chris@16
|
2303 else
|
Chris@16
|
2304 /// Ask the owner of this new vertex to add the vertex. We
|
Chris@16
|
2305 /// don't need a reply.
|
Chris@16
|
2306 send(self.process_group_, owner, msg_add_vertex_with_property,
|
Chris@16
|
2307 property);
|
Chris@16
|
2308 }
|
Chris@16
|
2309
|
Chris@16
|
2310 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2311 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
|
Chris@16
|
2312 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property::
|
Chris@16
|
2313 commit() const
|
Chris@16
|
2314 {
|
Chris@16
|
2315 BOOST_ASSERT(!this->committed);
|
Chris@16
|
2316 this->committed = true;
|
Chris@16
|
2317
|
Chris@16
|
2318 process_id_type owner
|
Chris@16
|
2319 = static_cast<graph_type&>(self).owner_by_property(property);
|
Chris@16
|
2320 local_vertex_descriptor local_v;
|
Chris@16
|
2321 if (owner == self.processor())
|
Chris@16
|
2322 /// Add the vertex locally.
|
Chris@16
|
2323 local_v = add_vertex(self.build_vertex_property(property),
|
Chris@16
|
2324 self.base());
|
Chris@16
|
2325 else {
|
Chris@16
|
2326 // Request that the remote process add the vertex immediately
|
Chris@16
|
2327 send_oob_with_reply(self.process_group_, owner,
|
Chris@16
|
2328 msg_add_vertex_with_property_and_reply, property,
|
Chris@16
|
2329 local_v);
|
Chris@16
|
2330 }
|
Chris@16
|
2331
|
Chris@16
|
2332 vertex_descriptor v(owner, local_v);
|
Chris@16
|
2333 if (self.on_add_vertex)
|
Chris@16
|
2334 self.on_add_vertex(v, self);
|
Chris@16
|
2335
|
Chris@16
|
2336 // Build the full vertex descriptor to return
|
Chris@16
|
2337 return v;
|
Chris@16
|
2338 }
|
Chris@16
|
2339
|
Chris@16
|
2340
|
Chris@16
|
2341 /**
|
Chris@16
|
2342 * Data structure returned from add_edge that will "lazily" add
|
Chris@16
|
2343 * the edge, either when it is converted to a
|
Chris@16
|
2344 * @c pair<edge_descriptor, bool> or when the most recent copy has
|
Chris@16
|
2345 * been destroyed.
|
Chris@16
|
2346 */
|
Chris@16
|
2347 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2348 struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge
|
Chris@16
|
2349 {
|
Chris@16
|
2350 /// Construct a lazy request to add an edge
|
Chris@16
|
2351 lazy_add_edge(adjacency_list& self,
|
Chris@16
|
2352 vertex_descriptor source, vertex_descriptor target)
|
Chris@16
|
2353 : self(self), source(source), target(target), committed(false) { }
|
Chris@16
|
2354
|
Chris@16
|
2355 /// Copying a lazy_add_edge transfers the responsibility for
|
Chris@16
|
2356 /// adding the edge to the newly-constructed object.
|
Chris@16
|
2357 lazy_add_edge(const lazy_add_edge& other)
|
Chris@16
|
2358 : self(other.self), source(other.source), target(other.target),
|
Chris@16
|
2359 committed(other.committed)
|
Chris@16
|
2360 {
|
Chris@16
|
2361 other.committed = true;
|
Chris@16
|
2362 }
|
Chris@16
|
2363
|
Chris@16
|
2364 /// If the edge has not yet been added, add the edge but don't
|
Chris@16
|
2365 /// wait for a reply.
|
Chris@16
|
2366 ~lazy_add_edge();
|
Chris@16
|
2367
|
Chris@16
|
2368 /// Returns commit().
|
Chris@16
|
2369 operator std::pair<edge_descriptor, bool>() const { return commit(); }
|
Chris@16
|
2370
|
Chris@16
|
2371 // Add the edge. This operation will block if a remote edge is
|
Chris@16
|
2372 // being added.
|
Chris@16
|
2373 std::pair<edge_descriptor, bool> commit() const;
|
Chris@16
|
2374
|
Chris@16
|
2375 protected:
|
Chris@16
|
2376 std::pair<edge_descriptor, bool>
|
Chris@16
|
2377 add_local_edge(const edge_property_type& property, directedS) const;
|
Chris@16
|
2378
|
Chris@16
|
2379 std::pair<edge_descriptor, bool>
|
Chris@16
|
2380 add_local_edge(const edge_property_type& property, bidirectionalS) const;
|
Chris@16
|
2381
|
Chris@16
|
2382 std::pair<edge_descriptor, bool>
|
Chris@16
|
2383 add_local_edge(const edge_property_type& property, undirectedS) const;
|
Chris@16
|
2384
|
Chris@16
|
2385 adjacency_list& self;
|
Chris@16
|
2386 vertex_descriptor source;
|
Chris@16
|
2387 vertex_descriptor target;
|
Chris@16
|
2388 mutable bool committed;
|
Chris@16
|
2389
|
Chris@16
|
2390 private:
|
Chris@16
|
2391 // No copy-assignment semantics
|
Chris@16
|
2392 void operator=(lazy_add_edge&);
|
Chris@16
|
2393 };
|
Chris@16
|
2394
|
Chris@16
|
2395 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2396 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::~lazy_add_edge()
|
Chris@16
|
2397 {
|
Chris@16
|
2398 /// If this edge has already been created or will be created by
|
Chris@16
|
2399 /// someone else, or if someone threw an exception, we will not
|
Chris@16
|
2400 /// create the edge now.
|
Chris@16
|
2401 if (committed || std::uncaught_exception())
|
Chris@16
|
2402 return;
|
Chris@16
|
2403
|
Chris@16
|
2404 committed = true;
|
Chris@16
|
2405
|
Chris@16
|
2406 if (source.owner == self.processor())
|
Chris@16
|
2407 this->add_local_edge(edge_property_type(), DirectedS());
|
Chris@16
|
2408 else
|
Chris@16
|
2409 // Request that the remote processor add an edge and, but
|
Chris@16
|
2410 // don't wait for a reply.
|
Chris@16
|
2411 send(self.process_group_, source.owner, msg_add_edge,
|
Chris@16
|
2412 msg_add_edge_data(source, target));
|
Chris@16
|
2413 }
|
Chris@16
|
2414
|
Chris@16
|
2415 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2416 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
|
Chris@16
|
2417 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::commit() const
|
Chris@16
|
2418 {
|
Chris@16
|
2419 BOOST_ASSERT(!committed);
|
Chris@16
|
2420 committed = true;
|
Chris@16
|
2421
|
Chris@16
|
2422 if (source.owner == self.processor())
|
Chris@16
|
2423 return this->add_local_edge(edge_property_type(), DirectedS());
|
Chris@16
|
2424 else {
|
Chris@16
|
2425 // Request that the remote processor add an edge
|
Chris@16
|
2426 boost::parallel::detail::untracked_pair<edge_descriptor, bool> result;
|
Chris@16
|
2427 send_oob_with_reply(self.process_group_, source.owner,
|
Chris@16
|
2428 msg_add_edge_with_reply,
|
Chris@16
|
2429 msg_add_edge_data(source, target), result);
|
Chris@16
|
2430 return result;
|
Chris@16
|
2431 }
|
Chris@16
|
2432 }
|
Chris@16
|
2433
|
Chris@16
|
2434 // Add a local edge into a directed graph
|
Chris@16
|
2435 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2436 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
|
Chris@16
|
2437 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::
|
Chris@16
|
2438 add_local_edge(const edge_property_type& property, directedS) const
|
Chris@16
|
2439 {
|
Chris@16
|
2440 // Add the edge to the local part of the graph
|
Chris@16
|
2441 std::pair<local_edge_descriptor, bool> inserted =
|
Chris@16
|
2442 detail::parallel::add_local_edge(source.local, target.local,
|
Chris@16
|
2443 self.build_edge_property(property),
|
Chris@16
|
2444 self.base());
|
Chris@16
|
2445
|
Chris@16
|
2446 if (inserted.second)
|
Chris@16
|
2447 // Keep track of the owner of the target
|
Chris@16
|
2448 put(edge_target_processor_id, self.base(), inserted.first,
|
Chris@16
|
2449 target.owner);
|
Chris@16
|
2450
|
Chris@16
|
2451 // Compose the edge descriptor and return the result
|
Chris@16
|
2452 edge_descriptor e(source.owner, target.owner, true, inserted.first);
|
Chris@16
|
2453
|
Chris@16
|
2454 // Trigger the on_add_edge event
|
Chris@16
|
2455 if (inserted.second && self.on_add_edge)
|
Chris@16
|
2456 self.on_add_edge(e, self);
|
Chris@16
|
2457
|
Chris@16
|
2458 return std::pair<edge_descriptor, bool>(e, inserted.second);
|
Chris@16
|
2459 }
|
Chris@16
|
2460
|
Chris@16
|
2461 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2462 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
|
Chris@16
|
2463 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::
|
Chris@16
|
2464 add_local_edge(const edge_property_type& property, bidirectionalS) const
|
Chris@16
|
2465 {
|
Chris@16
|
2466 // Add the directed edge.
|
Chris@16
|
2467 std::pair<edge_descriptor, bool> result
|
Chris@16
|
2468 = this->add_local_edge(property, directedS());
|
Chris@16
|
2469
|
Chris@16
|
2470 if (result.second) {
|
Chris@16
|
2471 if (target.owner == self.processor()) {
|
Chris@16
|
2472 // Edge is local, so add the stored edge to the in_edges list
|
Chris@16
|
2473 typedef detail::parallel::stored_in_edge<local_edge_descriptor>
|
Chris@16
|
2474 stored_edge;
|
Chris@16
|
2475
|
Chris@16
|
2476 stored_edge e(self.processor(), result.first.local);
|
Chris@16
|
2477 boost::graph_detail::push(get(vertex_in_edges,
|
Chris@16
|
2478 self.base())[target.local], e);
|
Chris@16
|
2479 }
|
Chris@16
|
2480 else {
|
Chris@16
|
2481 // Edge is remote, so notify the target's owner that an edge
|
Chris@16
|
2482 // has been added.
|
Chris@101
|
2483 if (self.process_group_.trigger_context() == boost::parallel::trc_out_of_band)
|
Chris@16
|
2484 send_oob(self.process_group_, target.owner, msg_nonlocal_edge,
|
Chris@16
|
2485 msg_nonlocal_edge_data(result.first.local, property));
|
Chris@16
|
2486 else
|
Chris@16
|
2487 send(self.process_group_, target.owner, msg_nonlocal_edge,
|
Chris@16
|
2488 msg_nonlocal_edge_data(result.first.local, property));
|
Chris@16
|
2489 }
|
Chris@16
|
2490 }
|
Chris@16
|
2491
|
Chris@16
|
2492 return result;
|
Chris@16
|
2493 }
|
Chris@16
|
2494
|
Chris@16
|
2495 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2496 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
|
Chris@16
|
2497 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::
|
Chris@16
|
2498 add_local_edge(const edge_property_type& property, undirectedS) const
|
Chris@16
|
2499 {
|
Chris@16
|
2500 // Add the directed edge
|
Chris@16
|
2501 std::pair<edge_descriptor, bool> result
|
Chris@16
|
2502 = this->add_local_edge(property, directedS());
|
Chris@16
|
2503
|
Chris@16
|
2504 if (result.second) {
|
Chris@16
|
2505 if (target.owner == self.processor()) {
|
Chris@16
|
2506 // Edge is local, so add the new edge to the list
|
Chris@16
|
2507
|
Chris@16
|
2508 // TODO: This is not what we want to do for an undirected
|
Chris@16
|
2509 // edge, because we haven't linked the source and target's
|
Chris@16
|
2510 // representations of those edges.
|
Chris@16
|
2511 local_edge_descriptor return_edge =
|
Chris@16
|
2512 detail::parallel::add_local_edge(target.local, source.local,
|
Chris@16
|
2513 self.build_edge_property(property),
|
Chris@16
|
2514 self.base()).first;
|
Chris@16
|
2515
|
Chris@16
|
2516 put(edge_target_processor_id, self.base(), return_edge,
|
Chris@16
|
2517 source.owner);
|
Chris@16
|
2518 }
|
Chris@16
|
2519 else {
|
Chris@16
|
2520 // Edge is remote, so notify the target's owner that an edge
|
Chris@16
|
2521 // has been added.
|
Chris@101
|
2522 if (self.process_group_.trigger_context() == boost::parallel::trc_out_of_band)
|
Chris@16
|
2523 send_oob(self.process_group_, target.owner, msg_nonlocal_edge,
|
Chris@16
|
2524 msg_nonlocal_edge_data(result.first.local, property));
|
Chris@16
|
2525 else
|
Chris@16
|
2526 send(self.process_group_, target.owner, msg_nonlocal_edge,
|
Chris@16
|
2527 msg_nonlocal_edge_data(result.first.local, property));
|
Chris@16
|
2528
|
Chris@16
|
2529 }
|
Chris@16
|
2530
|
Chris@16
|
2531 // Add this edge to the list of local edges
|
Chris@16
|
2532 graph_detail::push(self.local_edges(), result.first);
|
Chris@16
|
2533 }
|
Chris@16
|
2534
|
Chris@16
|
2535 return result;
|
Chris@16
|
2536 }
|
Chris@16
|
2537
|
Chris@16
|
2538
|
Chris@16
|
2539 /**
|
Chris@16
|
2540 * Data structure returned from add_edge that will "lazily" add
|
Chris@16
|
2541 * the edge with its property, either when it is converted to a
|
Chris@16
|
2542 * pair<edge_descriptor, bool> or when the most recent copy has
|
Chris@16
|
2543 * been destroyed.
|
Chris@16
|
2544 */
|
Chris@16
|
2545 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2546 struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property
|
Chris@16
|
2547 : lazy_add_edge
|
Chris@16
|
2548 {
|
Chris@16
|
2549 /// Construct a lazy request to add an edge
|
Chris@16
|
2550 lazy_add_edge_with_property(adjacency_list& self,
|
Chris@16
|
2551 vertex_descriptor source,
|
Chris@16
|
2552 vertex_descriptor target,
|
Chris@16
|
2553 const edge_property_type& property)
|
Chris@16
|
2554 : lazy_add_edge(self, source, target), property(property) { }
|
Chris@16
|
2555
|
Chris@16
|
2556 /// Copying a lazy_add_edge transfers the responsibility for
|
Chris@16
|
2557 /// adding the edge to the newly-constructed object.
|
Chris@16
|
2558 lazy_add_edge_with_property(const lazy_add_edge& other)
|
Chris@16
|
2559 : lazy_add_edge(other), property(other.property) { }
|
Chris@16
|
2560
|
Chris@16
|
2561 /// If the edge has not yet been added, add the edge but don't
|
Chris@16
|
2562 /// wait for a reply.
|
Chris@16
|
2563 ~lazy_add_edge_with_property();
|
Chris@16
|
2564
|
Chris@16
|
2565 /// Returns commit().
|
Chris@16
|
2566 operator std::pair<edge_descriptor, bool>() const { return commit(); }
|
Chris@16
|
2567
|
Chris@16
|
2568 // Add the edge. This operation will block if a remote edge is
|
Chris@16
|
2569 // being added.
|
Chris@16
|
2570 std::pair<edge_descriptor, bool> commit() const;
|
Chris@16
|
2571
|
Chris@16
|
2572 private:
|
Chris@16
|
2573 // No copy-assignment semantics
|
Chris@16
|
2574 void operator=(lazy_add_edge_with_property&);
|
Chris@16
|
2575
|
Chris@16
|
2576 edge_property_type property;
|
Chris@16
|
2577 };
|
Chris@16
|
2578
|
Chris@16
|
2579 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2580 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property::
|
Chris@16
|
2581 ~lazy_add_edge_with_property()
|
Chris@16
|
2582 {
|
Chris@16
|
2583 /// If this edge has already been created or will be created by
|
Chris@16
|
2584 /// someone else, or if someone threw an exception, we will not
|
Chris@16
|
2585 /// create the edge now.
|
Chris@16
|
2586 if (this->committed || std::uncaught_exception())
|
Chris@16
|
2587 return;
|
Chris@16
|
2588
|
Chris@16
|
2589 this->committed = true;
|
Chris@16
|
2590
|
Chris@16
|
2591 if (this->source.owner == this->self.processor())
|
Chris@16
|
2592 // Add a local edge
|
Chris@16
|
2593 this->add_local_edge(property, DirectedS());
|
Chris@16
|
2594 else
|
Chris@16
|
2595 // Request that the remote processor add an edge and, but
|
Chris@16
|
2596 // don't wait for a reply.
|
Chris@16
|
2597 send(this->self.process_group_, this->source.owner,
|
Chris@16
|
2598 msg_add_edge_with_property,
|
Chris@16
|
2599 msg_add_edge_with_property_data(this->source, this->target,
|
Chris@16
|
2600 property));
|
Chris@16
|
2601 }
|
Chris@16
|
2602
|
Chris@16
|
2603 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2604 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
|
Chris@16
|
2605 PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property::
|
Chris@16
|
2606 commit() const
|
Chris@16
|
2607 {
|
Chris@16
|
2608 BOOST_ASSERT(!this->committed);
|
Chris@16
|
2609 this->committed = true;
|
Chris@16
|
2610
|
Chris@16
|
2611 if (this->source.owner == this->self.processor())
|
Chris@16
|
2612 // Add a local edge
|
Chris@16
|
2613 return this->add_local_edge(property, DirectedS());
|
Chris@16
|
2614 else {
|
Chris@16
|
2615 // Request that the remote processor add an edge
|
Chris@16
|
2616 boost::parallel::detail::untracked_pair<edge_descriptor, bool> result;
|
Chris@16
|
2617 send_oob_with_reply(this->self.process_group_, this->source.owner,
|
Chris@16
|
2618 msg_add_edge_with_property_and_reply,
|
Chris@16
|
2619 msg_add_edge_with_property_data(this->source,
|
Chris@16
|
2620 this->target,
|
Chris@16
|
2621 property),
|
Chris@16
|
2622 result);
|
Chris@16
|
2623 return result;
|
Chris@16
|
2624 }
|
Chris@16
|
2625 }
|
Chris@16
|
2626
|
Chris@16
|
2627
|
Chris@16
|
2628 /**
|
Chris@16
|
2629 * Returns the set of vertices local to this processor. Note that
|
Chris@16
|
2630 * although this routine matches a valid expression of a
|
Chris@16
|
2631 * VertexListGraph, it does not meet the semantic requirements of
|
Chris@16
|
2632 * VertexListGraph because it returns only local vertices (not all
|
Chris@16
|
2633 * vertices).
|
Chris@16
|
2634 */
|
Chris@16
|
2635 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2636 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
2637 ::vertex_iterator,
|
Chris@16
|
2638 typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
2639 ::vertex_iterator>
|
Chris@16
|
2640 vertices(const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2641 {
|
Chris@16
|
2642 typedef typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
2643 ::vertex_descriptor Vertex;
|
Chris@16
|
2644
|
Chris@16
|
2645 typedef typename Vertex::generator generator;
|
Chris@16
|
2646
|
Chris@16
|
2647 return std::make_pair(make_transform_iterator(vertices(g.base()).first,
|
Chris@16
|
2648 generator(g.processor())),
|
Chris@16
|
2649 make_transform_iterator(vertices(g.base()).second,
|
Chris@16
|
2650 generator(g.processor())));
|
Chris@16
|
2651 }
|
Chris@16
|
2652
|
Chris@16
|
2653 /**
|
Chris@16
|
2654 * Returns the number of vertices local to this processor. Note that
|
Chris@16
|
2655 * although this routine matches a valid expression of a
|
Chris@16
|
2656 * VertexListGraph, it does not meet the semantic requirements of
|
Chris@16
|
2657 * VertexListGraph because it returns only a count of local vertices
|
Chris@16
|
2658 * (not all vertices).
|
Chris@16
|
2659 */
|
Chris@16
|
2660 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2661 typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
2662 ::vertices_size_type
|
Chris@16
|
2663 num_vertices(const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2664 {
|
Chris@16
|
2665 return num_vertices(g.base());
|
Chris@16
|
2666 }
|
Chris@16
|
2667
|
Chris@16
|
2668 /***************************************************************************
|
Chris@16
|
2669 * Implementation of Incidence Graph concept
|
Chris@16
|
2670 ***************************************************************************/
|
Chris@16
|
2671 /**
|
Chris@16
|
2672 * Returns the source of edge @param e in @param g.
|
Chris@16
|
2673 */
|
Chris@16
|
2674 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Edge>
|
Chris@16
|
2675 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
|
Chris@16
|
2676 source(const detail::parallel::edge_descriptor<Edge>& e,
|
Chris@16
|
2677 const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2678 {
|
Chris@16
|
2679 typedef typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
2680 ::vertex_descriptor Vertex;
|
Chris@16
|
2681 return Vertex(e.source_processor, source(e.local, g.base()));
|
Chris@16
|
2682 }
|
Chris@16
|
2683
|
Chris@16
|
2684 /**
|
Chris@16
|
2685 * Returns the target of edge @param e in @param g.
|
Chris@16
|
2686 */
|
Chris@16
|
2687 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Edge>
|
Chris@16
|
2688 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
|
Chris@16
|
2689 target(const detail::parallel::edge_descriptor<Edge>& e,
|
Chris@16
|
2690 const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2691 {
|
Chris@16
|
2692 typedef typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
2693 ::vertex_descriptor Vertex;
|
Chris@16
|
2694 return Vertex(e.target_processor, target(e.local, g.base()));
|
Chris@16
|
2695 }
|
Chris@16
|
2696
|
Chris@16
|
2697 /**
|
Chris@16
|
2698 * Return the set of edges outgoing from a particular vertex. The
|
Chris@16
|
2699 * vertex @param v must be local to the processor executing this
|
Chris@16
|
2700 * routine.
|
Chris@16
|
2701 */
|
Chris@16
|
2702 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2703 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator,
|
Chris@16
|
2704 typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator>
|
Chris@16
|
2705 out_edges(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
|
Chris@16
|
2706 const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2707 {
|
Chris@16
|
2708 BOOST_ASSERT(v.owner == g.processor());
|
Chris@16
|
2709
|
Chris@16
|
2710 typedef PBGL_DISTRIB_ADJLIST_TYPE impl;
|
Chris@16
|
2711 typedef typename impl::out_edge_generator generator;
|
Chris@16
|
2712
|
Chris@16
|
2713 return std::make_pair(
|
Chris@16
|
2714 make_transform_iterator(out_edges(v.local, g.base()).first,
|
Chris@16
|
2715 generator(g)),
|
Chris@16
|
2716 make_transform_iterator(out_edges(v.local, g.base()).second,
|
Chris@16
|
2717 generator(g)));
|
Chris@16
|
2718 }
|
Chris@16
|
2719
|
Chris@16
|
2720 /**
|
Chris@16
|
2721 * Return the number of edges outgoing from a particular vertex. The
|
Chris@16
|
2722 * vertex @param v must be local to the processor executing this
|
Chris@16
|
2723 * routine.
|
Chris@16
|
2724 */
|
Chris@16
|
2725 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2726 typename PBGL_DISTRIB_ADJLIST_TYPE::degree_size_type
|
Chris@16
|
2727 out_degree(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
|
Chris@16
|
2728 const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2729 {
|
Chris@16
|
2730 BOOST_ASSERT(v.owner == g.processor());
|
Chris@16
|
2731
|
Chris@16
|
2732 return out_degree(v.local, g.base());
|
Chris@16
|
2733 }
|
Chris@16
|
2734
|
Chris@16
|
2735 /***************************************************************************
|
Chris@16
|
2736 * Implementation of Bidirectional Graph concept
|
Chris@16
|
2737 ***************************************************************************/
|
Chris@16
|
2738 /**
|
Chris@16
|
2739 * Returns the set of edges incoming to a particular vertex. The
|
Chris@16
|
2740 * vertex @param v must be local to the processor executing this
|
Chris@16
|
2741 * routine.
|
Chris@16
|
2742 */
|
Chris@16
|
2743 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2744 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
2745 ::in_edge_iterator,
|
Chris@16
|
2746 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
2747 ::in_edge_iterator>
|
Chris@16
|
2748 in_edges(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
2749 ::vertex_descriptor v,
|
Chris@16
|
2750 const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
|
Chris@16
|
2751 {
|
Chris@16
|
2752 BOOST_ASSERT(v.owner == g.processor());
|
Chris@16
|
2753
|
Chris@16
|
2754 typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) impl;
|
Chris@16
|
2755 typedef typename impl::inherited base_graph_type;
|
Chris@16
|
2756 typedef typename impl::in_edge_generator generator;
|
Chris@16
|
2757
|
Chris@16
|
2758
|
Chris@16
|
2759 typename property_map<base_graph_type, vertex_in_edges_t>::const_type
|
Chris@16
|
2760 in_edges = get(vertex_in_edges, g.base());
|
Chris@16
|
2761
|
Chris@16
|
2762 return std::make_pair(make_transform_iterator(in_edges[v.local].begin(),
|
Chris@16
|
2763 generator(g)),
|
Chris@16
|
2764 make_transform_iterator(in_edges[v.local].end(),
|
Chris@16
|
2765 generator(g)));
|
Chris@16
|
2766 }
|
Chris@16
|
2767
|
Chris@16
|
2768 /**
|
Chris@16
|
2769 * \overload
|
Chris@16
|
2770 */
|
Chris@16
|
2771 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2772 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
|
Chris@16
|
2773 ::in_edge_iterator,
|
Chris@16
|
2774 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
|
Chris@16
|
2775 ::in_edge_iterator>
|
Chris@16
|
2776 in_edges(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
|
Chris@16
|
2777 ::vertex_descriptor v,
|
Chris@16
|
2778 const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
|
Chris@16
|
2779 {
|
Chris@16
|
2780 BOOST_ASSERT(v.owner == g.processor());
|
Chris@16
|
2781
|
Chris@16
|
2782 typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) impl;
|
Chris@16
|
2783 typedef typename impl::in_edge_generator generator;
|
Chris@16
|
2784
|
Chris@16
|
2785 return std::make_pair(
|
Chris@16
|
2786 make_transform_iterator(out_edges(v.local, g.base()).first,
|
Chris@16
|
2787 generator(g)),
|
Chris@16
|
2788 make_transform_iterator(out_edges(v.local, g.base()).second,
|
Chris@16
|
2789 generator(g)));
|
Chris@16
|
2790 }
|
Chris@16
|
2791
|
Chris@16
|
2792 /**
|
Chris@16
|
2793 * Returns the number of edges incoming to a particular vertex. The
|
Chris@16
|
2794 * vertex @param v must be local to the processor executing this
|
Chris@16
|
2795 * routine.
|
Chris@16
|
2796 */
|
Chris@16
|
2797 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2798 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)::degree_size_type
|
Chris@16
|
2799 in_degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
2800 ::vertex_descriptor v,
|
Chris@16
|
2801 const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
|
Chris@16
|
2802 {
|
Chris@16
|
2803 BOOST_ASSERT(v.owner == g.processor());
|
Chris@16
|
2804
|
Chris@16
|
2805 return get(vertex_in_edges, g.base())[v.local].size();
|
Chris@16
|
2806 }
|
Chris@16
|
2807
|
Chris@16
|
2808 /**
|
Chris@16
|
2809 * \overload
|
Chris@16
|
2810 */
|
Chris@16
|
2811 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2812 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::degree_size_type
|
Chris@16
|
2813 in_degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
|
Chris@16
|
2814 ::vertex_descriptor v,
|
Chris@16
|
2815 const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
|
Chris@16
|
2816 {
|
Chris@16
|
2817 BOOST_ASSERT(v.owner == g.processor());
|
Chris@16
|
2818
|
Chris@16
|
2819 return out_degree(v.local, g.base());
|
Chris@16
|
2820 }
|
Chris@16
|
2821
|
Chris@16
|
2822 /**
|
Chris@16
|
2823 * Returns the number of edges incident on the given vertex. The
|
Chris@16
|
2824 * vertex @param v must be local to the processor executing this
|
Chris@16
|
2825 * routine.
|
Chris@16
|
2826 */
|
Chris@16
|
2827 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2828 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
|
Chris@16
|
2829 ::degree_size_type
|
Chris@16
|
2830 degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
|
Chris@16
|
2831 ::vertex_descriptor v,
|
Chris@16
|
2832 const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
|
Chris@16
|
2833 {
|
Chris@16
|
2834 BOOST_ASSERT(v.owner == g.processor());
|
Chris@16
|
2835 return out_degree(v.local, g.base());
|
Chris@16
|
2836 }
|
Chris@16
|
2837
|
Chris@16
|
2838 /**
|
Chris@16
|
2839 * \overload
|
Chris@16
|
2840 */
|
Chris@16
|
2841 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2842 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
2843 ::degree_size_type
|
Chris@16
|
2844 degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
2845 ::vertex_descriptor v,
|
Chris@16
|
2846 const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
|
Chris@16
|
2847 {
|
Chris@16
|
2848 BOOST_ASSERT(v.owner == g.processor());
|
Chris@16
|
2849 return out_degree(v, g) + in_degree(v, g);
|
Chris@16
|
2850 }
|
Chris@16
|
2851
|
Chris@16
|
2852 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2853 typename PBGL_DISTRIB_ADJLIST_TYPE::edges_size_type
|
Chris@16
|
2854 num_edges(const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2855 {
|
Chris@16
|
2856 return num_edges(g.base());
|
Chris@16
|
2857 }
|
Chris@16
|
2858
|
Chris@16
|
2859 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2860 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edges_size_type
|
Chris@16
|
2861 num_edges(const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
|
Chris@16
|
2862 {
|
Chris@16
|
2863 return g.local_edges().size();
|
Chris@16
|
2864 }
|
Chris@16
|
2865
|
Chris@16
|
2866 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2867 std::pair<
|
Chris@16
|
2868 typename PBGL_DISTRIB_ADJLIST_TYPE::edge_iterator,
|
Chris@16
|
2869 typename PBGL_DISTRIB_ADJLIST_TYPE::edge_iterator>
|
Chris@16
|
2870 edges(const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2871 {
|
Chris@16
|
2872 typedef PBGL_DISTRIB_ADJLIST_TYPE impl;
|
Chris@16
|
2873 typedef typename impl::out_edge_generator generator;
|
Chris@16
|
2874
|
Chris@16
|
2875 return std::make_pair(make_transform_iterator(edges(g.base()).first,
|
Chris@16
|
2876 generator(g)),
|
Chris@16
|
2877 make_transform_iterator(edges(g.base()).second,
|
Chris@16
|
2878 generator(g)));
|
Chris@16
|
2879 }
|
Chris@16
|
2880
|
Chris@16
|
2881 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2882 std::pair<
|
Chris@16
|
2883 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edge_iterator,
|
Chris@16
|
2884 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edge_iterator>
|
Chris@16
|
2885 edges(const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
|
Chris@16
|
2886 {
|
Chris@16
|
2887 return std::make_pair(g.local_edges().begin(), g.local_edges().end());
|
Chris@16
|
2888 }
|
Chris@16
|
2889
|
Chris@16
|
2890 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2891 inline
|
Chris@16
|
2892 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
|
Chris@16
|
2893 vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertices_size_type n,
|
Chris@16
|
2894 const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2895 {
|
Chris@16
|
2896 typedef typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
|
Chris@16
|
2897 vertex_descriptor;
|
Chris@16
|
2898
|
Chris@16
|
2899 return vertex_descriptor(g.distribution()(n), g.distribution().local(n));
|
Chris@16
|
2900 }
|
Chris@16
|
2901
|
Chris@16
|
2902 /***************************************************************************
|
Chris@16
|
2903 * Access to particular edges
|
Chris@16
|
2904 ***************************************************************************/
|
Chris@16
|
2905 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
2906 std::pair<
|
Chris@16
|
2907 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::edge_descriptor,
|
Chris@16
|
2908 bool
|
Chris@16
|
2909 >
|
Chris@16
|
2910 edge(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor u,
|
Chris@16
|
2911 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor v,
|
Chris@16
|
2912 const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g)
|
Chris@16
|
2913 {
|
Chris@16
|
2914 typedef typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)
|
Chris@16
|
2915 ::edge_descriptor edge_descriptor;
|
Chris@16
|
2916
|
Chris@16
|
2917 // For directed graphs, u must be local
|
Chris@16
|
2918 BOOST_ASSERT(u.owner == process_id(g.process_group()));
|
Chris@16
|
2919
|
Chris@16
|
2920 typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)
|
Chris@16
|
2921 ::out_edge_iterator ei, ei_end;
|
Chris@16
|
2922 for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
|
Chris@16
|
2923 if (target(*ei, g) == v) return std::make_pair(*ei, true);
|
Chris@16
|
2924 }
|
Chris@16
|
2925 return std::make_pair(edge_descriptor(), false);
|
Chris@16
|
2926 }
|
Chris@16
|
2927
|
Chris@16
|
2928 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2929 std::pair<
|
Chris@16
|
2930 typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor,
|
Chris@16
|
2931 bool
|
Chris@16
|
2932 >
|
Chris@16
|
2933 edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
|
Chris@16
|
2934 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
|
Chris@16
|
2935 const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2936 {
|
Chris@16
|
2937 typedef typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
2938 ::edge_descriptor edge_descriptor;
|
Chris@16
|
2939
|
Chris@16
|
2940 // For bidirectional and undirected graphs, u must be local or v
|
Chris@16
|
2941 // must be local
|
Chris@16
|
2942 if (u.owner == process_id(g.process_group())) {
|
Chris@16
|
2943 typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator ei, ei_end;
|
Chris@16
|
2944 for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
|
Chris@16
|
2945 if (target(*ei, g) == v) return std::make_pair(*ei, true);
|
Chris@16
|
2946 }
|
Chris@16
|
2947 return std::make_pair(edge_descriptor(), false);
|
Chris@16
|
2948 } else if (v.owner == process_id(g.process_group())) {
|
Chris@16
|
2949 typename PBGL_DISTRIB_ADJLIST_TYPE::in_edge_iterator ei, ei_end;
|
Chris@16
|
2950 for (boost::tie(ei, ei_end) = in_edges(v, g); ei != ei_end; ++ei) {
|
Chris@16
|
2951 if (source(*ei, g) == u) return std::make_pair(*ei, true);
|
Chris@16
|
2952 }
|
Chris@16
|
2953 return std::make_pair(edge_descriptor(), false);
|
Chris@16
|
2954 } else {
|
Chris@16
|
2955 BOOST_ASSERT(false);
|
Chris@16
|
2956 abort();
|
Chris@16
|
2957 }
|
Chris@16
|
2958 }
|
Chris@16
|
2959
|
Chris@16
|
2960 #if 0
|
Chris@16
|
2961 // TBD: not yet supported
|
Chris@16
|
2962 std::pair<out_edge_iterator, out_edge_iterator>
|
Chris@16
|
2963 edge_range(vertex_descriptor u, vertex_descriptor v,
|
Chris@16
|
2964 const adjacency_list& g);
|
Chris@16
|
2965 #endif
|
Chris@16
|
2966
|
Chris@16
|
2967 /***************************************************************************
|
Chris@16
|
2968 * Implementation of Adjacency Graph concept
|
Chris@16
|
2969 ***************************************************************************/
|
Chris@16
|
2970 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2971 std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::adjacency_iterator,
|
Chris@16
|
2972 typename PBGL_DISTRIB_ADJLIST_TYPE::adjacency_iterator>
|
Chris@16
|
2973 adjacent_vertices(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
|
Chris@16
|
2974 const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2975 {
|
Chris@16
|
2976 typedef typename PBGL_DISTRIB_ADJLIST_TYPE::adjacency_iterator iter;
|
Chris@16
|
2977 return std::make_pair(iter(out_edges(v, g).first, &g),
|
Chris@16
|
2978 iter(out_edges(v, g).second, &g));
|
Chris@16
|
2979 }
|
Chris@16
|
2980
|
Chris@16
|
2981 /***************************************************************************
|
Chris@16
|
2982 * Implementation of Mutable Graph concept
|
Chris@16
|
2983 ***************************************************************************/
|
Chris@16
|
2984
|
Chris@16
|
2985 /************************************************************************
|
Chris@16
|
2986 * add_edge
|
Chris@16
|
2987 ************************************************************************/
|
Chris@16
|
2988 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
2989 typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge
|
Chris@16
|
2990 add_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
|
Chris@16
|
2991 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
|
Chris@16
|
2992 PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
2993 {
|
Chris@16
|
2994 typedef typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge lazy_add_edge;
|
Chris@16
|
2995
|
Chris@16
|
2996 return lazy_add_edge(g, u, v);
|
Chris@16
|
2997 }
|
Chris@16
|
2998
|
Chris@16
|
2999 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3000 typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
3001 ::lazy_add_edge_with_property
|
Chris@16
|
3002 add_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
|
Chris@16
|
3003 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
|
Chris@16
|
3004 typename PBGL_DISTRIB_ADJLIST_TYPE::edge_property_type const& p,
|
Chris@16
|
3005 PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3006 {
|
Chris@16
|
3007 typedef typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
3008 ::lazy_add_edge_with_property lazy_add_edge_with_property;
|
Chris@16
|
3009 return lazy_add_edge_with_property(g, u, v, p);
|
Chris@16
|
3010 }
|
Chris@16
|
3011
|
Chris@16
|
3012 /************************************************************************
|
Chris@16
|
3013 *
|
Chris@16
|
3014 * remove_edge
|
Chris@16
|
3015 *
|
Chris@16
|
3016 ************************************************************************/
|
Chris@16
|
3017 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3018 void
|
Chris@16
|
3019 remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor e,
|
Chris@16
|
3020 PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3021 {
|
Chris@16
|
3022 BOOST_ASSERT(source(e, g).owner == g.processor()
|
Chris@16
|
3023 || target(e, g).owner == g.processor());
|
Chris@16
|
3024
|
Chris@16
|
3025 if (target(e, g).owner == g.processor())
|
Chris@16
|
3026 detail::parallel::remove_in_edge(e, g, DirectedS());
|
Chris@16
|
3027 if (source(e, g).owner == g.processor())
|
Chris@16
|
3028 remove_edge(e.local, g.base());
|
Chris@16
|
3029
|
Chris@16
|
3030 g.remove_local_edge_from_list(source(e, g), target(e, g), DirectedS());
|
Chris@16
|
3031
|
Chris@16
|
3032 if (source(e, g).owner != g.processor()
|
Chris@16
|
3033 || (target(e, g).owner != g.processor()
|
Chris@16
|
3034 && !(is_same<DirectedS, directedS>::value))) {
|
Chris@16
|
3035 g.send_remove_edge_request(e);
|
Chris@16
|
3036 }
|
Chris@16
|
3037 }
|
Chris@16
|
3038
|
Chris@16
|
3039 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3040 void
|
Chris@16
|
3041 remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
|
Chris@16
|
3042 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
|
Chris@16
|
3043 PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3044 {
|
Chris@16
|
3045 typedef typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
3046 ::edge_descriptor edge_descriptor;
|
Chris@16
|
3047 std::pair<edge_descriptor, bool> the_edge = edge(u, v, g);
|
Chris@16
|
3048 if (the_edge.second) remove_edge(the_edge.first, g);
|
Chris@16
|
3049 }
|
Chris@16
|
3050
|
Chris@16
|
3051 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3052 inline void
|
Chris@16
|
3053 remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator ei,
|
Chris@16
|
3054 PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3055 {
|
Chris@16
|
3056 remove_edge(*ei, g);
|
Chris@16
|
3057 }
|
Chris@16
|
3058
|
Chris@16
|
3059 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
3060 inline void
|
Chris@16
|
3061 remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)
|
Chris@16
|
3062 ::out_edge_iterator ei,
|
Chris@16
|
3063 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g)
|
Chris@16
|
3064 {
|
Chris@16
|
3065 BOOST_ASSERT(source(*ei, g).owner == g.processor());
|
Chris@16
|
3066 remove_edge(ei->local, g.base());
|
Chris@16
|
3067 }
|
Chris@16
|
3068
|
Chris@16
|
3069 /************************************************************************
|
Chris@16
|
3070 *
|
Chris@16
|
3071 * remove_out_edge_if
|
Chris@16
|
3072 *
|
Chris@16
|
3073 ************************************************************************/
|
Chris@16
|
3074 namespace parallel { namespace detail {
|
Chris@16
|
3075 /**
|
Chris@16
|
3076 * Function object that applies the underlying predicate to
|
Chris@16
|
3077 * determine if an out-edge should be removed. If so, either
|
Chris@16
|
3078 * removes the incoming edge (if it is stored locally) or sends a
|
Chris@16
|
3079 * message to the owner of the target requesting that it remove
|
Chris@16
|
3080 * the edge.
|
Chris@16
|
3081 */
|
Chris@16
|
3082 template<typename Graph, typename Predicate>
|
Chris@16
|
3083 struct remove_out_edge_predicate
|
Chris@16
|
3084 {
|
Chris@16
|
3085 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
Chris@16
|
3086 typedef typename Graph::local_edge_descriptor argument_type;
|
Chris@16
|
3087 typedef typename Graph::directed_selector directed_selector;
|
Chris@16
|
3088 typedef bool result_type;
|
Chris@16
|
3089
|
Chris@16
|
3090 remove_out_edge_predicate(Graph& g, Predicate& predicate)
|
Chris@16
|
3091 : g(g), predicate(predicate) { }
|
Chris@16
|
3092
|
Chris@16
|
3093 bool operator()(const argument_type& le)
|
Chris@16
|
3094 {
|
Chris@16
|
3095 typedef typename edge_descriptor::template out_generator<Graph>
|
Chris@16
|
3096 generator;
|
Chris@16
|
3097
|
Chris@16
|
3098 edge_descriptor e = generator(g)(le);
|
Chris@16
|
3099
|
Chris@16
|
3100 if (predicate(e)) {
|
Chris@16
|
3101 if (source(e, g).owner != target(e, g).owner
|
Chris@16
|
3102 && !(is_same<directed_selector, directedS>::value))
|
Chris@16
|
3103 g.send_remove_edge_request(e);
|
Chris@16
|
3104 else
|
Chris@16
|
3105 ::boost::detail::parallel::remove_in_edge(e, g,
|
Chris@16
|
3106 directed_selector());
|
Chris@16
|
3107
|
Chris@16
|
3108 g.remove_local_edge_from_list(source(e, g), target(e, g),
|
Chris@16
|
3109 directed_selector());
|
Chris@16
|
3110 return true;
|
Chris@16
|
3111 } else return false;
|
Chris@16
|
3112 }
|
Chris@16
|
3113
|
Chris@16
|
3114 private:
|
Chris@16
|
3115 Graph& g;
|
Chris@16
|
3116 Predicate predicate;
|
Chris@16
|
3117 };
|
Chris@16
|
3118 } } // end namespace parallel::detail
|
Chris@16
|
3119
|
Chris@16
|
3120 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Predicate>
|
Chris@16
|
3121 inline void
|
Chris@16
|
3122 remove_out_edge_if
|
Chris@16
|
3123 (typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
|
Chris@16
|
3124 Predicate predicate,
|
Chris@16
|
3125 PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3126 {
|
Chris@16
|
3127 typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
|
Chris@16
|
3128 typedef parallel::detail::remove_out_edge_predicate<Graph, Predicate>
|
Chris@16
|
3129 Pred;
|
Chris@16
|
3130
|
Chris@16
|
3131 BOOST_ASSERT(u.owner == g.processor());
|
Chris@16
|
3132 remove_out_edge_if(u.local, Pred(g, predicate), g.base());
|
Chris@16
|
3133 }
|
Chris@16
|
3134
|
Chris@16
|
3135 /************************************************************************
|
Chris@16
|
3136 *
|
Chris@16
|
3137 * remove_in_edge_if
|
Chris@16
|
3138 *
|
Chris@16
|
3139 ************************************************************************/
|
Chris@16
|
3140 namespace parallel { namespace detail {
|
Chris@16
|
3141 /**
|
Chris@16
|
3142 * Function object that applies the underlying predicate to
|
Chris@16
|
3143 * determine if an in-edge should be removed. If so, either
|
Chris@16
|
3144 * removes the outgoing edge (if it is stored locally) or sends a
|
Chris@16
|
3145 * message to the owner of the target requesting that it remove
|
Chris@16
|
3146 * the edge. Only required for bidirectional graphs.
|
Chris@16
|
3147 */
|
Chris@16
|
3148 template<typename Graph, typename Predicate>
|
Chris@16
|
3149 struct remove_in_edge_predicate
|
Chris@16
|
3150 {
|
Chris@16
|
3151 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
Chris@16
|
3152 typedef bool result_type;
|
Chris@16
|
3153
|
Chris@16
|
3154 remove_in_edge_predicate(Graph& g, const Predicate& predicate)
|
Chris@16
|
3155 : g(g), predicate(predicate) { }
|
Chris@16
|
3156
|
Chris@16
|
3157 template<typename StoredEdge>
|
Chris@16
|
3158 bool operator()(const StoredEdge& le)
|
Chris@16
|
3159 {
|
Chris@16
|
3160 typedef typename edge_descriptor::template in_generator<Graph>
|
Chris@16
|
3161 generator;
|
Chris@16
|
3162
|
Chris@16
|
3163 edge_descriptor e = generator(g)(le);
|
Chris@16
|
3164
|
Chris@16
|
3165 if (predicate(e)) {
|
Chris@16
|
3166 if (source(e, g).owner != target(e, g).owner)
|
Chris@16
|
3167 g.send_remove_edge_request(e);
|
Chris@16
|
3168 else
|
Chris@16
|
3169 remove_edge(source(e, g).local, target(e, g).local, g.base());
|
Chris@16
|
3170 return true;
|
Chris@16
|
3171 } else return false;
|
Chris@16
|
3172 }
|
Chris@16
|
3173
|
Chris@16
|
3174 private:
|
Chris@16
|
3175 Graph& g;
|
Chris@16
|
3176 Predicate predicate;
|
Chris@16
|
3177 };
|
Chris@16
|
3178 } } // end namespace parallel::detail
|
Chris@16
|
3179
|
Chris@16
|
3180 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
|
Chris@16
|
3181 inline void
|
Chris@16
|
3182 remove_in_edge_if
|
Chris@16
|
3183 (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
3184 ::vertex_descriptor u,
|
Chris@16
|
3185 Predicate predicate,
|
Chris@16
|
3186 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
|
Chris@16
|
3187 {
|
Chris@16
|
3188 typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Graph;
|
Chris@16
|
3189 typedef parallel::detail::remove_in_edge_predicate<Graph, Predicate>
|
Chris@16
|
3190 Pred;
|
Chris@16
|
3191
|
Chris@16
|
3192 BOOST_ASSERT(u.owner == g.processor());
|
Chris@16
|
3193 graph_detail::erase_if(get(vertex_in_edges, g.base())[u.local],
|
Chris@16
|
3194 Pred(g, predicate));
|
Chris@16
|
3195 }
|
Chris@16
|
3196
|
Chris@16
|
3197 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
|
Chris@16
|
3198 inline void
|
Chris@16
|
3199 remove_in_edge_if
|
Chris@16
|
3200 (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
|
Chris@16
|
3201 ::vertex_descriptor u,
|
Chris@16
|
3202 Predicate predicate,
|
Chris@16
|
3203 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
|
Chris@16
|
3204 {
|
Chris@16
|
3205 remove_out_edge_if(u, predicate, g);
|
Chris@16
|
3206 }
|
Chris@16
|
3207
|
Chris@16
|
3208 /************************************************************************
|
Chris@16
|
3209 *
|
Chris@16
|
3210 * remove_edge_if
|
Chris@16
|
3211 *
|
Chris@16
|
3212 ************************************************************************/
|
Chris@16
|
3213 namespace parallel { namespace detail {
|
Chris@16
|
3214 /**
|
Chris@16
|
3215 * Function object that applies the underlying predicate to
|
Chris@16
|
3216 * determine if a directed edge can be removed. This only applies
|
Chris@16
|
3217 * to directed graphs.
|
Chris@16
|
3218 */
|
Chris@16
|
3219 template<typename Graph, typename Predicate>
|
Chris@16
|
3220 struct remove_directed_edge_predicate
|
Chris@16
|
3221 {
|
Chris@16
|
3222 typedef typename Graph::local_edge_descriptor argument_type;
|
Chris@16
|
3223 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
Chris@16
|
3224 typedef bool result_type;
|
Chris@16
|
3225
|
Chris@16
|
3226 remove_directed_edge_predicate(Graph& g, const Predicate& predicate)
|
Chris@16
|
3227 : g(g), predicate(predicate) { }
|
Chris@16
|
3228
|
Chris@16
|
3229 bool operator()(const argument_type& le)
|
Chris@16
|
3230 {
|
Chris@16
|
3231 typedef typename edge_descriptor::template out_generator<Graph>
|
Chris@16
|
3232 generator;
|
Chris@16
|
3233
|
Chris@16
|
3234 edge_descriptor e = generator(g)(le);
|
Chris@16
|
3235 return predicate(e);
|
Chris@16
|
3236 }
|
Chris@16
|
3237
|
Chris@16
|
3238 private:
|
Chris@16
|
3239 Graph& g;
|
Chris@16
|
3240 Predicate predicate;
|
Chris@16
|
3241 };
|
Chris@16
|
3242 } } // end namespace parallel::detail
|
Chris@16
|
3243
|
Chris@16
|
3244 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
|
Chris@16
|
3245 inline void
|
Chris@16
|
3246 remove_edge_if(Predicate predicate,
|
Chris@16
|
3247 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g)
|
Chris@16
|
3248 {
|
Chris@16
|
3249 typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS) Graph;
|
Chris@16
|
3250 typedef parallel::detail::remove_directed_edge_predicate<Graph,
|
Chris@16
|
3251 Predicate> Pred;
|
Chris@16
|
3252 remove_edge_if(Pred(g, predicate), g.base());
|
Chris@16
|
3253 }
|
Chris@16
|
3254
|
Chris@16
|
3255 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
|
Chris@16
|
3256 inline void
|
Chris@16
|
3257 remove_edge_if(Predicate predicate,
|
Chris@16
|
3258 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
|
Chris@16
|
3259 {
|
Chris@16
|
3260 typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Graph;
|
Chris@16
|
3261 typedef parallel::detail::remove_out_edge_predicate<Graph,
|
Chris@16
|
3262 Predicate> Pred;
|
Chris@16
|
3263 remove_edge_if(Pred(g, predicate), g.base());
|
Chris@16
|
3264 }
|
Chris@16
|
3265
|
Chris@16
|
3266 namespace parallel { namespace detail {
|
Chris@16
|
3267 /**
|
Chris@16
|
3268 * Function object that applies the underlying predicate to
|
Chris@16
|
3269 * determine if an undirected edge should be removed. If so,
|
Chris@16
|
3270 * removes the local edges associated with the edge and
|
Chris@16
|
3271 * (potentially) sends a message to the remote processor that also
|
Chris@16
|
3272 * is removing this edge.
|
Chris@16
|
3273 */
|
Chris@16
|
3274 template<typename Graph, typename Predicate>
|
Chris@16
|
3275 struct remove_undirected_edge_predicate
|
Chris@16
|
3276 {
|
Chris@16
|
3277 typedef typename graph_traits<Graph>::edge_descriptor argument_type;
|
Chris@16
|
3278 typedef bool result_type;
|
Chris@16
|
3279
|
Chris@16
|
3280 remove_undirected_edge_predicate(Graph& g, Predicate& predicate)
|
Chris@16
|
3281 : g(g), predicate(predicate) { }
|
Chris@16
|
3282
|
Chris@16
|
3283 bool operator()(const argument_type& e)
|
Chris@16
|
3284 {
|
Chris@16
|
3285 if (predicate(e)) {
|
Chris@16
|
3286 if (source(e, g).owner != target(e, g).owner)
|
Chris@16
|
3287 g.send_remove_edge_request(e);
|
Chris@16
|
3288 if (target(e, g).owner == g.processor())
|
Chris@16
|
3289 ::boost::detail::parallel::remove_in_edge(e, g, undirectedS());
|
Chris@16
|
3290 if (source(e, g).owner == g.processor())
|
Chris@16
|
3291 remove_edge(e.local, g.base());
|
Chris@16
|
3292 return true;
|
Chris@16
|
3293 } else return false;
|
Chris@16
|
3294 }
|
Chris@16
|
3295
|
Chris@16
|
3296 private:
|
Chris@16
|
3297 Graph& g;
|
Chris@16
|
3298 Predicate predicate;
|
Chris@16
|
3299 };
|
Chris@16
|
3300 } } // end namespace parallel::detail
|
Chris@16
|
3301
|
Chris@16
|
3302 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
|
Chris@16
|
3303 inline void
|
Chris@16
|
3304 remove_edge_if(Predicate predicate,
|
Chris@16
|
3305 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
|
Chris@16
|
3306 {
|
Chris@16
|
3307 typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Graph;
|
Chris@16
|
3308 typedef parallel::detail::remove_undirected_edge_predicate<Graph,
|
Chris@16
|
3309 Predicate> Pred;
|
Chris@16
|
3310 graph_detail::erase_if(g.local_edges(), Pred(g, predicate));
|
Chris@16
|
3311 }
|
Chris@16
|
3312
|
Chris@16
|
3313 /************************************************************************
|
Chris@16
|
3314 *
|
Chris@16
|
3315 * clear_vertex
|
Chris@16
|
3316 *
|
Chris@16
|
3317 ************************************************************************/
|
Chris@16
|
3318 namespace parallel { namespace detail {
|
Chris@16
|
3319 struct always_true
|
Chris@16
|
3320 {
|
Chris@16
|
3321 typedef bool result_type;
|
Chris@16
|
3322
|
Chris@16
|
3323 template<typename T> bool operator()(const T&) const { return true; }
|
Chris@16
|
3324 };
|
Chris@16
|
3325 } } // end namespace parallel::detail
|
Chris@16
|
3326
|
Chris@16
|
3327 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
3328 void
|
Chris@16
|
3329 clear_vertex
|
Chris@16
|
3330 (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
3331 ::vertex_descriptor u,
|
Chris@16
|
3332 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
|
Chris@16
|
3333 {
|
Chris@16
|
3334 clear_out_edges(u, g);
|
Chris@16
|
3335 clear_in_edges(u, g);
|
Chris@16
|
3336 }
|
Chris@16
|
3337
|
Chris@16
|
3338 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
3339 void
|
Chris@16
|
3340 clear_vertex
|
Chris@16
|
3341 (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
|
Chris@16
|
3342 ::vertex_descriptor u,
|
Chris@16
|
3343 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
|
Chris@16
|
3344 {
|
Chris@16
|
3345 remove_out_edge_if(u, parallel::detail::always_true(), g);
|
Chris@16
|
3346 }
|
Chris@16
|
3347
|
Chris@16
|
3348 /************************************************************************
|
Chris@16
|
3349 *
|
Chris@16
|
3350 * clear_out_edges
|
Chris@16
|
3351 *
|
Chris@16
|
3352 ************************************************************************/
|
Chris@16
|
3353 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
3354 void
|
Chris@16
|
3355 clear_out_edges
|
Chris@16
|
3356 (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor u,
|
Chris@16
|
3357 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g)
|
Chris@16
|
3358 {
|
Chris@16
|
3359 BOOST_ASSERT(u.owner == g.processor());
|
Chris@16
|
3360 clear_out_edges(u.local, g.base());
|
Chris@16
|
3361 }
|
Chris@16
|
3362
|
Chris@16
|
3363 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
3364 void
|
Chris@16
|
3365 clear_out_edges
|
Chris@16
|
3366 (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
3367 ::vertex_descriptor u,
|
Chris@16
|
3368 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
|
Chris@16
|
3369 {
|
Chris@16
|
3370 remove_out_edge_if(u, parallel::detail::always_true(), g);
|
Chris@16
|
3371 }
|
Chris@16
|
3372
|
Chris@16
|
3373 /************************************************************************
|
Chris@16
|
3374 *
|
Chris@16
|
3375 * clear_in_edges
|
Chris@16
|
3376 *
|
Chris@16
|
3377 ************************************************************************/
|
Chris@16
|
3378 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
|
Chris@16
|
3379 void
|
Chris@16
|
3380 clear_in_edges
|
Chris@16
|
3381 (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
|
Chris@16
|
3382 ::vertex_descriptor u,
|
Chris@16
|
3383 PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
|
Chris@16
|
3384 {
|
Chris@16
|
3385 remove_in_edge_if(u, parallel::detail::always_true(), g);
|
Chris@16
|
3386 }
|
Chris@16
|
3387
|
Chris@16
|
3388 /************************************************************************
|
Chris@16
|
3389 *
|
Chris@16
|
3390 * add_vertex
|
Chris@16
|
3391 *
|
Chris@16
|
3392 ************************************************************************/
|
Chris@16
|
3393 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3394 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
|
Chris@16
|
3395 add_vertex(PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3396 {
|
Chris@16
|
3397 typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type;
|
Chris@16
|
3398 typename graph_type::vertex_property_type p;
|
Chris@16
|
3399 return add_vertex(p, g);
|
Chris@16
|
3400 }
|
Chris@16
|
3401
|
Chris@16
|
3402 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3403 typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property
|
Chris@16
|
3404 add_vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_property_type const& p,
|
Chris@16
|
3405 PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3406 {
|
Chris@16
|
3407 typedef typename PBGL_DISTRIB_ADJLIST_TYPE
|
Chris@16
|
3408 ::lazy_add_vertex_with_property lazy_add_vertex;
|
Chris@16
|
3409 return lazy_add_vertex(g, p);
|
Chris@16
|
3410 }
|
Chris@16
|
3411
|
Chris@16
|
3412 /************************************************************************
|
Chris@16
|
3413 *
|
Chris@16
|
3414 * remove_vertex
|
Chris@16
|
3415 *
|
Chris@16
|
3416 ************************************************************************/
|
Chris@16
|
3417 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3418 void
|
Chris@16
|
3419 remove_vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
|
Chris@16
|
3420 PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3421 {
|
Chris@16
|
3422 typedef typename PBGL_DISTRIB_ADJLIST_TYPE::graph_type graph_type;
|
Chris@16
|
3423 typedef typename graph_type::named_graph_mixin named_graph_mixin;
|
Chris@16
|
3424 BOOST_ASSERT(u.owner == g.processor());
|
Chris@16
|
3425 static_cast<named_graph_mixin&>(static_cast<graph_type&>(g))
|
Chris@16
|
3426 .removing_vertex(u, boost::graph_detail::iterator_stability(g.base().m_vertices));
|
Chris@16
|
3427 g.distribution().clear();
|
Chris@16
|
3428 remove_vertex(u.local, g.base());
|
Chris@16
|
3429 }
|
Chris@16
|
3430
|
Chris@16
|
3431 /***************************************************************************
|
Chris@16
|
3432 * Implementation of Property Graph concept
|
Chris@16
|
3433 ***************************************************************************/
|
Chris@16
|
3434 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Property>
|
Chris@16
|
3435 struct property_map<PBGL_DISTRIB_ADJLIST_TYPE, Property>
|
Chris@16
|
3436 : detail::parallel::get_adj_list_pmap<Property>
|
Chris@16
|
3437 ::template apply<PBGL_DISTRIB_ADJLIST_TYPE>
|
Chris@16
|
3438 { };
|
Chris@16
|
3439
|
Chris@16
|
3440 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Property>
|
Chris@16
|
3441 struct property_map<PBGL_DISTRIB_ADJLIST_TYPE const, Property>
|
Chris@16
|
3442 : boost::detail::parallel::get_adj_list_pmap<Property>
|
Chris@16
|
3443 // FIXME: in the original code the following was not const
|
Chris@16
|
3444 ::template apply<PBGL_DISTRIB_ADJLIST_TYPE const>
|
Chris@16
|
3445 { };
|
Chris@16
|
3446
|
Chris@16
|
3447 template<typename Property, PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3448 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, Property>::type
|
Chris@16
|
3449 get(Property p, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3450 {
|
Chris@16
|
3451 typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
|
Chris@16
|
3452 typedef typename property_map<Graph, Property>::type result_type;
|
Chris@16
|
3453 typedef typename property_traits<result_type>::value_type value_type;
|
Chris@16
|
3454 typedef typename property_reduce<Property>::template apply<value_type>
|
Chris@16
|
3455 reduce;
|
Chris@16
|
3456
|
Chris@16
|
3457 typedef typename property_traits<result_type>::key_type descriptor;
|
Chris@16
|
3458 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
Chris@16
|
3459 typedef typename mpl::if_<is_same<descriptor, vertex_descriptor>,
|
Chris@16
|
3460 vertex_global_t, edge_global_t>::type
|
Chris@16
|
3461 global_map_t;
|
Chris@16
|
3462
|
Chris@16
|
3463 return result_type(g.process_group(), get(global_map_t(), g),
|
Chris@16
|
3464 get(p, g.base()), reduce());
|
Chris@16
|
3465 }
|
Chris@16
|
3466
|
Chris@16
|
3467 template<typename Property, PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3468 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, Property>::const_type
|
Chris@16
|
3469 get(Property p, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3470 {
|
Chris@16
|
3471 typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
|
Chris@16
|
3472 typedef typename property_map<Graph, Property>::const_type result_type;
|
Chris@16
|
3473 typedef typename property_traits<result_type>::value_type value_type;
|
Chris@16
|
3474 typedef typename property_reduce<Property>::template apply<value_type>
|
Chris@16
|
3475 reduce;
|
Chris@16
|
3476
|
Chris@16
|
3477 typedef typename property_traits<result_type>::key_type descriptor;
|
Chris@16
|
3478 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
Chris@16
|
3479 typedef typename mpl::if_<is_same<descriptor, vertex_descriptor>,
|
Chris@16
|
3480 vertex_global_t, edge_global_t>::type
|
Chris@16
|
3481 global_map_t;
|
Chris@16
|
3482
|
Chris@16
|
3483 return result_type(g.process_group(), get(global_map_t(), g),
|
Chris@16
|
3484 get(p, g.base()), reduce());
|
Chris@16
|
3485 }
|
Chris@16
|
3486
|
Chris@16
|
3487 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3488 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_local_index_t>::type
|
Chris@16
|
3489 get(vertex_local_index_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3490 {
|
Chris@16
|
3491 return get(vertex_local_index, g.base());
|
Chris@16
|
3492 }
|
Chris@16
|
3493
|
Chris@16
|
3494 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3495 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3496 vertex_local_index_t>::const_type
|
Chris@16
|
3497 get(vertex_local_index_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3498 {
|
Chris@16
|
3499 return get(vertex_local_index, g.base());
|
Chris@16
|
3500 }
|
Chris@16
|
3501
|
Chris@16
|
3502 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3503 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_global_t>::const_type
|
Chris@16
|
3504 get(vertex_global_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3505 {
|
Chris@16
|
3506 typedef typename property_map<
|
Chris@16
|
3507 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3508 vertex_global_t>::const_type result_type;
|
Chris@16
|
3509 return result_type();
|
Chris@16
|
3510 }
|
Chris@16
|
3511
|
Chris@16
|
3512 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3513 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_global_t>::const_type
|
Chris@16
|
3514 get(vertex_global_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3515 {
|
Chris@16
|
3516 typedef typename property_map<
|
Chris@16
|
3517 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3518 vertex_global_t>::const_type result_type;
|
Chris@16
|
3519 return result_type();
|
Chris@16
|
3520 }
|
Chris@16
|
3521
|
Chris@16
|
3522 /// Retrieve a property map mapping from a vertex descriptor to its
|
Chris@16
|
3523 /// owner.
|
Chris@16
|
3524 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3525 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_owner_t>::type
|
Chris@16
|
3526 get(vertex_owner_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3527 {
|
Chris@16
|
3528 typedef typename property_map<
|
Chris@16
|
3529 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3530 vertex_owner_t>::type result_type;
|
Chris@16
|
3531 return result_type();
|
Chris@16
|
3532 }
|
Chris@16
|
3533
|
Chris@16
|
3534 /// Retrieve a property map mapping from a vertex descriptor to its
|
Chris@16
|
3535 /// owner.
|
Chris@16
|
3536 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3537 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_owner_t>::const_type
|
Chris@16
|
3538 get(vertex_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3539 {
|
Chris@16
|
3540 typedef typename property_map<
|
Chris@16
|
3541 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3542 vertex_owner_t>::const_type result_type;
|
Chris@16
|
3543 return result_type();
|
Chris@16
|
3544 }
|
Chris@16
|
3545
|
Chris@16
|
3546 /// Retrieve the owner of a vertex
|
Chris@16
|
3547 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3548 inline processor_id_type
|
Chris@16
|
3549 get(vertex_owner_t, PBGL_DISTRIB_ADJLIST_TYPE&,
|
Chris@16
|
3550 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v)
|
Chris@16
|
3551 {
|
Chris@16
|
3552 return v.owner;
|
Chris@16
|
3553 }
|
Chris@16
|
3554
|
Chris@16
|
3555 /// Retrieve the owner of a vertex
|
Chris@16
|
3556 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3557 inline processor_id_type
|
Chris@16
|
3558 get(vertex_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE&,
|
Chris@16
|
3559 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v)
|
Chris@16
|
3560 {
|
Chris@16
|
3561 return v.owner;
|
Chris@16
|
3562 }
|
Chris@16
|
3563
|
Chris@16
|
3564 /// Retrieve a property map that maps from a vertex descriptor to
|
Chris@16
|
3565 /// its local descriptor.
|
Chris@16
|
3566 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3567 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_local_t>::type
|
Chris@16
|
3568 get(vertex_local_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3569 {
|
Chris@16
|
3570 typedef typename property_map<
|
Chris@16
|
3571 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3572 vertex_local_t>::type result_type;
|
Chris@16
|
3573 return result_type();
|
Chris@16
|
3574 }
|
Chris@16
|
3575
|
Chris@16
|
3576 /// Retrieve a property map that maps from a vertex descriptor to
|
Chris@16
|
3577 /// its local descriptor.
|
Chris@16
|
3578 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3579 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_local_t>::const_type
|
Chris@16
|
3580 get(vertex_local_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3581 {
|
Chris@16
|
3582 typedef typename property_map<
|
Chris@16
|
3583 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3584 vertex_local_t>::const_type result_type;
|
Chris@16
|
3585 return result_type();
|
Chris@16
|
3586 }
|
Chris@16
|
3587
|
Chris@16
|
3588 /// Retrieve the local descriptor of a vertex
|
Chris@16
|
3589 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3590 inline typename PBGL_DISTRIB_ADJLIST_TYPE::local_vertex_descriptor
|
Chris@16
|
3591 get(vertex_local_t, PBGL_DISTRIB_ADJLIST_TYPE&,
|
Chris@16
|
3592 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v)
|
Chris@16
|
3593 {
|
Chris@16
|
3594 return v.local;
|
Chris@16
|
3595 }
|
Chris@16
|
3596
|
Chris@16
|
3597 /// Retrieve the local descriptor of a vertex
|
Chris@16
|
3598 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3599 inline typename PBGL_DISTRIB_ADJLIST_TYPE::local_vertex_descriptor
|
Chris@16
|
3600 get(vertex_local_t, const PBGL_DISTRIB_ADJLIST_TYPE&,
|
Chris@16
|
3601 typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v)
|
Chris@16
|
3602 {
|
Chris@16
|
3603 return v.local;
|
Chris@16
|
3604 }
|
Chris@16
|
3605
|
Chris@16
|
3606
|
Chris@16
|
3607 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3608 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_global_t>::const_type
|
Chris@16
|
3609 get(edge_global_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3610 {
|
Chris@16
|
3611 typedef typename property_map<
|
Chris@16
|
3612 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3613 edge_global_t>::const_type result_type;
|
Chris@16
|
3614 return result_type();
|
Chris@16
|
3615 }
|
Chris@16
|
3616
|
Chris@16
|
3617 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3618 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_global_t>::const_type
|
Chris@16
|
3619 get(edge_global_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3620 {
|
Chris@16
|
3621 typedef typename property_map<
|
Chris@16
|
3622 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3623 edge_global_t>::const_type result_type;
|
Chris@16
|
3624 return result_type();
|
Chris@16
|
3625 }
|
Chris@16
|
3626
|
Chris@16
|
3627 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3628 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_owner_t>::type
|
Chris@16
|
3629 get(edge_owner_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3630 {
|
Chris@16
|
3631 typedef typename property_map<
|
Chris@16
|
3632 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3633 edge_owner_t>::type result_type;
|
Chris@16
|
3634 return result_type();
|
Chris@16
|
3635 }
|
Chris@16
|
3636
|
Chris@16
|
3637 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3638 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_owner_t>::const_type
|
Chris@16
|
3639 get(edge_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3640 {
|
Chris@16
|
3641 typedef typename property_map<
|
Chris@16
|
3642 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3643 edge_owner_t>::const_type result_type;
|
Chris@16
|
3644 return result_type();
|
Chris@16
|
3645 }
|
Chris@16
|
3646
|
Chris@16
|
3647 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3648 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_local_t>::type
|
Chris@16
|
3649 get(edge_local_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3650 {
|
Chris@16
|
3651 typedef typename property_map<
|
Chris@16
|
3652 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3653 edge_local_t>::type result_type;
|
Chris@16
|
3654 return result_type();
|
Chris@16
|
3655 }
|
Chris@16
|
3656
|
Chris@16
|
3657 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3658 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_local_t>::const_type
|
Chris@16
|
3659 get(edge_local_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3660 {
|
Chris@16
|
3661 typedef typename property_map<
|
Chris@16
|
3662 PBGL_DISTRIB_ADJLIST_TYPE,
|
Chris@16
|
3663 edge_local_t>::const_type result_type;
|
Chris@16
|
3664 return result_type();
|
Chris@16
|
3665 }
|
Chris@16
|
3666
|
Chris@16
|
3667 template<typename Property, PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS,
|
Chris@16
|
3668 typename Key>
|
Chris@16
|
3669 inline
|
Chris@16
|
3670 typename property_traits<typename property_map<
|
Chris@16
|
3671 PBGL_DISTRIB_ADJLIST_TYPE, Property>::const_type
|
Chris@16
|
3672 >::value_type
|
Chris@16
|
3673 get(Property p, const PBGL_DISTRIB_ADJLIST_TYPE& g, const Key& key)
|
Chris@16
|
3674 {
|
Chris@16
|
3675 if (owner(key) == process_id(g.process_group()))
|
Chris@16
|
3676 return get(p, g.base(), local(key));
|
Chris@16
|
3677 else
|
Chris@16
|
3678 BOOST_ASSERT(false);
|
Chris@16
|
3679 }
|
Chris@16
|
3680
|
Chris@16
|
3681 template<typename Property, PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS,
|
Chris@16
|
3682 typename Key, typename Value>
|
Chris@16
|
3683 void
|
Chris@16
|
3684 put(Property p, PBGL_DISTRIB_ADJLIST_TYPE& g, const Key& key, const Value& v)
|
Chris@16
|
3685 {
|
Chris@16
|
3686 if (owner(key) == process_id(g.process_group()))
|
Chris@16
|
3687 put(p, g.base(), local(key), v);
|
Chris@16
|
3688 else
|
Chris@16
|
3689 BOOST_ASSERT(false);
|
Chris@16
|
3690 }
|
Chris@16
|
3691
|
Chris@16
|
3692 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3693 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_index_t>::type
|
Chris@16
|
3694 get(vertex_index_t vi, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3695 {
|
Chris@16
|
3696 typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type;
|
Chris@16
|
3697 typedef typename property_map<graph_type, vertex_index_t>::type
|
Chris@16
|
3698 result_type;
|
Chris@16
|
3699 return result_type(g.process_group(), get(vertex_global, g),
|
Chris@16
|
3700 get(vi, g.base()));
|
Chris@16
|
3701 }
|
Chris@16
|
3702
|
Chris@16
|
3703 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3704 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_index_t>::const_type
|
Chris@16
|
3705 get(vertex_index_t vi, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3706 {
|
Chris@16
|
3707 typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type;
|
Chris@16
|
3708 typedef typename property_map<graph_type, vertex_index_t>::const_type
|
Chris@16
|
3709 result_type;
|
Chris@16
|
3710 return result_type(g.process_group(), get(vertex_global, g),
|
Chris@16
|
3711 get(vi, g.base()));
|
Chris@16
|
3712 }
|
Chris@16
|
3713
|
Chris@16
|
3714 /***************************************************************************
|
Chris@16
|
3715 * Implementation of bundled properties
|
Chris@16
|
3716 ***************************************************************************/
|
Chris@16
|
3717 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename T, typename Bundle>
|
Chris@16
|
3718 struct property_map<PBGL_DISTRIB_ADJLIST_TYPE, T Bundle::*>
|
Chris@16
|
3719 : detail::parallel::get_adj_list_pmap<T Bundle::*>
|
Chris@16
|
3720 ::template apply<PBGL_DISTRIB_ADJLIST_TYPE>
|
Chris@16
|
3721 { };
|
Chris@16
|
3722
|
Chris@16
|
3723 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename T, typename Bundle>
|
Chris@16
|
3724 struct property_map<PBGL_DISTRIB_ADJLIST_TYPE const, T Bundle::*>
|
Chris@16
|
3725 : detail::parallel::get_adj_list_pmap<T Bundle::*>
|
Chris@16
|
3726 ::template apply<PBGL_DISTRIB_ADJLIST_TYPE const>
|
Chris@16
|
3727 { };
|
Chris@16
|
3728
|
Chris@16
|
3729 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename T, typename Bundle>
|
Chris@16
|
3730 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, T Bundle::*>::type
|
Chris@16
|
3731 get(T Bundle::* p, PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3732 {
|
Chris@16
|
3733 typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
|
Chris@16
|
3734 typedef typename property_map<Graph, T Bundle::*>::type result_type;
|
Chris@16
|
3735 typedef typename property_traits<result_type>::value_type value_type;
|
Chris@16
|
3736 typedef typename property_reduce<T Bundle::*>::template apply<value_type>
|
Chris@16
|
3737 reduce;
|
Chris@16
|
3738
|
Chris@16
|
3739 typedef typename property_traits<result_type>::key_type descriptor;
|
Chris@16
|
3740 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
Chris@16
|
3741 typedef typename mpl::if_<is_same<descriptor, vertex_descriptor>,
|
Chris@16
|
3742 vertex_global_t, edge_global_t>::type
|
Chris@16
|
3743 global_map_t;
|
Chris@16
|
3744
|
Chris@16
|
3745 return result_type(g.process_group(), get(global_map_t(), g),
|
Chris@16
|
3746 get(p, g.base()), reduce());
|
Chris@16
|
3747 }
|
Chris@16
|
3748
|
Chris@16
|
3749 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename T, typename Bundle>
|
Chris@16
|
3750 typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, T Bundle::*>::const_type
|
Chris@16
|
3751 get(T Bundle::* p, const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3752 {
|
Chris@16
|
3753 typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
|
Chris@16
|
3754 typedef typename property_map<Graph, T Bundle::*>::const_type result_type;
|
Chris@16
|
3755 typedef typename property_traits<result_type>::value_type value_type;
|
Chris@16
|
3756 typedef typename property_reduce<T Bundle::*>::template apply<value_type>
|
Chris@16
|
3757 reduce;
|
Chris@16
|
3758
|
Chris@16
|
3759 typedef typename property_traits<result_type>::key_type descriptor;
|
Chris@16
|
3760 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
Chris@16
|
3761 typedef typename mpl::if_<is_same<descriptor, vertex_descriptor>,
|
Chris@16
|
3762 vertex_global_t, edge_global_t>::type
|
Chris@16
|
3763 global_map_t;
|
Chris@16
|
3764
|
Chris@16
|
3765 return result_type(g.process_group(), get(global_map_t(), g),
|
Chris@16
|
3766 get(p, g.base()), reduce());
|
Chris@16
|
3767 }
|
Chris@16
|
3768
|
Chris@16
|
3769 /***************************************************************************
|
Chris@16
|
3770 * Implementation of DistributedGraph concept
|
Chris@16
|
3771 ***************************************************************************/
|
Chris@16
|
3772 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3773 void synchronize(const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3774 {
|
Chris@16
|
3775 synchronize(g.process_group());
|
Chris@16
|
3776 }
|
Chris@16
|
3777
|
Chris@16
|
3778 template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
|
Chris@16
|
3779 ProcessGroup
|
Chris@16
|
3780 process_group(const PBGL_DISTRIB_ADJLIST_TYPE& g)
|
Chris@16
|
3781 { return g.process_group(); }
|
Chris@16
|
3782
|
Chris@16
|
3783 /***************************************************************************
|
Chris@16
|
3784 * Specializations of is_mpi_datatype for Serializable entities
|
Chris@16
|
3785 ***************************************************************************/
|
Chris@16
|
3786 namespace mpi {
|
Chris@16
|
3787 template<typename Directed, typename Vertex>
|
Chris@16
|
3788 struct is_mpi_datatype<boost::detail::edge_base<Directed, Vertex> >
|
Chris@16
|
3789 : is_mpi_datatype<Vertex> { };
|
Chris@16
|
3790
|
Chris@16
|
3791 template<typename Directed, typename Vertex>
|
Chris@16
|
3792 struct is_mpi_datatype<boost::detail::edge_desc_impl<Directed, Vertex> >
|
Chris@16
|
3793 : is_mpi_datatype<boost::detail::edge_base<Directed, Vertex> > { };
|
Chris@16
|
3794
|
Chris@16
|
3795 template<typename LocalDescriptor>
|
Chris@16
|
3796 struct is_mpi_datatype<boost::detail::parallel::global_descriptor<LocalDescriptor> >
|
Chris@16
|
3797 : is_mpi_datatype<LocalDescriptor> { };
|
Chris@16
|
3798
|
Chris@16
|
3799 template<typename Edge>
|
Chris@16
|
3800 struct is_mpi_datatype<boost::detail::parallel::edge_descriptor<Edge> >
|
Chris@16
|
3801 : is_mpi_datatype<Edge> { };
|
Chris@16
|
3802
|
Chris@16
|
3803 template<typename Vertex, typename LocalVertex>
|
Chris@16
|
3804 struct is_mpi_datatype<boost::detail::parallel::
|
Chris@16
|
3805 msg_add_edge_data<Vertex, LocalVertex> >
|
Chris@16
|
3806 : is_mpi_datatype<Vertex> { };
|
Chris@16
|
3807
|
Chris@16
|
3808 template<typename Vertex, typename LocalVertex, typename EdgeProperty>
|
Chris@16
|
3809 struct is_mpi_datatype<boost::detail::parallel::
|
Chris@16
|
3810 msg_add_edge_with_property_data<Vertex,
|
Chris@16
|
3811 LocalVertex,
|
Chris@16
|
3812 EdgeProperty> >
|
Chris@16
|
3813 : mpl::and_<is_mpi_datatype<Vertex>, is_mpi_datatype<EdgeProperty> > { };
|
Chris@16
|
3814
|
Chris@16
|
3815
|
Chris@16
|
3816 template<typename EdgeProperty, typename EdgeDescriptor>
|
Chris@16
|
3817 struct is_mpi_datatype<boost::detail::parallel::msg_nonlocal_edge_data<
|
Chris@16
|
3818 EdgeProperty,EdgeDescriptor> >
|
Chris@16
|
3819 : mpl::and_<
|
Chris@16
|
3820 is_mpi_datatype<boost::detail::parallel::maybe_store_property<
|
Chris@16
|
3821 EdgeProperty> >,
|
Chris@16
|
3822 is_mpi_datatype<EdgeDescriptor> >
|
Chris@16
|
3823 {};
|
Chris@16
|
3824
|
Chris@16
|
3825 template<typename EdgeDescriptor>
|
Chris@16
|
3826 struct is_mpi_datatype<
|
Chris@16
|
3827 boost::detail::parallel::msg_remove_edge_data<EdgeDescriptor> >
|
Chris@16
|
3828 : is_mpi_datatype<EdgeDescriptor> {};
|
Chris@16
|
3829 }
|
Chris@16
|
3830
|
Chris@16
|
3831 /***************************************************************************
|
Chris@16
|
3832 * Specializations of is_bitwise_serializable for Serializable entities
|
Chris@16
|
3833 ***************************************************************************/
|
Chris@16
|
3834 namespace serialization {
|
Chris@16
|
3835 template<typename Directed, typename Vertex>
|
Chris@16
|
3836 struct is_bitwise_serializable<boost::detail::edge_base<Directed, Vertex> >
|
Chris@16
|
3837 : is_bitwise_serializable<Vertex> { };
|
Chris@16
|
3838
|
Chris@16
|
3839 template<typename Directed, typename Vertex>
|
Chris@16
|
3840 struct is_bitwise_serializable<boost::detail::edge_desc_impl<Directed, Vertex> >
|
Chris@16
|
3841 : is_bitwise_serializable<boost::detail::edge_base<Directed, Vertex> > { };
|
Chris@16
|
3842
|
Chris@16
|
3843 template<typename LocalDescriptor>
|
Chris@16
|
3844 struct is_bitwise_serializable<boost::detail::parallel::global_descriptor<LocalDescriptor> >
|
Chris@16
|
3845 : is_bitwise_serializable<LocalDescriptor> { };
|
Chris@16
|
3846
|
Chris@16
|
3847 template<typename Edge>
|
Chris@16
|
3848 struct is_bitwise_serializable<boost::detail::parallel::edge_descriptor<Edge> >
|
Chris@16
|
3849 : is_bitwise_serializable<Edge> { };
|
Chris@16
|
3850
|
Chris@16
|
3851 template<typename Vertex, typename LocalVertex>
|
Chris@16
|
3852 struct is_bitwise_serializable<boost::detail::parallel::
|
Chris@16
|
3853 msg_add_edge_data<Vertex, LocalVertex> >
|
Chris@16
|
3854 : is_bitwise_serializable<Vertex> { };
|
Chris@16
|
3855
|
Chris@16
|
3856 template<typename Vertex, typename LocalVertex, typename EdgeProperty>
|
Chris@16
|
3857 struct is_bitwise_serializable<boost::detail::parallel::
|
Chris@16
|
3858 msg_add_edge_with_property_data<Vertex,
|
Chris@16
|
3859 LocalVertex,
|
Chris@16
|
3860 EdgeProperty> >
|
Chris@16
|
3861 : mpl::and_<is_bitwise_serializable<Vertex>,
|
Chris@16
|
3862 is_bitwise_serializable<EdgeProperty> > { };
|
Chris@16
|
3863
|
Chris@16
|
3864 template<typename EdgeProperty, typename EdgeDescriptor>
|
Chris@16
|
3865 struct is_bitwise_serializable<boost::detail::parallel::msg_nonlocal_edge_data<
|
Chris@16
|
3866 EdgeProperty,EdgeDescriptor> >
|
Chris@16
|
3867 : mpl::and_<
|
Chris@16
|
3868 is_bitwise_serializable<
|
Chris@16
|
3869 boost::detail::parallel::maybe_store_property<EdgeProperty> >,
|
Chris@16
|
3870 is_bitwise_serializable<EdgeDescriptor> >
|
Chris@16
|
3871 {};
|
Chris@16
|
3872
|
Chris@16
|
3873 template<typename EdgeDescriptor>
|
Chris@16
|
3874 struct is_bitwise_serializable<
|
Chris@16
|
3875 boost::detail::parallel::msg_remove_edge_data<EdgeDescriptor> >
|
Chris@16
|
3876 : is_bitwise_serializable<EdgeDescriptor> {};
|
Chris@16
|
3877
|
Chris@16
|
3878 template<typename Directed, typename Vertex>
|
Chris@16
|
3879 struct implementation_level<boost::detail::edge_base<Directed, Vertex> >
|
Chris@16
|
3880 : mpl::int_<object_serializable> {};
|
Chris@16
|
3881
|
Chris@16
|
3882 template<typename Directed, typename Vertex>
|
Chris@16
|
3883 struct implementation_level<boost::detail::edge_desc_impl<Directed, Vertex> >
|
Chris@16
|
3884 : mpl::int_<object_serializable> {};
|
Chris@16
|
3885
|
Chris@16
|
3886 template<typename LocalDescriptor>
|
Chris@16
|
3887 struct implementation_level<boost::detail::parallel::global_descriptor<LocalDescriptor> >
|
Chris@16
|
3888 : mpl::int_<object_serializable> {};
|
Chris@16
|
3889
|
Chris@16
|
3890 template<typename Edge>
|
Chris@16
|
3891 struct implementation_level<boost::detail::parallel::edge_descriptor<Edge> >
|
Chris@16
|
3892 : mpl::int_<object_serializable> {};
|
Chris@16
|
3893
|
Chris@16
|
3894 template<typename Vertex, typename LocalVertex>
|
Chris@16
|
3895 struct implementation_level<boost::detail::parallel::
|
Chris@16
|
3896 msg_add_edge_data<Vertex, LocalVertex> >
|
Chris@16
|
3897 : mpl::int_<object_serializable> {};
|
Chris@16
|
3898
|
Chris@16
|
3899 template<typename Vertex, typename LocalVertex, typename EdgeProperty>
|
Chris@16
|
3900 struct implementation_level<boost::detail::parallel::
|
Chris@16
|
3901 msg_add_edge_with_property_data<Vertex,
|
Chris@16
|
3902 LocalVertex,
|
Chris@16
|
3903 EdgeProperty> >
|
Chris@16
|
3904 : mpl::int_<object_serializable> {};
|
Chris@16
|
3905
|
Chris@16
|
3906 template<typename EdgeProperty, typename EdgeDescriptor>
|
Chris@16
|
3907 struct implementation_level<boost::detail::parallel::msg_nonlocal_edge_data<
|
Chris@16
|
3908 EdgeProperty,EdgeDescriptor> >
|
Chris@16
|
3909 : mpl::int_<object_serializable> {};
|
Chris@16
|
3910
|
Chris@16
|
3911 template<typename EdgeDescriptor>
|
Chris@16
|
3912 struct implementation_level<
|
Chris@16
|
3913 boost::detail::parallel::msg_remove_edge_data<EdgeDescriptor> >
|
Chris@16
|
3914 : mpl::int_<object_serializable> {};
|
Chris@16
|
3915
|
Chris@16
|
3916 template<typename Directed, typename Vertex>
|
Chris@16
|
3917 struct tracking_level<boost::detail::edge_base<Directed, Vertex> >
|
Chris@16
|
3918 : mpl::int_<track_never> {};
|
Chris@16
|
3919
|
Chris@16
|
3920 template<typename Directed, typename Vertex>
|
Chris@16
|
3921 struct tracking_level<boost::detail::edge_desc_impl<Directed, Vertex> >
|
Chris@16
|
3922 : mpl::int_<track_never> {};
|
Chris@16
|
3923
|
Chris@16
|
3924 template<typename LocalDescriptor>
|
Chris@16
|
3925 struct tracking_level<boost::detail::parallel::global_descriptor<LocalDescriptor> >
|
Chris@16
|
3926 : mpl::int_<track_never> {};
|
Chris@16
|
3927
|
Chris@16
|
3928 template<typename Edge>
|
Chris@16
|
3929 struct tracking_level<boost::detail::parallel::edge_descriptor<Edge> >
|
Chris@16
|
3930 : mpl::int_<track_never> {};
|
Chris@16
|
3931
|
Chris@16
|
3932 template<typename Vertex, typename LocalVertex>
|
Chris@16
|
3933 struct tracking_level<boost::detail::parallel::
|
Chris@16
|
3934 msg_add_edge_data<Vertex, LocalVertex> >
|
Chris@16
|
3935 : mpl::int_<track_never> {};
|
Chris@16
|
3936
|
Chris@16
|
3937 template<typename Vertex, typename LocalVertex, typename EdgeProperty>
|
Chris@16
|
3938 struct tracking_level<boost::detail::parallel::
|
Chris@16
|
3939 msg_add_edge_with_property_data<Vertex,
|
Chris@16
|
3940 LocalVertex,
|
Chris@16
|
3941 EdgeProperty> >
|
Chris@16
|
3942 : mpl::int_<track_never> {};
|
Chris@16
|
3943
|
Chris@16
|
3944 template<typename EdgeProperty, typename EdgeDescriptor>
|
Chris@16
|
3945 struct tracking_level<boost::detail::parallel::msg_nonlocal_edge_data<
|
Chris@16
|
3946 EdgeProperty,EdgeDescriptor> >
|
Chris@16
|
3947 : mpl::int_<track_never> {};
|
Chris@16
|
3948
|
Chris@16
|
3949 template<typename EdgeDescriptor>
|
Chris@16
|
3950 struct tracking_level<
|
Chris@16
|
3951 boost::detail::parallel::msg_remove_edge_data<EdgeDescriptor> >
|
Chris@16
|
3952 : mpl::int_<track_never> {};
|
Chris@16
|
3953 }
|
Chris@16
|
3954
|
Chris@16
|
3955 // Hash function for global descriptors
|
Chris@16
|
3956 template<typename LocalDescriptor>
|
Chris@16
|
3957 struct hash<detail::parallel::global_descriptor<LocalDescriptor> >
|
Chris@16
|
3958 {
|
Chris@16
|
3959 typedef detail::parallel::global_descriptor<LocalDescriptor> argument_type;
|
Chris@16
|
3960 std::size_t operator()(argument_type const& x) const
|
Chris@16
|
3961 {
|
Chris@16
|
3962 std::size_t hash = hash_value(x.owner);
|
Chris@16
|
3963 hash_combine(hash, x.local);
|
Chris@16
|
3964 return hash;
|
Chris@16
|
3965 }
|
Chris@16
|
3966 };
|
Chris@16
|
3967
|
Chris@16
|
3968 // Hash function for parallel edge descriptors
|
Chris@16
|
3969 template<typename Edge>
|
Chris@16
|
3970 struct hash<detail::parallel::edge_descriptor<Edge> >
|
Chris@16
|
3971 {
|
Chris@16
|
3972 typedef detail::parallel::edge_descriptor<Edge> argument_type;
|
Chris@16
|
3973
|
Chris@16
|
3974 std::size_t operator()(argument_type const& x) const
|
Chris@16
|
3975 {
|
Chris@16
|
3976 std::size_t hash = hash_value(x.owner());
|
Chris@16
|
3977 hash_combine(hash, x.local);
|
Chris@16
|
3978 return hash;
|
Chris@16
|
3979 }
|
Chris@16
|
3980 };
|
Chris@16
|
3981
|
Chris@16
|
3982 } // end namespace boost
|
Chris@16
|
3983
|
Chris@16
|
3984 #include <boost/graph/distributed/adjlist/handlers.hpp>
|
Chris@16
|
3985 #include <boost/graph/distributed/adjlist/initialize.hpp>
|
Chris@16
|
3986 #include <boost/graph/distributed/adjlist/redistribute.hpp>
|
Chris@16
|
3987 #include <boost/graph/distributed/adjlist/serialization.hpp>
|
Chris@16
|
3988
|
Chris@16
|
3989 #endif // BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
|