/Src/Dependencies/Boost/boost/graph/distributed/adjacency_list.hpp

http://hadesmem.googlecode.com/ · C++ Header · 3970 lines · 2664 code · 533 blank · 773 comment · 189 complexity · 3c4b75ee66cb03622c873a03e54057c9 MD5 · raw file

Large files are truncated click here to view the full file

  1. // Copyright (C) 2004-2006 The Trustees of Indiana University.
  2. // Copyright (C) 2007 Douglas Gregor
  3. // Use, modification and distribution is subject to the Boost Software
  4. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // Authors: Douglas Gregor
  7. // Andrew Lumsdaine
  8. #ifndef BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
  9. #define BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
  10. #ifndef BOOST_GRAPH_USE_MPI
  11. #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
  12. #endif
  13. #include <boost/graph/adjacency_list.hpp>
  14. #include <boost/graph/properties.hpp>
  15. #include <boost/graph/graph_traits.hpp>
  16. #include <boost/graph/iteration_macros.hpp>
  17. #include <boost/graph/distributed/concepts.hpp>
  18. #include <boost/iterator/transform_iterator.hpp>
  19. #include <boost/property_map/property_map.hpp>
  20. #include <boost/graph/adjacency_iterator.hpp>
  21. #include <boost/property_map/parallel/distributed_property_map.hpp>
  22. #include <boost/property_map/parallel/local_property_map.hpp>
  23. #include <boost/graph/parallel/detail/property_holders.hpp>
  24. #include <boost/mpl/if.hpp>
  25. #include <boost/type_traits/is_same.hpp>
  26. #include <boost/assert.hpp>
  27. #include <list>
  28. #include <algorithm>
  29. #include <boost/limits.hpp>
  30. #include <boost/graph/parallel/properties.hpp>
  31. #include <boost/graph/parallel/distribution.hpp>
  32. #include <boost/graph/parallel/algorithm.hpp>
  33. #include <boost/graph/distributed/selector.hpp>
  34. #include <boost/graph/parallel/process_group.hpp>
  35. // Callbacks
  36. #include <boost/function/function2.hpp>
  37. // Serialization
  38. #include <boost/serialization/base_object.hpp>
  39. #include <boost/mpi/datatype.hpp>
  40. #include <boost/pending/property_serialize.hpp>
  41. #include <boost/graph/distributed/unsafe_serialize.hpp>
  42. // Named vertices
  43. #include <boost/graph/distributed/named_graph.hpp>
  44. #include <boost/graph/distributed/shuffled_distribution.hpp>
  45. namespace boost {
  46. /// The type used to store an identifier that uniquely names a processor.
  47. // NGE: I doubt we'll be running on more than 32768 procs for the time being
  48. typedef /*int*/ short processor_id_type;
  49. // Tell which processor the target of an edge resides on (for
  50. // directed graphs) or which processor the other end point of the
  51. // edge resides on (for undirected graphs).
  52. enum edge_target_processor_id_t { edge_target_processor_id };
  53. BOOST_INSTALL_PROPERTY(edge, target_processor_id);
  54. // For undirected graphs, tells whether the edge is locally owned.
  55. enum edge_locally_owned_t { edge_locally_owned };
  56. BOOST_INSTALL_PROPERTY(edge, locally_owned);
  57. // For bidirectional graphs, stores the incoming edges.
  58. enum vertex_in_edges_t { vertex_in_edges };
  59. BOOST_INSTALL_PROPERTY(vertex, in_edges);
  60. /// Tag class for directed, distributed adjacency list
  61. struct directed_distributed_adj_list_tag
  62. : public virtual distributed_graph_tag,
  63. public virtual distributed_vertex_list_graph_tag,
  64. public virtual distributed_edge_list_graph_tag,
  65. public virtual incidence_graph_tag,
  66. public virtual adjacency_graph_tag {};
  67. /// Tag class for bidirectional, distributed adjacency list
  68. struct bidirectional_distributed_adj_list_tag
  69. : public virtual distributed_graph_tag,
  70. public virtual distributed_vertex_list_graph_tag,
  71. public virtual distributed_edge_list_graph_tag,
  72. public virtual incidence_graph_tag,
  73. public virtual adjacency_graph_tag,
  74. public virtual bidirectional_graph_tag {};
  75. /// Tag class for undirected, distributed adjacency list
  76. struct undirected_distributed_adj_list_tag
  77. : public virtual distributed_graph_tag,
  78. public virtual distributed_vertex_list_graph_tag,
  79. public virtual distributed_edge_list_graph_tag,
  80. public virtual incidence_graph_tag,
  81. public virtual adjacency_graph_tag,
  82. public virtual bidirectional_graph_tag {};
  83. namespace detail {
  84. template<typename Archiver, typename Directed, typename Vertex>
  85. void
  86. serialize(Archiver& ar, edge_base<Directed, Vertex>& e,
  87. const unsigned int /*version*/)
  88. {
  89. ar & unsafe_serialize(e.m_source)
  90. & unsafe_serialize(e.m_target);
  91. }
  92. template<typename Archiver, typename Directed, typename Vertex>
  93. void
  94. serialize(Archiver& ar, edge_desc_impl<Directed, Vertex>& e,
  95. const unsigned int /*version*/)
  96. {
  97. ar & boost::serialization::base_object<edge_base<Directed, Vertex> >(e)
  98. & unsafe_serialize(e.m_eproperty);
  99. }
  100. }
  101. namespace detail { namespace parallel {
  102. /**
  103. * A distributed vertex descriptor. These descriptors contain both
  104. * the ID of the processor that owns the vertex and a local vertex
  105. * descriptor that identifies the particular vertex for that
  106. * processor.
  107. */
  108. template<typename LocalDescriptor>
  109. struct global_descriptor
  110. {
  111. typedef LocalDescriptor local_descriptor_type;
  112. global_descriptor() : owner(), local() { }
  113. global_descriptor(processor_id_type owner, LocalDescriptor local)
  114. : owner(owner), local(local) { }
  115. processor_id_type owner;
  116. LocalDescriptor local;
  117. /**
  118. * A function object that, given a processor ID, generates
  119. * distributed vertex descriptors from local vertex
  120. * descriptors. This function object is used by the
  121. * vertex_iterator of the distributed adjacency list.
  122. */
  123. struct generator
  124. {
  125. typedef global_descriptor<LocalDescriptor> result_type;
  126. typedef LocalDescriptor argument_type;
  127. generator() {}
  128. generator(processor_id_type owner) : owner(owner) {}
  129. result_type operator()(argument_type v) const
  130. { return result_type(owner, v); }
  131. private:
  132. processor_id_type owner;
  133. };
  134. template<typename Archiver>
  135. void serialize(Archiver& ar, const unsigned int /*version*/)
  136. {
  137. ar & owner & unsafe_serialize(local);
  138. }
  139. };
  140. /// Determine the process that owns the given descriptor
  141. template<typename LocalDescriptor>
  142. inline processor_id_type owner(const global_descriptor<LocalDescriptor>& v)
  143. { return v.owner; }
  144. /// Determine the local portion of the given descriptor
  145. template<typename LocalDescriptor>
  146. inline LocalDescriptor local(const global_descriptor<LocalDescriptor>& v)
  147. { return v.local; }
  148. /// Compare distributed vertex descriptors for equality
  149. template<typename LocalDescriptor>
  150. inline bool
  151. operator==(const global_descriptor<LocalDescriptor>& u,
  152. const global_descriptor<LocalDescriptor>& v)
  153. {
  154. return u.owner == v.owner && u.local == v.local;
  155. }
  156. /// Compare distributed vertex descriptors for inequality
  157. template<typename LocalDescriptor>
  158. inline bool
  159. operator!=(const global_descriptor<LocalDescriptor>& u,
  160. const global_descriptor<LocalDescriptor>& v)
  161. { return !(u == v); }
  162. template<typename LocalDescriptor>
  163. inline bool
  164. operator<(const global_descriptor<LocalDescriptor>& u,
  165. const global_descriptor<LocalDescriptor>& v)
  166. {
  167. return (u.owner) < v.owner || (u.owner == v.owner && (u.local) < v.local);
  168. }
  169. template<typename LocalDescriptor>
  170. inline bool
  171. operator<=(const global_descriptor<LocalDescriptor>& u,
  172. const global_descriptor<LocalDescriptor>& v)
  173. {
  174. return u.owner <= v.owner || (u.owner == v.owner && u.local <= v.local);
  175. }
  176. template<typename LocalDescriptor>
  177. inline bool
  178. operator>(const global_descriptor<LocalDescriptor>& u,
  179. const global_descriptor<LocalDescriptor>& v)
  180. {
  181. return v < u;
  182. }
  183. template<typename LocalDescriptor>
  184. inline bool
  185. operator>=(const global_descriptor<LocalDescriptor>& u,
  186. const global_descriptor<LocalDescriptor>& v)
  187. {
  188. return v <= u;
  189. }
  190. // DPG TBD: Add <, <=, >=, > for global descriptors
  191. /**
  192. * A Readable Property Map that extracts a global descriptor pair
  193. * from a global_descriptor.
  194. */
  195. template<typename LocalDescriptor>
  196. struct global_descriptor_property_map
  197. {
  198. typedef std::pair<processor_id_type, LocalDescriptor> value_type;
  199. typedef value_type reference;
  200. typedef global_descriptor<LocalDescriptor> key_type;
  201. typedef readable_property_map_tag category;
  202. };
  203. template<typename LocalDescriptor>
  204. inline std::pair<processor_id_type, LocalDescriptor>
  205. get(global_descriptor_property_map<LocalDescriptor>,
  206. global_descriptor<LocalDescriptor> x)
  207. {
  208. return std::pair<processor_id_type, LocalDescriptor>(x.owner, x.local);
  209. }
  210. /**
  211. * A Readable Property Map that extracts the owner of a global
  212. * descriptor.
  213. */
  214. template<typename LocalDescriptor>
  215. struct owner_property_map
  216. {
  217. typedef processor_id_type value_type;
  218. typedef value_type reference;
  219. typedef global_descriptor<LocalDescriptor> key_type;
  220. typedef readable_property_map_tag category;
  221. };
  222. template<typename LocalDescriptor>
  223. inline processor_id_type
  224. get(owner_property_map<LocalDescriptor>,
  225. global_descriptor<LocalDescriptor> x)
  226. {
  227. return x.owner;
  228. }
  229. /**
  230. * A Readable Property Map that extracts the local descriptor from
  231. * a global descriptor.
  232. */
  233. template<typename LocalDescriptor>
  234. struct local_descriptor_property_map
  235. {
  236. typedef LocalDescriptor value_type;
  237. typedef value_type reference;
  238. typedef global_descriptor<LocalDescriptor> key_type;
  239. typedef readable_property_map_tag category;
  240. };
  241. template<typename LocalDescriptor>
  242. inline LocalDescriptor
  243. get(local_descriptor_property_map<LocalDescriptor>,
  244. global_descriptor<LocalDescriptor> x)
  245. {
  246. return x.local;
  247. }
  248. /**
  249. * Stores an incoming edge for a bidirectional distributed
  250. * adjacency list. The user does not see this type directly,
  251. * because it is just an implementation detail.
  252. */
  253. template<typename Edge>
  254. struct stored_in_edge
  255. {
  256. stored_in_edge(processor_id_type sp, Edge e)
  257. : source_processor(sp), e(e) {}
  258. processor_id_type source_processor;
  259. Edge e;
  260. };
  261. /**
  262. * A distributed edge descriptor. These descriptors contain the
  263. * underlying edge descriptor, the processor IDs for both the
  264. * source and the target of the edge, and a boolean flag that
  265. * indicates which of the processors actually owns the edge.
  266. */
  267. template<typename Edge>
  268. struct edge_descriptor
  269. {
  270. edge_descriptor(processor_id_type sp = processor_id_type(),
  271. processor_id_type tp = processor_id_type(),
  272. bool owns = false, Edge ld = Edge())
  273. : source_processor(sp), target_processor(tp),
  274. source_owns_edge(owns), local(ld) {}
  275. processor_id_type owner() const
  276. {
  277. return source_owns_edge? source_processor : target_processor;
  278. }
  279. /// The processor that the source vertex resides on
  280. processor_id_type source_processor;
  281. /// The processor that the target vertex resides on
  282. processor_id_type target_processor;
  283. /// True when the source processor owns the edge, false when the
  284. /// target processor owns the edge.
  285. bool source_owns_edge;
  286. /// The local edge descriptor.
  287. Edge local;
  288. /**
  289. * Function object that generates edge descriptors for the
  290. * out_edge_iterator of the given distributed adjacency list
  291. * from the edge descriptors of the underlying adjacency list.
  292. */
  293. template<typename Graph>
  294. class out_generator
  295. {
  296. typedef typename Graph::directed_selector directed_selector;
  297. public:
  298. typedef edge_descriptor<Edge> result_type;
  299. typedef Edge argument_type;
  300. out_generator() : g(0) {}
  301. explicit out_generator(const Graph& g) : g(&g) {}
  302. result_type operator()(argument_type e) const
  303. { return map(e, directed_selector()); }
  304. private:
  305. result_type map(argument_type e, directedS) const
  306. {
  307. return result_type(g->processor(),
  308. get(edge_target_processor_id, g->base(), e),
  309. true, e);
  310. }
  311. result_type map(argument_type e, bidirectionalS) const
  312. {
  313. return result_type(g->processor(),
  314. get(edge_target_processor_id, g->base(), e),
  315. true, e);
  316. }
  317. result_type map(argument_type e, undirectedS) const
  318. {
  319. return result_type(g->processor(),
  320. get(edge_target_processor_id, g->base(), e),
  321. get(edge_locally_owned, g->base(), e),
  322. e);
  323. }
  324. const Graph* g;
  325. };
  326. /**
  327. * Function object that generates edge descriptors for the
  328. * in_edge_iterator of the given distributed adjacency list
  329. * from the edge descriptors of the underlying adjacency list.
  330. */
  331. template<typename Graph>
  332. class in_generator
  333. {
  334. typedef typename Graph::directed_selector DirectedS;
  335. public:
  336. typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
  337. stored_in_edge<Edge>,
  338. Edge>::type argument_type;
  339. typedef edge_descriptor<Edge> result_type;
  340. in_generator() : g(0) {}
  341. explicit in_generator(const Graph& g) : g(&g) {}
  342. result_type operator()(argument_type e) const
  343. { return map(e, DirectedS()); }
  344. private:
  345. /**
  346. * For a bidirectional graph, we just generate the appropriate
  347. * edge. No tricks.
  348. */
  349. result_type map(argument_type e, bidirectionalS) const
  350. {
  351. return result_type(e.source_processor,
  352. g->processor(),
  353. true,
  354. e.e);
  355. }
  356. /**
  357. * For an undirected graph, we generate descriptors for the
  358. * incoming edges by swapping the source/target of the
  359. * underlying edge descriptor (a hack). The target processor
  360. * ID on the edge is actually the source processor for this
  361. * edge, and our processor is the target processor. If the
  362. * edge is locally owned, then it is owned by the target (us);
  363. * otherwise it is owned by the source.
  364. */
  365. result_type map(argument_type e, undirectedS) const
  366. {
  367. typename Graph::local_edge_descriptor local_edge(e);
  368. // TBD: This is a very, VERY lame hack that takes advantage
  369. // of our knowledge of the internals of the BGL
  370. // adjacency_list. There should be a cleaner way to handle
  371. // this...
  372. using std::swap;
  373. swap(local_edge.m_source, local_edge.m_target);
  374. return result_type(get(edge_target_processor_id, g->base(), e),
  375. g->processor(),
  376. !get(edge_locally_owned, g->base(), e),
  377. local_edge);
  378. }
  379. const Graph* g;
  380. };
  381. private:
  382. friend class boost::serialization::access;
  383. template<typename Archiver>
  384. void serialize(Archiver& ar, const unsigned int /*version*/)
  385. {
  386. ar
  387. & source_processor
  388. & target_processor
  389. & source_owns_edge
  390. & local;
  391. }
  392. };
  393. /// Determine the process that owns this edge
  394. template<typename Edge>
  395. inline processor_id_type
  396. owner(const edge_descriptor<Edge>& e)
  397. { return e.source_owns_edge? e.source_processor : e.target_processor; }
  398. /// Determine the local descriptor for this edge.
  399. template<typename Edge>
  400. inline Edge
  401. local(const edge_descriptor<Edge>& e)
  402. { return e.local; }
  403. /**
  404. * A Readable Property Map that extracts the owner and local
  405. * descriptor of an edge descriptor.
  406. */
  407. template<typename Edge>
  408. struct edge_global_property_map
  409. {
  410. typedef std::pair<processor_id_type, Edge> value_type;
  411. typedef value_type reference;
  412. typedef edge_descriptor<Edge> key_type;
  413. typedef readable_property_map_tag category;
  414. };
  415. template<typename Edge>
  416. inline std::pair<processor_id_type, Edge>
  417. get(edge_global_property_map<Edge>, const edge_descriptor<Edge>& e)
  418. {
  419. typedef std::pair<processor_id_type, Edge> result_type;
  420. return result_type(e.source_owns_edge? e.source_processor
  421. /* target owns edge*/: e.target_processor,
  422. e.local);
  423. }
  424. /**
  425. * A Readable Property Map that extracts the owner of an edge
  426. * descriptor.
  427. */
  428. template<typename Edge>
  429. struct edge_owner_property_map
  430. {
  431. typedef processor_id_type value_type;
  432. typedef value_type reference;
  433. typedef edge_descriptor<Edge> key_type;
  434. typedef readable_property_map_tag category;
  435. };
  436. template<typename Edge>
  437. inline processor_id_type
  438. get(edge_owner_property_map<Edge>, const edge_descriptor<Edge>& e)
  439. {
  440. return e.source_owns_edge? e.source_processor : e.target_processor;
  441. }
  442. /**
  443. * A Readable Property Map that extracts the local descriptor from
  444. * an edge descriptor.
  445. */
  446. template<typename Edge>
  447. struct edge_local_property_map
  448. {
  449. typedef Edge value_type;
  450. typedef value_type reference;
  451. typedef edge_descriptor<Edge> key_type;
  452. typedef readable_property_map_tag category;
  453. };
  454. template<typename Edge>
  455. inline Edge
  456. get(edge_local_property_map<Edge>,
  457. const edge_descriptor<Edge>& e)
  458. {
  459. return e.local;
  460. }
  461. /** Compare distributed edge descriptors for equality.
  462. *
  463. * \todo need edge_descriptor to know if it is undirected so we
  464. * can compare both ways.
  465. */
  466. template<typename Edge>
  467. inline bool
  468. operator==(const edge_descriptor<Edge>& e1,
  469. const edge_descriptor<Edge>& e2)
  470. {
  471. return (e1.source_processor == e2.source_processor
  472. && e1.target_processor == e2.target_processor
  473. && e1.local == e2.local);
  474. }
  475. /// Compare distributed edge descriptors for inequality.
  476. template<typename Edge>
  477. inline bool
  478. operator!=(const edge_descriptor<Edge>& e1,
  479. const edge_descriptor<Edge>& e2)
  480. { return !(e1 == e2); }
  481. /**
  482. * Configuration for the distributed adjacency list. We use this
  483. * parameter to store all of the configuration details for the
  484. * implementation of the distributed adjacency list, which allows us to
  485. * get at the distribution type in the maybe_named_graph.
  486. */
  487. template<typename OutEdgeListS, typename ProcessGroup,
  488. typename InVertexListS, typename InDistribution,
  489. typename DirectedS, typename VertexProperty,
  490. typename EdgeProperty, typename GraphProperty,
  491. typename EdgeListS>
  492. struct adjacency_list_config
  493. {
  494. typedef typename mpl::if_<is_same<InVertexListS, defaultS>,
  495. vecS, InVertexListS>::type
  496. VertexListS;
  497. /// Introduce the target processor ID property for each edge
  498. typedef property<edge_target_processor_id_t, processor_id_type,
  499. EdgeProperty> edge_property_with_id;
  500. /// For undirected graphs, introduce the locally-owned property for edges
  501. typedef typename boost::mpl::if_<is_same<DirectedS, undirectedS>,
  502. property<edge_locally_owned_t, bool,
  503. edge_property_with_id>,
  504. edge_property_with_id>::type
  505. base_edge_property_type;
  506. /// The edge descriptor type for the local subgraph
  507. typedef typename adjacency_list_traits<OutEdgeListS,
  508. VertexListS,
  509. directedS>::edge_descriptor
  510. local_edge_descriptor;
  511. /// For bidirectional graphs, the type of an incoming stored edge
  512. typedef stored_in_edge<local_edge_descriptor> bidir_stored_edge;
  513. /// The container type that will store incoming edges for a
  514. /// bidirectional graph.
  515. typedef typename container_gen<EdgeListS, bidir_stored_edge>::type
  516. in_edge_list_type;
  517. // Bidirectional graphs have an extra vertex property to store
  518. // the incoming edges.
  519. typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
  520. property<vertex_in_edges_t, in_edge_list_type,
  521. VertexProperty>,
  522. VertexProperty>::type
  523. base_vertex_property_type;
  524. // The type of the distributed adjacency list
  525. typedef adjacency_list<OutEdgeListS,
  526. distributedS<ProcessGroup,
  527. VertexListS,
  528. InDistribution>,
  529. DirectedS, VertexProperty, EdgeProperty,
  530. GraphProperty, EdgeListS>
  531. graph_type;
  532. // The type of the underlying adjacency list implementation
  533. typedef adjacency_list<OutEdgeListS, VertexListS, directedS,
  534. base_vertex_property_type,
  535. base_edge_property_type,
  536. GraphProperty,
  537. EdgeListS>
  538. inherited;
  539. typedef InDistribution in_distribution_type;
  540. typedef typename inherited::vertices_size_type vertices_size_type;
  541. typedef typename ::boost::graph::distributed::select_distribution<
  542. in_distribution_type, VertexProperty, vertices_size_type,
  543. ProcessGroup>::type
  544. base_distribution_type;
  545. typedef ::boost::graph::distributed::shuffled_distribution<
  546. base_distribution_type> distribution_type;
  547. typedef VertexProperty vertex_property_type;
  548. typedef EdgeProperty edge_property_type;
  549. typedef ProcessGroup process_group_type;
  550. typedef VertexListS vertex_list_selector;
  551. typedef OutEdgeListS out_edge_list_selector;
  552. typedef DirectedS directed_selector;
  553. typedef GraphProperty graph_property_type;
  554. typedef EdgeListS edge_list_selector;
  555. };
  556. // Maybe initialize the indices of each vertex
  557. template<typename IteratorPair, typename VertexIndexMap>
  558. void
  559. maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index,
  560. read_write_property_map_tag)
  561. {
  562. typedef typename property_traits<VertexIndexMap>::value_type index_t;
  563. index_t next_index = 0;
  564. while (p.first != p.second)
  565. put(to_index, *p.first++, next_index++);
  566. }
  567. template<typename IteratorPair, typename VertexIndexMap>
  568. inline void
  569. maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index,
  570. readable_property_map_tag)
  571. {
  572. // Do nothing
  573. }
  574. template<typename IteratorPair, typename VertexIndexMap>
  575. inline void
  576. maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index)
  577. {
  578. typedef typename property_traits<VertexIndexMap>::category category;
  579. maybe_initialize_vertex_indices(p, to_index, category());
  580. }
  581. template<typename IteratorPair>
  582. inline void
  583. maybe_initialize_vertex_indices(IteratorPair p,
  584. ::boost::detail::error_property_not_found)
  585. { }
  586. /***********************************************************************
  587. * Message Payloads *
  588. ***********************************************************************/
  589. /**
  590. * Data stored with a msg_add_edge message, which requests the
  591. * remote addition of an edge.
  592. */
  593. template<typename Vertex, typename LocalVertex>
  594. struct msg_add_edge_data
  595. {
  596. msg_add_edge_data() { }
  597. msg_add_edge_data(Vertex source, Vertex target)
  598. : source(source.local), target(target) { }
  599. /// The source of the edge; the processor will be the
  600. /// receiving processor.
  601. LocalVertex source;
  602. /// The target of the edge.
  603. Vertex target;
  604. template<typename Archiver>
  605. void serialize(Archiver& ar, const unsigned int /*version*/)
  606. {
  607. ar & unsafe_serialize(source) & target;
  608. }
  609. };
  610. /**
  611. * Like @c msg_add_edge_data, but also includes a user-specified
  612. * property value to be attached to the edge.
  613. */
  614. template<typename Vertex, typename LocalVertex, typename EdgeProperty>
  615. struct msg_add_edge_with_property_data
  616. : msg_add_edge_data<Vertex, LocalVertex>,
  617. maybe_store_property<EdgeProperty>
  618. {
  619. private:
  620. typedef msg_add_edge_data<Vertex, LocalVertex> inherited_data;
  621. typedef maybe_store_property<EdgeProperty> inherited_property;
  622. public:
  623. msg_add_edge_with_property_data() { }
  624. msg_add_edge_with_property_data(Vertex source,
  625. Vertex target,
  626. const EdgeProperty& property)
  627. : inherited_data(source, target),
  628. inherited_property(property) { }
  629. template<typename Archiver>
  630. void serialize(Archiver& ar, const unsigned int /*version*/)
  631. {
  632. ar & boost::serialization::base_object<inherited_data>(*this)
  633. & boost::serialization::base_object<inherited_property>(*this);
  634. }
  635. };
  636. //------------------------------------------------------------------------
  637. // Distributed adjacency list property map details
  638. /**
  639. * Metafunction that extracts the given property from the given
  640. * distributed adjacency list type. This could be implemented much
  641. * more cleanly, but even newer versions of GCC (e.g., 3.2.3)
  642. * cannot properly handle partial specializations involving
  643. * enumerator types.
  644. */
  645. template<typename Property>
  646. struct get_adj_list_pmap
  647. {
  648. template<typename Graph>
  649. struct apply
  650. {
  651. typedef Graph graph_type;
  652. typedef typename graph_type::process_group_type process_group_type;
  653. typedef typename graph_type::inherited base_graph_type;
  654. typedef typename property_map<base_graph_type, Property>::type
  655. local_pmap;
  656. typedef typename property_map<base_graph_type, Property>::const_type
  657. local_const_pmap;
  658. typedef graph_traits<graph_type> traits;
  659. typedef typename graph_type::local_vertex_descriptor local_vertex;
  660. typedef typename property_traits<local_pmap>::key_type local_key_type;
  661. typedef typename property_traits<local_pmap>::value_type value_type;
  662. typedef typename property_map<Graph, vertex_global_t>::const_type
  663. vertex_global_map;
  664. typedef typename property_map<Graph, edge_global_t>::const_type
  665. edge_global_map;
  666. typedef typename mpl::if_c<(is_same<local_key_type,
  667. local_vertex>::value),
  668. vertex_global_map, edge_global_map>::type
  669. global_map;
  670. public:
  671. typedef ::boost::parallel::distributed_property_map<
  672. process_group_type, global_map, local_pmap> type;
  673. typedef ::boost::parallel::distributed_property_map<
  674. process_group_type, global_map, local_const_pmap> const_type;
  675. };
  676. };
  677. /**
  678. * The local vertex index property map is actually a mapping from
  679. * the local vertex descriptors to vertex indices.
  680. */
  681. template<>
  682. struct get_adj_list_pmap<vertex_local_index_t>
  683. {
  684. template<typename Graph>
  685. struct apply
  686. : ::boost::property_map<typename Graph::inherited, vertex_index_t>
  687. { };
  688. };
  689. /**
  690. * The vertex index property map maps from global descriptors
  691. * (e.g., the vertex descriptor of a distributed adjacency list)
  692. * to the underlying local index. It is not valid to use this
  693. * property map with nonlocal descriptors.
  694. */
  695. template<>
  696. struct get_adj_list_pmap<vertex_index_t>
  697. {
  698. template<typename Graph>
  699. struct apply
  700. {
  701. private:
  702. typedef typename property_map<Graph, vertex_global_t>::const_type
  703. global_map;
  704. typedef property_map<typename Graph::inherited, vertex_index_t> local;
  705. public:
  706. typedef local_property_map<typename Graph::process_group_type,
  707. global_map,
  708. typename local::type> type;
  709. typedef local_property_map<typename Graph::process_group_type,
  710. global_map,
  711. typename local::const_type> const_type;
  712. };
  713. };
  714. /**
  715. * The vertex owner property map maps from vertex descriptors to
  716. * the processor that owns the vertex.
  717. */
  718. template<>
  719. struct get_adj_list_pmap<vertex_global_t>
  720. {
  721. template<typename Graph>
  722. struct apply
  723. {
  724. private:
  725. typedef typename Graph::local_vertex_descriptor
  726. local_vertex_descriptor;
  727. public:
  728. typedef global_descriptor_property_map<local_vertex_descriptor> type;
  729. typedef type const_type;
  730. };
  731. };
  732. /**
  733. * The vertex owner property map maps from vertex descriptors to
  734. * the processor that owns the vertex.
  735. */
  736. template<>
  737. struct get_adj_list_pmap<vertex_owner_t>
  738. {
  739. template<typename Graph>
  740. struct apply
  741. {
  742. private:
  743. typedef typename Graph::local_vertex_descriptor
  744. local_vertex_descriptor;
  745. public:
  746. typedef owner_property_map<local_vertex_descriptor> type;
  747. typedef type const_type;
  748. };
  749. };
  750. /**
  751. * The vertex local property map maps from vertex descriptors to
  752. * the local descriptor for that vertex.
  753. */
  754. template<>
  755. struct get_adj_list_pmap<vertex_local_t>
  756. {
  757. template<typename Graph>
  758. struct apply
  759. {
  760. private:
  761. typedef typename Graph::local_vertex_descriptor
  762. local_vertex_descriptor;
  763. public:
  764. typedef local_descriptor_property_map<local_vertex_descriptor> type;
  765. typedef type const_type;
  766. };
  767. };
  768. /**
  769. * The edge global property map maps from edge descriptors to
  770. * a pair of the owning processor and local descriptor.
  771. */
  772. template<>
  773. struct get_adj_list_pmap<edge_global_t>
  774. {
  775. template<typename Graph>
  776. struct apply
  777. {
  778. private:
  779. typedef typename Graph::local_edge_descriptor
  780. local_edge_descriptor;
  781. public:
  782. typedef edge_global_property_map<local_edge_descriptor> type;
  783. typedef type const_type;
  784. };
  785. };
  786. /**
  787. * The edge owner property map maps from edge descriptors to
  788. * the processor that owns the edge.
  789. */
  790. template<>
  791. struct get_adj_list_pmap<edge_owner_t>
  792. {
  793. template<typename Graph>
  794. struct apply
  795. {
  796. private:
  797. typedef typename Graph::local_edge_descriptor
  798. local_edge_descriptor;
  799. public:
  800. typedef edge_owner_property_map<local_edge_descriptor> type;
  801. typedef type const_type;
  802. };
  803. };
  804. /**
  805. * The edge local property map maps from edge descriptors to
  806. * the local descriptor for that edge.
  807. */
  808. template<>
  809. struct get_adj_list_pmap<edge_local_t>
  810. {
  811. template<typename Graph>
  812. struct apply
  813. {
  814. private:
  815. typedef typename Graph::local_edge_descriptor
  816. local_edge_descriptor;
  817. public:
  818. typedef edge_local_property_map<local_edge_descriptor> type;
  819. typedef type const_type;
  820. };
  821. };
  822. //------------------------------------------------------------------------
  823. // Directed graphs do not have in edges, so this is a no-op
  824. template<typename Graph>
  825. inline void
  826. remove_in_edge(typename Graph::edge_descriptor, Graph&, directedS)
  827. { }
  828. // Bidirectional graphs have in edges stored in the
  829. // vertex_in_edges property.
  830. template<typename Graph>
  831. inline void
  832. remove_in_edge(typename Graph::edge_descriptor e, Graph& g, bidirectionalS)
  833. {
  834. typedef typename Graph::in_edge_list_type in_edge_list_type;
  835. in_edge_list_type& in_edges =
  836. get(vertex_in_edges, g.base())[target(e, g).local];
  837. typename in_edge_list_type::iterator i = in_edges.begin();
  838. while (i != in_edges.end()
  839. && !(i->source_processor == source(e, g).owner)
  840. && i->e == e.local)
  841. ++i;
  842. BOOST_ASSERT(i != in_edges.end());
  843. in_edges.erase(i);
  844. }
  845. // Undirected graphs have in edges stored as normal edges.
  846. template<typename Graph>
  847. inline void
  848. remove_in_edge(typename Graph::edge_descriptor e, Graph& g, undirectedS)
  849. {
  850. typedef typename Graph::inherited base_type;
  851. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  852. // TBD: can we make this more efficient?
  853. // Removing edge (v, u). v is local
  854. base_type& bg = g.base();
  855. vertex_descriptor u = source(e, g);
  856. vertex_descriptor v = target(e, g);
  857. if (v.owner != process_id(g.process_group())) {
  858. using std::swap;
  859. swap(u, v);
  860. }
  861. typename graph_traits<base_type>::out_edge_iterator ei, ei_end;
  862. for (boost::tie(ei, ei_end) = out_edges(v.local, bg); ei != ei_end; ++ei)
  863. {
  864. if (target(*ei, g.base()) == u.local
  865. // TBD: deal with parallel edges properly && *ei == e
  866. && get(edge_target_processor_id, bg, *ei) == u.owner) {
  867. remove_edge(ei, bg);
  868. return;
  869. }
  870. }
  871. if (v.owner == process_id(g.process_group())) {
  872. }
  873. }
  874. //------------------------------------------------------------------------
  875. // Lazy addition of edges
  876. // Work around the fact that an adjacency_list with vecS vertex
  877. // storage automatically adds edges when the descriptor is
  878. // out-of-range.
  879. template <class Graph, class Config, class Base>
  880. inline std::pair<typename Config::edge_descriptor, bool>
  881. add_local_edge(typename Config::vertex_descriptor u,
  882. typename Config::vertex_descriptor v,
  883. const typename Config::edge_property_type& p,
  884. vec_adj_list_impl<Graph, Config, Base>& g_)
  885. {
  886. adj_list_helper<Config, Base>& g = g_;
  887. return add_edge(u, v, p, g);
  888. }
  889. template <class Graph, class Config, class Base>
  890. inline std::pair<typename Config::edge_descriptor, bool>
  891. add_local_edge(typename Config::vertex_descriptor u,
  892. typename Config::vertex_descriptor v,
  893. const typename Config::edge_property_type& p,
  894. boost::adj_list_impl<Graph, Config, Base>& g)
  895. {
  896. return add_edge(u, v, p, g);
  897. }
  898. template <class EdgeProperty,class EdgeDescriptor>
  899. struct msg_nonlocal_edge_data
  900. : public detail::parallel::maybe_store_property<EdgeProperty>
  901. {
  902. typedef EdgeProperty edge_property_type;
  903. typedef EdgeDescriptor local_edge_descriptor;
  904. typedef detail::parallel::maybe_store_property<edge_property_type>
  905. inherited;
  906. msg_nonlocal_edge_data() {}
  907. msg_nonlocal_edge_data(local_edge_descriptor e,
  908. const edge_property_type& p)
  909. : inherited(p), e(e) { }
  910. local_edge_descriptor e;
  911. template<typename Archiver>
  912. void serialize(Archiver& ar, const unsigned int /*version*/)
  913. {
  914. ar & boost::serialization::base_object<inherited>(*this) & e;
  915. }
  916. };
  917. template <class EdgeDescriptor>
  918. struct msg_remove_edge_data
  919. {
  920. typedef EdgeDescriptor edge_descriptor;
  921. msg_remove_edge_data() {}
  922. explicit msg_remove_edge_data(edge_descriptor e) : e(e) {}
  923. edge_descriptor e;
  924. template<typename Archiver>
  925. void serialize(Archiver& ar, const unsigned int /*version*/)
  926. {
  927. ar & e;
  928. }
  929. };
  930. } } // end namespace detail::parallel
  931. /**
  932. * Adjacency list traits for a distributed adjacency list. Contains
  933. * the vertex and edge descriptors, the directed-ness, and the
  934. * parallel edges typedefs.
  935. */
  936. template<typename OutEdgeListS, typename ProcessGroup,
  937. typename InVertexListS, typename InDistribution, typename DirectedS>
  938. struct adjacency_list_traits<OutEdgeListS,
  939. distributedS<ProcessGroup,
  940. InVertexListS,
  941. InDistribution>,
  942. DirectedS>
  943. {
  944. private:
  945. typedef typename mpl::if_<is_same<InVertexListS, defaultS>,
  946. vecS,
  947. InVertexListS>::type VertexListS;
  948. typedef adjacency_list_traits<OutEdgeListS, VertexListS, directedS>
  949. base_type;
  950. public:
  951. typedef typename base_type::vertex_descriptor local_vertex_descriptor;
  952. typedef typename base_type::edge_descriptor local_edge_descriptor;
  953. typedef typename boost::mpl::if_<typename DirectedS::is_bidir_t,
  954. bidirectional_tag,
  955. typename boost::mpl::if_<typename DirectedS::is_directed_t,
  956. directed_tag, undirected_tag
  957. >::type
  958. >::type directed_category;
  959. typedef typename parallel_edge_traits<OutEdgeListS>::type
  960. edge_parallel_category;
  961. typedef detail::parallel::global_descriptor<local_vertex_descriptor>
  962. vertex_descriptor;
  963. typedef detail::parallel::edge_descriptor<local_edge_descriptor>
  964. edge_descriptor;
  965. };
  966. #define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS \
  967. typename OutEdgeListS, typename ProcessGroup, typename InVertexListS, \
  968. typename InDistribution, typename DirectedS, typename VertexProperty, \
  969. typename EdgeProperty, typename GraphProperty, typename EdgeListS
  970. #define PBGL_DISTRIB_ADJLIST_TYPE \
  971. adjacency_list<OutEdgeListS, \
  972. distributedS<ProcessGroup, InVertexListS, InDistribution>, \
  973. DirectedS, VertexProperty, EdgeProperty, GraphProperty, \
  974. EdgeListS>
  975. #define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG \
  976. typename OutEdgeListS, typename ProcessGroup, typename InVertexListS, \
  977. typename InDistribution, typename VertexProperty, \
  978. typename EdgeProperty, typename GraphProperty, typename EdgeListS
  979. #define PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directed) \
  980. adjacency_list<OutEdgeListS, \
  981. distributedS<ProcessGroup, InVertexListS, InDistribution>, \
  982. directed, VertexProperty, EdgeProperty, GraphProperty, \
  983. EdgeListS>
  984. /** A distributed adjacency list.
  985. *
  986. * This class template partial specialization defines a distributed
  987. * (or "partitioned") adjacency list graph. The distributed
  988. * adjacency list is similar to the standard Boost Graph Library
  989. * adjacency list, which stores a list of vertices and for each
  990. * verted the list of edges outgoing from the vertex (and, in some
  991. * cases, also the edges incoming to the vertex). The distributed
  992. * adjacency list differs in that it partitions the graph into
  993. * several subgraphs that are then divided among different
  994. * processors (or nodes within a cluster). The distributed adjacency
  995. * list attempts to maintain a high degree of compatibility with the
  996. * standard, non-distributed adjacency list.
  997. *
  998. * The graph is partitioned by vertex, with each processor storing
  999. * all of the required information for a particular subset of the
  1000. * vertices, including vertex properties, outgoing edges, and (for
  1001. * bidirectional graphs) incoming edges. This information is
  1002. * accessible only on the processor that owns the vertex: for
  1003. * instance, if processor 0 owns vertex @c v, no other processor can
  1004. * directly access the properties of @c v or enumerate its outgoing
  1005. * edges.
  1006. *
  1007. * Edges in a graph may be entirely local (connecting two local
  1008. * vertices), but more often it is the case that edges are
  1009. * non-local, meaning that the two vertices they connect reside in
  1010. * different processes. Edge properties are stored with the
  1011. * originating vertex for directed and bidirectional graphs, and are
  1012. * therefore only accessible from the processor that owns the
  1013. * originating vertex. Other processors may query the source and
  1014. * target of the edge, but cannot access its properties. This is
  1015. * particularly interesting when accessing the incoming edges of a
  1016. * bidirectional graph, which are not guaranteed to be stored on the
  1017. * processor that is able to perform the iteration. For undirected
  1018. * graphs the situation is more complicated, since no vertex clearly
  1019. * owns the edges: the list of edges incident to a vertex may
  1020. * contain a mix of local and non-local edges.
  1021. *
  1022. * The distributed adjacency list is able to model several of the
  1023. * existing Graph concepts. It models the Graph concept because it
  1024. * exposes vertex and edge descriptors in the normal way; these
  1025. * descriptors model the GlobalDescriptor concept (because they have
  1026. * an owner and a local descriptor), and as such the distributed
  1027. * adjacency list models the DistributedGraph concept. The adjacency
  1028. * list also models the IncidenceGraph and AdjacencyGraph concepts,
  1029. * although this is only true so long as the domain of the valid
  1030. * expression arguments are restricted to vertices and edges stored
  1031. * locally. Likewise, bidirectional and undirected distributed
  1032. * adjacency lists model the BidirectionalGraph concept (vertex and
  1033. * edge domains must be respectived) and the distributed adjacency
  1034. * list models the MutableGraph concept (vertices and edges can only
  1035. * be added or removed locally). T he distributed adjacency list
  1036. * does not, however, model the VertexListGraph or EdgeListGraph
  1037. * concepts, because we can not efficiently enumerate all vertices
  1038. * or edges in the graph. Instead, the local subsets of vertices and
  1039. * edges can be enumerated (with the same syntax): the distributed
  1040. * adjacency list therefore models the DistributedVertexListGraph
  1041. * and DistributedEdgeListGraph concepts, because concurrent
  1042. * iteration over all of the vertices or edges stored on each
  1043. * processor will visit each vertex or edge.
  1044. *
  1045. * The distributed adjacency list is distinguished from the
  1046. * non-distributed version by the vertex list descriptor, which will
  1047. * be @c distributedS<ProcessGroup,VertexListS>. Here,
  1048. * the VertexListS type plays the same role as the VertexListS type
  1049. * in the non-distributed adjacency list: it allows one to select
  1050. * the data structure that will be used to store the local
  1051. * vertices. The ProcessGroup type, on the other hand, is unique to
  1052. * distributed data structures: it is the type that abstracts a
  1053. * group of cooperating processes, and it used for process
  1054. * identification, communication, and synchronization, among other
  1055. * things. Different process group types represent different
  1056. * communication mediums (e.g., MPI, PVM, TCP) or different models
  1057. * of communication (LogP, CGM, BSP, synchronous, etc.). This
  1058. * distributed adjacency list assumes a model based on non-blocking
  1059. * sends.
  1060. *
  1061. * Distribution of vertices across different processors is
  1062. * accomplished in two different ways. When initially constructing
  1063. * the graph, the user may provide a distribution object (that
  1064. * models the Distribution concept), which will determine the
  1065. * distribution of vertices to each process. Additionally, the @c
  1066. * add_vertex and @c add_edge operations add vertices or edges
  1067. * stored on the local processor. For @c add_edge, this is
  1068. * accomplished by requiring that the source vertex of the new edge
  1069. * be local to the process executing @c add_edge.
  1070. *
  1071. * Internal properties of a distributed adjacency list are
  1072. * accessible in the same manner as internal properties for a
  1073. * non-distributed adjacency list for local vertices or
  1074. * edges. Access to properties for remote vertices or edges occurs
  1075. * with the same syntax, but involve communication with the owner of
  1076. * the information: for more information, refer to class template
  1077. * @ref distributed_property_map, which manages distributed
  1078. * property maps. Note that the distributed property maps created
  1079. * for internal properties determine their reduction operation via
  1080. * the metafunction @ref property_reduce, which for the vast
  1081. * majority of uses is correct behavior.
  1082. *
  1083. * Communication among the processes coordinating on a particular
  1084. * distributed graph relies on non-blocking message passing along
  1085. * with synchronization. Local portions of the distributed graph may
  1086. * be modified concurrently, including the introduction of non-local
  1087. * edges, but prior to accessing the graph it is recommended that
  1088. * the @c synchronize free function be invoked on the graph to clear
  1089. * up any pending interprocess communication and modifications. All
  1090. * processes will then be released from the synchronization barrier
  1091. * concurrently.
  1092. *
  1093. * \todo Determine precisely what we should do with nonlocal edges
  1094. * in undirected graphs. Our parallelization of certain algorithms
  1095. * relies on the ability to access edge property maps immediately
  1096. * (e.g., edge_weight_t), so it may be necessary to duplicate the
  1097. * edge properties in both processes (but then we need some form of
  1098. * coherence protocol).
  1099. *
  1100. * \todo What does the user do if @c property_reduce doesn't do the
  1101. * right thing?
  1102. */
  1103. template<typename OutEdgeListS, typename ProcessGroup,
  1104. typename InVertexListS, typename InDistribution, typename DirectedS,
  1105. typename VertexProperty, typename EdgeProperty,
  1106. typename GraphProperty, typename EdgeListS>
  1107. class adjacency_list<OutEdgeListS,
  1108. distributedS<ProcessGroup,
  1109. InVertexListS,
  1110. InDistribution>,
  1111. DirectedS, VertexProperty,
  1112. EdgeProperty, GraphProperty, EdgeListS>
  1113. : // Support for named vertices
  1114. public graph::distributed::maybe_named_graph<
  1115. adjacency_list<OutEdgeListS,
  1116. distributedS<ProcessGroup,
  1117. InVertexListS,
  1118. InDistribution>,
  1119. DirectedS, VertexProperty,
  1120. EdgeProperty, GraphProperty, EdgeListS>,
  1121. typename adjacency_list_traits<OutEdgeListS,
  1122. distributedS<ProcessGroup,
  1123. InVertexListS,
  1124. InDistribution>,
  1125. DirectedS>::vertex_descriptor,
  1126. typename adjacency_list_traits<OutEdgeListS,
  1127. distributedS<ProcessGroup,
  1128. InVertexListS,
  1129. InDistribution>,
  1130. DirectedS>::edge_descriptor,
  1131. detail::parallel::adjacency_list_config<OutEdgeListS, ProcessGroup,
  1132. InVertexListS, InDistribution,
  1133. DirectedS, VertexProperty,
  1134. EdgeProperty, GraphProperty,
  1135. EdgeListS> >
  1136. {
  1137. typedef detail::parallel::adjacency_list_config<OutEdgeListS, ProcessGroup,
  1138. InVertexListS, InDistribution,
  1139. DirectedS, VertexProperty,
  1140. EdgeProperty, GraphProperty,
  1141. EdgeListS>
  1142. config_type;
  1143. typedef adjacency_list_traits<OutEdgeListS,
  1144. distributedS<ProcessGroup,
  1145. InVertexListS,
  1146. InDistribution>,
  1147. DirectedS>
  1148. traits_type;
  1149. typedef typename DirectedS::is_directed_t is_directed;
  1150. typedef EdgeListS edge_list_selector;
  1151. public:
  1152. /// The container type that will store incoming edges for a
  1153. /// bidirectional graph.
  1154. typedef typename config_type::in_edge_list_type in_edge_list_type;
  1155. // typedef typename inherited::edge_descriptor edge_descriptor;
  1156. /// The type of the underlying adjacency list implementation
  1157. typedef typename config_type::inherited inherited;
  1158. /// The type of properties stored in the local subgraph
  1159. /// Bidirectional graphs have an extra vertex property to store
  1160. /// the incoming edges.
  1161. typedef typename inherited::vertex_property_type
  1162. base_vertex_property_type;
  1163. /// The type of the distributed adjacency list (this type)
  1164. typedef typename config_type::graph_type graph_type;
  1165. /// Expose graph components and graph category
  1166. typedef typename traits_type::local_vertex_descriptor
  1167. local_vertex_descriptor;
  1168. typedef typename traits_type::local_edge_descriptor
  1169. local_edge_descriptor;
  1170. typedef typename traits