annotate DEPENDENCIES/generic/include/boost/graph/distributed/adjacency_list.hpp @ 118:770eb830ec19 emscripten

Typo fix
author Chris Cannam
date Wed, 18 May 2016 16:14:08 +0100
parents c530137014c0
children
rev   line source
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