Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r52313 - in trunk: boost/graph/distributed boost/property_map boost/property_map/parallel boost/property_map/parallel/impl libs/graph libs/graph/build libs/graph/src libs/graph_parallel libs/graph_parallel/build libs/graph_parallel/doc libs/graph_parallel/doc/html libs/graph_parallel/example libs/graph_parallel/src libs/graph_parallel/test
From: jewillco_at_[hidden]
Date: 2009-04-10 21:33:13


Author: jewillco
Date: 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
New Revision: 52313
URL: http://svn.boost.org/trac/boost/changeset/52313

Log:
Merged in code and docs from Parallel BGL; CMake-based build system for tests and examples and docs is not working; src and doc can be built with bjam
Added:
   trunk/boost/property_map/parallel/
   trunk/boost/property_map/parallel/caching_property_map.hpp (contents, props changed)
   trunk/boost/property_map/parallel/distributed_property_map.hpp (contents, props changed)
   trunk/boost/property_map/parallel/global_index_map.hpp (contents, props changed)
   trunk/boost/property_map/parallel/impl/
   trunk/boost/property_map/parallel/impl/distributed_property_map.cpp (contents, props changed)
   trunk/boost/property_map/parallel/local_property_map.hpp (contents, props changed)
   trunk/libs/graph_parallel/
   trunk/libs/graph_parallel/CMakeLists.txt
      - copied, changed from r52301, /trunk/libs/graph/CMakeLists.txt
   trunk/libs/graph_parallel/build/
   trunk/libs/graph_parallel/build/Jamfile.v2
      - copied, changed from r52301, /trunk/libs/graph/build/Jamfile.v2
   trunk/libs/graph_parallel/doc/
   trunk/libs/graph_parallel/doc/CMakeLists.txt (contents, props changed)
   trunk/libs/graph_parallel/doc/DistributedEdgeListGraph.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/DistributedGraph.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/DistributedVertexListGraph.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/GlobalDescriptor.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/Jamfile.v2
      - copied, changed from r52301, /trunk/libs/parameter/doc/Jamfile.v2
   trunk/libs/graph_parallel/doc/architecture.graffle (contents, props changed)
   trunk/libs/graph_parallel/doc/architecture.png (contents, props changed)
   trunk/libs/graph_parallel/doc/betweenness_centrality.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/boman_et_al_graph_coloring.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/breadth_first_search.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/connected_components.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/connected_components_parallel_search.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/dehne_gotz_min_spanning_tree.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/dijkstra_dist3_graph.graffle (contents, props changed)
   trunk/libs/graph_parallel/doc/dijkstra_dist3_graph.png (contents, props changed)
   trunk/libs/graph_parallel/doc/dijkstra_example.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/dijkstra_seq_graph.graffle (contents, props changed)
   trunk/libs/graph_parallel/doc/dijkstra_seq_graph.png (contents, props changed)
   trunk/libs/graph_parallel/doc/dijkstra_shortest_paths.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/dist-adjlist.graffle (contents, props changed)
   trunk/libs/graph_parallel/doc/dist-adjlist.png (contents, props changed)
   trunk/libs/graph_parallel/doc/dist-pmap.graffle (contents, props changed)
   trunk/libs/graph_parallel/doc/dist-pmap.png (contents, props changed)
   trunk/libs/graph_parallel/doc/distributed-graph.graffle (contents, props changed)
   trunk/libs/graph_parallel/doc/distributed-graph.png (contents, props changed)
   trunk/libs/graph_parallel/doc/distributedS.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/distributed_adjacency_list.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/distributed_property_map.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/distributed_queue.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/fruchterman_reingold.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/graph.png (contents, props changed)
   trunk/libs/graph_parallel/doc/html/
   trunk/libs/graph_parallel/doc/html/DistributedEdgeListGraph.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/DistributedGraph.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/DistributedVertexListGraph.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/GlobalDescriptor.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/betweenness_centrality.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/boman_et_al_graph_coloring.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/breadth_first_search.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/connected_components.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/connected_components_parallel_search.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/dehne_gotz_min_spanning_tree.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/dijkstra_example.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/dijkstra_shortest_paths.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/distributedS.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/distributed_adjacency_list.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/distributed_property_map.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/distributed_queue.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/fruchterman_reingold.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/index.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/local_subgraph.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/mesh_generator.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/metis.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/overview.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/page_rank.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/process_group.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/rmat_generator.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/scalable_rmat_generator.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/simple_trigger.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/sorted_rmat_generator.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/sorted_unique_rmat_generator.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/ssca_generator.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/st_connected.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/strong_components.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/tsin_depth_first_visit.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/unique_rmat_generator.html (contents, props changed)
   trunk/libs/graph_parallel/doc/html/vertex_list_adaptor.html (contents, props changed)
   trunk/libs/graph_parallel/doc/index.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/local_subgraph.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/mesh_generator.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/metis.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/overview.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/page_rank.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/process_group.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/rmat_generator.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/scalable_rmat_generator.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/simple_trigger.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/small_world_1_70_6_0p02.png (contents, props changed)
   trunk/libs/graph_parallel/doc/sorted_rmat_generator.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/sorted_unique_rmat_generator.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/ssca_generator.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/st_connected.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/strong_components.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/tsin_depth_first_visit.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/unique_rmat_generator.rst (contents, props changed)
   trunk/libs/graph_parallel/doc/vertex_coloring.png (contents, props changed)
   trunk/libs/graph_parallel/doc/vertex_list_adaptor.rst (contents, props changed)
   trunk/libs/graph_parallel/example/
   trunk/libs/graph_parallel/example/CMakeLists.txt (contents, props changed)
   trunk/libs/graph_parallel/example/breadth_first_search.cpp (contents, props changed)
   trunk/libs/graph_parallel/example/dijkstra_shortest_paths.cpp (contents, props changed)
   trunk/libs/graph_parallel/module.cmake
      - copied, changed from r52301, /trunk/libs/graph/module.cmake
   trunk/libs/graph_parallel/src/
   trunk/libs/graph_parallel/src/CMakeLists.txt (contents, props changed)
   trunk/libs/graph_parallel/src/mpi_process_group.cpp (contents, props changed)
   trunk/libs/graph_parallel/src/tag_allocator.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/
   trunk/libs/graph_parallel/test/CMakeLists.txt (contents, props changed)
   trunk/libs/graph_parallel/test/adjlist_build_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/adjlist_redist_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/adjlist_remove_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/algorithm_performance.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_adjacency_list_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_betweenness_centrality_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_connected_components_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_csr_algorithm_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_csr_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_dfs_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_dimacs_reader.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_graph_coloring_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_mst_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_page_rank_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_property_map_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_queue_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_rmat_cc.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_rmat_cc_ps.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_rmat_pagerank.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_shortest_paths_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/distributed_strong_components_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/hohberg_biconnected_components_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/mesh_generator_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/named_vertices_hash_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/named_vertices_seq.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/named_vertices_test.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/process_group_serialization.cpp (contents, props changed)
   trunk/libs/graph_parallel/test/ssca.cpp (contents, props changed)
Removed:
   trunk/libs/graph/src/mpi_process_group.cpp
   trunk/libs/graph/src/tag_allocator.cpp
Text files modified:
   trunk/boost/graph/distributed/rmat_graph_generator.hpp | 8
   trunk/boost/property_map/property_map.hpp | 199 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/property_map/vector_property_map.hpp | 90 ++++++++++++++++++
   trunk/libs/graph/CMakeLists.txt | 8 -
   trunk/libs/graph/build/Jamfile.v2 | 23 ----
   trunk/libs/graph/module.cmake | 1
   trunk/libs/graph/src/CMakeLists.txt | 1
   trunk/libs/graph_parallel/CMakeLists.txt | 24 +---
   trunk/libs/graph_parallel/build/Jamfile.v2 | 41 -------
   trunk/libs/graph_parallel/doc/Jamfile.v2 | 2
   trunk/libs/graph_parallel/module.cmake | 4
   11 files changed, 311 insertions(+), 90 deletions(-)

Modified: trunk/boost/graph/distributed/rmat_graph_generator.hpp
==============================================================================
--- trunk/boost/graph/distributed/rmat_graph_generator.hpp (original)
+++ trunk/boost/graph/distributed/rmat_graph_generator.hpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -14,7 +14,7 @@
 #endif
 
 #include <boost/graph/parallel/algorithm.hpp>
-#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/parallel/process_group.hpp>
 
 namespace boost {
 
@@ -23,7 +23,8 @@
   // requires an MPI process group. Run-time is slightly worse than
   // the unique rmat generator. Edge list generated is sorted and
   // unique.
- template<typename Distribution, typename RandomGenerator, typename Graph>
+ template<typename ProcessGroup, typename Distribution,
+ typename RandomGenerator, typename Graph>
   class scalable_rmat_iterator
   {
       typedef typename graph_traits<Graph>::directed_category directed_category;
@@ -43,8 +44,7 @@
       { }
 
       // Initialize for edge generation
- scalable_rmat_iterator(boost::graph::distributed::mpi_process_group pg,
- Distribution distrib,
+ scalable_rmat_iterator(ProcessGroup pg, Distribution distrib,
                              RandomGenerator& gen, vertices_size_type n,
                              edges_size_type m, double a, double b, double c,
                              double d, bool permute_vertices = true)

Added: trunk/boost/property_map/parallel/caching_property_map.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/property_map/parallel/caching_property_map.hpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,96 @@
+// Copyright 2004 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+#ifndef BOOST_PARALLEL_CACHING_PROPERTY_MAP_HPP
+#define BOOST_PARALLEL_CACHING_PROPERTY_MAP_HPP
+
+#ifndef BOOST_GRAPH_USE_MPI
+#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
+#endif
+
+#include <boost/property_map/property_map.hpp>
+
+namespace boost {
+
+// This probably doesn't belong here
+template<typename Key, typename Value>
+inline void local_put(dummy_property_map, const Key&, const Value&) {}
+
+namespace parallel {
+
+/** Property map that caches values placed in it but does not
+ * broadcast values to remote processors. This class template is
+ * meant as an adaptor for @ref distributed_property_map that
+ * suppresses communication in the event of a remote @c put operation
+ * by mapping it to a local @c put operation.
+ *
+ * @todo Find a better name for @ref caching_property_map
+ */
+template<typename PropertyMap>
+class caching_property_map
+{
+public:
+ typedef typename property_traits<PropertyMap>::key_type key_type;
+ typedef typename property_traits<PropertyMap>::value_type value_type;
+ typedef typename property_traits<PropertyMap>::reference reference;
+ typedef typename property_traits<PropertyMap>::category category;
+
+ explicit caching_property_map(const PropertyMap& property_map)
+ : property_map(property_map) {}
+
+ PropertyMap& base() { return property_map; }
+ const PropertyMap& base() const { return property_map; }
+
+ template<typename Reduce>
+ void set_reduce(const Reduce& reduce)
+ { property_map.set_reduce(reduce); }
+
+ void reset() { property_map.reset(); }
+
+#if 0
+ reference operator[](const key_type& key) const
+ {
+ return property_map[key];
+ }
+#endif
+
+private:
+ PropertyMap property_map;
+};
+
+template<typename PropertyMap, typename Key>
+inline typename caching_property_map<PropertyMap>::value_type
+get(const caching_property_map<PropertyMap>& pm, const Key& key)
+{ return get(pm.base(), key); }
+
+template<typename PropertyMap, typename Key, typename Value>
+inline void
+local_put(const caching_property_map<PropertyMap>& pm, const Key& key,
+ const Value& value)
+{ local_put(pm.base(), key, value); }
+
+template<typename PropertyMap, typename Key, typename Value>
+inline void
+cache(const caching_property_map<PropertyMap>& pm, const Key& key,
+ const Value& value)
+{ cache(pm.base(), key, value); }
+
+template<typename PropertyMap, typename Key, typename Value>
+inline void
+put(const caching_property_map<PropertyMap>& pm, const Key& key,
+ const Value& value)
+{ local_put(pm.base(), key, value); }
+
+template<typename PropertyMap>
+inline caching_property_map<PropertyMap>
+make_caching_property_map(const PropertyMap& pm)
+{ return caching_property_map<PropertyMap>(pm); }
+
+} } // end namespace boost::parallel
+
+#endif // BOOST_PARALLEL_CACHING_PROPERTY_MAP_HPP

Added: trunk/boost/property_map/parallel/distributed_property_map.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/property_map/parallel/distributed_property_map.hpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,694 @@
+// Copyright (C) 2004-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Nick Edmonds
+// Andrew Lumsdaine
+
+// The placement of this #include probably looks very odd relative to
+// the #ifndef/#define pair below. However, this placement is
+// extremely important to allow the various property map headers to be
+// included in any order.
+#include <boost/property_map/property_map.hpp>
+
+#ifndef BOOST_PARALLEL_DISTRIBUTED_PROPERTY_MAP_HPP
+#define BOOST_PARALLEL_DISTRIBUTED_PROPERTY_MAP_HPP
+
+#ifndef BOOST_GRAPH_USE_MPI
+#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
+#endif
+
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/graph/parallel/process_group.hpp>
+#include <boost/graph/detail/edge.hpp>
+#include <boost/function/function1.hpp>
+#include <vector>
+#include <set>
+#include <boost/graph/parallel/basic_reduce.hpp>
+#include <boost/graph/parallel/detail/untracked_pair.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/property_map/parallel/local_property_map.hpp>
+#include <map>
+#include <boost/version.hpp>
+#include <boost/graph/distributed/unsafe_serialize.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+
+// Serialization functions for constructs we use
+#include <boost/serialization/utility.hpp>
+
+namespace boost { namespace parallel {
+
+using boost::graph::parallel::trigger_receive_context;
+
+namespace detail {
+ /**************************************************************************
+ * Metafunction that degrades an Lvalue Property Map category tag to
+ * a Read Write Property Map category tag.
+ **************************************************************************/
+ template<bool IsLvaluePropertyMap>
+ struct make_nonlvalue_property_map
+ {
+ template<typename T> struct apply { typedef T type; };
+ };
+
+ template<>
+ struct make_nonlvalue_property_map<true>
+ {
+ template<typename>
+ struct apply
+ {
+ typedef read_write_property_map_tag type;
+ };
+ };
+
+ /**************************************************************************
+ * Performs a "put" on a property map so long as the property map is
+ * a Writable Property Map or a mutable Lvalue Property Map. This
+ * is required because the distributed property map's message
+ * handler handles "put" messages even for a const property map,
+ * although receipt of a "put" message is ill-formed.
+ **************************************************************************/
+ template<bool IsLvaluePropertyMap>
+ struct maybe_put_in_lvalue_pm
+ {
+ template<typename PropertyMap, typename Key, typename Value>
+ static inline void
+ do_put(PropertyMap, const Key&, const Value&)
+ { assert(false); }
+ };
+
+ template<>
+ struct maybe_put_in_lvalue_pm<true>
+ {
+ template<typename PropertyMap, typename Key, typename Value>
+ static inline void
+ do_put(PropertyMap pm, const Key& key, const Value& value)
+ {
+ using boost::put;
+
+ put(pm, key, value);
+ }
+ };
+
+ template<typename PropertyMap, typename Key, typename Value>
+ inline void
+ maybe_put_impl(PropertyMap pm, const Key& key, const Value& value,
+ writable_property_map_tag)
+ {
+ using boost::put;
+
+ put(pm, key, value);
+ }
+
+ template<typename PropertyMap, typename Key, typename Value>
+ inline void
+ maybe_put_impl(PropertyMap pm, const Key& key, const Value& value,
+ lvalue_property_map_tag)
+ {
+ typedef typename property_traits<PropertyMap>::value_type value_type;
+ typedef typename property_traits<PropertyMap>::reference reference;
+ // DPG TBD: Some property maps are improperly characterized as
+ // lvalue_property_maps, when in fact they do not provide true
+ // references. The most typical example is those property maps
+ // built from vector<bool> and its iterators, which deal with
+ // proxies. We don't want to mischaracterize these as not having a
+ // "put" operation, so we only consider an lvalue_property_map as
+ // constant if its reference is const value_type&. In fact, this
+ // isn't even quite correct (think of a
+ // vector<bool>::const_iterator), but at present C++ doesn't
+ // provide us with any alternatives.
+ typedef is_same<const value_type&, reference> is_constant;
+
+ maybe_put_in_lvalue_pm<(!is_constant::value)>::do_put(pm, key, value);
+ }
+
+ template<typename PropertyMap, typename Key, typename Value>
+ inline void
+ maybe_put_impl(PropertyMap, const Key&, const Value&, ...)
+ { assert(false); }
+
+ template<typename PropertyMap, typename Key, typename Value>
+ inline void
+ maybe_put(PropertyMap pm, const Key& key, const Value& value)
+ {
+ maybe_put_impl(pm, key, value,
+ typename property_traits<PropertyMap>::category());
+ }
+} // end namespace detail
+
+/** The consistency model used by the distributed property map. */
+enum consistency_model {
+ cm_forward = 1 << 0,
+ cm_backward = 1 << 1,
+ cm_bidirectional = cm_forward | cm_backward,
+ cm_flush = 1 << 2,
+ cm_reset = 1 << 3,
+ cm_clear = 1 << 4
+};
+
+/** Distributed property map adaptor.
+ *
+ * The distributed property map adaptor is a property map whose
+ * stored values are distributed across multiple non-overlapping
+ * memory spaces on different processes. Values local to the current
+ * process are stored within a local property map and may be
+ * immediately accessed via @c get and @c put. Values stored on
+ * remote processes may also be access via @c get and @c put, but the
+ * behavior differs slightly:
+ *
+ * - @c put operations update a local ghost cell and send a "put"
+ * message to the process that owns the value. The owner is free to
+ * update its own "official" value or may ignore the put request.
+ *
+ * - @c get operations returns the contents of the local ghost
+ * cell. If no ghost cell is available, one is created using the
+ * default value provided by the "reduce" operation. See, e.g.,
+ * @ref basic_reduce and @ref property_reduce.
+ *
+ * Using distributed property maps requires a bit more care than using
+ * local, sequential property maps. While the syntax and semantics are
+ * similar, distributed property maps may contain out-of-date
+ * information that can only be guaranteed to be synchronized by
+ * calling the @ref synchronize function in all processes.
+ *
+ * To address the issue of out-of-date values, distributed property
+ * maps are supplied with a reduction operation. The reduction
+ * operation has two roles:
+ *
+ * -# When a value is needed for a remote key but no value is
+ * immediately available, the reduction operation provides a
+ * suitable default. For instance, a distributed property map
+ * storing distances may have a reduction operation that returns
+ * an infinite value as the default, whereas a distributed
+ * property map for vertex colors may return white as the
+ * default.
+ *
+ * -# When a value is received from a remote process, the process
+ * owning the key associated with that value must determine which
+ * value---the locally stored value, the value received from a
+ * remote process, or some combination of the two---will be
+ * stored as the "official" value in the property map. The
+ * reduction operation transforms the local and remote values
+ * into the "official" value to be stored.
+ *
+ * @tparam ProcessGroup the type of the process group over which the
+ * property map is distributed and is also the medium for
+ * communication.
+ *
+ * @tparam StorageMap the type of the property map that will
+ * store values for keys local to this processor. The @c value_type of
+ * this property map will become the @c value_type of the distributed
+ * property map. The distributed property map models the same property
+ * map concepts as the @c LocalPropertyMap, with one exception: a
+ * distributed property map cannot be an LvaluePropertyMap (because
+ * remote values are not addressable), and is therefore limited to
+ * ReadWritePropertyMap.
+ */
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+class distributed_property_map
+{
+ public:
+ /// The key type of the property map.
+ typedef typename property_traits<GlobalMap>::key_type key_type;
+
+ /// The value type of the property map.
+ typedef typename property_traits<StorageMap>::value_type value_type;
+ typedef typename property_traits<StorageMap>::reference reference;
+ typedef ProcessGroup process_group_type;
+
+ private:
+ typedef distributed_property_map self_type;
+ typedef typename property_traits<StorageMap>::category local_category;
+ typedef typename property_traits<StorageMap>::key_type local_key_type;
+ typedef typename property_traits<GlobalMap>::value_type owner_local_pair;
+ typedef typename ProcessGroup::process_id_type process_id_type;
+
+ enum property_map_messages {
+ /** A request to store a value in a property map. The message
+ * contains a std::pair<key, data>.
+ */
+ property_map_put,
+
+ /** A request to retrieve a particular value in a property
+ * map. The message contains a key. The owner of that key will
+ * reply with a value.
+ */
+ property_map_get,
+
+ /** A request to update values stored on a remote processor. The
+ * message contains a vector of keys for which the source
+ * requests updated values. This message will only be transmitted
+ * during synchronization.
+ */
+ property_map_multiget,
+
+ /** A request to store values in a ghost cell. This message
+ * contains a vector of key/value pairs corresponding to the
+ * sequence of keys sent to the source processor.
+ */
+ property_map_multiget_reply,
+
+ /** The payload containing a vector of local key-value pairs to be
+ * put into the remote property map. A key-value std::pair will be
+ * used to store each local key-value pair.
+ */
+ property_map_multiput
+ };
+
+ public:
+ /// The type of the ghost cells
+ typedef multi_index::multi_index_container<
+ std::pair<key_type, value_type>,
+ multi_index::indexed_by<
+ multi_index::sequenced<>,
+ multi_index::hashed_unique<
+ multi_index::member<std::pair<key_type, value_type>,
+ key_type,
+ &std::pair<key_type, value_type>::first>
+ >
+ >
+ > ghost_cells_type;
+
+ /// Iterator into the ghost cells
+ typedef typename ghost_cells_type::iterator iterator;
+
+ /// Key-based index into the ghost cells
+ typedef typename ghost_cells_type::template nth_index<1>::type
+ ghost_cells_key_index_type;
+
+ /// Iterator into the ghost cells (by key)
+ typedef typename ghost_cells_key_index_type::iterator key_iterator;
+
+ /** The property map category. A distributed property map cannot be
+ * an Lvalue Property Map, because values on remote processes cannot
+ * be addresses.
+ */
+ typedef typename detail::make_nonlvalue_property_map<
+ (is_base_and_derived<lvalue_property_map_tag, local_category>::value
+ || is_same<lvalue_property_map_tag, local_category>::value)>
+ ::template apply<local_category>::type category;
+
+ /** Default-construct a distributed property map. This function
+ * creates an initialized property map that must be assigned to a
+ * valid value before being used. It is only provided here because
+ * property maps must be Default Constructible.
+ */
+ distributed_property_map() {}
+
+ /** Construct a distributed property map. Builds a distributed
+ * property map communicating over the given process group and using
+ * the given local property map for storage. Since no reduction
+ * operation is provided, the default reduction operation @c
+ * basic_reduce<value_type> is used.
+ */
+ distributed_property_map(const ProcessGroup& pg, const GlobalMap& global,
+ const StorageMap& pm)
+ : data(new data_t(pg, global, pm, basic_reduce<value_type>(), false))
+ {
+ typedef handle_message<basic_reduce<value_type> > Handler;
+
+ data->ghost_cells.reset(new ghost_cells_type());
+ Handler handler(data);
+ data->process_group.replace_handler(handler, true);
+ data->process_group.template get_receiver<Handler>()
+ ->setup_triggers(data->process_group);
+ }
+
+ /** Construct a distributed property map. Builds a distributed
+ * property map communicating over the given process group and using
+ * the given local property map for storage. The given @p reduce
+ * parameter is used as the reduction operation.
+ */
+ template<typename Reduce>
+ distributed_property_map(const ProcessGroup& pg, const GlobalMap& global,
+ const StorageMap& pm,
+ const Reduce& reduce);
+
+ ~distributed_property_map();
+
+ /// Set the reduce operation of the distributed property map.
+ template<typename Reduce>
+ void set_reduce(const Reduce& reduce);
+
+ // Set the consistency model for the distributed property map
+ void set_consistency_model(int model);
+
+ // Get the consistency model
+ int get_consistency_model() const { return data->model; }
+
+ // Set the maximum number of ghost cells that we are allowed to
+ // maintain. If 0, all ghost cells will be retained.
+ void set_max_ghost_cells(std::size_t max_ghost_cells);
+
+ // Clear out all ghost cells
+ void clear();
+
+ // Reset the values in all ghost cells to the default value
+ void reset();
+
+ // Flush all values destined for remote processors
+ void flush();
+
+ reference operator[](const key_type& key) const
+ {
+ owner_local_pair p = get(data->global, key);
+
+ if (p.first == process_id(data->process_group)) {
+ return data->storage[p.second];
+ } else {
+ return cell(key);
+ }
+ }
+
+ process_group_type process_group() const
+ {
+ return data->process_group.base();
+ }
+
+ StorageMap& base() { return data->storage; }
+ const StorageMap& base() const { return data->storage; }
+
+ /** Sends a "put" request.
+ * \internal
+ *
+ */
+ void
+ request_put(process_id_type p, const key_type& k, const value_type& v) const
+ {
+ send(data->process_group, p, property_map_put,
+ boost::parallel::detail::make_untracked_pair(k, v));
+ }
+
+ /** Access the ghost cell for the given key.
+ * \internal
+ */
+ value_type& cell(const key_type& k, bool request_if_missing = true) const;
+
+ /** Perform synchronization
+ * \internal
+ */
+ void do_synchronize();
+
+ const GlobalMap& global() const { return data->global; }
+ GlobalMap& global() { return data->global; }
+
+ struct data_t
+ {
+ data_t(const ProcessGroup& pg, const GlobalMap& global,
+ const StorageMap& pm, const function1<value_type, key_type>& dv,
+ bool has_default_resolver)
+ : process_group(pg), global(global), storage(pm),
+ ghost_cells(), max_ghost_cells(1000000), get_default_value(dv),
+ has_default_resolver(has_default_resolver), model(cm_forward) { }
+
+ /// The process group
+ ProcessGroup process_group;
+
+ /// A mapping from the keys of this property map to the global
+ /// descriptor.
+ GlobalMap global;
+
+ /// Local property map
+ StorageMap storage;
+
+ /// The ghost cells
+ shared_ptr<ghost_cells_type> ghost_cells;
+
+ /// The maximum number of ghost cells we are permitted to hold. If
+ /// zero, we are permitted to have an infinite number of ghost
+ /// cells.
+ std::size_t max_ghost_cells;
+
+ /// Default value for remote ghost cells, as defined by the
+ /// reduction operation.
+ function1<value_type, key_type> get_default_value;
+
+ /// True if this resolver is the "default" resolver, meaning that
+ /// we should not be able to get() a default value; it needs to be
+ /// request()ed first.
+ bool has_default_resolver;
+
+ // Current consistency model
+ int model;
+
+ // Function that resets all of the ghost cells to their default
+ // values. It knows the type of the resolver, so we can eliminate
+ // a large number of calls through function pointers.
+ void (data_t::*reset)();
+
+ // Clear out all ghost cells
+ void clear();
+
+ // Flush all values destined for remote processors
+ void flush();
+
+ // Send out requests to "refresh" the values of ghost cells that
+ // we're holding.
+ void refresh_ghost_cells();
+
+ private:
+ template<typename Resolver> void do_reset();
+
+ friend class distributed_property_map;
+ };
+ friend struct data_t;
+
+ shared_ptr<data_t> data;
+
+ private:
+ // Prunes the least recently used ghost cells until we have @c
+ // max_ghost_cells or fewer ghost cells.
+ void prune_ghost_cells() const;
+
+ /** Handles incoming messages.
+ *
+ * This function object is responsible for handling all incoming
+ * messages for the distributed property map.
+ */
+ template<typename Reduce>
+ struct handle_message
+ {
+ explicit handle_message(const shared_ptr<data_t>& data,
+ const Reduce& reduce = Reduce())
+ : data_ptr(data), reduce(reduce) { }
+
+ void operator()(process_id_type source, int tag);
+
+ /// Individual message handlers
+ void
+ handle_put(int source, int tag,
+ const boost::parallel::detail::untracked_pair<key_type, value_type>& data,
+ trigger_receive_context);
+
+ value_type
+ handle_get(int source, int tag, const key_type& data,
+ trigger_receive_context);
+
+ void
+ handle_multiget(int source, int tag,
+ const std::vector<key_type>& data,
+ trigger_receive_context);
+
+ void
+ handle_multiget_reply
+ (int source, int tag,
+ const std::vector<boost::parallel::detail::untracked_pair<key_type, value_type> >& msg,
+ trigger_receive_context);
+
+ void
+ handle_multiput
+ (int source, int tag,
+ const std::vector<unsafe_pair<local_key_type, value_type> >& data,
+ trigger_receive_context);
+
+ void setup_triggers(process_group_type& pg);
+
+ private:
+ weak_ptr<data_t> data_ptr;
+ Reduce reduce;
+ };
+
+ /* Sets up the next stage in a multi-stage synchronization, for
+ bidirectional consistency. */
+ struct on_synchronize
+ {
+ explicit on_synchronize(const shared_ptr<data_t>& data) : data_ptr(data) { }
+
+ void operator()();
+
+ private:
+ weak_ptr<data_t> data_ptr;
+ };
+};
+
+/* An implementation helper macro for the common case of naming
+ distributed property maps with all of the normal template
+ parameters. */
+#define PBGL_DISTRIB_PMAP \
+ distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
+
+/* Request that the value for the given remote key be retrieved in
+ the next synchronization round. */
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+inline void
+request(const PBGL_DISTRIB_PMAP& pm,
+ typename PBGL_DISTRIB_PMAP::key_type const& key)
+{
+ if (get(pm.data->global, key).first != process_id(pm.data->process_group))
+ pm.cell(key, false);
+}
+
+/** Get the value associated with a particular key. Retrieves the
+ * value associated with the given key. If the key denotes a
+ * locally-owned object, it returns the value from the local property
+ * map; if the key denotes a remotely-owned object, retrieves the
+ * value of the ghost cell for that key, which may be the default
+ * value provided by the reduce operation.
+ *
+ * Complexity: For a local key, O(1) get operations on the underlying
+ * property map. For a non-local key, O(1) accesses to the ghost cells.
+ */
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+inline
+typename PBGL_DISTRIB_PMAP::value_type
+get(const PBGL_DISTRIB_PMAP& pm,
+ typename PBGL_DISTRIB_PMAP::key_type const& key)
+{
+ using boost::get;
+
+ typename property_traits<GlobalMap>::value_type p =
+ get(pm.data->global, key);
+
+ if (p.first == process_id(pm.data->process_group)) {
+ return get(pm.data->storage, p.second);
+ } else {
+ return pm.cell(key);
+ }
+}
+
+/** Put a value associated with the given key into the property map.
+ * When the key denotes a locally-owned object, this operation updates
+ * the underlying local property map. Otherwise, the local ghost cell
+ * is updated and a "put" message is sent to the processor owning this
+ * key.
+ *
+ * Complexity: For a local key, O(1) put operations on the underlying
+ * property map. For a nonlocal key, O(1) accesses to the ghost cells
+ * and will send O(1) messages of size O(sizeof(key) + sizeof(value)).
+ */
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void
+put(const PBGL_DISTRIB_PMAP& pm,
+ typename PBGL_DISTRIB_PMAP::key_type const & key,
+ typename PBGL_DISTRIB_PMAP::value_type const & value)
+{
+ using boost::put;
+
+ typename property_traits<GlobalMap>::value_type p =
+ get(pm.data->global, key);
+
+ if (p.first == process_id(pm.data->process_group)) {
+ put(pm.data->storage, p.second, value);
+ } else {
+ if (pm.data->model & cm_forward)
+ pm.request_put(p.first, key, value);
+
+ pm.cell(key, false) = value;
+ }
+}
+
+/** Put a value associated with a given key into the local view of the
+ * property map. This operation is equivalent to @c put, but with one
+ * exception: no message will be sent to the owning processor in the
+ * case of a remote update. The effect is that any value written via
+ * @c local_put for a remote key may be overwritten in the next
+ * synchronization round.
+ */
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void
+local_put(const PBGL_DISTRIB_PMAP& pm,
+ typename PBGL_DISTRIB_PMAP::key_type const & key,
+ typename PBGL_DISTRIB_PMAP::value_type const & value)
+{
+ using boost::put;
+
+ typename property_traits<GlobalMap>::value_type p =
+ get(pm.data->global, key);
+
+ if (p.first == process_id(pm.data->process_group))
+ put(pm.data->storage, p.second, value);
+ else pm.cell(key, false) = value;
+}
+
+/** Cache the value associated with the given remote key. If the key
+ * is local, ignore the operation. */
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+inline void
+cache(const PBGL_DISTRIB_PMAP& pm,
+ typename PBGL_DISTRIB_PMAP::key_type const & key,
+ typename PBGL_DISTRIB_PMAP::value_type const & value)
+{
+ typename ProcessGroup::process_id_type id = get(pm.data->global, key).first;
+
+ if (id != process_id(pm.data->process_group)) pm.cell(key, false) = value;
+}
+
+/// Synchronize the property map.
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void
+synchronize(PBGL_DISTRIB_PMAP& pm)
+{
+ pm.do_synchronize();
+}
+
+/// Create a distributed property map.
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+inline distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
+make_distributed_property_map(const ProcessGroup& pg, GlobalMap global,
+ StorageMap storage)
+{
+ typedef distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
+ result_type;
+ return result_type(pg, global, storage);
+}
+
+/**
+ * \overload
+ */
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap,
+ typename Reduce>
+inline distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
+make_distributed_property_map(const ProcessGroup& pg, GlobalMap global,
+ StorageMap storage, Reduce reduce)
+{
+ typedef distributed_property_map<ProcessGroup, GlobalMap, StorageMap>
+ result_type;
+ return result_type(pg, global, storage, reduce);
+}
+
+} } // end namespace boost::parallel
+
+// Boost's functional/hash
+namespace boost {
+ template<typename D, typename V>
+ struct hash<boost::detail::edge_desc_impl<D, V> >
+ {
+ std::size_t operator()(const boost::detail::edge_desc_impl<D, V> & x) const
+ { return hash_value(x.get_property()); }
+ };
+}
+
+#include <boost/property_map/parallel/impl/distributed_property_map.cpp>
+
+#undef PBGL_DISTRIB_PMAP
+
+#endif // BOOST_PARALLEL_DISTRIBUTED_PROPERTY_MAP_HPP

Added: trunk/boost/property_map/parallel/global_index_map.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/property_map/parallel/global_index_map.hpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,74 @@
+// Copyright 2005 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+#ifndef BOOST_PARALLEL_GLOBAL_INDEX_MAP_HPP
+#define BOOST_PARALLEL_GLOBAL_INDEX_MAP_HPP
+
+#ifndef BOOST_GRAPH_USE_MPI
+#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
+#endif
+
+#include <boost/property_map/property_map.hpp>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+namespace boost { namespace parallel {
+
+template<typename IndexMap, typename GlobalMap>
+class global_index_map
+{
+public:
+ typedef typename property_traits<IndexMap>::key_type key_type;
+ typedef typename property_traits<IndexMap>::value_type value_type;
+ typedef value_type reference;
+ typedef readable_property_map_tag category;
+
+ template<typename ProcessGroup>
+ global_index_map(ProcessGroup pg, value_type num_local_indices,
+ IndexMap index_map, GlobalMap global)
+ : index_map(index_map), global(global)
+ {
+ typedef typename ProcessGroup::process_id_type process_id_type;
+ starting_index.reset(new std::vector<value_type>(num_processes(pg) + 1));
+ send(pg, 0, 0, num_local_indices);
+ synchronize(pg);
+
+ // Populate starting_index in all processes
+ if (process_id(pg) == 0) {
+ (*starting_index)[0] = 0;
+ for (process_id_type src = 0; src < num_processes(pg); ++src) {
+ value_type n;
+ receive(pg, src, 0, n);
+ (*starting_index)[src + 1] = (*starting_index)[src] + n;
+ }
+ for (process_id_type dest = 1; dest < num_processes(pg); ++dest)
+ send(pg, dest, 1, &starting_index->front(), num_processes(pg));
+ synchronize(pg);
+ } else {
+ synchronize(pg);
+ receive(pg, 0, 1, &starting_index->front(), num_processes(pg));
+ }
+ }
+
+ friend inline value_type
+ get(const global_index_map& gim, const key_type& x)
+ {
+ using boost::get;
+ return (*gim.starting_index)[get(gim.global, x).first]
+ + get(gim.index_map, x);
+ }
+
+private:
+ shared_ptr<std::vector<value_type> > starting_index;
+ IndexMap index_map;
+ GlobalMap global;
+};
+
+} } // end namespace boost::parallel
+
+#endif // BOOST_PARALLEL_GLOBAL_INDEX_MAP_HPP

Added: trunk/boost/property_map/parallel/impl/distributed_property_map.cpp
==============================================================================
--- (empty file)
+++ trunk/boost/property_map/parallel/impl/distributed_property_map.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,431 @@
+// Copyright (C) 2004-2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Nick Edmonds
+// Andrew Lumsdaine
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/graph/parallel/detail/untracked_pair.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/bind.hpp>
+#include <boost/graph/parallel/simple_trigger.hpp>
+
+#ifndef BOOST_GRAPH_USE_MPI
+#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
+#endif
+
+namespace boost { namespace parallel {
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+PBGL_DISTRIB_PMAP
+::distributed_property_map(const ProcessGroup& pg, const GlobalMap& global,
+ const StorageMap& pm, const Reduce& reduce)
+ : data(new data_t(pg, global, pm, reduce, Reduce::non_default_resolver))
+{
+ typedef handle_message<Reduce> Handler;
+
+ data->ghost_cells.reset(new ghost_cells_type());
+ data->reset = &data_t::template do_reset<Reduce>;
+ data->process_group.replace_handler(Handler(data, reduce));
+ data->process_group.template get_receiver<Handler>()
+ ->setup_triggers(data->process_group);
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+PBGL_DISTRIB_PMAP::~distributed_property_map() { }
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+void
+PBGL_DISTRIB_PMAP::set_reduce(const Reduce& reduce)
+{
+ typedef handle_message<Reduce> Handler;
+ data->process_group.replace_handler(Handler(data, reduce));
+ Handler* handler = data->process_group.template get_receiver<Handler>();
+ assert(handler);
+ handler->setup_triggers(data->process_group);
+ data->get_default_value = reduce;
+ data->has_default_resolver = Reduce::non_default_resolver;
+ int model = data->model;
+ data->reset = &data_t::template do_reset<Reduce>;
+ set_consistency_model(model);
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void PBGL_DISTRIB_PMAP::prune_ghost_cells() const
+{
+ if (data->max_ghost_cells == 0)
+ return;
+
+ while (data->ghost_cells->size() > data->max_ghost_cells) {
+ // Evict the last ghost cell
+
+ if (data->model & cm_flush) {
+ // We need to flush values when we evict them.
+ boost::parallel::detail::untracked_pair<key_type, value_type> const& victim
+ = data->ghost_cells->back();
+ send(data->process_group, get(data->global, victim.first).first,
+ property_map_put, victim);
+ }
+
+ // Actually remove the ghost cell
+ data->ghost_cells->pop_back();
+ }
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+typename PBGL_DISTRIB_PMAP::value_type&
+PBGL_DISTRIB_PMAP::cell(const key_type& key, bool request_if_missing) const
+{
+ // Index by key
+ ghost_cells_key_index_type const& key_index
+ = data->ghost_cells->template get<1>();
+
+ // Search for the ghost cell by key, and project back to the sequence
+ iterator ghost_cell
+ = data->ghost_cells->template project<0>(key_index.find(key));
+ if (ghost_cell == data->ghost_cells->end()) {
+ value_type value;
+ if (data->has_default_resolver)
+ // Since we have a default resolver, use it to create a default
+ // value for this ghost cell.
+ value = data->get_default_value(key);
+ else if (request_if_missing)
+ // Request the actual value of this key from its owner
+ send_oob_with_reply(data->process_group, get(data->global, key).first,
+ property_map_get, key, value);
+ else
+ value = value_type();
+
+ // Create a ghost cell containing the new value
+ ghost_cell
+ = data->ghost_cells->push_front(std::make_pair(key, value)).first;
+
+ // If we need to, prune the ghost cells
+ if (data->max_ghost_cells > 0)
+ prune_ghost_cells();
+ } else if (data->max_ghost_cells > 0)
+ // Put this cell at the beginning of the MRU list
+ data->ghost_cells->relocate(data->ghost_cells->begin(), ghost_cell);
+
+ return const_cast<value_type&>(ghost_cell->second);
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+void
+PBGL_DISTRIB_PMAP
+::handle_message<Reduce>::operator()(process_id_type source, int tag)
+{
+ assert(false);
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+void
+PBGL_DISTRIB_PMAP::handle_message<Reduce>::
+handle_put(int /*source*/, int /*tag*/,
+ const boost::parallel::detail::untracked_pair<key_type, value_type>& req, trigger_receive_context)
+{
+ using boost::get;
+
+ shared_ptr<data_t> data(data_ptr);
+
+ owner_local_pair p = get(data->global, req.first);
+ assert(p.first == process_id(data->process_group));
+
+ detail::maybe_put(data->storage, p.second,
+ reduce(req.first,
+ get(data->storage, p.second),
+ req.second));
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+typename PBGL_DISTRIB_PMAP::value_type
+PBGL_DISTRIB_PMAP::handle_message<Reduce>::
+handle_get(int source, int /*tag*/, const key_type& key,
+ trigger_receive_context)
+{
+ using boost::get;
+
+ shared_ptr<data_t> data(data_ptr);
+ assert(data);
+
+ owner_local_pair p = get(data->global, key);
+ return get(data->storage, p.second);
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+void
+PBGL_DISTRIB_PMAP::handle_message<Reduce>::
+handle_multiget(int source, int tag, const std::vector<key_type>& keys,
+ trigger_receive_context)
+{
+ shared_ptr<data_t> data(data_ptr);
+ assert(data);
+
+ typedef boost::parallel::detail::untracked_pair<key_type, value_type> key_value;
+ std::vector<key_value> results;
+ std::size_t n = keys.size();
+ results.reserve(n);
+
+ using boost::get;
+
+ for (std::size_t i = 0; i < n; ++i) {
+ local_key_type local_key = get(data->global, keys[i]).second;
+ results.push_back(key_value(keys[i], get(data->storage, local_key)));
+ }
+ send(data->process_group, source, property_map_multiget_reply, results);
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+void
+PBGL_DISTRIB_PMAP::handle_message<Reduce>::
+handle_multiget_reply
+ (int source, int tag,
+ const std::vector<boost::parallel::detail::untracked_pair<key_type, value_type> >& msg,
+ trigger_receive_context)
+{
+ shared_ptr<data_t> data(data_ptr);
+ assert(data);
+
+ // Index by key
+ ghost_cells_key_index_type const& key_index
+ = data->ghost_cells->template get<1>();
+
+ std::size_t n = msg.size();
+ for (std::size_t i = 0; i < n; ++i) {
+ // Search for the ghost cell by key, and project back to the sequence
+ iterator position
+ = data->ghost_cells->template project<0>(key_index.find(msg[i].first));
+
+ if (position != data->ghost_cells->end())
+ const_cast<value_type&>(position->second) = msg[i].second;
+ }
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+void
+PBGL_DISTRIB_PMAP::handle_message<Reduce>::
+handle_multiput
+ (int source, int tag,
+ const std::vector<unsafe_pair<local_key_type, value_type> >& values,
+ trigger_receive_context)
+{
+ using boost::get;
+
+ shared_ptr<data_t> data(data_ptr);
+ assert(data);
+
+ std::size_t n = values.size();
+ for (std::size_t i = 0; i < n; ++i) {
+ local_key_type local_key = values[i].first;
+ value_type local_value = get(data->storage, local_key);
+ detail::maybe_put(data->storage, values[i].first,
+ reduce(values[i].first,
+ local_value,
+ values[i].second));
+ }
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Reduce>
+void
+PBGL_DISTRIB_PMAP::handle_message<Reduce>::
+setup_triggers(process_group_type& pg)
+{
+ using boost::graph::parallel::simple_trigger;
+
+ simple_trigger(pg, property_map_put, this, &handle_message::handle_put);
+ simple_trigger(pg, property_map_get, this, &handle_message::handle_get);
+ simple_trigger(pg, property_map_multiget, this,
+ &handle_message::handle_multiget);
+ simple_trigger(pg, property_map_multiget_reply, this,
+ &handle_message::handle_multiget_reply);
+ simple_trigger(pg, property_map_multiput, this,
+ &handle_message::handle_multiput);
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void
+PBGL_DISTRIB_PMAP
+::on_synchronize::operator()()
+{
+ int stage=0; // we only get called at the start now
+ shared_ptr<data_t> data(data_ptr);
+ assert(data);
+
+ // Determine in which stage backward consistency messages should be sent.
+ int backward_stage = -1;
+ if (data->model & cm_backward) {
+ if (data->model & cm_flush) backward_stage = 1;
+ else backward_stage = 0;
+ }
+
+ // Flush results in first stage
+ if (stage == 0 && data->model & cm_flush)
+ data->flush();
+
+ // Backward consistency
+ if (stage == backward_stage && !(data->model & (cm_clear | cm_reset)))
+ data->refresh_ghost_cells();
+
+ // Optionally clear results
+ if (data->model & cm_clear)
+ data->clear();
+
+ // Optionally reset results
+ if (data->model & cm_reset) {
+ if (data->reset) ((*data).*data->reset)();
+ }
+}
+
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void
+PBGL_DISTRIB_PMAP::set_consistency_model(int model)
+{
+ data->model = model;
+
+ int stages = 1;
+ bool need_on_synchronize = (model != cm_forward);
+
+ // Backward consistency is a two-stage process.
+ if (model & cm_backward) {
+ if (model & cm_flush) stages = 3;
+ else stages = 2;
+
+ // For backward consistency to work, we absolutely cannot throw
+ // away any ghost cells.
+ data->max_ghost_cells = 0;
+ }
+
+ // attach the on_synchronize handler.
+ if (need_on_synchronize)
+ data->process_group.replace_on_synchronize_handler(on_synchronize(data));
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void
+PBGL_DISTRIB_PMAP::set_max_ghost_cells(std::size_t max_ghost_cells)
+{
+ if ((data->model & cm_backward) && max_ghost_cells > 0)
+ boost::throw_exception(std::runtime_error("distributed_property_map::set_max_ghost_cells: "
+ "cannot limit ghost-cell usage with a backward "
+ "consistency model"));
+
+ if (max_ghost_cells == 1)
+ // It is not safe to have only 1 ghost cell; the cell() method
+ // will fail.
+ max_ghost_cells = 2;
+
+ data->max_ghost_cells = max_ghost_cells;
+ prune_ghost_cells();
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void PBGL_DISTRIB_PMAP::clear()
+{
+ data->clear();
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void PBGL_DISTRIB_PMAP::data_t::clear()
+{
+ ghost_cells->clear();
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void PBGL_DISTRIB_PMAP::reset()
+{
+ if (data->reset) ((*data).*data->reset)();
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void PBGL_DISTRIB_PMAP::flush()
+{
+ data->flush();
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void PBGL_DISTRIB_PMAP::data_t::refresh_ghost_cells()
+{
+ using boost::get;
+
+ std::vector<std::vector<key_type> > keys;
+ keys.resize(num_processes(process_group));
+
+ // Collect the set of keys for which we will request values
+ for (iterator i = ghost_cells->begin(); i != ghost_cells->end(); ++i)
+ keys[get(global, i->first).first].push_back(i->first);
+
+ // Send multiget requests to each of the other processors
+ typedef typename ProcessGroup::process_size_type process_size_type;
+ process_size_type n = num_processes(process_group);
+ process_id_type id = process_id(process_group);
+ for (process_size_type p = (id + 1) % n ; p != id ; p = (p + 1) % n) {
+ if (!keys[p].empty())
+ send(process_group, p, property_map_multiget, keys[p]);
+ }
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void PBGL_DISTRIB_PMAP::data_t::flush()
+{
+ using boost::get;
+
+ int n = num_processes(process_group);
+ std::vector<std::vector<unsafe_pair<local_key_type, value_type> > > values;
+ values.resize(n);
+
+ // Collect all of the flushed values
+ for (iterator i = ghost_cells->begin(); i != ghost_cells->end(); ++i) {
+ std::pair<int, local_key_type> g = get(global, i->first);
+ values[g.first].push_back(std::make_pair(g.second, i->second));
+ }
+
+ // Transmit flushed values
+ for (int p = 0; p < n; ++p) {
+ if (!values[p].empty())
+ send(process_group, p, property_map_multiput, values[p]);
+ }
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+void PBGL_DISTRIB_PMAP::do_synchronize()
+{
+ if (data->model & cm_backward) {
+ synchronize(data->process_group);
+ return;
+ }
+
+ // Request refreshes of the values of our ghost cells
+ data->refresh_ghost_cells();
+
+ // Allows all of the multigets to get to their destinations
+ synchronize(data->process_group);
+
+ // Allows all of the multiget responses to get to their destinations
+ synchronize(data->process_group);
+}
+
+template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+template<typename Resolver>
+void PBGL_DISTRIB_PMAP::data_t::do_reset()
+{
+ Resolver* resolver = get_default_value.template target<Resolver>();
+ assert(resolver);
+
+ for (iterator i = ghost_cells->begin(); i != ghost_cells->end(); ++i)
+ const_cast<value_type&>(i->second) = (*resolver)(i->first);
+}
+
+} } // end namespace boost::parallel

Added: trunk/boost/property_map/parallel/local_property_map.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/property_map/parallel/local_property_map.hpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,91 @@
+// Copyright (C) 2004-2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+// The placement of this #include probably looks very odd relative to
+// the #ifndef/#define pair below. However, this placement is
+// extremely important to allow the various property map headers to be
+// included in any order.
+#include <boost/property_map/property_map.hpp>
+
+#ifndef BOOST_PARALLEL_LOCAL_PROPERTY_MAP_HPP
+#define BOOST_PARALLEL_LOCAL_PROPERTY_MAP_HPP
+
+#ifndef BOOST_GRAPH_USE_MPI
+#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
+#endif
+
+#include <cassert>
+
+namespace boost {
+ /** Property map that accesses an underlying, local property map
+ * using a subset of the global keys.
+ */
+ template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+ class local_property_map
+ {
+ typedef typename property_traits<GlobalMap>::value_type owner_local_pair;
+
+ public:
+ typedef ProcessGroup process_group_type;
+ typedef typename property_traits<StorageMap>::value_type value_type;
+ typedef typename property_traits<GlobalMap>::key_type key_type;
+ typedef typename property_traits<StorageMap>::reference reference;
+ typedef typename property_traits<StorageMap>::category category;
+
+ local_property_map() { }
+
+ local_property_map(const ProcessGroup& process_group,
+ const GlobalMap& global, const StorageMap& storage)
+ : process_group_(process_group), global_(global), storage(storage) { }
+
+ reference operator[](const key_type& key)
+ {
+ owner_local_pair p = get(global_, key);
+ assert(p.first == process_id(process_group_));
+ return storage[p.second];
+ }
+
+ GlobalMap& global() const { return global_; }
+ StorageMap& base() const { return storage; }
+
+ ProcessGroup& process_group() { return process_group_; }
+ const ProcessGroup& process_group() const { return process_group_; }
+
+ private:
+ ProcessGroup process_group_;
+ mutable GlobalMap global_;
+ mutable StorageMap storage;
+ };
+
+ template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+ inline
+ typename local_property_map<ProcessGroup, GlobalMap, StorageMap>::reference
+ get(const local_property_map<ProcessGroup, GlobalMap, StorageMap>& pm,
+ typename local_property_map<ProcessGroup, GlobalMap, StorageMap>::key_type
+ const & key)
+
+ {
+ typename property_traits<GlobalMap>::value_type p = get(pm.global(), key);
+ return get(pm.base(), p.second);
+ }
+
+ template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
+ inline void
+ put(const local_property_map<ProcessGroup, GlobalMap, StorageMap>& pm,
+ typename local_property_map<ProcessGroup, GlobalMap, StorageMap>
+ ::key_type const & key,
+ typename local_property_map<ProcessGroup, GlobalMap, StorageMap>
+ ::value_type const& v)
+ {
+ typename property_traits<GlobalMap>::value_type p = get(pm.global(), key);
+ assert(p.first == process_id(pm.process_group()));
+ put(pm.base(), p.second, v);
+ }
+} // end namespace boost
+#endif // BOOST_PARALLEL_LOCAL_PROPERTY_MAP_HPP

Modified: trunk/boost/property_map/property_map.hpp
==============================================================================
--- trunk/boost/property_map/property_map.hpp (original)
+++ trunk/boost/property_map/property_map.hpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -584,6 +584,205 @@
 
 } // namespace boost
 
+#ifdef BOOST_GRAPH_USE_MPI
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/property_map/parallel/local_property_map.hpp>
+
+namespace boost {
+/** Distributed iterator property map.
+ *
+ * This specialization of @ref iterator_property_map builds a
+ * distributed iterator property map given the local index maps
+ * generated by distributed graph types that automatically have index
+ * properties.
+ *
+ * This specialization is useful when creating external distributed
+ * property maps via the same syntax used to create external
+ * sequential property maps.
+ */
+template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalMap, typename StorageMap,
+ typename ValueType, typename Reference>
+class iterator_property_map
+ <RandomAccessIterator,
+ local_property_map<ProcessGroup, GlobalMap, StorageMap>,
+ ValueType, Reference>
+ : public parallel::distributed_property_map
+ <ProcessGroup,
+ GlobalMap,
+ iterator_property_map<RandomAccessIterator, StorageMap,
+ ValueType, Reference> >
+{
+ typedef iterator_property_map<RandomAccessIterator, StorageMap,
+ ValueType, Reference> local_iterator_map;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ local_iterator_map> inherited;
+
+ typedef local_property_map<ProcessGroup, GlobalMap, StorageMap>
+ index_map_type;
+ typedef iterator_property_map self_type;
+
+public:
+ iterator_property_map() { }
+
+ iterator_property_map(RandomAccessIterator cc, const index_map_type& id)
+ : inherited(id.process_group(), id.global(),
+ local_iterator_map(cc, id.base())) { }
+};
+
+/** Distributed iterator property map.
+ *
+ * This specialization of @ref iterator_property_map builds a
+ * distributed iterator property map given a distributed index
+ * map. Only the local portion of the distributed index property map
+ * is utilized.
+ *
+ * This specialization is useful when creating external distributed
+ * property maps via the same syntax used to create external
+ * sequential property maps.
+ */
+template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalMap, typename StorageMap,
+ typename ValueType, typename Reference>
+class iterator_property_map<
+ RandomAccessIterator,
+ parallel::distributed_property_map<ProcessGroup,GlobalMap,StorageMap>,
+ ValueType, Reference
+ >
+ : public parallel::distributed_property_map
+ <ProcessGroup,
+ GlobalMap,
+ iterator_property_map<RandomAccessIterator, StorageMap,
+ ValueType, Reference> >
+{
+ typedef iterator_property_map<RandomAccessIterator, StorageMap,
+ ValueType, Reference> local_iterator_map;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ local_iterator_map> inherited;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ StorageMap>
+ index_map_type;
+
+public:
+ iterator_property_map() { }
+
+ iterator_property_map(RandomAccessIterator cc, const index_map_type& id)
+ : inherited(id.process_group(), id.global(),
+ local_iterator_map(cc, id.base())) { }
+};
+
+namespace parallel {
+// Generate an iterator property map with a specific kind of ghost
+// cells
+template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalMap, typename StorageMap>
+distributed_property_map<ProcessGroup,
+ GlobalMap,
+ iterator_property_map<RandomAccessIterator,
+ StorageMap> >
+make_iterator_property_map(RandomAccessIterator cc,
+ local_property_map<ProcessGroup, GlobalMap,
+ StorageMap> index_map)
+{
+ typedef distributed_property_map<
+ ProcessGroup, GlobalMap,
+ iterator_property_map<RandomAccessIterator, StorageMap> >
+ result_type;
+ return result_type(index_map.process_group(), index_map.global(),
+ make_iterator_property_map(cc, index_map.base()));
+}
+
+} // end namespace parallel
+
+/** Distributed safe iterator property map.
+ *
+ * This specialization of @ref safe_iterator_property_map builds a
+ * distributed iterator property map given the local index maps
+ * generated by distributed graph types that automatically have index
+ * properties.
+ *
+ * This specialization is useful when creating external distributed
+ * property maps via the same syntax used to create external
+ * sequential property maps.
+ */
+template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalMap, typename StorageMap, typename ValueType,
+ typename Reference>
+class safe_iterator_property_map
+ <RandomAccessIterator,
+ local_property_map<ProcessGroup, GlobalMap, StorageMap>,
+ ValueType, Reference>
+ : public parallel::distributed_property_map
+ <ProcessGroup,
+ GlobalMap,
+ safe_iterator_property_map<RandomAccessIterator, StorageMap,
+ ValueType, Reference> >
+{
+ typedef safe_iterator_property_map<RandomAccessIterator, StorageMap,
+ ValueType, Reference> local_iterator_map;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ local_iterator_map> inherited;
+
+ typedef local_property_map<ProcessGroup, GlobalMap, StorageMap> index_map_type;
+
+public:
+ safe_iterator_property_map() { }
+
+ safe_iterator_property_map(RandomAccessIterator cc, std::size_t n,
+ const index_map_type& id)
+ : inherited(id.process_group(), id.global(),
+ local_iterator_map(cc, n, id.base())) { }
+};
+
+/** Distributed safe iterator property map.
+ *
+ * This specialization of @ref safe_iterator_property_map builds a
+ * distributed iterator property map given a distributed index
+ * map. Only the local portion of the distributed index property map
+ * is utilized.
+ *
+ * This specialization is useful when creating external distributed
+ * property maps via the same syntax used to create external
+ * sequential property maps.
+ */
+template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalMap, typename StorageMap,
+ typename ValueType, typename Reference>
+class safe_iterator_property_map<
+ RandomAccessIterator,
+ parallel::distributed_property_map<ProcessGroup,GlobalMap,StorageMap>,
+ ValueType, Reference>
+ : public parallel::distributed_property_map
+ <ProcessGroup,
+ GlobalMap,
+ safe_iterator_property_map<RandomAccessIterator, StorageMap,
+ ValueType, Reference> >
+{
+ typedef safe_iterator_property_map<RandomAccessIterator, StorageMap,
+ ValueType, Reference> local_iterator_map;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ local_iterator_map> inherited;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ StorageMap>
+ index_map_type;
+
+public:
+ safe_iterator_property_map() { }
+
+ safe_iterator_property_map(RandomAccessIterator cc, std::size_t n,
+ const index_map_type& id)
+ : inherited(id.process_group(), id.global(),
+ local_iterator_map(cc, n, id.base())) { }
+};
+
+}
+#endif // BOOST_GRAPH_USE_MPI
 
 #include <boost/property_map/vector_property_map.hpp>
 

Modified: trunk/boost/property_map/vector_property_map.hpp
==============================================================================
--- trunk/boost/property_map/vector_property_map.hpp (original)
+++ trunk/boost/property_map/vector_property_map.hpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -92,4 +92,94 @@
     }
 }
 
+#ifdef BOOST_GRAPH_USE_MPI
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/property_map/parallel/local_property_map.hpp>
+
+namespace boost {
+
+/** Distributed vector property map.
+ *
+ * This specialization of @ref vector_property_map builds a
+ * distributed vector property map given the local index maps
+ * generated by distributed graph types that automatically have index
+ * properties.
+ *
+ * This specialization is useful when creating external distributed
+ * property maps via the same syntax used to create external
+ * sequential property maps.
+ */
+template<typename T, typename ProcessGroup, typename GlobalMap,
+ typename StorageMap>
+class vector_property_map<T,
+ local_property_map<ProcessGroup, GlobalMap,
+ StorageMap> >
+ : public parallel::distributed_property_map<
+ ProcessGroup, GlobalMap, vector_property_map<T, StorageMap> >
+{
+ typedef vector_property_map<T, StorageMap> local_iterator_map;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ local_iterator_map> inherited;
+
+ typedef local_property_map<ProcessGroup, GlobalMap, StorageMap> index_map_type;
+
+public:
+ vector_property_map(const index_map_type& index = index_map_type())
+ : inherited(index.process_group(), index.global(),
+ local_iterator_map(index.base())) { }
+
+ vector_property_map(unsigned inital_size,
+ const index_map_type& index = index_map_type())
+ : inherited(index.process_group(), index.global(),
+ local_iterator_map(inital_size, index.base())) { }
+};
+
+/** Distributed vector property map.
+ *
+ * This specialization of @ref vector_property_map builds a
+ * distributed vector property map given the local index maps
+ * generated by distributed graph types that automatically have index
+ * properties.
+ *
+ * This specialization is useful when creating external distributed
+ * property maps via the same syntax used to create external
+ * sequential property maps.
+ */
+template<typename T, typename ProcessGroup, typename GlobalMap,
+ typename StorageMap>
+class vector_property_map<
+ T,
+ parallel::distributed_property_map<
+ ProcessGroup,
+ GlobalMap,
+ StorageMap
+ >
+ >
+ : public parallel::distributed_property_map<
+ ProcessGroup, GlobalMap, vector_property_map<T, StorageMap> >
+{
+ typedef vector_property_map<T, StorageMap> local_iterator_map;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ local_iterator_map> inherited;
+
+ typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
+ StorageMap>
+ index_map_type;
+
+public:
+ vector_property_map(const index_map_type& index = index_map_type())
+ : inherited(index.process_group(), index.global(),
+ local_iterator_map(index.base())) { }
+
+ vector_property_map(unsigned inital_size,
+ const index_map_type& index = index_map_type())
+ : inherited(index.process_group(), index.global(),
+ local_iterator_map(inital_size, index.base())) { }
+};
+
+}
+#endif // BOOST_GRAPH_USE_MPI
+
 #endif

Modified: trunk/libs/graph/CMakeLists.txt
==============================================================================
--- trunk/libs/graph/CMakeLists.txt (original)
+++ trunk/libs/graph/CMakeLists.txt 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -1,16 +1,12 @@
 #----------------------------------------------------------------------------
 # This file was automatically generated from the original CMakeLists.txt file
-# Add a variable to hold the headers for the library
-set (lib_headers
- graph
-)
 
 # Add a library target to the build system
 boost_library_project(
   graph
   SRCDIRS src
   TESTDIRS test
- HEADERS ${lib_headers}
+ HEADERS graph
   # DOCDIRS
   DESCRIPTION "The BGL graph interface and graph components are generic, in the same sense as the the Standard Template Library (STL)."
   MODULARIZED
@@ -20,5 +16,3 @@
            "Douglas Gregor <doug.gregor -at- gmail.com>"
   # MAINTAINERS
 )
-
-

Modified: trunk/libs/graph/build/Jamfile.v2
==============================================================================
--- trunk/libs/graph/build/Jamfile.v2 (original)
+++ trunk/libs/graph/build/Jamfile.v2 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -45,33 +45,10 @@
 }
 explicit graphml ;
 
-if [ mpi.configured ]
-{
- alias pbgl
- : mpi_process_group.cpp tag_allocator.cpp
- : # requirements
- <library>../../mpi/build//boost_mpi
- <library>/mpi//mpi [ mpi.extra-requirements ]
- : # default built
- : # usage requirements
- <library>../../mpi/build//boost_mpi
- <library>/mpi//mpi [ mpi.extra-requirements ]
- ;
-}
-else
-{
- message pbgl
- : "warning: Graph library does not contain MPI-based parallel components."
- : "note: to enable them, add \"using mpi ;\" to your user_config.jam"
- ;
-}
-explicit graphml ;
-
 lib boost_graph
     :
     read_graphviz_spirit.cpp
     graphml
- pbgl
     :
     <define>BOOST_GRAPH_NO_LIB=1
     <link>shared:<define>BOOST_GRAPH_DYN_LINK=1

Modified: trunk/libs/graph/module.cmake
==============================================================================
--- trunk/libs/graph/module.cmake (original)
+++ trunk/libs/graph/module.cmake 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -1,3 +1,4 @@
 boost_module(graph DEPENDS property_map tuple multi_index any random)
+boost_module(graph_mpi DEPENDS mpi graph)
 
 # any is there because of the dependency on boost/property_map/dynamic_property_map.hpp

Modified: trunk/libs/graph/src/CMakeLists.txt
==============================================================================
--- trunk/libs/graph/src/CMakeLists.txt (original)
+++ trunk/libs/graph/src/CMakeLists.txt 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -24,3 +24,4 @@
   LINK_LIBS ${BOOST_GRAPH_OPTIONAL_LIBRARIES}
   SHARED_COMPILE_FLAGS "-DBOOST_GRAPH_DYN_LINK=1"
   )
+

Deleted: trunk/libs/graph/src/mpi_process_group.cpp
==============================================================================
--- trunk/libs/graph/src/mpi_process_group.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
+++ (empty file)
@@ -1,1108 +0,0 @@
-// Copyright (C) 2004-2006 The Trustees of Indiana University.
-// Copyright (C) 2007 Douglas Gregor <doug.gregor_at_[hidden]>
-// Copyright (C) 2007 Matthias Troyer <troyer_at_[hidden]>
-
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// Authors: Douglas Gregor
-// Andrew Lumsdaine
-// Matthias Troyer
-#include <boost/graph/use_mpi.hpp>
-#include <boost/graph/distributed/mpi_process_group.hpp>
-#include <boost/mpi/environment.hpp>
-#include <boost/lexical_cast.hpp>
-#include <memory>
-#include <algorithm>
-
-//#define DEBUG 1
-
-
-//#define MAX_BATCHES 1500
-#define PREALLOCATE_BATCHES 250
-// 500 is a better setting for PREALLOCATE_BATCHES if you're not using process
-// subgroups and are building 64-bit binaries. 250 allows all the CTest
-// tests to pass in both 32 and 64-bit modes. If you create multiple process
-// groups with PREALLOCATE_BATCHES at a reasonable level in 32-bit mode you
-// _will_ run out of memory and get "malloc failed" errors
-
-//#define NO_ISEND_BATCHES
-//#define NO_IMMEDIATE_PROCESSING
-//#define NO_SPLIT_BATCHES
-#define IRECV_BATCH
-
-// we cannot keep track of how many we received if we do not process them
-#ifdef NO_IMMEDIATE_PROCESSING
-#undef IRECV_BATCH
-#endif
-
-#ifdef DEBUG
-# include <iostream>
-#endif // DEBUG
-
-namespace boost { namespace graph { namespace distributed {
-
-struct mpi_process_group::deallocate_block
-{
- explicit deallocate_block(blocks_type* blocks) : blocks(blocks) { }
-
- void operator()(int* block_num)
- {
- block_type* block = (*blocks)[*block_num];
-
- // Mark this block as inactive
- (*blocks)[*block_num] = 0;
-
-#ifdef DEBUG
- fprintf(stderr, "Processor %i deallocated block #%i\n",
- boost::mpi::communicator().rank(), *block_num);
-#endif
-
- // Delete the block and its block number
- delete block_num;
- delete block;
- }
-
-private:
- blocks_type* blocks;
-};
-
-mpi_process_group::impl::incoming_messages::incoming_messages()
-{
- next_header.push_back(headers.begin());
-}
-
-mpi_process_group::impl::impl(std::size_t num_headers, std::size_t buffer_sz,
- communicator_type parent_comm)
- : comm(parent_comm, boost::mpi::comm_duplicate),
- oob_reply_comm(parent_comm, boost::mpi::comm_duplicate),
- allocated_tags(boost::mpi::environment::max_tag())
-{
- max_sent=0;
- max_received=0;
- int n = comm.size();
- outgoing.resize(n);
- incoming.resize(n);
-
- // no synchronization stage means -1
- // to keep the convention
- synchronizing_stage.resize(n,-1);
- number_sent_batches.resize(n);
- number_received_batches.resize(n);
- trigger_context = trc_none;
- processing_batches = 0;
-
- // Allocator a placeholder block "0"
- blocks.push_back(new block_type);
-
- synchronizing = false;
-
- set_batch_size(num_headers,buffer_sz);
-
- for (int i = 0; i < n; ++i) {
- incoming[i].next_header.front() = incoming[i].headers.end();
- outgoing[i].buffer.reserve(batch_message_size);
- }
-
-#ifdef PREALLOCATE_BATCHES
- batch_pool.resize(PREALLOCATE_BATCHES);
- for (std::size_t i = 0 ; i < batch_pool.size(); ++i) {
- batch_pool[i].buffer.reserve(batch_message_size);
- batch_pool[i].request=MPI_REQUEST_NULL;
- free_batches.push(i);
- }
-#endif
-}
-
-void mpi_process_group::impl::set_batch_size(std::size_t header_num, std::size_t buffer_sz)
-{
- batch_header_number = header_num;
- batch_buffer_size = buffer_sz;
-
- // determine batch message size by serializing the largest possible batch
- outgoing_messages msg;
- msg.headers.resize(batch_header_number);
- msg.buffer.resize(batch_buffer_size);
- boost::mpi::packed_oarchive oa(comm);
- oa << const_cast<const outgoing_messages&>(msg);
- batch_message_size = oa.size();
-}
-
-
-mpi_process_group::impl::~impl()
-{
- // Delete the placeholder "0" block
- delete blocks.front();
- if (!boost::mpi::environment::finalized())
- for (std::vector<MPI_Request>::iterator it=requests.begin();
- it != requests.end();++it)
- MPI_Cancel(&(*it));
-}
-
-namespace detail {
-// global batch handlers
-void handle_batch (mpi_process_group const& self, int source, int,
- mpi_process_group::outgoing_messages& batch,bool out_of_band)
-{
-#ifdef DEBUG
- std::cerr << "Processing batch trigger\n";
- std::cerr << "BATCH: " << process_id(self) << " <- " << source << " ("
- << batch.headers.size() << " headers, "
- << batch.buffer.size() << " bytes)"
- << std::endl;
-#endif
- // If we are not synchronizing, then this must be an early receive
- trigger_receive_context old_context = self.impl_->trigger_context;
- if (self.impl_->trigger_context != trc_in_synchronization)
- self.impl_->trigger_context = trc_early_receive;
-
- // Receive the batched messages
- self.receive_batch(source,batch);
-
- // Restore the previous context
- self.impl_->trigger_context = old_context;
-}
-
-// synchronization handler
-void handle_sync (mpi_process_group const& self, int source, int tag, int val,
- bool)
-{
- // increment the stage for the source
- std::size_t stage = static_cast<std::size_t>(
- ++self.impl_->synchronizing_stage[source]);
-
- assert(source != process_id(self));
-
-#ifdef DEBUG
- std::ostringstream out;
- out << process_id(self) << ": handle_sync from " << source
- << " (stage = " << self.impl_->synchronizing_stage[source] << ")\n";
- std::cerr << out.str();
-#endif
-
- // record how many still have messages to be sent
- if (self.impl_->synchronizing_unfinished.size()<=stage) {
- assert(self.impl_->synchronizing_unfinished.size() == stage);
- self.impl_->synchronizing_unfinished.push_back(val >= 0 ? 1 : 0);
- }
- else
- self.impl_->synchronizing_unfinished[stage]+=(val >= 0 ? 1 : 0);
-
- // record how many are in that stage
- if (self.impl_->processors_synchronizing_stage.size()<=stage) {
- assert(self.impl_->processors_synchronizing_stage.size() == stage);
- self.impl_->processors_synchronizing_stage.push_back(1);
- }
- else
- ++self.impl_->processors_synchronizing_stage[stage];
-
- // subtract how many batches we were supposed to receive
- if (val>0)
- self.impl_->number_received_batches[source] -= val;
-}
-
-
-}
-
-mpi_process_group::mpi_process_group(communicator_type parent_comm)
-{
- // 64K messages and 1MB buffer turned out to be a reasonable choice
- impl_.reset(new impl(64*1024,1024*1024,parent_comm));
-#ifndef IRECV_BATCH
- global_trigger<outgoing_messages>(msg_batch,&detail::handle_batch);
-#else // use irecv version by providing a maximum buffer size
- global_trigger<outgoing_messages>(msg_batch,&detail::handle_batch,
- impl_->batch_message_size);
-#endif
- global_trigger<outgoing_messages>(msg_large_batch,&detail::handle_batch);
- global_trigger<int>(msg_synchronizing,&detail::handle_sync);
- rank = impl_->comm.rank();
- size = impl_->comm.size();
-
-#ifdef SEND_OOB_BSEND
- // let us try with a default bufferr size of 16 MB
- if (!message_buffer_size())
- set_message_buffer_size(16*1024*1024);
-#endif
-}
-
-mpi_process_group::mpi_process_group(std::size_t h, std::size_t sz,
- communicator_type parent_comm)
-{
- impl_.reset(new impl(h,sz,parent_comm));
-#ifndef IRECV_BATCH
- global_trigger<outgoing_messages>(msg_batch,&detail::handle_batch);
-#else // use irecv version by providing a maximum buffer size
- global_trigger<outgoing_messages>(msg_batch,&detail::handle_batch,
- impl_->batch_message_size);
-#endif
- global_trigger<outgoing_messages>(msg_large_batch,&detail::handle_batch);
- global_trigger<int>(msg_synchronizing,&detail::handle_sync);
- rank = impl_->comm.rank();
- size = impl_->comm.size();
-#ifdef SEND_OOB_BSEND
- // let us try with a default bufferr size of 16 MB
- if (!message_buffer_size())
- set_message_buffer_size(16*1024*1024);
-#endif
-}
-
-mpi_process_group::mpi_process_group(const mpi_process_group& other,
- const receiver_type& handler, bool)
- : impl_(other.impl_)
-{
- rank = impl_->comm.rank();
- size = impl_->comm.size();
- replace_handler(handler);
-}
-
-mpi_process_group::mpi_process_group(const mpi_process_group& other,
- attach_distributed_object, bool)
- : impl_(other.impl_)
-{
- rank = impl_->comm.rank();
- size = impl_->comm.size();
- allocate_block();
-
- for (std::size_t i = 0; i < impl_->incoming.size(); ++i) {
- if (my_block_number() >= (int)impl_->incoming[i].next_header.size()) {
- impl_->incoming[i].next_header
- .push_back(impl_->incoming[i].headers.begin());
- } else {
- impl_->incoming[i].next_header[my_block_number()] =
- impl_->incoming[i].headers.begin();
- }
-
-#ifdef DEBUG
- if (process_id(*this) == 0) {
- std::cerr << "Allocated tag block " << my_block_number() << std::endl;
- }
-#endif
- }
-}
-
-mpi_process_group::~mpi_process_group() {
- /*
- std::string msg = boost::lexical_cast<std::string>(process_id(*this)) + " " +
- boost::lexical_cast<std::string>(impl_->max_received) + " " +
- boost::lexical_cast<std::string>(impl_->max_sent) + "\n";
- std::cerr << msg << "\n";
- */
-}
-
-
-mpi_process_group::communicator_type communicator(const mpi_process_group& pg)
-{ return pg.impl_->comm; }
-
-void
-mpi_process_group::replace_handler(const receiver_type& handler,
- bool out_of_band_receive)
-{
- make_distributed_object();
-
- // Attach the receive handler
- impl_->blocks[my_block_number()]->on_receive = handler;
-}
-
-void
-mpi_process_group::make_distributed_object()
-{
- if (my_block_number() == 0) {
- allocate_block();
-
- for (std::size_t i = 0; i < impl_->incoming.size(); ++i) {
- if (my_block_number() >= (int)impl_->incoming[i].next_header.size()) {
- impl_->incoming[i].next_header
- .push_back(impl_->incoming[i].headers.begin());
- } else {
- impl_->incoming[i].next_header[my_block_number()] =
- impl_->incoming[i].headers.begin();
- }
-
-#ifdef DEBUG
- if (process_id(*this) == 0) {
- std::cerr << "Allocated tag block " << my_block_number() << std::endl;
- }
-#endif
- }
- } else {
- // Clear out the existing triggers
- std::vector<shared_ptr<trigger_base> >()
- .swap(impl_->blocks[my_block_number()]->triggers);
- }
-
- // Clear out the receive handler
- impl_->blocks[my_block_number()]->on_receive = 0;
-}
-
-void
-mpi_process_group::
-replace_on_synchronize_handler(const on_synchronize_event_type& handler)
-{
- if (my_block_number() > 0)
- impl_->blocks[my_block_number()]->on_synchronize = handler;
-}
-
-int mpi_process_group::allocate_block(bool out_of_band_receive)
-{
- assert(!block_num);
- block_iterator i = impl_->blocks.begin();
- while (i != impl_->blocks.end() && *i) ++i;
-
- if (i == impl_->blocks.end()) {
- impl_->blocks.push_back(new block_type());
- i = impl_->blocks.end() - 1;
- } else {
- *i = new block_type();
- }
-
- block_num.reset(new int(i - impl_->blocks.begin()),
- deallocate_block(&impl_->blocks));
-
-#ifdef DEBUG
- fprintf(stderr,
- "Processor %i allocated block #%i\n", process_id(*this), *block_num);
-#endif
-
- return *block_num;
-}
-
-bool mpi_process_group::maybe_emit_receive(int process, int encoded_tag) const
-{
- std::pair<int, int> decoded = decode_tag(encoded_tag);
-
- assert (decoded.first < static_cast<int>(impl_->blocks.size()));
-
- block_type* block = impl_->blocks[decoded.first];
- if (!block) {
- std::cerr << "Received message from process " << process << " with tag "
- << decoded.second << " for non-active block "
- << decoded.first << std::endl;
- std::cerr << "Active blocks are: ";
- for (std::size_t i = 0; i < impl_->blocks.size(); ++i)
- if (impl_->blocks[i])
- std::cerr << i << ' ';
- std::cerr << std::endl;
- assert(block);
- }
-
- if (decoded.second < static_cast<int>(block->triggers.size())
- && block->triggers[decoded.second]) {
- // We have a trigger for this message; use it
- trigger_receive_context old_context = impl_->trigger_context;
- impl_->trigger_context = trc_out_of_band;
- block->triggers[decoded.second]->receive(*this, process, decoded.second,
- impl_->trigger_context,
- decoded.first);
- impl_->trigger_context = old_context;
- }
- else
- return false;
- // We receives the message above
- return true;
-}
-
-bool mpi_process_group::emit_receive(int process, int encoded_tag) const
-{
- std::pair<int, int> decoded = decode_tag(encoded_tag);
-
- if (decoded.first >= static_cast<int>(impl_->blocks.size()))
- // This must be an out-of-band message destined for
- // send_oob_with_reply; ignore it.
- return false;
-
- // Find the block that will receive this message
- block_type* block = impl_->blocks[decoded.first];
- assert(block);
- if (decoded.second < static_cast<int>(block->triggers.size())
- && block->triggers[decoded.second])
- // We have a trigger for this message; use it
- block->triggers[decoded.second]->receive(*this,process, decoded.second,
- impl_->trigger_context);
- else if (block->on_receive)
- // Fall back to the normal message handler
- block->on_receive(process, decoded.second);
- else
- // There was no handler for this message
- return false;
-
- // The message was handled above
- return true;
-}
-
-void mpi_process_group::emit_on_synchronize() const
-{
- for (block_iterator i = impl_->blocks.begin(); i != impl_->blocks.end(); ++i)
- if (*i && (*i)->on_synchronize) (*i)->on_synchronize();
-}
-
-
-optional<std::pair<mpi_process_group::process_id_type, int> >
-mpi_process_group::probe() const
-{
-#ifdef DEBUG
- std::cerr << "PROBE: " << process_id(*this) << ", tag block = "
- << my_block_number() << std::endl;
-#endif
-
- typedef std::pair<process_id_type, int> result_type;
-
- int tag_block = my_block_number();
-
- for (std::size_t source = 0; source < impl_->incoming.size(); ++source) {
- impl::incoming_messages& incoming = impl_->incoming[source];
- std::vector<impl::message_header>::iterator& i =
- incoming.next_header[tag_block];
- std::vector<impl::message_header>::iterator end = incoming.headers.end();
-
- while (i != end) {
- if (i->tag != -1 && decode_tag(i->tag).first == my_block_number()) {
-#ifdef DEBUG
- std::cerr << "PROBE: " << process_id(*this) << " <- " << source
- << ", block = " << my_block_number() << ", tag = "
- << decode_tag(i->tag).second << ", bytes = " << i->bytes
- << std::endl;
-#endif
- return result_type(source, decode_tag(i->tag).second);
- }
- ++i;
- }
- }
- return optional<result_type>();
-}
-
-void
-mpi_process_group::maybe_send_batch(process_id_type dest) const
-{
-#ifndef NO_SPLIT_BATCHES
- impl::outgoing_messages& outgoing = impl_->outgoing[dest];
- if (outgoing.buffer.size() >= impl_->batch_buffer_size ||
- outgoing.headers.size() >= impl_->batch_header_number) {
- // we are full and need to send
- outgoing_messages batch;
- batch.buffer.reserve(impl_->batch_buffer_size);
- batch.swap(outgoing);
- if (batch.buffer.size() >= impl_->batch_buffer_size
- && batch.headers.size()>1 ) {
- // we are too large, keep the last message in the outgoing buffer
- std::copy(batch.buffer.begin()+batch.headers.back().offset,
- batch.buffer.end(),std::back_inserter(outgoing.buffer));
- batch.buffer.resize(batch.headers.back().offset);
- outgoing.headers.push_back(batch.headers.back());
- batch.headers.pop_back();
- outgoing.headers.front().offset=0;
- }
- send_batch(dest,batch);
- }
-#endif
-}
-
-void
-mpi_process_group::send_batch(process_id_type dest) const
-{
- impl::outgoing_messages& outgoing = impl_->outgoing[dest];
- if (outgoing.headers.size()) {
- // need to copy to avoid race conditions
- outgoing_messages batch;
- batch.buffer.reserve(impl_->batch_buffer_size);
- batch.swap(outgoing);
- send_batch(dest,batch);
- }
-}
-
-
-void
-mpi_process_group::send_batch(process_id_type dest,
- outgoing_messages& outgoing) const
-{
- impl_->free_sent_batches();
- process_id_type id = process_id(*this);
-
- // clear the batch
-#ifdef DEBUG
- std::cerr << "Sending batch: " << id << " -> " << dest << std::endl;
-#endif
- // we increment the number of batches sent
- ++impl_->number_sent_batches[dest];
- // and send the batch
- assert(outgoing.headers.size() <= impl_->batch_header_number);
- if (id != dest) {
-#ifdef NO_ISEND_BATCHES
- impl::batch_request req;
-#else
-#ifdef PREALLOCATE_BATCHES
- while (impl_->free_batches.empty()) {
- impl_->free_sent_batches();
- poll();
- }
- impl::batch_request& req = impl_->batch_pool[impl_->free_batches.top()];
- impl_->free_batches.pop();
-#else
- impl_->sent_batches.push_back(impl::batch_request());
- impl::batch_request& req = impl_->sent_batches.back();
-#endif
-#endif
- boost::mpi::packed_oarchive oa(impl_->comm,req.buffer);
- oa << outgoing;
-
- int tag = msg_batch;
-
-#ifdef IRECV_BATCH
- if (oa.size() > impl_->batch_message_size)
- tag = msg_large_batch;
-#endif
-
- int result = MPI_Isend(const_cast<void*>(oa.address()), oa.size(),
- MPI_PACKED, dest, tag, impl_->comm,
- &req.request);
- assert(result == MPI_SUCCESS);
- impl_->max_sent = (std::max)(impl_->max_sent,impl_->sent_batches.size());
-#ifdef NO_ISEND_BATCHES
- int done=0;
- do {
- poll();
- MPI_Test(&req.request,&done,MPI_STATUS_IGNORE);
- } while (!done);
-#else
-#ifdef MAX_BATCHES
- while (impl_->sent_batches.size() >= MAX_BATCHES-1) {
- impl_->free_sent_batches();
- poll();
- }
-#endif
-#endif
- }
- else
- receive_batch(id,outgoing);
-}
-
-void mpi_process_group::process_batch(int source) const
-{
- bool processing_from_queue = !impl_->new_batches.empty();
- impl_->processing_batches++;
- typedef std::vector<impl::message_header>::iterator iterator;
-
- impl::incoming_messages& incoming = impl_->incoming[source];
-
- // Set up the iterators pointing to the next header in each block
- for (std::size_t i = 0; i < incoming.next_header.size(); ++i)
- incoming.next_header[i] = incoming.headers.begin();
-
- buffer_type remaining_buffer;
- std::vector<impl::message_header> remaining_headers;
-
- iterator end = incoming.headers.end();
-
- for (iterator i = incoming.headers.begin(); i != end; ++i) {
- // This this message has already been received, skip it
- if (i->tag == -1)
- continue;
-
-#ifdef BATCH_DEBUG
- std::cerr << process_id(*this) << ": emit_receive(" << source << ", "
- << decode_tag(i->tag).first << ":" << decode_tag(i->tag).second
- << ")\n";
-#endif
-
- if (!emit_receive(source, i->tag)) {
-#ifdef BATCH_DEBUG
- std::cerr << process_id(*this) << ": keeping message # "
- << remaining_headers.size() << " from " << source << " ("
- << decode_tag(i->tag).first << ":"
- << decode_tag(i->tag).second << ", "
- << i->bytes << " bytes)\n";
-#endif
- // Hold on to this message until the next stage
- remaining_headers.push_back(*i);
- remaining_headers.back().offset = remaining_buffer.size();
- remaining_buffer.insert(remaining_buffer.end(),
- &incoming.buffer[i->offset],
- &incoming.buffer[i->offset] + i->bytes);
- }
- }
-
- // Swap the remaining messages into the "incoming" set.
- incoming.headers.swap(remaining_headers);
- incoming.buffer.swap(remaining_buffer);
-
- // Set up the iterators pointing to the next header in each block
- for (std::size_t i = 0; i < incoming.next_header.size(); ++i)
- incoming.next_header[i] = incoming.headers.begin();
- impl_->processing_batches--;
-
- if (!processing_from_queue)
- while (!impl_->new_batches.empty()) {
- receive_batch(impl_->new_batches.front().first,
- impl_->new_batches.front().second);
- impl_->new_batches.pop();
- }
-}
-
-
-void mpi_process_group::receive_batch(process_id_type source,
- outgoing_messages& new_messages) const
-{
- impl_->free_sent_batches();
- if(!impl_->processing_batches) {
- // increase the number of received batches
- ++impl_->number_received_batches[source];
- // and receive the batch
- impl::incoming_messages& incoming = impl_->incoming[source];
- typedef std::vector<impl::message_header>::iterator iterator;
- iterator end = new_messages.headers.end();
- for (iterator i = new_messages.headers.begin(); i != end; ++i) {
- incoming.headers.push_back(*i);
- incoming.headers.back().offset = incoming.buffer.size();
- incoming.buffer.insert(incoming.buffer.end(),
- &new_messages.buffer[i->offset],
- &new_messages.buffer[i->offset] + i->bytes);
- }
- // Set up the iterators pointing to the next header in each block
- for (std::size_t i = 0; i < incoming.next_header.size(); ++i)
- incoming.next_header[i] = incoming.headers.begin();
-#ifndef NO_IMMEDIATE_PROCESSING
- process_batch(source);
-#endif
- }
- else {
- #ifdef DEBUG
- std::cerr << "Pushing incoming message batch onto queue since we are already processing a batch.\n";
- #endif
- // use swap to avoid copying
- impl_->new_batches.push(std::make_pair(int(source),outgoing_messages()));
- impl_->new_batches.back().second.swap(new_messages);
- impl_->max_received = (std::max)(impl_->max_received,impl_->new_batches.size());
- }
-}
-
-
-void mpi_process_group::pack_headers() const
-{
- for (process_id_type other = 0; other < num_processes(*this); ++other) {
- typedef std::vector<impl::message_header>::iterator iterator;
-
- impl::incoming_messages& incoming = impl_->incoming[other];
-
- buffer_type remaining_buffer;
- std::vector<impl::message_header> remaining_headers;
-
- iterator end = incoming.headers.end();
- for (iterator i = incoming.headers.begin(); i != end; ++i) {
- if (i->tag == -1)
- continue;
-
- // Hold on to this message until the next stage
- remaining_headers.push_back(*i);
- remaining_headers.back().offset = remaining_buffer.size();
- remaining_buffer.insert(remaining_buffer.end(),
- &incoming.buffer[i->offset],
- &incoming.buffer[i->offset] + i->bytes);
- }
-
- // Swap the remaining messages into the "incoming" set.
- incoming.headers.swap(remaining_headers);
- incoming.buffer.swap(remaining_buffer);
-
- // Set up the iterators pointing to the next header in each block
- for (std::size_t i = 0; i < incoming.next_header.size(); ++i)
- incoming.next_header[i] = incoming.headers.begin();
- }
-}
-
-void mpi_process_group::receive_batch(boost::mpi::status& status) const
-{
- //std::cerr << "Handling batch\n";
- outgoing_messages batch;
- //impl_->comm.recv(status.source(),status.tag(),batch);
-
- //receive_oob(*this,status.source(),msg_batch,batch);
-
- // Determine how big the receive buffer should be
-#if BOOST_VERSION >= 103600
- int size = status.count<boost::mpi::packed>().get();
-#else
- int size;
- MPI_Status mpi_status(status);
- MPI_Get_count(&mpi_status, MPI_PACKED, &size);
-#endif
-
- // Allocate the receive buffer
- boost::mpi::packed_iarchive in(impl_->comm,size);
-
- // Receive the message data
- MPI_Recv(in.address(), size, MPI_PACKED,
- status.source(), status.tag(),
- impl_->comm, MPI_STATUS_IGNORE);
-
- // Unpack the message data
- in >> batch;
- receive_batch(status.source(),batch);
-}
-
-std::pair<boost::mpi::communicator, int>
-mpi_process_group::actual_communicator_and_tag(int tag, int block) const
-{
- if (tag >= max_tags * static_cast<int>(impl_->blocks.size()))
- // Use the out-of-band reply communicator
- return std::make_pair(impl_->oob_reply_comm, tag);
- else
- // Use the normal communicator and translate the tag
- return std::make_pair(impl_->comm,
- encode_tag(block == -1? my_block_number() : block,
- tag));
-}
-
-
-void mpi_process_group::synchronize() const
-{
- // Don't synchronize if we've already finished
- if (boost::mpi::environment::finalized())
- return;
-
-#ifdef DEBUG
- std::cerr << "SYNC: " << process_id(*this) << std::endl;
-#endif
-
- emit_on_synchronize();
-
- process_id_type id = process_id(*this); // Our rank
- process_size_type p = num_processes(*this); // The number of processes
-
- // Pack the remaining incoming messages into the beginning of the
- // buffers, so that we can receive new messages in this
- // synchronization step without losing those messages that have not
- // yet been received.
- pack_headers();
-
- impl_->synchronizing_stage[id] = -1;
- int stage=-1;
- bool no_new_messages = false;
- while (true) {
- ++stage;
-#ifdef DEBUG
- std::cerr << "SYNC: " << id << " starting stage " << (stage+1) << ".\n";
-#endif
-
- // Tell everyone that we are synchronizing. Note: we use MPI_Isend since
- // we absolutely cannot have any of these operations blocking.
-
- // increment the stage for the source
- ++impl_->synchronizing_stage[id];
- if (impl_->synchronizing_stage[id] != stage)
- std::cerr << "Expected stage " << stage << ", got " << impl_->synchronizing_stage[id] << std::endl;
- assert(impl_->synchronizing_stage[id]==stage);
- // record how many still have messages to be sent
- if (static_cast<int>(impl_->synchronizing_unfinished.size())<=stage) {
- assert(static_cast<int>(impl_->synchronizing_unfinished.size()) == stage);
- impl_->synchronizing_unfinished.push_back(no_new_messages ? 0 : 1);
- }
- else
- impl_->synchronizing_unfinished[stage]+=(no_new_messages ? 0 : 1);
-
- // record how many are in that stage
- if (static_cast<int>(impl_->processors_synchronizing_stage.size())<=stage) {
- assert(static_cast<int>(impl_->processors_synchronizing_stage.size()) == stage);
- impl_->processors_synchronizing_stage.push_back(1);
- }
- else
- ++impl_->processors_synchronizing_stage[stage];
-
- impl_->synchronizing = true;
-
- for (int dest = 0; dest < p; ++dest) {
- int sync_message = no_new_messages ? -1 : impl_->number_sent_batches[dest];
- if (dest != id) {
- impl_->number_sent_batches[dest]=0;
- MPI_Request request;
- MPI_Isend(&sync_message, 1, MPI_INT, dest, msg_synchronizing, impl_->comm,&request);
- int done=0;
- do {
- poll();
- MPI_Test(&request,&done,MPI_STATUS_IGNORE);
- } while (!done);
- }
- else { // need to subtract how many messages I should have received
- impl_->number_received_batches[id] -=impl_->number_sent_batches[id];
- impl_->number_sent_batches[id]=0;
- }
- }
-
- // Keep handling out-of-band messages until everyone has gotten
- // to this point.
- while (impl_->processors_synchronizing_stage[stage] <p) {
- // with the trigger based solution we cannot easily pass true here
- poll(/*wait=*/false, -1, true);
-
- }
-
- // check that everyone is at least here
- for (int source=0; source<p ; ++source)
- assert(impl_->synchronizing_stage[source] >= stage);
-
- // receive any batches sent in the meantime
- // all have to be available already
- while (true) {
- bool done=true;
- for (int source=0; source<p ; ++source)
- if(impl_->number_received_batches[source] < 0)
- done = false;
- if (done)
- break;
- poll(false,-1,true);
- }
-
-#ifndef NO_IMMEDIATE_PROCESSING
- for (int source=0; source<p ; ++source)
- assert(impl_->number_received_batches[source] >= 0);
-#endif
-
- impl_->synchronizing = false;
-
- // Flush out remaining messages
- if (impl_->synchronizing_unfinished[stage]==0)
- break;
-#ifdef NO_IMMEDIATE_PROCESSING
- for (process_id_type dest = 0; dest < p; ++dest)
- process_batch(dest);
-#endif
-
- no_new_messages = true;
- for (process_id_type dest = 0; dest < p; ++dest) {
- if (impl_->outgoing[dest].headers.size() ||
- impl_->number_sent_batches[dest]>0)
- no_new_messages = false;
- send_batch(dest);
- }
- }
-
- impl_->comm.barrier/*nomacro*/();
-#if 0
- // set up for next synchronize call
- for (int source=0; source<p; ++source) {
- if (impl_->synchronizing_stage[source] != stage) {
- std::cerr << id << ": expecting stage " << stage << " from source "
- << source << ", got " << impl_->synchronizing_stage[source]
- << std::endl;
- }
- assert(impl_->synchronizing_stage[source]==stage);
- }
-#endif
- std::fill(impl_->synchronizing_stage.begin(),
- impl_->synchronizing_stage.end(), -1);
-
- // get rid of the information regarding recorded numbers of processors
- // for the stages we just finished
- impl_->processors_synchronizing_stage.clear();
- impl_->synchronizing_unfinished.clear();
-
- for (process_id_type dest = 0; dest < p; ++dest)
- assert (impl_->outgoing[dest].headers.empty());
-#ifndef NO_IMMEDIATE_PROCESSING
- for (int source=0; source<p ; ++source)
- assert (impl_->number_received_batches[source] == 0);
-#endif
-
- impl_->free_sent_batches();
-#ifdef DEBUG
- std::cerr << "SYNC: " << process_id(*this) << " completed." << std::endl;
-#endif
-}
-
-optional<std::pair<mpi_process_group::process_id_type, int> >
-probe(const mpi_process_group& pg)
-{ return pg.probe(); }
-
-void mpi_process_group::poll_requests(int block) const
-{
- int size = impl_->requests.size();
- if (size==0)
- return;
- std::vector<MPI_Status> statuses(size);
- std::vector<int> indices(size);
-
- while (true) {
- MPI_Testsome(impl_->requests.size(),&impl_->requests[0],
- &size,&indices[0],&statuses[0]);
- if (size==0)
- return; // no message waiting
-
- // remove handled requests before we get the chance to be recursively called
- if (size) {
- std::vector<MPI_Request> active_requests;
- std::size_t i=0;
- int j=0;
- for (;i< impl_->requests.size() && j< size; ++i) {
- if (int(i)==indices[j])
- // release the dealt-with request
- ++j;
- else // copy and keep the request
- active_requests.push_back(impl_->requests[i]);
- }
- while (i < impl_->requests.size())
- active_requests.push_back(impl_->requests[i++]);
- impl_->requests.swap(active_requests);
- }
-
- optional<std::pair<int, int> > result;
- for (int i=0;i < size; ++i) {
- std::pair<int, int> decoded = decode_tag(statuses[i].MPI_TAG);
- block_type* block = impl_->blocks[decoded.first];
-
- assert (decoded.second < static_cast<int>(block->triggers.size()) && block->triggers[decoded.second]);
- // We have a trigger for this message; use it
- trigger_receive_context old_context = impl_->trigger_context;
- impl_->trigger_context = trc_irecv_out_of_band;
- block->triggers[decoded.second]->receive(*this, statuses[i].MPI_SOURCE,
- decoded.second, impl_->trigger_context, decoded.first);
- impl_->trigger_context = old_context;
- }
- }
-}
-
-
-optional<std::pair<int, int> >
-mpi_process_group::
-poll(bool wait, int block, bool synchronizing) const
-{
- // Set the new trigger context for these receive operations
- trigger_receive_context old_context = impl_->trigger_context;
- if (synchronizing)
- impl_->trigger_context = trc_in_synchronization;
- else
- impl_->trigger_context = trc_out_of_band;
-
- //wait = false;
- optional<boost::mpi::status> status;
- bool finished=false;
- optional<std::pair<int, int> > result;
- do {
- poll_requests(block);
- // Check for any messages not yet received.
-#ifdef PBGL_PROCESS_GROUP_NO_IRECV
- if (wait)
- status = impl_->comm.probe();
- else
-#endif
- status = impl_->comm.iprobe();
-
- if (status) { // we have a message
- // Decode the message
- std::pair<int, int> decoded = decode_tag(status.get().tag());
- if (maybe_emit_receive(status.get().source(), status.get().tag()))
- // We received the message out-of-band; poll again
- finished = false;
- else if (decoded.first == (block == -1 ? my_block_number() : block)) {
- // This message is for us, but not through a trigger. Return
- // the decoded message.
- result = std::make_pair(status.get().source(), decoded.second);
- // otherwise we didn't match any message we know how to deal with, so
- // pretend no message exists.
- finished = true;
- }
- }
- else
- // We don't have a message to process; we're done.
- finished=!wait;
- } while (!finished);
-
- // Restore the prior trigger context
- impl_->trigger_context = old_context;
- poll_requests(block);
- return result;
-}
-
-void synchronize(const mpi_process_group& pg) { pg.synchronize(); }
-
-mpi_process_group mpi_process_group::base() const
-{
- mpi_process_group copy(*this);
- copy.block_num.reset();
- return copy;
-}
-
-
-void mpi_process_group::impl::free_sent_batches()
-{
- typedef std::list<batch_request>::iterator iterator;
- iterator it = sent_batches.begin();
- int flag;
- int result;
- while(it != sent_batches.end()) {
- result = MPI_Test(&it->request,&flag,MPI_STATUS_IGNORE);
- assert(result == MPI_SUCCESS);
- iterator next=it;
- ++next;
- if (flag)
- sent_batches.erase(it);
- it=next;
- }
-#ifdef PREALLOCATE_BATCHES
- for (std::size_t i=0; i< batch_pool.size();++i) {
- if(batch_pool[i].request != MPI_REQUEST_NULL) {
- result = MPI_Test(&batch_pool[i].request,&flag,MPI_STATUS_IGNORE);
- assert(result == MPI_SUCCESS);
- if (flag) {
- free_batches.push(i);
- batch_pool[i].request = MPI_REQUEST_NULL;
- batch_pool[i].buffer.resize(0);
- }
- }
- }
-#endif
-}
-
-void
-mpi_process_group::install_trigger(int tag, int block,
- shared_ptr<trigger_base> const& launcher)
-{
- block_type* my_block = impl_->blocks[block];
- assert(my_block);
-
- // Make sure we have enough space in the structure for this trigger.
- if (launcher->tag() >= static_cast<int>(my_block->triggers.size()))
- my_block->triggers.resize(launcher->tag() + 1);
-
- // If someone already put a trigger in this spot, we have a big
- // problem.
- if (my_block->triggers[launcher->tag()]) {
- std::cerr << "Block " << my_block_number()
- << " already has a trigger for tag " << launcher->tag()
- << std::endl;
- }
- assert(!my_block->triggers[launcher->tag()]);
-
- // Attach a new trigger launcher
- my_block->triggers[launcher->tag()] = launcher;
-}
-
-std::size_t mpi_process_group::message_buffer_size()
-{
- return message_buffer.size();
-}
-
-
-void mpi_process_group::set_message_buffer_size(std::size_t s)
-{
- int sz;
- void* ptr;
- if (!message_buffer.empty()) {
- MPI_Buffer_detach(&ptr,&sz);
- assert(ptr == &message_buffer.front());
- assert(static_cast<std::size_t>(sz) == message_buffer.size());
- }
- else if (old_buffer != 0)
- MPI_Buffer_detach(&old_buffer,&old_buffer_size);
- message_buffer.resize(s);
- if (s)
- MPI_Buffer_attach(&message_buffer.front(), message_buffer.size());
- else if (old_buffer_size)
- MPI_Buffer_attach(old_buffer, old_buffer_size);
-}
-
-
-std::vector<char> mpi_process_group::message_buffer;
-int mpi_process_group::old_buffer_size=0;
-void* mpi_process_group::old_buffer=0;
-
-} } } // end namespace boost::graph::distributed

Deleted: trunk/libs/graph/src/tag_allocator.cpp
==============================================================================
--- trunk/libs/graph/src/tag_allocator.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
+++ (empty file)
@@ -1,45 +0,0 @@
-// Copyright (C) 2007 Douglas Gregor <doug.gregor_at_[hidden]>
-
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/graph/use_mpi.hpp>
-#include <boost/graph/distributed/detail/tag_allocator.hpp>
-
-namespace boost { namespace graph { namespace distributed { namespace detail {
-
-tag_allocator::token tag_allocator::get_tag()
-{
- int tag;
-
- if (!freed.empty()) {
- // Grab the tag at the top of the stack.
- tag = freed.back();
- freed.pop_back();
- } else
- // Grab the bottom tag and move the bottom down
- tag = bottom--;
-
- return token(this, tag);
-}
-
-tag_allocator::token::token(const token& other)
- : allocator(other.allocator), tag_(other.tag_)
-{
- // other no longer owns this tag
- other.tag_ = -1;
-}
-
-tag_allocator::token::~token()
-{
- if (tag_ != -1) {
- if (tag_ == allocator->bottom + 1)
- // This is the bottommost tag: just bump up the bottom
- ++allocator->bottom;
- else
- // This tag isn't the bottom, so push it only the freed stack
- allocator->freed.push_back(tag_);
- }
-}
-
-} } } } // end namespace boost::graph::distributed::detail

Copied: trunk/libs/graph_parallel/CMakeLists.txt (from r52301, /trunk/libs/graph/CMakeLists.txt)
==============================================================================
--- /trunk/libs/graph/CMakeLists.txt (original)
+++ trunk/libs/graph_parallel/CMakeLists.txt 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -1,23 +1,15 @@
-#----------------------------------------------------------------------------
-# This file was automatically generated from the original CMakeLists.txt file
-# Add a variable to hold the headers for the library
-set (lib_headers
- graph
-)
-
 # Add a library target to the build system
 boost_library_project(
- graph
- SRCDIRS src
+ graph_parallel
+ SRCDIRS src
   TESTDIRS test
- HEADERS ${lib_headers}
- # DOCDIRS
- DESCRIPTION "The BGL graph interface and graph components are generic, in the same sense as the the Standard Template Library (STL)."
- MODULARIZED
- AUTHORS "Jeremy Siek <jeremy.siek -at- gmail.com>"
- "Lie-Quan Lee"
+ HEADERS graph graph/parallel
+ # DOCDIRS doc
+ DESCRIPTION "Parallel support using MPI for Boost.Graph."
+ AUTHORS "Douglas Gregor <doug.gregor -at- gmail.com>"
+ "Nicholas Edmonds <ngedmond -at- osl.iu.edu>"
+ "Jeremiah Willcock <jewillco -at- osl.iu.edu>"
            "Andrew Lumsdaine"
- "Douglas Gregor <doug.gregor -at- gmail.com>"
   # MAINTAINERS
 )
 

Copied: trunk/libs/graph_parallel/build/Jamfile.v2 (from r52301, /trunk/libs/graph/build/Jamfile.v2)
==============================================================================
--- /trunk/libs/graph/build/Jamfile.v2 (original)
+++ trunk/libs/graph_parallel/build/Jamfile.v2 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -6,7 +6,7 @@
 
 import mpi ;
 
-project boost/graph
+project boost/graph_parallel
     : requirements <include>../src
     : source-location ../src
     ;
@@ -14,37 +14,6 @@
 local optional_sources ;
 local optional_reqs ;
 
-if [ modules.peek : EXPAT_INCLUDE ] && [ modules.peek : EXPAT_LIBPATH ]
-{
- local EXPAT_INCLUDE = [ modules.peek : EXPAT_INCLUDE ] ;
- local EXPAT_LIBPATH = [ modules.peek : EXPAT_LIBPATH ] ;
-
- if --debug-configuration in [ modules.peek : ARGV ]
- {
- ECHO "Expat include directory: $(EXPAT_INCLUDE)" ;
- ECHO "Expat library directory: $(EXPAT_LIBPATH)" ;
- }
-
- alias graphml
- : graphml.cpp
- : # requirements
- : # default built
- : # usage requirements
- <include>$(EXPAT_INCLUDE)
- <library-path>$(EXPAT_LIBPATH)
- <find-shared-library>expat
- ;
-}
-else
-{
- message graphml
- : "warning: Graph library does not contain optional GraphML reader."
- : "note: to enable GraphML support, set EXPAT_INCLUDE and EXPAT_LIBPATH to the"
- : "note: directories containing the Expat headers and libraries, respectively."
- ;
-}
-explicit graphml ;
-
 if [ mpi.configured ]
 {
   alias pbgl
@@ -65,12 +34,10 @@
       : "note: to enable them, add \"using mpi ;\" to your user_config.jam"
       ;
 }
-explicit graphml ;
+explicit pbgl ;
 
-lib boost_graph
+lib boost_graph_parallel
     :
- read_graphviz_spirit.cpp
- graphml
     pbgl
     :
     <define>BOOST_GRAPH_NO_LIB=1
@@ -82,4 +49,4 @@
     <toolset>msvc-8.0:<cxxflags>-GR-
     ;
 
-boost-install boost_graph ;
+boost-install boost_graph_parallel ;

Added: trunk/libs/graph_parallel/doc/CMakeLists.txt
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/CMakeLists.txt 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,63 @@
+set(PBGL_DOCS
+ DistributedGraph
+ DistributedEdgeListGraph
+ DistributedVertexListGraph
+ GlobalDescriptor
+ boman_et_al_graph_coloring
+ breadth_first_search
+ connected_components
+ dehne_gotz_min_spanning_tree
+ dijkstra_example
+ dijkstra_shortest_paths
+ distributed_adjacency_list
+ distributed_property_map
+ distributed_queue
+ distributedS
+ index
+ local_subgraph
+ metis
+ overview
+ page_rank
+ process_group
+ simple_trigger
+ strong_components
+ tsin_depth_first_visit
+ vertex_list_adaptor
+ rmat_generator
+ sorted_rmat_generator
+ unique_rmat_generator
+ sorted_unique_rmat_generator
+ scalable_rmat_generator
+ mesh_generator
+ ssca_generator
+ fruchterman_reingold
+ st_connected
+ betweenness_centrality
+ connected_components_parallel_search
+ )
+
+set(PBGL_IMAGES
+ dijkstra_dist3_graph.png dijkstra_seq_graph.png vertex_coloring.png
+ architecture.png dist-adjlist.png dist-pmap.png distributed-graph.png
+ graph.png)
+
+set(PBGL_DOC_TARGETS)
+separate_arguments(RST2HTML_FLAGS)
+foreach(DOC ${PBGL_DOCS})
+ add_custom_command(OUTPUT "${PBGL_BINARY_DIR}/libs/graph/doc/parallel/${DOC}.html"
+ COMMAND "${RST2HTML}"
+ ARGS ${RST2HTML_FLAGS} "${PBGL_SOURCE_DIR}/libs/graph/doc/parallel/${DOC}.rst"
+ "${PBGL_BINARY_DIR}/libs/graph/doc/parallel/${DOC}.html"
+ COMMENT "Generating document ${DOC}.html..."
+ )
+ list(APPEND PBGL_DOC_TARGETS "${PBGL_BINARY_DIR}/libs/graph/doc/parallel/${DOC}.html")
+endforeach(DOC)
+
+add_custom_target(doc ALL
+ DEPENDS ${PBGL_DOC_TARGETS})
+
+install(FILES ${PBGL_DOC_TARGETS} ${PBGL_IMAGES}
+ DESTINATION "doc/pbgl-${PBGL_VERSION}"
+ COMPONENT "Documentation"
+ OPTIONAL
+ )

Added: trunk/libs/graph_parallel/doc/DistributedEdgeListGraph.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/DistributedEdgeListGraph.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,86 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+==========================================
+|Logo| Concept Distributed Edge List Graph
+==========================================
+
+.. contents::
+
+Description
+-----------
+
+A Distributed Edge List Graph is a graph whose vertices are
+distributed across multiple processes or address spaces. The
+``vertices`` and ``num_vertices`` functions retain the same
+signatures as in the `Edge List Graph`_ concept, but return only
+the local set (and size of the local set) of vertices.
+
+Notation
+--------
+
+G
+ A type that models the Distributed Edge List Graph concept.
+
+g
+ An object of type ``G``.
+
+Refinement of
+-------------
+
+ - `Graph`_
+
+Associated types
+----------------
+
++----------------+---------------------------------------+---------------------------------+
+|Edge |``graph_traits<G>::edge_descriptor`` |Must model the |
+|descriptor type | |`Global Descriptor`_ concept. |
++----------------+---------------------------------------+---------------------------------+
+|Edge iterator |``graph_traits<G>::edge_iterator`` |Iterates over edges stored |
+|type | |locally. The value type must be |
+| | |``edge_descriptor``. |
++----------------+---------------------------------------+---------------------------------+
+|Edges size |``graph_traits<G>::edges_size_type`` |The unsigned integral type used |
+|type | |to store the number of edges |
+| | |in the local subgraph. |
++----------------+---------------------------------------+---------------------------------+
+
+Valid Expressions
+-----------------
+
++----------------+---------------------+----------------------+-------------------------------------+
+|Name |Expression |Type |Semantics |
++================+=====================+======================+=====================================+
+|Local edge set |``edges(g)`` |``std::pair<`` |Returns an iterator range |
+| | |``edge_iterator,`` |providing access to the local |
+| | |``edge_iterator>`` |edges in the graph. |
++----------------+---------------------+----------------------+-------------------------------------+
+|Number of local |``num_edges(g)`` |``edges_size_type`` |Returns the number of edges |
+|edges. | | |stored locally in the graph. |
++----------------+---------------------+----------------------+-------------------------------------+
+
+
+Models
+------
+
+ - `Distributed adjacency list`_
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Graph: http://www.boost.org/libs/graph/doc/Graph.html
+.. _Edge List Graph: http://www.boost.org/libs/graph/doc/EdgeListGraph.html
+.. _Distributed Graph: DistributedGraph.html
+.. _Global descriptor: GlobalDescriptor.html
+.. _Distributed adjacency list: distributed_adjacency_list.html

Added: trunk/libs/graph_parallel/doc/DistributedGraph.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/DistributedGraph.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,62 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+================================
+|Logo| Concept Distributed Graph
+================================
+
+.. contents::
+
+Description
+-----------
+
+A Distributed Graph is a graph whose vertices or edges are
+distributed across multiple processes or address spaces. The
+descriptors of a Distributed Graph must model the `Global
+Descriptor`_ concept.
+
+Notation
+--------
+
+G
+ A type that models the Distributed Graph concept.
+
+
+Refinement of
+-------------
+
+ - Graph_
+
+Associated types
+----------------
+
++----------------+---------------------------------------+---------------------------------+
+|Vertex |``graph_traits<G>::vertex_descriptor`` |Must model the |
+|descriptor type | |`Global Descriptor`_ concept. |
++----------------+---------------------------------------+---------------------------------+
+|Edge |``graph_traits<G>::edge_descriptor`` |Must model the |
+|descriptor type | |`Global Descriptor`_ concept. |
++----------------+---------------------------------------+---------------------------------+
+
+
+Models
+------
+
+ - `Distributed adjacency list`_
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Graph: http://www.boost.org/libs/graph/doc/Graph.html
+.. _Global descriptor: GlobalDescriptor.html
+.. _Distributed adjacency list: distributed_adjacency_list.html

Added: trunk/libs/graph_parallel/doc/DistributedVertexListGraph.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/DistributedVertexListGraph.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,86 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+============================================
+|Logo| Concept Distributed Vertex List Graph
+============================================
+
+.. contents::
+
+Description
+-----------
+
+A Distributed Vertex List Graph is a graph whose vertices are
+distributed across multiple processes or address spaces. The
+``vertices`` and ``num_vertices`` functions retain the same
+signatures as in the `Vertex List Graph`_ concept, but return only
+the local set (and size of the local set) of vertices.
+
+Notation
+--------
+
+G
+ A type that models the Distributed Vertex List Graph concept.
+
+g
+ An object of type ``G``.
+
+Refinement of
+-------------
+
+ - `Graph`_
+
+Associated types
+----------------
+
++----------------+---------------------------------------+---------------------------------+
+|Vertex |``graph_traits<G>::vertex_descriptor`` |Must model the |
+|descriptor type | |`Global Descriptor`_ concept. |
++----------------+---------------------------------------+---------------------------------+
+|Vertex iterator |``graph_traits<G>::vertex_iterator`` |Iterates over vertices stored |
+|type | |locally. The value type must be |
+| | |``vertex_descriptor``. |
++----------------+---------------------------------------+---------------------------------+
+|Vertices size |``graph_traits<G>::vertices_size_type``|The unsigned integral type used |
+|type | |to store the number of vertices |
+| | |in the local subgraph. |
++----------------+---------------------------------------+---------------------------------+
+
+Valid Expressions
+-----------------
+
++----------------+---------------------+----------------------+-------------------------------------+
+|Name |Expression |Type |Semantics |
++================+=====================+======================+=====================================+
+|Local vertex set|``vertices(g)`` |``std::pair<`` |Returns an iterator range |
+| | |``vertex_iterator,`` |providing access to the local |
+| | |``vertex_iterator>`` |vertices in the graph. |
++----------------+---------------------+----------------------+-------------------------------------+
+|Number of local |``num_vertices(g)`` |``vertices_size_type``|Returns the number of vertices |
+|vertices. | | |stored locally in the graph. |
++----------------+---------------------+----------------------+-------------------------------------+
+
+
+Models
+------
+
+ - `Distributed adjacency list`_
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Graph: http://www.boost.org/libs/graph/doc/Graph.html
+.. _Vertex List Graph: http://www.boost.org/libs/graph/doc/VertexListGraph.html
+.. _Distributed Graph: DistributedGraph.html
+.. _Global descriptor: GlobalDescriptor.html
+.. _Distributed adjacency list: distributed_adjacency_list.html

Added: trunk/libs/graph_parallel/doc/GlobalDescriptor.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/GlobalDescriptor.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,78 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+================================
+|Logo| Concept Global Descriptor
+================================
+
+.. contents::
+
+Description
+-----------
+
+A global descriptor is an object that represents an entity that is
+owned by some process and may reside in an address space not
+accessible to the currently-executing process. The global descriptor
+consists of two parts: the *owner* of the entity, which is the
+identifier of that process in which the entity resides, and a *local
+descriptor*, that uniquely identifies the entity with the address
+space of the owner.
+
+Refinement of
+-------------
+
+ - `Default Constructible`_
+ - Assignable_
+
+Notation
+--------
+X
+ A type that models the Global Descriptor concept.
+
+x
+ Object of type X
+
+
+Associated types
+----------------
+
++----------------+--------------------+---------------------------------+
+|Process ID type |``process_id_type`` |Determined by the process group |
+| | |associated with type X. |
++----------------+--------------------+---------------------------------+
+|Local descriptor|``local_type`` |Determined by the data structure |
+|type | |the descriptor accesses. |
+| | |Must model `Equality Comparable`_|
+| | |and `Copy Constructible`_. |
++----------------+--------------------+---------------------------------+
+
+Valid Expressions
+-----------------
+
++----------------+---------------------+---------------------+-------------------------------------+
+|Name |Expression |Type |Semantics |
++================+=====================+=====================+=====================================+
+|Owner |``owner(x)`` |``process_id_type`` |Returns the owner of ``x``. |
++----------------+---------------------+---------------------+-------------------------------------+
+|Local descriptor|``local(x)`` |``local_type`` |Returns the local descriptor |
+| | | |uniquely identifying ``x``. |
++----------------+---------------------+---------------------+-------------------------------------+
+
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Assignable: http://www.sgi.com/tech/stl/Assignable.html
+.. _Copy constructible: http://www.sgi.com/tech/stl/CopyConstructible.html
+.. _Default constructible: http://www.sgi.com/tech/stl/DefaultConstructible.html
+.. _Equality comparable: http://www.sgi.com/tech/stl/EqualityComparable.html

Copied: trunk/libs/graph_parallel/doc/Jamfile.v2 (from r52301, /trunk/libs/parameter/doc/Jamfile.v2)
==============================================================================
--- /trunk/libs/parameter/doc/Jamfile.v2 (original)
+++ trunk/libs/graph_parallel/doc/Jamfile.v2 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -22,3 +22,5 @@
 
 alias htmls : $(bases) ;
 stage html : $(bases) ;
+
+# JJW note: rebuild HTML docs for PBGL with "bjam docutils=`which rst2html.py`"

Added: trunk/libs/graph_parallel/doc/architecture.graffle
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/architecture.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/betweenness_centrality.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/betweenness_centrality.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,19 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+=============================
+|Logo| Betweenness Centrality
+=============================
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl

Added: trunk/libs/graph_parallel/doc/boman_et_al_graph_coloring.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/boman_et_al_graph_coloring.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,191 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+=================================
+|Logo| Boman et al graph coloring
+=================================
+
+::
+
+ namespace graph {
+ template<typename DistributedGraph, typename ColorMap>
+ typename property_traits<ColorMap>::value_type
+ boman_et_al_graph_coloring
+ (const DistributedGraph& g,
+ ColorMap color,
+ typename graph_traits<DistributedGraph>::vertices_size_type s = 100);
+
+ template<typename DistributedGraph, typename ColorMap, typename ChooseColor>
+ typename property_traits<ColorMap>::value_type
+ boman_et_al_graph_coloring
+ (const DistributedGraph& g,
+ ColorMap color,
+ typename graph_traits<DistributedGraph>::vertices_size_type s,
+ ChooseColor choose_color);
+
+ template<typename DistributedGraph, typename ColorMap, typename ChooseColor,
+ typename VertexOrdering>
+ typename property_traits<ColorMap>::value_type
+ boman_et_al_graph_coloring
+ (const DistributedGraph& g, ColorMap color,
+ typename graph_traits<DistributedGraph>::vertices_size_type s,
+ ChooseColor choose_color, VertexOrdering ordering);
+
+ template<typename DistributedGraph, typename ColorMap, typename ChooseColor,
+ typename VertexOrdering, typename VertexIndexMap>
+ typename property_traits<ColorMap>::value_type
+ boman_et_al_graph_coloring
+ (const DistributedGraph& g,
+ ColorMap color,
+ typename graph_traits<DistributedGraph>::vertices_size_type s,
+ ChooseColor choose_color,
+ VertexOrdering ordering, VertexIndexMap vertex_index);
+ }
+
+The ``boman_et_al_graph_coloring`` function colors the vertices of an
+undirected, distributed graph such that no two adjacent vertices have
+the same color. All of the vertices of a given color form an
+independent set in the graph. Graph coloring has been used to solve
+various problems, including register allocation in compilers,
+optimization problems, and scheduling problems.
+
+.. image:: vertex_coloring.png
+ :width: 462
+ :height: 269
+ :alt: Vertex coloring example
+ :align: right
+
+The problem of coloring a graph with the fewest possible number of
+colors is NP-complete, so many algorithms (including the one
+implemented here) are heuristic algorithms that try to minimize the
+number of colors but are not guaranteed to provide an optimal
+solution. This algorithm [BBC05]_ is similar to the
+``sequential_vertex_coloring`` algorithm, that iterates through the
+vertices once and selects the lowest-numbered color that the current
+vertex can have. The coloring and the number of colors is therefore
+related to the ordering of the vertices in the sequential case.
+
+The distributed ``boman_et_al_graph_coloring`` algorithm will produce
+different colorings depending on the ordering and distribution of the
+vertices and the number of parallel processes cooperating to perform
+the coloring.
+
+The algorithm returns the number of colors ``num_colors`` used to
+color the graph.
+
+.. contents::
+
+Where Defined
+~~~~~~~~~~~~~
+<``boost/graph/distributed/boman_et_al_graph_coloring.hpp``>
+
+Parameters
+~~~~~~~~~~
+
+IN: ``Graph& g``
+ The graph type must be a model of `Distributed Vertex List Graph`_ and
+ `Distributed Edge List Graph`_.
+
+
+
+UTIL/OUT: ``ColorMap color``
+ Stores the color of each vertex, which will be a value in the range
+ [0, ``num_colors``). The type ``ColorMap`` must model the
+ `Read/Write Property Map`_ concept and must be a `distributed
+ property map`_.
+
+
+
+IN: ``vertices_size_type s``
+ The number of vertices to color within each superstep. After
+ ``s`` vertices have been colored, the colors of boundary vertices
+ will be sent to their out-of-process neighbors. Smaller values
+ communicate more often but may reduce the risk of conflicts,
+ whereas larger values do more work in between communication steps
+ but may create many conflicts.
+
+ **Default**: 100
+
+IN: ``ChooseColor choose_color``
+ A function object that chooses the color for a vertex given the
+ colors of its neighbors. The function object will be passed a vector
+ of values (``marked``) and a ``marked_true`` value, and should
+ return a ``color`` value such that ``color >= marked.size()`` or
+ ``marked[color] != marked_true``.
+
+ **Default**:
+ ``boost::graph::distributed::first_fit_color<color_type>()``, where
+ ``color_type`` is the value type of the ``ColorMap`` property map.
+
+IN: ``VertexOrdering ordering``
+ A binary predicate function object that provides total ordering on
+ the vertices in the graph. Whenever a conflict arises, only one of
+ the processes involved will recolor the vertex in the next round,
+ and this ordering determines which vertex should be considered
+ conflicting (its owning process will then handle the
+ conflict). Ideally, this predicate should order vertices so that
+ conflicting vertices will be spread uniformly across
+ processes. However, this predicate *must* resolve the same way on
+ both processors.
+
+ **Default**: *unspecified*
+
+IN: ``VertexIndexMap index``
+ A mapping from vertex descriptors to indices in the range *[0,
+ num_vertices(g))*. This must be a `Readable Property Map`_ whose
+ key type is a vertex descriptor and whose value type is an integral
+ type, typically the ``vertices_size_type`` of the graph.
+
+ **Default:** ``get(vertex_index, g)``
+
+Complexity
+~~~~~~~~~~
+The complexity of this algorithm is hard to characterize,
+because it depends greatly on the number of *conflicts* that occur
+during the algorithm. A conflict occurs when a *boundary vertex*
+(i.e., a vertex that is adjacent to a vertex stored on a different
+processor) is given the same color is a boundary vertex adjacency to
+it (but on another processor). Conflicting vertices must be assigned
+new colors, requiring additional work and communication. The work
+involved in reassigning a color for a conflicting vertex is *O(d)*,
+where *d* is the degree of the vertex and *O(1)* messages of *O(1)*
+size are needed to resolve the conflict. Note that the number of
+conflicts grows with (1) the number of processes and (2) the number
+of inter-process edges.
+
+Performance
+~~~~~~~~~~~
+
+The performance of this implementation of Bomen et al's graph coloring
+algorithm is illustrated by the following charts. Scaling and
+performance is reasonable for all of the graphs we have tried.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&cluster=Odin&columns=11
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&cluster=Odin&columns=11&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&cluster=Odin&columns=11
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&cluster=Odin&columns=11&speedup=1
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Distributed Vertex List Graph: DistributedVertexListGraph.html
+.. _Distributed Edge List Graph: DistributedEdgeListGraph.html
+.. _Distributed property map: distributed_property_map.html
+.. _Readable Property Map: http://www.boost.org/libs/property_map/ReadablePropertyMap.html
+.. _Read/Write Property Map: http://www.boost.org/libs/property_map/ReadWritePropertyMap.html
+.. [BBC05] Erik G. Boman, Doruk Bozdag, Umit Catalyurek, Assefaw
+ H. Gebremedhin, and Fredrik Manne. A Scalable Parallel Graph Coloring
+ Algorithm for Distributed Memory Computers. [preprint]

Added: trunk/libs/graph_parallel/doc/breadth_first_search.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/breadth_first_search.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,278 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===========================
+|Logo| Breadth-First Search
+===========================
+
+::
+
+ // named parameter version
+ template <class Graph, class P, class T, class R>
+ void breadth_first_search(Graph& G,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ const bgl_named_params<P, T, R>& params);
+
+ // non-named parameter version
+ template <class Graph, class Buffer, class BFSVisitor,
+ class ColorMap>
+ void breadth_first_search(const Graph& g,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ Buffer& Q, BFSVisitor vis, ColorMap color);
+
+The ``breadth_first_search()`` function performs a distributed breadth-first
+traversal of a directed or undirected graph. The distributed BFS is
+syntactically equivalent to its `sequential counterpart`_, which
+provides additional background and discussion. Differences in
+semantics are highlighted here, and we refer the reader to the
+documentation of the `sequential breadth-first search`_ for the
+remainder of the details.
+
+This distributed breadth-first search algorithm implements a
+*level-synchronized* breadth-first search, meaning that all vertices
+in a given level of the BFS tree will be processed (potentially in
+parallel) before any vertices from a successive level in the tree are
+processed. Distributed breadth-first search visitors should account
+for this behavior, a topic discussed further in `Visitor Event
+Points`_.
+
+.. contents::
+
+Where Defined
+-------------
+<``boost/graph/breadth_first_search.hpp``>
+
+Parameter Defaults
+------------------
+All parameters of the `sequential breadth-first search`_ are supported
+and have essentially the same meaning. Only differences are documented
+here.
+
+IN: ``Graph& g``
+ The graph type must be a model of `Distributed Graph`_.
+
+
+IN: ``vertex_descriptor s``
+ The start vertex must be the same in every process.
+
+
+IN: ``visitor(BFSVisitor vis)``
+ The visitor must be a distributed BFS visitor. The suble differences
+ between sequential and distributed BFS visitors are discussed in the
+ section `Visitor Event Points`_.
+
+UTIL/OUT: ``color_map(ColorMap color)``
+ The color map must be a `Distributed Property Map`_ with the same
+ process group as the graph ``g`` whose colors must monotonically
+ darken (white -> gray -> black). The default value is a distributed
+ ``iterator_property_map`` created from a ``std::vector`` of
+ ``default_color_type``.
+
+
+UTIL: ``buffer(Buffer& Q)``
+ The queue must be a distributed queue that passes vertices to their
+ owning process. If already-visited vertices should not be visited
+ again (as is typical for BFS), the queue must filter duplicates
+ itself. The queue controls synchronization within the algorithm: its
+ ``empty()`` method must not return ``true`` until all local queues
+ are empty.
+
+ **Default:** A ``distributed_queue`` of a ``filtered_queue`` over a
+ standard ``boost::queue``. This queue filters out duplicate
+ vertices and distributes vertices appropriately.
+
+Complexity
+----------
+This algorithm performs *O(V + E)* work in *d + 1* BSP supersteps,
+where *d* is the diameter of the connected component being
+searched. Over all supersteps, *O(E)* messages of constant size will
+be transmitted.
+
+Visitor Event Points
+--------------------
+The `BFS Visitor`_ concept defines 9 event points that will be
+triggered by the `sequential breadth-first search`_. The distributed
+BFS retains these nine event points, but the sequence of events
+triggered and the process in which each event occurs will change
+depending on the distribution of the graph.
+
+``initialize_vertex(s, g)``
+ This will be invoked by every process for each local vertex.
+
+
+``discover_vertex(u, g)``
+ This will be invoked each time a process discovers a new vertex
+ ``u``. Due to incomplete information in distributed property maps,
+ this event may be triggered many times for the same vertex ``u``.
+
+
+``examine_vertex(u, g)``
+ This will be invoked by the process owning the vertex ``u``. If the
+ distributed queue prevents duplicates, it will be invoked only
+ once for a particular vertex ``u``.
+
+
+``examine_edge(e, g)``
+ This will be invoked by the process owning the source vertex of
+ ``e``. If the distributed queue prevents duplicates, it will be
+ invoked only once for a particular edge ``e``.
+
+
+``tree_edge(e, g)``
+ Similar to ``examine_edge``, this will be invoked by the process
+ owning the source vertex and may be invoked only once. Unlike the
+ sequential BFS, this event may be triggered even when the target has
+ already been discovered (but by a different process). Thus, some
+ ``non_tree_edge`` events in a sequential BFS may become
+ ``tree_edge`` in a distributed BFS.
+
+
+``non_tree_edge(e, g)``
+ Some ``non_tree_edge`` events in a sequential BFS may become
+ ``tree_edge`` events in a distributed BFS. See the description of
+ ``tree_edge`` for additional details.
+
+
+``gray_target(e, g)``
+ As with ``tree_edge`` not knowing when another process has already
+ discovered a vertex, ``gray_target`` events may occur in a
+ distributed BFS when ``black_target`` events may occur in a
+ sequential BFS, due to a lack of information on a given
+ processor. The source of edge ``e`` will be local to the process
+ executing this event.
+
+
+``black_target(e, g)``
+ See documentation for ``gray_target``
+
+
+``finish_vertex(e, g)``
+ See documentation for ``examine_vertex``.
+
+Making Visitors Safe for Distributed BFS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The three most important things to remember when updating an existing
+BFS visitor for distributed BFS or writing a new distributed BFS
+visitor are:
+
+1. Be sure that all state is either entirely local or in a
+ distributed data structure (most likely a property map!) using
+ the same process group as the graph.
+
+2. Be sure that the visitor doesn't require precise event sequences
+ that cannot be guaranteed by distributed BFS, e.g., requiring
+ ``tree_edge`` and ``non_tree_edge`` events to be completely
+ distinct.
+
+3. Be sure that the visitor can operate on incomplete
+ information. This often includes using an appropriate reduction
+ operation in a `distributed property map`_ and verifying that
+ results written are "better" that what was previously written.
+
+Distributed BFS Visitor Example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+To illustrate the differences between sequential and distributed BFS
+visitors, we consider a BFS visitor that places the distance from the
+source vertex to every other vertex in a property map. The sequential
+visitor is very simple::
+
+ template<typename DistanceMap>
+ struct bfs_discovery_visitor : bfs_visitor<>
+ {
+ bfs_discovery_visitor(DistanceMap distance) : distance(distance) {}
+
+ template<typename Edge, typename Graph>
+ void tree_edge(Edge e, const Graph& g)
+ {
+ std::size_t new_distance = get(distance, source(e, g)) + 1;
+ put(distance, target(e, g), new_distance);
+ }
+
+ private:
+ DistanceMap distance;
+ };
+
+To revisit this code for distributed BFS, we consider the three points
+in the section `Making Visitors Safe for Distributed BFS`_:
+
+1. The distance map will need to become distributed, because the
+ distance to each vertex should be stored in the process owning the
+ vertex. This is actually a requirement on the user to provide such
+ a distributed property map, although in many cases the property map
+ will automatically be distributed and no syntactic changes will be
+ required.
+
+2. This visitor *does* require a precise sequence of events that may
+ change with a distributed BFS. The extraneous ``tree_edge`` events
+ that may occur could result in attempts to put distances into the
+ distance map multiple times for a single vertex. We therefore need
+ to consider bullet #3.
+
+3. Since multiple distance values may be written for each vertex, we
+ must always choose the best value we can find to update the
+ distance map. The distributed property map ``distance`` needs to
+ resolve distances to the smallest distance it has seen. For
+ instance, process 0 may find vertex ``u`` at level 3 but process 1
+ finds it at level 5: the distance must remain at 3. To do this, we
+ state that the property map's *role* is as a distance map, which
+ introduces an appropriate reduction operation::
+
+ set_property_map_role(vertex_distance, distance);
+
+The resulting distributed BFS visitor (which also applies, with no
+changes, in the sequential BFS) is very similar to our original
+sequential BFS visitor. Note the single-line difference in the
+constructor::
+
+ template<typename DistanceMap>
+ struct bfs_discovery_visitor : bfs_visitor<>
+ {
+ bfs_discovery_visitor(DistanceMap distance) : distance(distance)
+ {
+ set_property_map_role(vertex_distance, distance);
+ }
+
+ template<typename Edge, typename Graph>
+ void tree_edge(Edge e, const Graph& g)
+ {
+ std::size_t new_distance = get(distance, source(e, g)) + 1;
+ put(distance, target(e, g), new_distance);
+ }
+
+ private:
+ DistanceMap distance;
+ };
+
+
+Performance
+-----------
+The performance of Breadth-First Search is illustrated by the
+following charts. Scaling and performance is reasonable for all of the
+graphs we have tried.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=4
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=4&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=4
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=4&speedup=1
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _sequential counterpart: http://www.boost.org/libs/graph/doc/breadth_first_search.html
+.. _sequential breadth-first search: http://www.boost.org/libs/graph/doc/breadth_first_search.html
+.. _Distributed Graph: DistributedGraph.html
+.. _Distributed Property Map: distributed_property_map.html
+.. _BFS Visitor: http://www.boost.org/libs/graph/doc/BFSVisitor.html

Added: trunk/libs/graph_parallel/doc/connected_components.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/connected_components.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,147 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===========================
+|Logo| Connected Components
+===========================
+
+::
+
+ namespace graph {
+ // Default constructed ParentMap
+ template<typename Graph, typename ComponentMap, typename ParentMap>
+ typename property_traits<ComponentMap>::value_type
+ connected_components( const Graph& g, ComponentMap c);
+
+ // User supplied ParentMap
+ template<typename Graph, typename ComponentMap, typename ParentMap>
+ typename property_traits<ComponentMap>::value_type
+ connected_components( const Graph& g, ComponentMap c, ParentMap p);
+ }
+
+The ``connected_components()`` function computes the connected
+components of an undirected graph. The distributed connected
+components algorithm uses the sequential version of the connected
+components algorithm to compute the connected components of the local
+subgraph, then executes the parallel phase of the algorithm. The
+parallel portion of the connected components algorithm is loosely
+based on the work of Goddard, Kumar, and Prins. The interface is a
+superset of the interface to the BGL `sequential connected
+components`_ algorithm.
+
+Prior to executing the sequential phase of the algorithm, each process
+identifies the roots of its local components. An adjacency list of
+all vertices adjacent to members of the component is then constructed
+at the root vertex of each component.
+
+The parallel phase of the distributed connected components algorithm
+consists of a series of supersteps. In each superstep, each root
+attempts to hook to a member of it's adjacency list by assigning it's
+parent pointer to that vertex. Hooking is restricted to vertices
+which are logically less than the current vertex to prevent looping.
+Vertices which hook successfully are removed from the list of roots
+and placed on another list of completed vertices. All completed
+vertices now execute a pointer jumping step until every completed
+vertex has as its parent the root of a component. This pointer
+jumping step may be further optimized by the addition of Cycle
+Reduction (CR) rules developed by Johnson and Metaxas, however current
+performance evaluations indicate that this would have a negligible
+impact on the overall performance of the algorithm. These CR rules
+reduce the number of pointer jumping steps from *O(n)* to *O(log n)*.
+Following this pointer jumping step, roots which have hooked in this
+phase transmit their adjacency list to their new parent. The
+remaining roots receive these edges and execute a pruning step on
+their adjacency lists to remove vertices that are now members of their
+component. The parallel phase of the algorithm is complete when no
+root successfully hooks. Once the parallel phase is complete a final
+pointer jumping step is performed on all vertices to assign the parent
+pointers of the leaves of the initial local subgraph components to
+their final parent which has now been determined.
+
+The single largest performance bottleneck in the distributed connected
+components algorithm is the effect of poor vertex distribution on the
+algorithm. For sparse graphs with a single large component, many
+roots may hook to the same component, resulting in severe load
+imbalance at the process owning this component. Several methods of
+modifying the hooking strategy to avoid this behavior have been
+implemented but none has been successful as of yet.
+
+.. contents::
+
+Where Defined
+-------------
+<``boost/graph/connected_components.hpp``>
+
+Parameters
+----------
+
+IN: ``Graph& g``
+ The graph typed must be a model of `Distributed Graph`_.
+
+IN: ``ComponentMap c``
+ The algorithm computes how many connected components are in the
+ graph, and assigns each component an integer label. The algorithm
+ then records to which component each vertex in the graph belongs by
+ recording the component number in the component property map. The
+ ``ComponentMap`` type must be a `Distributed Property Map`_. The
+ value type must be the ``vertices_size_type`` of the graph. The key
+ type must be the graph's vertex descriptor type. If you do not wish
+ to compute component numbers, pass ``dummy_property_map`` as the
+ component map and parent information will be provided in the parent
+ map.
+
+IN: ``ParentMap p``
+ A parent map may be supplied to the algorithm, if not supplied the
+ parent map will be constructed automatically. The ``ParentMap`` type
+ must be a `Distributed Property Map`_. The value type and key type
+ must be the graph's vertex descriptor type.
+
+OUT: ``property_traits<ComponentMap>::value_type``
+ The number of components found will be returned as the value type of
+ the component map.
+
+Complexity
+----------
+
+The local phase of the algorithm is *O(V + E)*. The parallel phase of
+the algorithm requires at most *O(d)* supersteps where *d* is the
+number of initial roots. *d* is at most *O(V)* but becomes
+significantly smaller as *E* increases. The pointer jumping phase
+within each superstep requires at most *O(c)* steps on each of the
+completed roots where *c* is the length of the longest cycle.
+Application of CR rules can reduce this to *O(log c)*.
+
+Performance
+-----------
+The following charts illustrate the performance of the Parallel BGL
+connected components algorithm. It performs well on very sparse and
+very dense graphs. However, for cases where the graph has a medium
+density with a giant connected component, the algorithm will perform
+poorly. This is a known problem with the algorithm and as far as we
+know all implemented algorithms have this degenerate behavior.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=9
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=9&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=9
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=9&speedup=1
+
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004 The Trustees of Indiana University.
+
+Authors: Nick Edmonds, Douglas Gregor, and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Sequential connected components: http://www.boost.org/libs/graph/doc/connected_components.html
+.. _Distributed Graph: DistributedGraph.html
+.. _Distributed Property Map: distributed_property_map.html

Added: trunk/libs/graph_parallel/doc/connected_components_parallel_search.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/connected_components_parallel_search.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,19 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===========================================
+|Logo| Connected Components Parallel Search
+===========================================
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl

Added: trunk/libs/graph_parallel/doc/dehne_gotz_min_spanning_tree.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/dehne_gotz_min_spanning_tree.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,423 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+============================
+|Logo| Minimum Spanning Tree
+============================
+
+The Parallel BGL contains four `minimum spanning tree`_ (MST)
+algorithms [DG98]_ for use on undirected, weighted, distributed
+graphs. The graphs need not be connected: each algorithm will compute
+a minimum spanning forest (MSF) when provided with a disconnected
+graph.
+
+The interface to each of the four algorithms is similar to the
+implementation of 'Kruskal's algorithm'_ in the sequential BGL. Each
+accepts, at a minimum, a graph, a weight map, and an output
+iterator. The edges of the MST (or MSF) will be output via the output
+iterator on process 0: other processes may receive edges on their
+output iterators, but the set may not be complete, depending on the
+algorithm. The algorithm parameters are documented together, because
+they do not vary greatly. See the section `Selecting an MST
+algorithm`_ for advice on algorithm selection.
+
+The graph itself must model the `Vertex List Graph`_ concept and the
+Distributed Edge List Graph concept. Since the most common
+distributed graph structure, the `distributed adjacency list`_, only
+models the Distributed Vertex List Graph concept, it may only be used
+with these algorithms when wrapped in a suitable adaptor, such as the
+`vertex_list_adaptor`_.
+
+.. contents::
+
+Where Defined
+-------------
+<``boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp``>
+
+Parameters
+----------
+
+IN: ``Graph& g``
+ The graph type must be a model of `Vertex List Graph`_ and
+ `Distributed Edge List Graph`_.
+
+
+
+IN/OUT: ``WeightMap weight``
+ The weight map must be a `Distributed Property Map`_ and a `Readable
+ Property Map`_ whose key type is the edge descriptor of the graph
+ and whose value type is numerical.
+
+
+
+IN/OUT: ``OutputIterator out``
+ The output iterator through which the edges of the MSF will be
+ written. Must be capable of accepting edge descriptors for output.
+
+
+
+
+IN: ``VertexIndexMap index``
+ A mapping from vertex descriptors to indices in the range *[0,
+ num_vertices(g))*. This must be a `Readable Property Map`_ whose
+ key type is a vertex descriptor and whose value type is an integral
+ type, typically the ``vertices_size_type`` of the graph.
+
+ **Default:** ``get(vertex_index, g)``
+
+
+IN/UTIL: ``RankMap rank_map``
+ Stores the rank of each vertex, which is used for maintaining
+ union-find data structures. This must be a `Read/Write Property Map`_
+ whose key type is a vertex descriptor and whose value type is an
+ integral type.
+
+ **Default:** An ``iterator_property_map`` built from an STL vector
+ of the ``vertices_size_type`` of the graph and the vertex index map.
+
+
+IN/UTIL: ``ParentMap parent_map``
+ Stores the parent (representative) of each vertex, which is used for
+ maintaining union-find data structures. This must be a `Read/Write
+ Property Map`_ whose key type is a vertex descriptor and whose value
+ type is also a vertex descriptor.
+
+ **Default:** An ``iterator_property_map`` built from an STL vector
+ of the ``vertex_descriptor`` of the graph and the vertex index map.
+
+
+IN/UTIL: ``SupervertexMap supervertex_map``
+ Stores the supervertex index of each vertex, which is used for
+ maintaining the supervertex list data structures. This must be a
+ `Read/Write Property Map`_ whose key type is a vertex descriptor and
+ whose value type is an integral type.
+
+ **Default:** An ``iterator_property_map`` built from an STL vector
+ of the ``vertices_size_type`` of the graph and the vertex index map.
+
+
+
+``dense_boruvka_minimum_spanning_tree``
+---------------------------------------
+
+::
+
+ namespace graph {
+ template<typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap, typename RankMap, typename ParentMap,
+ typename SupervertexMap>
+ OutputIterator
+ dense_boruvka_minimum_spanning_tree(const Graph& g, WeightMap weight_map,
+ OutputIterator out,
+ VertexIndexMap index,
+ RankMap rank_map, ParentMap parent_map,
+ SupervertexMap supervertex_map);
+
+ template<typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndex>
+ OutputIterator
+ dense_boruvka_minimum_spanning_tree(const Graph& g, WeightMap weight_map,
+ OutputIterator out, VertexIndex index);
+
+ template<typename Graph, typename WeightMap, typename OutputIterator>
+ OutputIterator
+ dense_boruvka_minimum_spanning_tree(const Graph& g, WeightMap weight_map,
+ OutputIterator out);
+ }
+
+Description
+~~~~~~~~~~~
+
+The dense Boruvka distributed minimum spanning tree algorithm is a
+direct parallelization of the sequential MST algorithm by
+Boruvka. The algorithm first creates a *supervertex* out of each
+vertex. Then, in each iteration, it finds the smallest-weight edge
+incident to each vertex, collapses supervertices along these edges,
+and removals all self loops. The only difference between the
+sequential and parallel algorithms is that the parallel algorithm
+performs an all-reduce operation so that all processes have the
+global minimum set of edges.
+
+Unlike the other three algorithms, this algorithm emits the complete
+list of edges in the minimum spanning forest via the output iterator
+on all processes. It may therefore be more useful than the others
+when parallelizing sequential BGL programs.
+
+Complexity
+~~~~~~~~~~
+
+The distributed algorithm requires *O(log n)* BSP supersteps, each of
+which requires *O(m/p + n)* time and *O(n)* communication per
+process.
+
+Performance
+~~~~~~~~~~~
+
+The following charts illustrate the performance of this algorithm on
+various random graphs. We see that the algorithm scales well up to 64
+or 128 processors, depending on the type of graph, for dense
+graphs. However, for sparse graphs performance tapers off as the
+number of processors surpases *m/n*, i.e., the average degree (which
+is 30 for this graph). This behavior is expected from the algorithm.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=5
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=5&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=5
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=5&speedup=1
+
+``merge_local_minimum_spanning_trees``
+--------------------------------------
+
+::
+
+ namespace graph {
+ template<typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap>
+ OutputIterator
+ merge_local_minimum_spanning_trees(const Graph& g, WeightMap weight,
+ OutputIterator out,
+ VertexIndexMap index);
+
+ template<typename Graph, typename WeightMap, typename OutputIterator>
+ inline OutputIterator
+ merge_local_minimum_spanning_trees(const Graph& g, WeightMap weight,
+ OutputIterator out);
+ }
+
+Description
+~~~~~~~~~~~
+
+The merging local MSTs algorithm operates by computing minimum
+spanning forests from the edges stored on each process. Then the
+processes merge their edge lists along a tree. The child nodes cease
+participating in the computation, but the parent nodes recompute MSFs
+from the newly acquired edges. In the final round, the root of the
+tree computes the global MSFs, having received candidate edges from
+every other process via the tree.
+
+Complexity
+~~~~~~~~~~
+
+This algorithm requires *O(log_D p)* BSP supersteps (where *D* is the
+number of children in the tree, and is currently fixed at 3). Each
+superstep requires *O((m/p) log (m/p) + n)* time and *O(m/p)*
+communication per process.
+
+Performance
+~~~~~~~~~~~
+
+The following charts illustrate the performance of this algorithm on
+various random graphs. The algorithm only scales well for very dense
+graphs, where most of the work is performed in the initial stage and
+there is very little work in the later stages.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=6
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=6&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=6
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=6&speedup=1
+
+
+``boruvka_then_merge``
+----------------------
+
+::
+
+ namespace graph {
+ template<typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap, typename RankMap, typename ParentMap,
+ typename SupervertexMap>
+ OutputIterator
+ boruvka_then_merge(const Graph& g, WeightMap weight, OutputIterator out,
+ VertexIndexMap index, RankMap rank_map,
+ ParentMap parent_map, SupervertexMap
+ supervertex_map);
+
+ template<typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap>
+ inline OutputIterator
+ boruvka_then_merge(const Graph& g, WeightMap weight, OutputIterator out,
+ VertexIndexMap index);
+
+ template<typename Graph, typename WeightMap, typename OutputIterator>
+ inline OutputIterator
+ boruvka_then_merge(const Graph& g, WeightMap weight, OutputIterator out);
+ }
+
+Description
+~~~~~~~~~~~
+
+This algorithm applies both Boruvka steps and local MSF merging steps
+together to achieve better asymptotic performance than either
+algorithm alone. It first executes Boruvka steps until only *n/(log_d
+p)^2* supervertices remain, then completes the MSF computation by
+performing local MSF merging on the remaining edges and
+supervertices.
+
+Complexity
+~~~~~~~~~~
+
+This algorithm requires *log_D p* + *log log_D p* BSP supersteps. The
+time required by each superstep depends on the type of superstep
+being performed; see the distributed Boruvka or merging local MSFS
+algorithms for details.
+
+Performance
+~~~~~~~~~~~
+
+The following charts illustrate the performance of this algorithm on
+various random graphs. We see that the algorithm scales well up to 64
+or 128 processors, depending on the type of graph, for dense
+graphs. However, for sparse graphs performance tapers off as the
+number of processors surpases *m/n*, i.e., the average degree (which
+is 30 for this graph). This behavior is expected from the algorithm.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=7
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=7&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=7
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=7&speedup=1
+
+``boruvka_mixed_merge``
+-----------------------
+
+::
+
+ namespace {
+ template<typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap, typename RankMap, typename ParentMap,
+ typename SupervertexMap>
+ OutputIterator
+ boruvka_mixed_merge(const Graph& g, WeightMap weight, OutputIterator out,
+ VertexIndexMap index, RankMap rank_map,
+ ParentMap parent_map, SupervertexMap
+ supervertex_map);
+
+ template<typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap>
+ inline OutputIterator
+ boruvka_mixed_merge(const Graph& g, WeightMap weight, OutputIterator out,
+ VertexIndexMap index);
+
+ template<typename Graph, typename WeightMap, typename OutputIterator>
+ inline OutputIterator
+ boruvka_mixed_merge(const Graph& g, WeightMap weight, OutputIterator out);
+ }
+
+Description
+~~~~~~~~~~~
+
+This algorithm applies both Boruvka steps and local MSF merging steps
+together to achieve better asymptotic performance than either method
+alone. In each iteration, the algorithm first performs a Boruvka step
+and then merges the local MSFs computed based on the supervertex
+graph.
+
+Complexity
+~~~~~~~~~~
+
+This algorithm requires *log_D p* BSP supersteps. The
+time required by each superstep depends on the type of superstep
+being performed; see the distributed Boruvka or merging local MSFS
+algorithms for details. However, the algorithm is
+communication-optional (requiring *O(n)* communication overall) when
+the graph is sufficiently dense, i.e., *m/n >= p*.
+
+Performance
+~~~~~~~~~~~
+
+The following charts illustrate the performance of this algorithm on
+various random graphs. We see that the algorithm scales well up to 64
+or 128 processors, depending on the type of graph, for dense
+graphs. However, for sparse graphs performance tapers off as the
+number of processors surpases *m/n*, i.e., the average degree (which
+is 30 for this graph). This behavior is expected from the algorithm.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=8
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeSparse&columns=8&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=8
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&dataset=TimeDense&columns=8&speedup=1
+
+
+Selecting an MST algorithm
+--------------------------
+
+Dehne and Gotz reported [DG98]_ mixed results when evaluating these
+four algorithms. No particular algorithm was clearly better than the
+others in all cases. However, the asymptotically best algorithm
+(``boruvka_mixed_merge``) seemed to perform more poorly in their tests
+than the other merging-based algorithms. The following performance
+charts illustrate the performance of these four minimum spanning tree
+implementations.
+
+Overall, ``dense_boruvka_minimum_spanning_tree`` gives the most
+consistent performance and scalability for the graphs we
+tested. Additionally, it may be more suitable for sequential programs
+that are being parallelized, because it emits complete MSF edge lists
+via the output iterators in every process.
+
+Performance on Sparse Graphs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&dataset=TimeSparse&columns=5,6,7,8
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&dataset=TimeSparse&columns=5,6,7,8&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&dataset=TimeSparse&columns=5,6,7,8
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&dataset=TimeSparse&columns=5,6,7,8&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&dataset=TimeSparse&columns=5,6,7,8
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&dataset=TimeSparse&columns=5,6,7,8&speedup=1
+
+Performance on Dense Graphs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&dataset=TimeDense&columns=5,6,7,8
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&dataset=TimeDense&columns=5,6,7,8&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&dataset=TimeDense&columns=5,6,7,8
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&dataset=TimeDense&columns=5,6,7,8&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&dataset=TimeDense&columns=5,6,7,8
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&dataset=TimeDense&columns=5,6,7,8&speedup=1
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _minimum spanning tree: http://www.boost.org/libs/graph/doc/graph_theory_review.html#sec:minimum-spanning-tree
+.. _Kruskal's algorithm: http://www.boost.org/libs/graph/doc/kruskal_min_spanning_tree.html
+.. _Vertex list graph: http://www.boost.org/libs/graph/doc/VertexListGraph.html
+.. _distributed adjacency list: distributed_adjacency_list.html
+.. _vertex_list_adaptor: vertex_list_adaptor.html
+.. _Distributed Edge List Graph: DistributedEdgeListGraph.html
+.. _Distributed property map: distributed_property_map.html
+.. _Readable Property Map: http://www.boost.org/libs/property_map/ReadablePropertyMap.html
+.. _Read/Write Property Map: http://www.boost.org/libs/property_map/ReadWritePropertyMap.html
+
+.. [DG98] Frank Dehne and Silvia Gotz. *Practical Parallel Algorithms
+ for Minimum Spanning Trees*. In Symposium on Reliable Distributed Systems,
+ pages 366--371, 1998.
+

Added: trunk/libs/graph_parallel/doc/dijkstra_dist3_graph.graffle
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/dijkstra_dist3_graph.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/dijkstra_example.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/dijkstra_example.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,164 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+=======================
+Parallel Shortest Paths
+=======================
+To illustrate the use of the Parallel Boost Graph Library, we
+illustrate the use of both the sequential and parallel BGL to find
+the shortest paths from vertex A to every other vertex in the
+following simple graph:
+
+.. image:: dijkstra_seq_graph.png
+
+With the sequential BGL_, the program to calculate shortest paths has
+three stages. Readers familiar with the BGL may wish to skip ahead to
+the section `Distributing the graph`_.
+
+
+ - `Define the graph type`_
+ - `Construct the graph`_
+ - `Invoke Dijkstra's algorithm`_
+
+Define the graph type
+~~~~~~~~~~~~~~~~~~~~~
+
+For this problem we use an adjacency list representation of the graph,
+using the BGL ``adjacency_list``_ class template. It will be a directed
+graph (``directedS`` parameter ) whose vertices are stored in an
+``std::vector`` (``vecS`` parameter) where the outgoing edges of each
+vertex are stored in an ``std::list`` (``listS`` parameter). To each
+of the edges we attach an integral weight.
+
+::
+
+ typedef adjacency_list<listS, vecS, directedS,
+ no_property, // Vertex properties
+ property<edge_weight_t, int> // Edge properties
+ > graph_t;
+ typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
+ typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
+
+Construct the graph
+~~~~~~~~~~~~~~~~~~~
+To build the graph, we declare an enumeration containing the node
+names (for our own use) and create two arrays: the first,
+``edge_array``, contains the source and target of each edge, whereas
+the second, ``weights``, contains the integral weight of each
+edge. We pass the contents of the arrays via pointers (used here as
+iterators) to the graph constructor to build our graph:
+
+::
+
+ typedef std::pair<int, int> Edge;
+ const int num_nodes = 5;
+ enum nodes { A, B, C, D, E };
+ char name[] = "ABCDE";
+ Edge edge_array[] = { Edge(A, C), Edge(B, B), Edge(B, D), Edge(B, E),
+ Edge(C, B), Edge(C, D), Edge(D, E), Edge(E, A), Edge(E, B)
+ };
+ int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1 };
+ int num_arcs = sizeof(edge_array) / sizeof(Edge);
+
+ graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes);
+
+
+Invoke Dijkstra's algorithm
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+To invoke Dijkstra's algorithm, we need to first decide how we want
+to receive the results of the algorithm, namely the distance to each
+vertex and the predecessor of each vertex (allowing reconstruction of
+the shortest paths themselves). In our case, we will create two
+vectors, ``p`` for predecessors and ``d`` for distances.
+
+Next, we determine our starting vertex ``s`` using the ``vertex``
+operation on the ``adjacency_list``_ and call
+``dijkstra_shortest_paths``_ with the graph ``g``, starting vertex
+``s``, and two ``property maps``_ that instruct the algorithm to
+store predecessors in the ``p`` vector and distances in the ``d``
+vector. The algorithm automatically uses the edge weights stored
+within the graph, although this capability can be overridden.
+
+::
+
+ // Keeps track of the predecessor of each vertex
+ std::vector<vertex_descriptor> p(num_vertices(g));
+ // Keeps track of the distance to each vertex
+ std::vector<int> d(num_vertices(g));
+
+ vertex_descriptor s = vertex(A, g);
+ dijkstra_shortest_paths
+ (g, s,
+ predecessor_map(
+ make_iterator_property_map(p.begin(), get(vertex_index, g))).
+ distance_map(
+ make_iterator_property_map(d.begin(), get(vertex_index, g)))
+ );
+
+Distributing the graph
+~~~~~~~~~~~~~~~~~~~~~~
+The prior computation is entirely sequential, with the graph stored
+within a single address space. To distribute the graph across several
+processors without a shared address space, we need to represent the
+processors and communication among them and alter the graph type.
+
+Processors and their interactions are abstracted via a *process
+group*. In our case, we will use MPI_ for communication with
+inter-processor messages sent immediately:
+
+::
+
+ typedef mpi::process_group<mpi::immediateS> process_group_type;
+
+Next, we instruct the ``adjacency_list`` template
+to distribute the vertices of the graph across our process group,
+storing the local vertices in an ``std::vector``::
+
+ typedef adjacency_list<listS,
+ distributedS<process_group_type, vecS>,
+ directedS,
+ no_property, // Vertex properties
+ property<edge_weight_t, int> // Edge properties
+ > graph_t;
+ typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
+ typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
+
+Note that the only difference from the sequential BGL is the use of
+the ``distributedS`` selector, which identifies a distributed
+graph. The vertices of the graph will be distributed among the
+various processors, and the processor that owns a vertex also stores
+the edges outgoing from that vertex and any properties associated
+with that vertex or its edges. With three processors and the default
+block distribution, the graph would be distributed in this manner:
+
+.. image:: dijkstra_dist3_graph.png
+
+Processor 0 (red) owns vertices A and B, including all edges outoing
+from those vertices, processor 1 (green) owns vertices C and D (and
+their edges), and processor 2 (blue) owns vertex E. Constructing this
+graph uses the same syntax is the sequential graph, as in the section
+`Construct the graph`_.
+
+The call to ``dijkstra_shortest_paths`` is syntactically equivalent to
+the sequential call, but the mechanisms used are very different. The
+property maps passed to ``dijkstra_shortest_paths`` are actually
+*distributed* property maps, which store properties for local edges
+or vertices and perform implicit communication to access properties
+of remote edges or vertices when needed. The formulation of Dijkstra's
+algorithm is also slightly different, because each processor can
+only attempt to relax edges outgoing from local vertices: as shorter
+paths to a vertex are discovered, messages to the processor owning
+that vertex indicate that the vertex may require reprocessing.
+
+----------------------------------------------------------------------
+
+Return to the `Parallel BGL home page`_
+
+.. _Parallel BGL home page: index.html
+.. _dijkstra_shortest_paths: http://www.boost.org/libs/graph/doc/dijkstra_shortest_paths.html
+.. _property maps: http://www.boost.org/libs/graph/doc/using_property_maps.html
+.. _adjacency_list: http://www.boost.org/libs/graph/doc/adjacency_list.html
+.. _MPI: http://www-unix.mcs.anl.gov/mpi/
+.. _BGL: http://www.boost.org/libs/graph/doc

Added: trunk/libs/graph_parallel/doc/dijkstra_seq_graph.graffle
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/dijkstra_seq_graph.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/dijkstra_shortest_paths.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/dijkstra_shortest_paths.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,408 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+==============================================
+|Logo| Dijkstra's Single-Source Shortest Paths
+==============================================
+
+::
+
+ // named parameter version
+ template <typename Graph, typename P, typename T, typename R>
+ void
+ dijkstra_shortest_paths(Graph& g,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ const bgl_named_params<P, T, R>& params);
+
+ // non-named parameter version
+ template <typename Graph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap,
+ typename WeightMap, typename VertexIndexMap, typename CompareFunction, typename CombineFunction,
+ typename DistInf, typename DistZero>
+ void dijkstra_shortest_paths
+ (const Graph& g,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
+ VertexIndexMap index_map,
+ CompareFunction compare, CombineFunction combine, DistInf inf, DistZero zero,
+ DijkstraVisitor vis);
+
+The ``dijkstra_shortest_paths()`` function solves the single-source
+shortest paths problem on a weighted, undirected or directed
+distributed graph. There are two implementations of distributed
+Dijkstra's algorithm, which offer different performance
+tradeoffs. Both are accessible via the ``dijkstra_shortest_paths()``
+function (for compatibility with sequential BGL programs). The
+distributed Dijkstra algorithms are very similar to their sequential
+counterparts. Only the differences are highlighted here; please refer
+to the `sequential Dijkstra implementation`_ for additional
+details. The best-performing implementation for most cases is the
+`Delta-Stepping algorithm`_; however, one can also employ the more
+conservative `Crauser et al.'s algorithm`_ or the simlistic `Eager
+Dijkstra's algorithm`_.
+
+.. contents::
+
+Where Defined
+-------------
+<``boost/graph/dijkstra_shortest_paths.hpp``>
+
+Parameters
+----------
+
+All parameters of the `sequential Dijkstra implementation`_ are
+supported and have essentially the same meaning. The distributed
+Dijkstra implementations introduce a new parameter that allows one to
+select `Eager Dijkstra's algorithm`_ and control the amount of work it
+performs. Only differences and new parameters are documented here.
+
+IN: ``Graph& g``
+ The graph type must be a model of `Distributed Graph`_.
+
+
+IN: ``vertex_descriptor s``
+ The start vertex must be the same in every process.
+
+
+OUT: ``predecessor_map(PredecessorMap p_map)``
+ The predecessor map must be a `Distributed Property Map`_ or
+ ``dummy_property_map``, although only the local portions of the map
+ will be written.
+
+ **Default:** ``dummy_property_map``
+
+
+UTIL/OUT: ``distance_map(DistanceMap d_map)``
+ The distance map must be either a `Distributed Property Map`_ or
+ ``dummy_property_map``. It will be given the ``vertex_distance``
+ role.
+
+
+IN: ``visitor(DijkstraVisitor vis)``
+ The visitor must be a distributed Dijkstra visitor. The suble differences
+ between sequential and distributed Dijkstra visitors are discussed in the
+ section `Visitor Event Points`_.
+
+
+UTIL/OUT: ``color_map(ColorMap color)``
+ The color map must be a `Distributed Property Map`_ with the same
+ process group as the graph ``g`` whose colors must monotonically
+ darken (white -> gray -> black). The default value is a distributed
+ ``iterator_property_map`` created from a ``std::vector`` of
+ ``default_color_type``.
+
+
+IN: ``lookahead(distance_type look)``
+
+ When this parameter is supplied, the implementation will use the
+ `Eager Dijkstra's algorithm`_ with the given lookahead value.
+ Lookahead permits distributed Dijkstra's algorithm to speculatively
+ process vertices whose shortest distance from the source may not
+ have been found yet. When the distance found is the shortest
+ distance, parallelism is improved and the algorithm may terminate
+ more quickly. However, if the distance is not the shortest distance,
+ the vertex will need to be reprocessed later, resulting in more
+ work.
+
+ The type ``distance_type`` is the value type of the ``DistanceMap``
+ property map. It is a nonnegative value specifying how far ahead
+ Dijkstra's algorithm may process values.
+
+ **Default:** no value (lookahead is not employed; uses `Crauser et
+ al.'s algorithm`_).
+
+Visitor Event Points
+--------------------
+The `Dijkstra Visitor`_ concept defines 7 event points that will be
+triggered by the `sequential Dijkstra implementation`_. The distributed
+Dijkstra retains these event points, but the sequence of events
+triggered and the process in which each event occurs will change
+depending on the distribution of the graph, lookahead, and edge
+weights.
+
+``initialize_vertex(s, g)``
+ This will be invoked by every process for each local vertex.
+
+
+``discover_vertex(u, g)``
+ This will be invoked each type a process discovers a new vertex
+ ``u``. Due to incomplete information in distributed property maps,
+ this event may be triggered many times for the same vertex ``u``.
+
+
+``examine_vertex(u, g)``
+ This will be invoked by the process owning the vertex ``u``. This
+ event may be invoked multiple times for the same vertex when the
+ graph contains negative edges or lookahead is employed.
+
+
+``examine_edge(e, g)``
+ This will be invoked by the process owning the source vertex of
+ ``e``. As with ``examine_vertex``, this event may be invoked
+ multiple times for the same edge.
+
+
+``edge_relaxed(e, g)``
+ Similar to ``examine_edge``, this will be invoked by the process
+ owning the source vertex and may be invoked multiple times (even
+ without lookahead or negative edges).
+
+
+``edge_not_relaxed(e, g)``
+ Similar to ``edge_relaxed``. Some ``edge_not_relaxed`` events that
+ would be triggered by sequential Dijkstra's will become
+ ``edge_relaxed`` events in distributed Dijkstra's algorithm.
+
+
+``finish_vertex(e, g)``
+ See documentation for ``examine_vertex``. Note that a "finished"
+ vertex is not necessarily finished if lookahead is permitted or
+ negative edges exist in the graph.
+
+
+Crauser et al.'s algorithm
+--------------------------
+
+::
+
+ namespace graph {
+ template<typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap, typename WeightMap,
+ typename IndexMap, typename ColorMap, typename Compare,
+ typename Combine, typename DistInf, typename DistZero>
+ void
+ crauser_et_al_shortest_paths
+ (const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
+ IndexMap index_map, ColorMap color_map,
+ Compare compare, Combine combine, DistInf inf, DistZero zero,
+ DijkstraVisitor vis);
+
+ template<typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap, typename WeightMap>
+ void
+ crauser_et_al_shortest_paths
+ (const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight);
+
+ template<typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap>
+ void
+ crauser_et_al_shortest_paths
+ (const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance);
+ }
+
+The formulation of Dijkstra's algorithm by Crauser, Mehlhorn, Meyer,
+and Sanders [CMMS98a]_ improves the scalability of parallel Dijkstra's
+algorithm by increasing the number of vertices that can be processed
+in a given superstep. This algorithm adapts well to various graph
+types, and is a simple algorithm to use, requiring no additional user
+input to achieve reasonable performance. The disadvantage of this
+algorithm is that the implementation is required to manage three
+priority queues, which creates a large amount of work at each node.
+
+This algorithm is used by default in distributed
+``dijkstra_shortest_paths()``.
+
+Where Defined
+~~~~~~~~~~~~~
+<``boost/graph/distributed/crauser_et_al_shortest_paths.hpp``>
+
+Complexity
+~~~~~~~~~~
+This algorithm performs *O(V log V)* work in *d + 1* BSP supersteps,
+where *d* is at most *O(V)* but is generally much smaller. On directed
+Erdos-Renyi graphs with edge weights in [0, 1), the expected number of
+supersteps *d* is *O(n^(1/3))* with high probability.
+
+Performance
+~~~~~~~~~~~
+The following charts illustrate the performance of the Parallel BGL implementation of Crauser et al.'s
+algorithm on graphs with edge weights uniformly selected from the
+range *[0, 1)*.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&generator=ER,SF,SW&dataset=TimeSparse&columns=4
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&generator=ER,SF,SW&dataset=TimeSparse&columns=4&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&generator=ER,SF,SW&dataset=TimeDense&columns=4
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&generator=ER,SF,SW&dataset=TimeDense&columns=4&speedup=1
+
+
+Eager Dijkstra's algorithm
+--------------------------
+
+::
+
+ namespace graph {
+ template<typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap, typename WeightMap,
+ typename IndexMap, typename ColorMap, typename Compare,
+ typename Combine, typename DistInf, typename DistZero>
+ void
+ eager_dijkstra_shortest_paths
+ (const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance,
+ typename property_traits<DistanceMap>::value_type lookahead,
+ WeightMap weight, IndexMap index_map, ColorMap color_map,
+ Compare compare, Combine combine, DistInf inf, DistZero zero,
+ DijkstraVisitor vis);
+
+ template<typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap, typename WeightMap>
+ void
+ eager_dijkstra_shortest_paths
+ (const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance,
+ typename property_traits<DistanceMap>::value_type lookahead,
+ WeightMap weight);
+
+ template<typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap>
+ void
+ eager_dijkstra_shortest_paths
+ (const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance,
+ typename property_traits<DistanceMap>::value_type lookahead);
+ }
+
+In each superstep, parallel Dijkstra's algorithm typically only
+processes nodes whose distances equivalent to the global minimum
+distance, because these distances are guaranteed to be correct. This
+variation on the algorithm allows the algorithm to process all
+vertices whose distances are within some constant value of the
+minimum distance. The value is called the "lookahead" value and is
+provided by the user as the fifth parameter to the function. Small
+values of the lookahead parameter will likely result in limited
+parallelization opportunities, whereas large values will expose more
+parallelism but may introduce (non-infinite) looping and result in
+extra work. The optimal value for the lookahead parameter depends on
+the input graph; see [CMMS98b]_ and [MS98]_.
+
+This algorithm will be used by ``dijkstra_shortest_paths()`` when it
+is provided with a lookahead value.
+
+Where Defined
+~~~~~~~~~~~~~
+<``boost/graph/distributed/eager_dijkstra_shortest_paths.hpp``>
+
+Complexity
+~~~~~~~~~~
+This algorithm performs *O(V log V)* work in *d
++ 1* BSP supersteps, where *d* is at most *O(V)* but may be smaller
+depending on the lookahead value. the algorithm may perform more work
+when a large lookahead is provided, because vertices will be
+reprocessed.
+
+Performance
+~~~~~~~~~~~
+The performance of the eager Dijkstra's algorithm varies greatly
+depending on the lookahead value. The following charts illustrate the
+performance of the Parallel BGL on graphs with edge weights uniformly
+selected from the range *[0, 1)* and a constant lookahead of 0.1.
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&generator=ER,SF,SW&dataset=TimeSparse&columns=5
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&generator=ER,SF,SW&dataset=TimeSparse&columns=5&speedup=1
+
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&generator=ER,SF,SW&dataset=TimeDense&columns=5
+ :align: left
+.. image:: http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&generator=ER,SF,SW&dataset=TimeDense&columns=5&speedup=1
+
+Delta-Stepping algorithm
+--------------------------
+
+::
+
+ namespace boost { namespace graph { namespace distributed {
+
+ template <typename Graph, typename PredecessorMap,
+ typename DistanceMap, typename WeightMap>
+ void delta_stepping_shortest_paths
+ (const Graph& g,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
+ typename property_traits<WeightMap>::value_type delta)
+
+
+ template <typename Graph, typename PredecessorMap,
+ typename DistanceMap, typename WeightMap>
+ void delta_stepping_shortest_paths
+ (const Graph& g,
+ typename graph_traits<Graph>::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight)
+ }
+
+ } } }
+
+
+The delta-stepping algorithm [MS98]_ is another variant of the parallel
+Dijkstra algorithm. Like the eager Dijkstra algorithm, it employs a
+lookahead (``delta``) value that allows processors to process vertices
+before we are guaranteed to find their minimum distances, permitting
+more parallelism than a conservative strategy. Delta-stepping also
+introduces a multi-level bucket data structure that provides more
+relaxed ordering constraints than the priority queues employed by the
+other Dijkstra variants, reducing the complexity of insertions,
+relaxations, and removals from the central data structure. The
+delta-stepping algorithm is the best-performing of the Dijkstra
+variants.
+
+The lookahead value ``delta`` determines how large each of the
+"buckets" within the delta-stepping queue will be, where the ith
+bucket contains edges within tentative distances between ``delta``*i
+and ``delta``*(i+1). ``delta`` must be a positive value. When omitted,
+``delta`` will be set to the maximum edge weight divided by the
+maximum degree.
+
+Where Defined
+~~~~~~~~~~~~~
+<``boost/graph/distributed/delta_stepping_shortest_paths.hpp``>
+
+Example
+-------
+See the separate `Dijkstra example`_.
+
+
+Bibliography
+------------
+
+.. [CMMS98a] Andreas Crauser, Kurt Mehlhorn, Ulrich Meyer, and Peter Sanders. A
+ Parallelization of Dijkstra's Shortest Path Algorithm. In
+ *Mathematical Foundations of Computer Science (MFCS)*, volume 1450 of
+ Lecture Notes in Computer Science, pages 722--731, 1998. Springer.
+
+.. [CMMS98b] Andreas Crauser, Kurt Mehlhorn, Ulrich Meyer, and Peter
+ Sanders. Parallelizing Dijkstra's shortest path algorithm. Technical
+ report, MPI-Informatik, 1998.
+
+.. [MS98] Ulrich Meyer and Peter Sanders. Delta-stepping: A parallel
+ shortest path algorithm. In *6th ESA*, LNCS. Springer, 1998.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004, 2005, 2006, 2007, 2008 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _sequential Dijkstra implementation: http://www.boost.org/libs/graph/doc/dijkstra_shortest_paths.html
+.. _distributed breadth-first search: breadth_first_search.html
+.. _Distributed Graph: DistributedGraph.html
+.. _Distributed Property Map: distributed_property_map.html
+.. _Dijkstra Visitor: http://www.boost.org/libs/graph/doc/DijkstraVisitor.html
+.. _Dijkstra example: dijkstra_example.html

Added: trunk/libs/graph_parallel/doc/dist-adjlist.graffle
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/dist-adjlist.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/dist-pmap.graffle
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/dist-pmap.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/distributed-graph.graffle
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/distributed-graph.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/distributedS.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/distributedS.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,49 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+======================================
+``distributedS`` Distribution Selector
+======================================
+
+The Boost Graph Library's class template adjacency_list_ supports
+several selectors that indicate what data structure should be used for
+the storage of edges or vertices. The selector ``vecS``, for instance,
+indicates storage in a ``std::vector`` whereas ``listS`` indicates
+storage in a ``std::list``. The Parallel BGL's `distributed
+adjacency list`_ supports an additional selector, ``distributedS``,
+that indicates that the storage should be distributed across multiple
+processes. This selector can transform a sequential adjacency list
+into a distributed adjacency list.
+
+::
+
+ template<typename ProcessGroup, typename LocalSelector = vecS>
+ struct distributedS;
+
+
+Template parameters
+~~~~~~~~~~~~~~~~~~~
+
+**ProcessGroup**:
+ The type of the process group over which the property map is
+ distributed and also the medium for communication. This type must
+ model the `Process Group`_ concept, but certain data structures may
+ place additional requirements on this parameter.
+
+**LocalSelector**:
+ A selector type (e.g., ``vecS``) that indicates how vertices or
+ edges should be stored in each process.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+
+.. _adjacency_list: http://www.boost.org/libs/graph/doc/adjacency_list.html
+.. _Distributed adjacency list: distributed_adjacency_list.html
+.. _Process group: ../parallel/ProcessGroup.html
+

Added: trunk/libs/graph_parallel/doc/distributed_adjacency_list.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/distributed_adjacency_list.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,964 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+=================================
+|Logo| Distributed Adjacency List
+=================================
+
+.. contents::
+
+Introduction
+------------
+
+The distributed adjacency list implements a graph data structure using
+an adjacency list representation. Its interface and behavior are
+roughly equivalent to the Boost Graph Library's adjacency_list_
+class template. However, the distributed adjacency list partitions the
+vertices of the graph across several processes (which need not share
+an address space). Edges outgoing from any vertex stored by a process
+are also stored on that process, except in the case of undirected
+graphs, where either the source or the target may store the edge.
+
+::
+
+ template<typename OutEdgeListS, typename ProcessGroup, typename VertexListS,
+ typename DirectedS, typename VertexProperty, typename EdgeProperty,
+ typename GraphProperty, typename EdgeListS>
+ class adjacency_list<OutEdgeListS,
+ distributedS<ProcessGroup, VertexListS>,
+ DirectedS, VertexProperty,
+ EdgeProperty, GraphProperty, EdgeListS>;
+
+Defining a Distributed Adjacency List
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+To create a distributed adjacency list, first determine the
+representation of the graph in a single address space using these
+guidelines_. Next, replace the vertex list selector (``VertexListS``)
+with an instantiation of distributedS_, which includes:
+
+- Selecting a `process group`_ type that represents the various
+ coordinating processes that will store the distributed graph. For
+ example, the `MPI process group`_.
+
+- A selector indicating how the vertex lists in each process will be
+ stored. Only the ``vecS`` and ``listS`` selectors are well-supported
+ at this time.
+
+
+The following ``typedef`` defines a distributed adjacency list
+containing directed edges. The vertices in the graph will be
+distributed over several processes, using the MPI process group
+for communication. In each process, the vertices and outgoing edges
+will be stored in STL vectors. There are no properties attached to the
+vertices or edges of the graph.
+
+::
+
+ using namespace boost;
+ typedef adjacency_list<vecS,
+ distributedS<parallel::mpi::bsp_process_group, vecS>,
+ directedS>
+ Graph;
+
+
+Distributed Vertex and Edge Properties
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Vertex and edge properties for distributed graphs mirror their
+counterparts for non-distributed graphs. With a distributed graph,
+however, vertex and edge properties are stored only in the process
+that owns the vertex or edge.
+
+The most direct way to attach properties to a distributed graph is to
+create a structure that will be attached to each of the vertices and
+edges of the graph. For example, if we wish to model a simplistic map
+of the United States interstate highway system, we might state that
+the vertices of the graph are cities and the edges are highways, then
+define the information that we maintain for each city and highway:
+
+::
+
+ struct City {
+ City() { }
+ City(const std::string& name, const std::string& mayor = "Unknown", int population = 0)
+ : name(name), mayor(mayor), population(population) { }
+
+ std::string name;
+ std::string mayor;
+ int population;
+
+ // Serialization support is required!
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/) {
+ ar & name & mayor & population;
+ }
+ };
+
+ struct Highway {
+ Highway() { }
+ Highway(const std::string& name, int lanes, int miles_per_hour, int length)
+ : name(name), lanes(lanes), miles_per_hour(miles_per_hour), length(length) { }
+
+ std::string name;
+ int lanes;
+ int miles_per_hour;
+ int length;
+
+ // Serialization support is required!
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/) {
+ ar & name & lanes & miles_per_hour & length;
+ }
+ };
+
+
+To create a distributed graph for a road map, we supply ``City`` and
+``Highway`` as the fourth and fifth parameters to ``adjacency_list``,
+respectively:
+
+::
+
+ typedef adjacency_list<vecS,
+ distributedS<parallel::mpi::bsp_process_group, vecS>,
+ directedS,
+ City, Highway>
+ RoadMap;
+
+
+Property maps for internal properties retain their behavior with
+distributed graphs via `distributed property maps`_, which automate
+communication among processes so that ``put`` and ``get`` operations
+may be applied to non-local vertices and edges. However, for
+distributed adjacency lists that store vertices in a vector
+(``VertexListS`` is ``vecS``), the automatic ``vertex_index``
+property map restricts the domain of ``put`` and ``get`` operations
+to vertices local to the process executing the operation. For example,
+we can create a property map that accesses the length of each highway
+as follows:
+
+::
+
+ RoadMap map; // distributed graph instance
+
+ typedef property_map<RoadMap, int Highway::*>::type
+ road_length = get(&Highway::length, map);
+
+
+Now, one can access the length of any given road based on its edge
+descriptor ``e`` with the expression ``get(road_length, e)``,
+regardless of which process stores the edge ``e``.
+
+Named Vertices
+~~~~~~~~~~~~~~
+
+The vertices of a graph typically correspond to named entities within
+the application domain. In the road map example from the previous
+section, the vertices in the graph represent cities. The distributed
+adjacency list supports named vertices, which provides an implicit
+mapping from the names of the vertices in the application domain
+(e.g., the name of a city, such as "Bloomington") to the actual vertex
+descriptor stored within the distributed graph (e.g., the third vertex
+on processor 1). By enabling support for named vertices, one can refer
+to vertices by name when manipulating the graph. For example, one can
+add a highway from Indianapolis to Chicago:
+
+::
+
+ add_edge("Indianapolis", "Chicago", Highway("I-65", 4, 65, 151), map);
+
+The distributed adjacency list will find vertices associated with the
+names "Indianapolis" and "Chicago", then add an edge between these
+vertices that represents I-65. The vertices may be stored on any
+processor, local or remote.
+
+To enable named vertices, specialize the ``internal_vertex_name``
+property for the structure attached to the vertices in your
+graph. ``internal_vertex_name`` contains a single member, ``type``,
+which is the type of a function object that accepts a vertex property
+and returns the name stored within that vertex property. In the case
+of our road map, the ``name`` field contains the name of each city, so
+we use the ``member`` function object from the `Boost.MultiIndex`_
+library to extract the name, e.g.,
+
+::
+
+ namespace boost { namespace graph {
+
+ template<>
+ struct internal_vertex_name<City>
+ {
+ typedef multi_index::member<City, std::string, &City::name> type;
+ };
+
+ } }
+
+
+That's it! One can now refer to vertices by name when interacting with
+the distributed adjacency list.
+
+What happens when one uses the name of a vertex that does not exist?
+For example, in our ``add_edge`` call above, what happens if the
+vertex named "Indianapolis" has not yet been added to the graph? By
+default, the distributed adjacency list will throw an exception if a
+named vertex does not yet exist. However, one can customize this
+behavior by specifying a function object that constructs an instance
+of the vertex property (e.g., ``City``) from just the name of the
+vertex. This customization occurs via the
+``internal_vertex_constructor`` trait. For example, using the
+``vertex_from_name`` template (provided with the Parallel BGL), we can
+state that a ``City`` can be constructed directly from the name of the
+city using its second constructor:
+
+::
+
+ namespace boost { namespace graph {
+
+ template<>
+ struct internal_vertex_constructor<City>
+ {
+ typedef vertex_from_name<City> type;
+ };
+
+ } }
+
+Now, one can add edges by vertex name freely, without worrying about
+the explicit addition of vertices. The ``mayor`` and ``population``
+fields will have default values, but the graph structure will be
+correct.
+
+Building a Distributed Graph
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once you have determined the layout of your graph type, including the
+specific data structures and properties, it is time to construct an
+instance of the graph by adding the appropriate vertices and
+edges. Construction of distributed graphs can be slightly more
+complicated than construction of normal, non-distributed graph data
+structures, because one must account for both the distribution of the
+vertices and edges and the multiple processes executing
+concurrently. There are three main ways to construct distributed
+graphs:
+
+1. *Sequence constructors*: if your data can easily be generated by a
+pair of iterators that produce (source, target) pairs, you can use the
+sequence constructors to build the distributed graph in parallel. This
+method is often preferred when creating benchmarks, because random
+graph generators like the sorted_erdos_renyi_iterator_ create the
+appropriate input sequence. Note that one must provide the same input
+iterator sequence on all processes. This method has the advantage that
+the sequential graph-building code is identical to the parallel
+graph-building code. An example constructing a random graph this way:
+
+ ::
+
+ typedef boost::sorted_erdos_renyi_iterator<boost::minstd_rand, Graph> ERIter;
+ boost::minstd_rand gen;
+ unsigned long n = 1000000; // 1M vertices
+ Graph g(ERIter(gen, n, 0.00005), ERIter(), n);
+
+2. *Adding edges by vertex number*: if you are able to map your
+vertices into values in the random [0, *n*), where *n* is the number
+of vertices in the distributed graph. Use this method rather than the
+sequence constructors when your algorithm cannot easily be moved into
+input iterators, or if you can't replicate the input sequence. For
+example, you might be reading the graph from an input file:
+
+ ::
+
+ Graph g(n); // initialize with the total number of vertices, n
+ if (process_id(g.process_group()) == 0) {
+ // Only process 0 loads the graph, which is distributed automatically
+ int source, target;
+ for (std::cin >> source >> target)
+ add_edge(vertex(source, g), vertex(target, g), g);
+ }
+
+ // All processes synchronize at this point, then the graph is complete
+ synchronize(g.process_group());
+
+3. *Adding edges by name*: if you are using named vertices, you can
+construct your graph just by calling ``add_edge`` with the names of
+the source and target vertices. Be careful to make sure that each edge
+is added by only one process (it doesn't matter which process it is),
+otherwise you will end up with multiple edges. For example, in the
+following program we read edges from the standard input of process 0,
+adding those edges by name. Vertices and edges will be created and
+distributed automatically.
+
+ ::
+
+ Graph g;
+ if (process_id(g.process_group()) == 0) {
+ // Only process 0 loads the graph, which is distributed automatically
+ std:string source, target;
+ for(std::cin >> source >> target)
+ add_edge(source, target, g);
+ }
+
+ // All processes synchronize at this point, then the graph is complete
+ synchronize(g.process_group());
+
+
+Graph Concepts
+~~~~~~~~~~~~~~
+
+The distributed adjacency list models the Graph_ concept, and in
+particular the `Distributed Graph`_ concept. It also models the
+`Incidence Graph`_ and `Adjacency Graph`_ concept, but restricts the
+input domain of the operations to correspond to local vertices
+only. For instance, a process may only access the outgoing edges of a
+vertex if that vertex is stored in that process. Undirected and
+bidirectional distributed adjacency lists model the `Bidirectional
+Graph`_ concept, with the same domain restrictions. Distributed
+adjacency lists also model the `Mutable Graph`_ concept (with domain
+restrictions; see the Reference_ section), `Property Graph`_ concept,
+and `Mutable Property Graph`_ concept.
+
+Unlike its non-distributed counterpart, the distributed adjacency
+list does **not** model the `Vertex List Graph`_ or `Edge List
+Graph`_ concepts, because one cannot enumerate all vertices or edges
+within a distributed graph. Instead, it models the weaker
+`Distributed Vertex List Graph`_ and `Distributed Edge List Graph`_
+concepts, which permit access to the local edges and vertices on each
+processor. Note that if all processes within the process group over
+which the graph is distributed iterator over their respective vertex
+or edge lists, all vertices and edges will be covered once.
+
+Reference
+---------
+Since the distributed adjacency list closely follows the
+non-distributed adjacency_list_, this reference documentation
+only describes where the two implementations differ.
+
+Where Defined
+~~~~~~~~~~~~~
+
+<boost/graph/distributed/adjacency_list.hpp>
+
+Associated Types
+~~~~~~~~~~~~~~~~
+
+::
+
+ adjacency_list::process_group_type
+
+The type of the process group over which the graph will be
+distributed.
+
+-----------------------------------------------------------------------------
+
+ adjacency_list::distribution_type
+
+The type of distribution used to partition vertices in the graph.
+
+-----------------------------------------------------------------------------
+
+ adjacency_list::vertex_name_type
+
+If the graph supports named vertices, this is the type used to name
+vertices. Otherwise, this type is not present within the distributed
+adjacency list.
+
+
+Member Functions
+~~~~~~~~~~~~~~~~
+
+::
+
+ adjacency_list(const ProcessGroup& pg = ProcessGroup());
+
+ adjacency_list(const GraphProperty& g,
+ const ProcessGroup& pg = ProcessGroup());
+
+Construct an empty distributed adjacency list with the given process
+group (or default) and graph property (or default).
+
+-----------------------------------------------------------------------------
+
+::
+
+ adjacency_list(vertices_size_type n, const GraphProperty& p,
+ const ProcessGroup& pg, const Distribution& distribution);
+
+ adjacency_list(vertices_size_type n, const ProcessGroup& pg,
+ const Distribution& distribution);
+
+ adjacency_list(vertices_size_type n, const GraphProperty& p,
+ const ProcessGroup& pg = ProcessGroup());
+
+ adjacency_list(vertices_size_type n,
+ const ProcessGroup& pg = ProcessGroup());
+
+Construct a distributed adjacency list with ``n`` vertices,
+optionally providing the graph property, process group, or
+distribution. The ``n`` vertices will be distributed via the given
+(or default-constructed) distribution. This operation is collective,
+requiring all processes with the process group to execute it
+concurrently.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template <class EdgeIterator>
+ adjacency_list(EdgeIterator first, EdgeIterator last,
+ vertices_size_type n,
+ const ProcessGroup& pg = ProcessGroup(),
+ const GraphProperty& p = GraphProperty());
+
+ template <class EdgeIterator, class EdgePropertyIterator>
+ adjacency_list(EdgeIterator first, EdgeIterator last,
+ EdgePropertyIterator ep_iter,
+ vertices_size_type n,
+ const ProcessGroup& pg = ProcessGroup(),
+ const GraphProperty& p = GraphProperty());
+
+ template <class EdgeIterator>
+ adjacency_list(EdgeIterator first, EdgeIterator last,
+ vertices_size_type n,
+ const ProcessGroup& process_group,
+ const Distribution& distribution,
+ const GraphProperty& p = GraphProperty());
+
+ template <class EdgeIterator, class EdgePropertyIterator>
+ adjacency_list(EdgeIterator first, EdgeIterator last,
+ EdgePropertyIterator ep_iter,
+ vertices_size_type n,
+ const ProcessGroup& process_group,
+ const Distribution& distribution,
+ const GraphProperty& p = GraphProperty());
+
+Construct a distributed adjacency list with ``n`` vertices and with
+edges specified in the edge list given by the range ``[first, last)``. The
+``EdgeIterator`` must be a model of InputIterator_. The value type of the
+``EdgeIterator`` must be a ``std::pair``, where the type in the pair is an
+integer type. The integers will correspond to vertices, and they must
+all fall in the range of ``[0, n)``. When provided, ``ep_iter``
+refers to an edge property list ``[ep_iter, ep_iter + m)`` contains
+properties for each of the edges.
+
+This constructor is a collective operation and must be executed
+concurrently by each process with the same argument list. Most
+importantly, the edge lists provided to the constructor in each process
+should be equivalent. The vertices will be partitioned among the
+processes according to the ``distribution``, with edges placed on the
+process owning the source of the edge. Note that this behavior
+permits sequential graph construction code to be parallelized
+automatically, regardless of the underlying distribution.
+
+-----------------------------------------------------------------------------
+
+::
+
+ void clear()
+
+Removes all of the edges and vertices from the local graph. To
+eliminate all vertices and edges from the graph, this routine must be
+executed in all processes.
+
+-----------------------------------------------------------------------------
+
+::
+
+ process_group_type& process_group();
+ const process_group_type& process_group() const;
+
+Returns the process group over which this graph is distributed.
+
+-----------------------------------------------------------------------------
+
+::
+
+ distribution_type& distribution();
+ const distribution_type& distribution() const;
+
+Returns the distribution used for initial placement of vertices.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template<typename VertexProcessorMap>
+ void redistribute(VertexProcessorMap vertex_to_processor);
+
+Redistributes the vertices (and, therefore, the edges) of the
+graph. The property map ``vertex_to_processor`` provides, for each
+vertex, the process identifier indicating where the vertex should be
+moved. Once this collective routine has completed, the distributed
+graph will reflect the new distribution. All vertex and edge
+descsriptors and internal and external property maps are invalidated
+by this operation.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template<typename OStreamConstructibleArchive>
+ void save(std::string const& filename) const;
+
+ template<typename IStreamConstructibleArchive>
+ void load(std::string const& filename);
+
+Serializes the graph to a Boost.Serialization archive.
+``OStreamConstructibleArchive`` and ``IStreamConstructibleArchive``
+are models of Boost.Serialization *Archive* with the extra
+requirement that they can be constructed from a ``std::ostream``
+and ``std::istream``.
+``filename`` names a directory that will hold files for
+the different processes.
+
+
+Non-Member Functions
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ std::pair<vertex_iterator, vertex_iterator>
+ vertices(const adjacency_list& g);
+
+Returns an iterator-range providing access to the vertex set of graph
+``g`` stored in this process. Each of the processes that contain ``g``
+will get disjoint sets of vertices.
+
+-----------------------------------------------------------------------------
+
+::
+
+ std::pair<edge_iterator, edge_iterator>
+ edges(const adjacency_list& g);
+
+Returns an iterator-range providing access to the edge set of graph
+``g`` stored in this process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ std::pair<adjacency_iterator, adjacency_iterator>
+ adjacent_vertices(vertex_descriptor u, const adjacency_list& g);
+
+Returns an iterator-range providing access to the vertices adjacent to
+vertex ``u`` in graph ``g``. The vertex ``u`` must be local to this process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ std::pair<out_edge_iterator, out_edge_iterator>
+ out_edges(vertex_descriptor u, const adjacency_list& g);
+
+Returns an iterator-range providing access to the out-edges of vertex
+``u`` in graph ``g``. If the graph is undirected, this iterator-range
+provides access to all edges incident on vertex ``u``. For both
+directed and undirected graphs, for an out-edge ``e``, ``source(e, g)
+== u`` and ``target(e, g) == v`` where ``v`` is a vertex adjacent to
+``u``. The vertex ``u`` must be local to this process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ std::pair<in_edge_iterator, in_edge_iterator>
+ in_edges(vertex_descriptor v, const adjacency_list& g);
+
+Returns an iterator-range providing access to the in-edges of vertex
+``v`` in graph ``g``. This operation is only available if
+``bidirectionalS`` was specified for the ``Directed`` template
+parameter. For an in-edge ``e``, ``target(e, g) == v`` and ``source(e,
+g) == u`` for some vertex ``u`` that is adjacent to ``v``, whether the
+graph is directed or undirected. The vertex ``v`` must be local to
+this process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ degree_size_type
+ out_degree(vertex_descriptor u, const adjacency_list& g);
+
+Returns the number of edges leaving vertex ``u``. Vertex ``u`` must
+be local to the executing process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ degree_size_type
+ in_degree(vertex_descriptor u, const adjacency_list& g);
+
+Returns the number of edges entering vertex ``u``. This operation is
+only available if ``bidirectionalS`` was specified for the
+``Directed`` template parameter. Vertex ``u`` must be local to the
+executing process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ vertices_size_type
+ num_vertices(const adjacency_list& g);
+
+Returns the number of vertices in the graph ``g`` that are stored in
+the executing process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ edges_size_type
+ num_edges(const adjacency_list& g);
+
+Returns the number of edges in the graph ``g`` that are stored in the
+executing process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ vertex_descriptor
+ vertex(vertices_size_type n, const adjacency_list& g);
+
+Returns the ``n``th vertex in the graph's vertex list, according to the
+distribution used to partition the graph. ``n`` must be a value
+between zero and the sum of ``num_vertices(g)`` in each process (minus
+one). Note that it is not necessarily the case that ``vertex(0, g) ==
+*num_vertices(g).first``. This function is only guaranteed to be
+accurate when no vertices have been added to or removed from the
+graph after its initial construction.
+
+-----------------------------------------------------------------------------
+
+::
+
+ std::pair<edge_descriptor, bool>
+ edge(vertex_descriptor u, vertex_descriptor v,
+ const adjacency_list& g);
+
+Returns an edge connecting vertex ``u`` to vertex ``v`` in graph
+``g``. For bidirectional and undirected graphs, either vertex ``u`` or
+vertex ``v`` must be local; for directed graphs, vertex ``u`` must be
+local.
+
+-----------------------------------------------------------------------------
+
+::
+
+ std::pair<out_edge_iterator, out_edge_iterator>
+ edge_range(vertex_descriptor u, vertex_descriptor v,
+ const adjacency_list& g);
+
+TODO: Not implemented. Returns a pair of out-edge iterators that give
+the range for all the parallel edges from ``u`` to ``v``. This function only
+works when the ``OutEdgeList`` for the ``adjacency_list`` is a container that
+sorts the out edges according to target vertex, and allows for
+parallel edges. The ``multisetS`` selector chooses such a
+container. Vertex ``u`` must be stored in the executing process.
+
+Structure Modification
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ unspecified add_edge(vertex_descriptor u, vertex_descriptor v, adjacency_list& g);
+ unspecified add_edge(vertex_name_type u, vertex_descriptor v, adjacency_list& g);
+ unspecified add_edge(vertex_descriptor u, vertex_name_type v, adjacency_list& g);
+ unspecified add_edge(vertex_name_type u, vertex_name_type v, adjacency_list& g);
+
+Adds edge ``(u,v)`` to the graph. The return type itself is
+unspecified, but the type can be copy-constructed and implicitly
+converted into a ``std::pair<edge_descriptor,bool>``. The edge
+descriptor describes the added (or found) edge. For graphs that do not
+allow parallel edges, if the edge
+is already in the graph then a duplicate will not be added and the
+``bool`` flag will be ``false``. Also, if u and v are descriptors for
+the same vertex (creating a self loop) and the graph is undirected,
+then the edge will not be added and the flag will be ``false``. When
+the flag is ``false``, the returned edge descriptor points to the
+already existing edge.
+
+The parameters ``u`` and ``v`` can be either vertex descriptors or, if
+the graph uses named vertices, the names of vertices. If no vertex
+with the given name exists, the internal vertex constructor will be
+invoked to create a new vertex property and a vertex with that
+property will be added to the graph implicitly. The default internal
+vertex constructor throws an exception.
+
+-----------------------------------------------------------------------------
+
+::
+
+ unspecified add_edge(vertex_descriptor u, vertex_descriptor v, const EdgeProperties& p, adjacency_list& g);
+ unspecified add_edge(vertex_name_type u, vertex_descriptor v, const EdgeProperties& p, adjacency_list& g);
+ unspecified add_edge(vertex_descriptor u, vertex_name_type v, const EdgeProperties& p, adjacency_list& g);
+ unspecified add_edge(vertex_name_type u, vertex_name_type v, const EdgeProperties& p, adjacency_list& g);
+
+
+Adds edge ``(u,v)`` to the graph and attaches ``p`` as the value of the edge's
+internal property storage. See the previous ``add_edge()`` member
+function for more details.
+
+-----------------------------------------------------------------------------
+
+::
+
+ void
+ remove_edge(vertex_descriptor u, vertex_descriptor v,
+ adjacency_list& g);
+
+Removes the edge ``(u,v)`` from the graph. If the directed selector is
+``bidirectionalS`` or ``undirectedS``, either the source or target
+vertex of the graph must be local. If the directed selector is
+``directedS``, then the source vertex must be local.
+
+-----------------------------------------------------------------------------
+
+::
+
+ void
+ remove_edge(edge_descriptor e, adjacency_list& g);
+
+Removes the edge ``e`` from the graph. If the directed selector is
+``bidirectionalS`` or ``undirectedS``, either the source or target
+vertex of the graph must be local. If the directed selector is
+``directedS``, then the source vertex must be local.
+
+-----------------------------------------------------------------------------
+
+::
+
+ void remove_edge(out_edge_iterator iter, adjacency_list& g);
+
+This has the same effect as ``remove_edge(*iter, g)``. For directed
+(but not bidirectional) graphs, this will be more efficient than
+``remove_edge(*iter, g)``.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template <class Predicate >
+ void remove_out_edge_if(vertex_descriptor u, Predicate predicate,
+ adjacency_list& g);
+
+Removes all out-edges of vertex ``u`` from the graph that satisfy the
+predicate. That is, if the predicate returns ``true`` when applied to an
+edge descriptor, then the edge is removed. The vertex ``u`` must be local.
+
+The affect on descriptor and iterator stability is the same as that of
+invoking remove_edge() on each of the removed edges.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template <class Predicate >
+ void remove_in_edge_if(vertex_descriptor v, Predicate predicate,
+ adjacency_list& g);
+
+Removes all in-edges of vertex ``v`` from the graph that satisfy the
+predicate. That is, if the predicate returns true when applied to an
+edge descriptor, then the edge is removed. The vertex ``v`` must be local.
+
+The affect on descriptor and iterator stability is the same as that of
+invoking ``remove_edge()`` on each of the removed edges.
+
+This operation is available for undirected and bidirectional
+adjacency_list graphs, but not for directed.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template <class Predicate>
+ void remove_edge_if(Predicate predicate, adjacency_list& g);
+
+Removes all edges from the graph that satisfy the predicate. That is,
+if the predicate returns true when applied to an edge descriptor, then
+the edge is removed.
+
+The affect on descriptor and iterator stability is the same as that
+of invoking ``remove_edge()`` on each of the removed edges.
+
+-----------------------------------------------------------------------------
+
+::
+
+ vertex_descriptor add_vertex(adjacency_list& g);
+
+Adds a vertex to the graph and returns the vertex descriptor for the
+new vertex. The vertex will be stored in the local process. This
+function is not available when using named vertices.
+
+-----------------------------------------------------------------------------
+
+::
+
+ unspecified add_vertex(const VertexProperties& p, adjacency_list& g);
+ unspecified add_vertex(const vertex_name_type& p, adjacency_list& g);
+
+Adds a vertex to the graph with the specified properties. If the graph
+is using vertex names, the vertex will be added on whichever process
+"owns" that name. Otherwise, the vertex will be stored in the local
+process. Note that the second constructor will invoke the
+user-customizable internal vertex constructor, which (by default)
+throws an exception when it sees an unknown vertex.
+
+The return type is of unspecified type, but can be copy-constructed
+and can be implicitly converted into a vertex descriptor.
+
+-----------------------------------------------------------------------------
+
+::
+
+ void clear_vertex(vertex_descriptor u, adjacency_list& g);
+
+Removes all edges to and from vertex ``u``. The vertex still appears
+in the vertex set of the graph.
+
+The affect on descriptor and iterator stability is the same as that of
+invoking ``remove_edge()`` for all of the edges that have ``u`` as the source
+or target.
+
+This operation is not applicable to directed graphs, because the
+incoming edges to vertex ``u`` are not known.
+
+-----------------------------------------------------------------------------
+
+::
+
+ void clear_out_edges(vertex_descriptor u, adjacency_list& g);
+
+Removes all out-edges from vertex ``u``. The vertex still appears in
+the vertex set of the graph.
+
+The affect on descriptor and iterator stability is the same as that of
+invoking ``remove_edge()`` for all of the edges that have ``u`` as the
+source.
+
+This operation is not applicable to undirected graphs (use
+``clear_vertex()`` instead).
+
+-----------------------------------------------------------------------------
+
+::
+
+ void clear_in_edges(vertex_descriptor u, adjacency_list& g);
+
+Removes all in-edges from vertex ``u``. The vertex still appears in
+the vertex set of the graph.
+
+The affect on descriptor and iterator stability is the same as that of
+invoking ``remove_edge()`` for all of the edges that have ``u`` as the
+target.
+
+This operation is only applicable to bidirectional graphs.
+
+-----------------------------------------------------------------------------
+
+::
+
+ void remove_vertex(vertex_descriptor u, adjacency_list& g);
+
+Remove vertex ``u`` from the vertex set of the graph. It is assumed
+that there are no edges to or from vertex ``u`` when it is
+removed. One way to make sure of this is to invoke ``clear_vertex()``
+beforehand. The vertex ``u`` must be stored locally.
+
+Property Map Accessors
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ template <class PropertyTag>
+ property_map<adjacency_list, PropertyTag>::type
+ get(PropertyTag, adjacency_list& g);
+
+ template <class PropertyTag>
+ property_map<adjacency_list, Tag>::const_type
+ get(PropertyTag, const adjacency_list& g);
+
+Returns the property map object for the vertex property specified by
+``PropertyTag``. The ``PropertyTag`` must match one of the properties
+specified in the graph's ``VertexProperty`` template argument. The
+returned property map will be a `distributed property map`_.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template <class PropertyTag , class X>
+ typename property_traits<property_map<adjacency_list, PropertyTag>::const_type>::value_type
+ get(PropertyTag, const adjacency_list& g, X x);
+
+This returns the property value for ``x``, where ``x`` is either a vertex or
+edge descriptor. The entity referred to by descriptor ``x`` must be
+stored in the local process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template <class PropertyTag , class X, class Value>
+ void put(PropertyTag, const adjacency_list& g, X x, const Value& value);
+
+This sets the property value for ``x`` to value. ``x`` is either a
+vertex or edge descriptor. ``Value`` must be convertible to ``typename
+property_traits<property_map<adjacency_list,
+PropertyTag>::type>::value_type``.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template <class GraphProperties, class GraphPropertyTag>
+ typename graph_property<adjacency_list, GraphPropertyTag>::type&
+ get_property(adjacency_list& g, GraphPropertyTag);
+
+ template <class GraphProperties, class GraphPropertyTag >
+ const typename graph_property<adjacency_list, GraphPropertyTag>::type&
+ get_property(const adjacency_list& g, GraphPropertyTag);
+
+TODO: not implemented.
+
+Return the property specified by ``GraphPropertyTag`` that is attached
+to the graph object ``g``. The ``graph_property`` traits class is
+defined in ``boost/graph/adjacency_list.hpp``.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004 The Trustees of Indiana University.
+
+Copyright (C) 2007 Douglas Gregor
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _adjacency_list: http://www.boost.org/libs/graph/doc/adjacency_list.html
+.. _guidelines: http://www.boost.org/libs/graph/doc/using_adjacency_list.html
+.. _process group: process_group.html
+.. _mpi process group: process_group.html
+.. _distributedS: distributedS.html
+.. _Graph: http://www.boost.org/libs/graph/doc/Graph.html
+.. _Distributed graph: DistributedGraph.html
+.. _Incidence Graph: http://www.boost.org/libs/graph/doc/IncidenceGraph.html
+.. _Adjacency Graph: http://www.boost.org/libs/graph/doc/AdjacencyGraph.html
+.. _Bidirectional Graph: http://www.boost.org/libs/graph/doc/BidirectionalGraph.html
+.. _Mutable Graph: http://www.boost.org/libs/graph/doc/MutableGraph.html
+.. _Property Graph: http://www.boost.org/libs/graph/doc/PropertyGraph.html
+.. _Mutable Property Graph: http://www.boost.org/libs/graph/doc/MutablePropertyGraph.html
+.. _Vertex List Graph: http://www.boost.org/libs/graph/doc/VertexListGraph.html
+.. _Edge List Graph: http://www.boost.org/libs/graph/doc/EdgeListGraph.html
+.. _Distribution: concepts/Distribution.html
+.. _distributed property map: distributed_property_map.html
+.. _distributed property maps: distributed_property_map.html
+.. _Distributed Vertex List Graph: DistributedVertexListGraph.html
+.. _Distributed Edge List Graph: DistributedEdgeListGraph.html
+.. _InputIterator: http://www.boost.org/doc/html/InputIterator.html
+.. _member: http://www.boost.org/libs/multi_index/doc/reference/key_extraction.html#member_synopsis
+.. _Boost.MultiIndex: http://www.boost.org/libs/multi_index/doc/index.html
+.. _sorted_erdos_renyi_iterator: http://www.boost.org/libs/graph/doc/sorted_erdos_renyi_gen.html

Added: trunk/libs/graph_parallel/doc/distributed_property_map.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/distributed_property_map.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,744 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===============================
+|Logo| Distributed Property Map
+===============================
+
+A distributed property map adaptor is a property map whose stored
+values are distributed across multiple non-overlapping memory spaces
+on different processes. Values local to the current process are stored
+within a local property map and may be immediately accessed via
+``get`` and ``put``. Values stored on remote processes may also be
+accessed via ``get`` and ``put``, but the behavior differs slightly:
+
+ - ``put`` operations update a local ghost cell and send a "put"
+ message to the process that owns the value. The owner is free to
+ update its own "official" value or may ignore the put request.
+
+ - ``get`` operations returns the contents of the local ghost
+ cell. If no ghost cell is available, one is created using a
+ (customizable) default value.
+
+Using distributed property maps requires a bit more care than using
+local, sequential property maps. While the syntax and semantics are
+similar, distributed property maps may contain out-of-date
+information that can only be guaranteed to be synchronized by
+calling the ``synchronize`` function in all processes.
+
+To address the issue of out-of-date values, distributed property
+maps support multiple `consistency models`_ and may be supplied with a
+`reduction operation`_.
+
+Distributed property maps meet the requirements of the `Readable
+Property Map`_ and, potentially, the `Writable Property Map`_ and
+`Read/Write Property Map`_ concepts. Distributed property maps do
+*not*, however, meet the requirements of the `Lvalue Property Map`_
+concept, because elements residing in another process are not
+directly addressible. There are several forms of distributed property
+maps:
+
+ - `Distributed property map adaptor`_
+ - `Distributed iterator property map`_
+ - `Distributed safe iterator property map`_
+ - `Local property map`_
+
+------------------
+Consistency models
+------------------
+
+Distributed property maps offer many consistency models, which affect
+how the values read from and written to remote keys relate to the
+"official" value for that key stored in the owning process. The
+consistency model of a distributed property map can be set with the
+member function ``set_consistency_model`` to a bitwise-OR of the
+flags in the ``boost::parallel::consistency_model`` enumeration. The
+individual flags are:
+
+ - ``cm_forward``: The default consistency model, which propagates
+ values forward from ``put`` operations on remote processors to
+ the owner of the value being changed.
+
+ - ``cm_backward``: After all values have been forwarded or flushed
+ to the owning processes, each process receives updates values for
+ each of its ghost cells. After synchronization, the values in
+ ghost cells are guaranteed to match the values stored on the
+ owning processor.
+
+ - ``cm_bidirectional``: A combination of both ``cm_forward`` and
+ ``cm_backward``.
+
+ - ``cm_flush``: At the beginning of synchronization, all of the
+ values stored locally in ghost cells are sent to their owning
+ processors.
+
+ - ``cm_reset``: Executes a ``reset()`` operation after
+ synchronization, setting the values in each ghost cell to their
+ default value.
+
+ - ``cm_clear``: Executes a ``clear()`` operation after
+ synchronizing, eliminating all ghost cells.
+
+
+There are several common combinations of flags that result in
+interesting consistency models. Some of these combinations are:
+
+ - ``cm_forward``: By itself, the forward consistency model enables
+ algorithms such as `Dijkstra's shortest paths`_ and
+ `Breadth-First Search`_ to operate correctly.
+
+ - ``cm_flush & cm_reset``: All updates values are queued locally,
+ then flushed during the synchronization step. Once the flush has
+ occurred, the ghost cells are restored to their default
+ values. This consistency model is used by the PageRank_
+ implementation to locally accumulate rank for each node.
+
+
+-------------------
+Reduction operation
+-------------------
+
+The reduction operation maintains consistency by determining how
+multiple writes to a property map are resolved and what the property
+map should do if unknown values are requested. More specifically, a
+reduction operation is used in two cases:
+
+ 1. When a value is needed for a remote key but no value is
+ immediately available, the reduction operation provides a
+ suitable default. For instance, a distributed property map
+ storing distances may have a reduction operation that returns
+ an infinite value as the default, whereas a distributed
+ property map for vertex colors may return white as the
+ default.
+
+ 2. When a value is received from a remote process, the process
+ owning the key associated with that value must determine which
+ value---the locally stored value, the value received from a
+ remote process, or some combination of the two---will be
+ stored as the "official" value in the property map. The
+ reduction operation transforms the local and remote values
+ into the "official" value to be stored.
+
+The reduction operation of a distributed property map can be set with
+the ``set_reduce`` method of ``distributed_property_map``. The reduce
+operation is a function object with two signatures. The first
+signature takes a (remote) key and returns a default value for it,
+whereas the second signatures takes a key and two values (local first,
+then remote) and will return the combined value that will be stored in
+the local property map. Reduction operations must also contain a
+static constant ``non_default_resolver", which states whether the
+reduction operation's default value actually acts like a default
+value. It should be ``true`` when the default is meaningful (e.g.,
+infinity for a distance) and ``false`` when the default should not be
+used.
+
+The following reduction operation is used by the distributed PageRank
+algorithm. The default rank for a remote node is 0. Rank is
+accumulated locally, and then the reduction operation combines local
+and remote values by adding them. Combined with a consistency model
+that flushes all values to the owner and then resets the values
+locally in each step, the resulting property map will compute partial
+sums on each processor and then accumulate the results on the owning
+processor. The PageRank reduction operation is defined as follows.
+
+::
+
+ template<typename T>
+ struct rank_accumulate_reducer {
+ static const bool non_default_resolver = true;
+
+ // The default rank of an unknown node
+ template<typename K>
+ T operator()(const K&) const { return T(0); }
+
+ template<typename K>
+ T operator()(const K&, const T& x, const T& y) const { return x + y; }
+ };
+
+
+--------------------------------
+Distributed property map adaptor
+--------------------------------
+
+The distributed property map adaptor creates a distributed property
+map from a local property map, a `process group`_ over which
+distribution should occur, and a `global descriptor`_ type that
+indexes the distributed property map.
+
+
+Synopsis
+~~~~~~~~
+
+::
+
+ template<typename ProcessGroup, typename LocalPropertyMap, typename Key,
+ typename GhostCellS = gc_mapS>
+ class distributed_property_map
+ {
+ public:
+ typedef ... ghost_regions_type;
+
+ distributed_property_map();
+
+ distributed_property_map(const ProcessGroup& pg,
+ const LocalPropertyMap& pm);
+
+ template<typename Reduce>
+ distributed_property_map(const ProcessGroup& pg,
+ const LocalPropertyMap& pm,
+ const Reduce& reduce);
+
+ template<typename Reduce> void set_reduce(const Reduce& reduce);
+ void set_consistency_model(int model);
+
+ void flush();
+ void reset();
+ void clear();
+ };
+
+ reference get(distributed_property_map pm, const key_type& key);
+
+ void
+ put(distributed_property_map pm, const key_type& key, const value_type& value);
+ local_put(distributed_property_map pm, const key_type& key, const value_type& value);
+
+ void request(distributed_property_map pm, const key_type& key);
+
+ void synchronize(distributed_property_map& pm);
+
+ template<typename Key, typename ProcessGroup, typename LocalPropertyMap>
+ distributed_property_map<ProcessGroup, LocalPropertyMap, Key>
+ make_distributed_property_map(const ProcessGroup& pg, LocalPropertyMap pmap);
+
+ template<typename Key, typename ProcessGroup, typename LocalPropertyMap,
+ typename Reduce>
+ distributed_property_map<ProcessGroup, LocalPropertyMap, Key>
+ make_distributed_property_map(const ProcessGroup& pg, LocalPropertyMap pmap,
+ Reduce reduce);
+
+Template parameters
+~~~~~~~~~~~~~~~~~~~
+
+**ProcessGroup**:
+ The type of the process group over which the
+ property map is distributed and is also the medium for
+ communication.
+
+
+**LocalPropertyMap**:
+ The type of the property map that will store values
+ for keys local to this processor. The ``value_type`` of this
+ property map will become the ``value_type`` of the distributed
+ property map. The distributed property map models the same property
+ map concepts as the ``LocalPropertyMap``, with one exception: a
+ distributed property map cannot be an `Lvalue Property Map`_
+ (because remote values are not addressable), and is therefore
+ limited to `Read/Write Property Map`_.
+
+
+**Key**:
+ The ``key_type`` of the distributed property map, which
+ must model the `Global Descriptor`_ concept. The process ID type of
+ the ``Key`` parameter must match the process ID type of the
+ ``ProcessGroup``, and the local descriptor type of the ``Key`` must
+ be convertible to the ``key_type`` of the ``LocalPropertyMap``.
+
+
+**GhostCellS**:
+ A selector type that indicates how ghost cells should be stored in
+ the distributed property map. There are either two or three
+ options, depending on your compiler:
+
+ - ``boost::parallel::gc_mapS`` (default): Uses an STL ``map`` to
+ store the ghost cells for each process.
+
+ - ``boost::parallel::gc_vector_mapS``: Uses a sorted STL
+ ``vector`` to store the ghost cells for each process. This
+ option works well when there are likely to be few insertions
+ into the ghost cells; for instance, if the only ghost cells used
+ are for neighboring vertices, the property map can be
+ initialized with cells for each neighboring vertex, providing
+ faster lookups than a ``map`` and using less space.
+
+ - ``boost::parallel::gc_hash_mapS``: Uses the GCC ``hash_map`` to
+ store ghost cells. This option may improve performance over
+ ``map`` for large problems sizes, where the set of ghost cells
+ cannot be predetermined.
+
+
+Member functions
+~~~~~~~~~~~~~~~~
+
+::
+
+ distributed_property_map();
+
+Default-construct a distributed property map. The property map is in
+an invalid state, and may only be used if it is reassigned to a valid
+property map.
+
+------------------------------------------------------------------------------
+
+::
+
+ distributed_property_map(const ProcessGroup& pg,
+ const LocalPropertyMap& pm);
+
+ template<typename Reduce>
+ distributed_property_map(const ProcessGroup& pg,
+ const LocalPropertyMap& pm,
+ const Reduce& reduce);
+
+Construct a property map from a process group and a local property
+map. If a ``reduce`` operation is not supplied, a default of
+``basic_reduce<value_type>`` will be used.
+
+------------------------------------------------------------------------------
+
+::
+
+ template<typename Reduce> void set_reduce(const Reduce& reduce);
+
+Replace the current reduction operation with the new operation
+``reduce``.
+
+------------------------------------------------------------------------------
+
+::
+
+ void set_consistency_model(int model);
+
+Sets the consistency model of the distributed property map, which will
+take effect on the next synchronization step. See the section
+`Consistency models`_ for a description of the effect of various
+consistency model flags.
+
+------------------------------------------------------------------------------
+
+::
+
+ void flush();
+
+Emits a message sending the contents of all local ghost cells to the
+owners of those cells.
+
+------------------------------------------------------------------------------
+
+::
+
+ void reset();
+
+Replaces the values stored in each of the ghost cells with the default
+value generated by the reduction operation.
+
+------------------------------------------------------------------------------
+
+::
+
+ void clear();
+
+Removes all ghost cells from the property map.
+
+
+Free functions
+~~~~~~~~~~~~~~
+
+::
+
+ reference get(distributed_property_map pm, const key_type& key);
+
+Retrieves the element in ``pm`` associated with the given ``key``. If
+the key refers to data stored locally, returns the actual value
+associated with the key. If the key refers to nonlocal data, returns
+the value of the ghost cell. If no ghost cell exists, the behavior
+depends on the current reduction operation: if a reduction operation
+has been set and has ``non_default_resolver`` set ``true``, then a
+ghost cell will be created according to the default value provided by
+the reduction operation. Otherwise, the call to ``get`` will abort
+because no value exists for this remote cell. To avoid this problem,
+either set a reduction operation that generates default values,
+``request()`` the value and then perform a synchronization step, or
+``put`` a value into the cell before reading it.
+
+------------------------------------------------------------------------------
+
+::
+
+ void
+ put(distributed_property_map pm, const key_type& key, const value_type& value);
+
+Places the given ``value`` associated with ``key`` into property map
+``pm``. If the key refers to data stored locally, the value is
+immediately updates. If the key refers to data stored in a remote
+process, updates (or creates) a local ghost cell containing this
+value for the key and sends the new value to the owning process. Note
+that the owning process may reject this value based on the reduction
+operation, but this will not be detected until the next
+synchronization step.
+
+------------------------------------------------------------------------------
+
+::
+
+ void
+ local_put(distributed_property_map pm, const key_type& key, const value_type& value);
+
+Equivalent to ``put(pm, key, value)``, except that no message is sent
+to the owning process when the value is changed for a nonlocal key.
+
+------------------------------------------------------------------------------
+
+::
+
+ void synchronize(distributed_property_map& pm);
+
+Synchronize the values stored in the distributed property maps. Each
+process much execute ``synchronize`` at the same time, after which
+the ghost cells in every process will reflect the actual value stored
+in the owning process.
+
+------------------------------------------------------------------------------
+
+::
+
+ void request(distributed_property_map pm, const key_type& key);
+
+Request that the element "key" be available after the next
+synchronization step. For a non-local key, this means establishing a
+ghost cell and requesting.
+
+------------------------------------------------------------------------------
+
+::
+
+ template<typename Key, typename ProcessGroup, typename LocalPropertyMap>
+ distributed_property_map<ProcessGroup, LocalPropertyMap, Key>
+ make_distributed_property_map(const ProcessGroup& pg, LocalPropertyMap pmap);
+
+ template<typename Key, typename ProcessGroup, typename LocalPropertyMap,
+ typename Reduce>
+ distributed_property_map<ProcessGroup, LocalPropertyMap, Key>
+ make_distributed_property_map(const ProcessGroup& pg, LocalPropertyMap pmap,
+ Reduce reduce);
+
+Create a distributed property map over process group ``pg`` and local
+property map ``pmap``. A default reduction operation will be generated
+if it is not provided.
+
+---------------------------------
+Distributed iterator property map
+---------------------------------
+
+The distributed iterator property map adaptor permits the creation of
+distributed property maps from random access iterators using the same
+syntax as non-distributed iterator property maps. The specialization
+is based on a `local property map`_, which contains the
+indices for local descriptors and is typically returned to describe
+the vertex indices of a distributed graph.
+
+Synopsis
+~~~~~~~~
+
+::
+
+ template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference>
+ class iterator_property_map<RandomAccessIterator,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap>,
+ ValueType, Reference>
+ {
+ public:
+ typedef local_property_map<ProcessGroup, GlobalKey, LocalMap> index_map_type;
+
+ iterator_property_map();
+ iterator_property_map(RandomAccessIterator iter, const index_map_type& id);
+ };
+
+ reference get(iterator_property_map pm, const key_type& key);
+ void put(iterator_property_map pm, const key_type& key, const value_type& value);
+
+ template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap>
+ iterator_property_map<RandomAccessIterator,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap> >
+ make_iterator_property_map(RandomAccessIterator iter,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap> id);
+
+
+Member functions
+~~~~~~~~~~~~~~~~
+
+::
+
+ iterator_property_map();
+
+Default-constructs a distributed iterator property map. The property
+map is in an invalid state, and must be reassigned before it may be
+used.
+
+------------------------------------------------------------------------------
+
+::
+
+ iterator_property_map(RandomAccessIterator iter, const index_map_type& id);
+
+Constructs a distributed iterator property map using the property map
+``id`` to map global descriptors to local indices. The random access
+iterator sequence ``[iter, iter + n)`` must be a valid range, where
+``[0, n)`` is the range of local indices.
+
+Free functions
+~~~~~~~~~~~~~~
+
+::
+
+ reference get(iterator_property_map pm, const key_type& key);
+
+Returns the value associated with the given ``key`` from the
+distributed property map.
+
+------------------------------------------------------------------------------
+
+::
+
+ void put(iterator_property_map pm, const key_type& key, const value_type& value);
+
+Associates the value with the given key in the distributed property map.
+
+------------------------------------------------------------------------------
+
+::
+
+ template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference>
+ iterator_property_map<RandomAccessIterator,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap>,
+ ValueType, Reference>
+ make_iterator_property_map(RandomAccessIterator iter,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap>,
+ ValueType, Reference> id);
+
+Creates a distributed iterator property map using the given iterator
+``iter`` and local index property map ``id``.
+
+--------------------------------------
+Distributed safe iterator property map
+--------------------------------------
+
+The distributed safe iterator property map adaptor permits the
+creation of distributed property maps from random access iterators
+using the same syntax as non-distributed safe iterator property
+maps. The specialization is based on a `local property map`_, which
+contains the indices for local descriptors and is typically returned
+to describe the vertex indices of a distributed graph. Safe iterator
+property maps check the indices of accesses to ensure that they are
+not out-of-bounds before attempting to access an value.
+
+Synopsis
+~~~~~~~~
+
+::
+
+ template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference>
+ class safe_iterator_property_map<RandomAccessIterator,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap>,
+ ValueType, Reference>
+ {
+ public:
+ typedef local_property_map<ProcessGroup, GlobalKey, LocalMap> index_map_type;
+
+ safe_iterator_property_map();
+ safe_iterator_property_map(RandomAccessIterator iter, std::size_t n,
+ const index_map_type& id);
+ };
+
+ reference get(safe_iterator_property_map pm, const key_type& key);
+ void put(safe_iterator_property_map pm, const key_type& key, const value_type& value);
+
+ template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference>
+ safe_iterator_property_map<RandomAccessIterator,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap>,
+ ValueType, Reference>
+ make_safe_iterator_property_map(RandomAccessIterator iter,
+ std::size_t n,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap>,
+ ValueType, Reference> id);
+
+Member functions
+~~~~~~~~~~~~~~~~
+
+::
+
+ safe_iterator_property_map();
+
+Default-constructs a distributed safe iterator property map. The property
+map is in an invalid state, and must be reassigned before it may be
+used.
+
+------------------------------------------------------------------------------
+
+::
+
+ safe_iterator_property_map(RandomAccessIterator iter, std::size_t n,
+ const index_map_type& id);
+
+Constructs a distributed safe iterator property map using the property map
+``id`` to map global descriptors to local indices. The random access
+iterator sequence ``[iter, iter + n)``.
+
+Free functions
+~~~~~~~~~~~~~~
+
+::
+
+ reference get(safe_iterator_property_map pm, const key_type& key);
+
+Returns the value associated with the given ``key`` from the
+distributed property map.
+
+------------------------------------------------------------------------------
+
+::
+
+ void put(safe_iterator_property_map pm, const key_type& key, const value_type& value);
+
+Associates the value with the given key in the distributed property map.
+
+------------------------------------------------------------------------------
+
+::
+
+ template<typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference>
+ safe_iterator_property_map<RandomAccessIterator,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap>,
+ ValueType, Reference>
+ make_safe_iterator_property_map(RandomAccessIterator iter,
+ std::size_t n,
+ local_property_map<ProcessGroup, GlobalKey, LocalMap>,
+ ValueType, Reference> id);
+
+Creates a distributed safe iterator property map using the given iterator
+``iter`` and local index property map ``id``. The indices in ``id`` must
+
+------------------
+Local property map
+------------------
+
+A property map adaptor that accesses an underlying property map whose
+key type is the local part of the ``Key`` type for the local subset
+of keys. Local property maps are typically used by distributed graph
+types for vertex index properties.
+
+Synopsis
+~~~~~~~~
+
+::
+
+ template<typename ProcessGroup, typename GlobalKey, typename LocalMap>
+ class local_property_map
+ {
+ public:
+ typedef typename property_traits<LocalMap>::value_type value_type;
+ typedef GlobalKey key_type;
+ typedef typename property_traits<LocalMap>::reference reference;
+ typedef typename property_traits<LocalMap>::category category;
+
+ explicit
+ local_property_map(const ProcessGroup& process_group = ProcessGroup(),
+ const LocalMap& local_map = LocalMap());
+
+ reference operator[](const key_type& key);
+ };
+
+ reference get(const local_property_map& pm, key_type key);
+ void put(local_property_map pm, const key_type& key, const value_type& value);
+
+Template parameters
+~~~~~~~~~~~~~~~~~~~
+
+:ProcessGroup: the type of the process group over which the global
+ keys are distributed.
+
+:GlobalKey: The ``key_type`` of the local property map, which
+ must model the `Global Descriptor`_ concept. The process ID type of
+ the ``GlobalKey`` parameter must match the process ID type of the
+ ``ProcessGroup``, and the local descriptor type of the ``GlobalKey``
+ must be convertible to the ``key_type`` of the ``LocalMap``.
+
+:LocalMap: the type of the property map that will store values
+ for keys local to this processor. The ``value_type`` of this
+ property map will become the ``value_type`` of the local
+ property map. The local property map models the same property
+ map concepts as the ``LocalMap``.
+
+Member functions
+~~~~~~~~~~~~~~~~
+
+::
+
+ explicit
+ local_property_map(const ProcessGroup& process_group = ProcessGroup(),
+ const LocalMap& local_map = LocalMap());
+
+Constructs a local property map whose keys are distributed across the
+given process group and which accesses the given local map.
+
+------------------------------------------------------------------------------
+
+::
+
+ reference operator[](const key_type& key);
+
+Access the value associated with the given key, which must be local
+to this process.
+
+Free functions
+~~~~~~~~~~~~~~
+
+::
+
+ reference get(const local_property_map& pm, key_type key);
+
+Return the value associated with the given key, which must be local
+to this process.
+
+------------------------------------------------------------------------------
+
+::
+
+ void put(local_property_map pm, const key_type& key, const value_type& value);
+
+Set the value associated with the given key, which must be local to
+this process.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004, 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Readable Property Map: http://www.boost.org/libs/property_map/ReadablePropertyMap.html
+.. _Writable Property Map: http://www.boost.org/libs/property_map/WritablePropertyMap.html
+.. _Read/Write Property Map: http://www.boost.org/libs/property_map/ReadWritePropertyMap.html
+.. _Lvalue Property Map: http://www.boost.org/libs/property_map/LvaluePropertyMap.html
+.. _Process Group: process_group.html
+.. _Global Descriptor: GlobalDescriptor.html
+.. _Dijkstra's shortest paths: dijkstra_shortest_paths.html
+.. _Breadth-First Search: breadth_first_search.html
+.. _PageRank: page_rank.html
+

Added: trunk/libs/graph_parallel/doc/distributed_queue.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/distributed_queue.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,210 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+================================
+|Logo| Distributed queue adaptor
+================================
+
+::
+
+ template<typename ProcessGroup, typename Buffer>
+ class distributed_queue
+ {
+ public:
+ typedef ProcessGroup process_group_type;
+ typedef Buffer buffer_type;
+ typedef typename buffer_type::value_type value_type;
+ typedef typename buffer_type::size_type size_type;
+
+ explicit
+ distributed_queue(const ProcessGroup& process_group = ProcessGroup(),
+ const Buffer& buffer = Buffer(),
+ bool polling = false);
+
+ distributed_queue(const ProcessGroup& process_group, bool polling);
+
+ void push(const value_type& x);
+ void pop();
+ value_type& top();
+ const value_type& top() const;
+ bool empty() const;
+ size_type size() const;
+ };
+
+ template<typename ProcessGroup, typename Buffer>
+ inline distributed_queue<ProcessGroup, Buffer>
+ make_distributed_queue(const ProcessGroup& process_group, const Buffer& buffer,
+ bool polling = false);
+
+Class template ``distributed_queue`` implements a distributed queue
+across a process group. The distributed queue is an adaptor over an
+existing (local) queue, which must model the Buffer_ concept. Each
+process stores a distinct copy of the local queue, from which it draws
+or removes elements via the ``pop`` and ``top`` members.
+
+The value type of the local queue must be a model of the
+`Global Descriptor`_ concept. The ``push`` operation of the
+distributed queue passes (via a message) the value to its owning
+processor. Thus, the elements within a particular local queue are
+guaranteed to have the process owning that local queue as an owner.
+
+Synchronization of distributed queues occurs in the ``empty`` and
+``size`` functions, which will only return "empty" values (true or 0,
+respectively) when the entire distributed queue is empty. If the local
+queue is empty but the distributed queue is not, the operation will
+block until either condition changes. When the ``size`` function of a
+nonempty queue returns, it returns the size of the local queue. These
+semantics were selected so that sequential code that processes
+elements in the queue via the following idiom can be parallelized via
+introduction of a distributed queue:
+
+::
+
+ distributed_queue<...> Q;
+ Q.push(x);
+ while (!Q.empty()) {
+ // do something, that may push a value onto Q
+ }
+
+In the parallel version, the initial ``push`` operation will place
+the value ``x`` onto its owner's queue. All processes will
+synchronize at the call to empty, and only the process owning ``x``
+will be allowed to execute the loop (``Q.empty()`` returns
+false). This iteration may in turn push values onto other remote
+queues, so when that process finishes execution of the loop body
+and all processes synchronize again in ``empty``, more processes
+may have nonempty local queues to execute. Once all local queues
+are empty, ``Q.empty()`` returns ``false`` for all processes.
+
+The distributed queue can receive messages at two different times:
+during synchronization and when polling ``empty``. Messages are
+always received during synchronization, to ensure that accurate
+local queue sizes can be determines. However, whether ``empty``
+should poll for messages is specified as an option to the
+constructor. Polling may be desired when the order in which
+elements in the queue are processed is not important, because it
+permits fewer synchronization steps and less communication
+overhead. However, when more strict ordering guarantees are
+required, polling may be semantically incorrect. By disabling
+polling, one ensures that parallel execution using the idiom above
+will not process an element at a later "level" before an earlier
+"level".
+
+The distributed queue nearly models the Buffer_
+concept. However, the ``push`` routine does not necessarily
+increase the result of ``size()`` by one (although the size of the
+global queue does increase by one).
+
+Member Functions
+----------------
+
+::
+
+ explicit
+ distributed_queue(const ProcessGroup& process_group = ProcessGroup(),
+ const Buffer& buffer = Buffer(),
+ bool polling = false);
+
+Build a new distributed queue that communicates over the given
+``process_group``, whose local queue is initialized via ``buffer`` and
+which may or may not poll for messages.
+
+-----------------------------------------------------------------------------
+
+::
+
+ distributed_queue(const ProcessGroup& process_group, bool polling);
+
+Build a new distributed queue that communicates over the given
+``process_group``, whose local queue is default-initalized and which
+may or may not poll for messages.
+
+-----------------------------------------------------------------------------
+
+::
+
+ void push(const value_type& x);
+
+Push an element onto the distributed queue.
+
+The element will be sent to its owner process to be added to that
+process's local queue. If polling is enabled for this queue and
+the owner process is the current process, the value will be
+immediately pushed onto the local queue.
+
+Complexity: O(1) messages of size O(``sizeof(value_type)``) will be
+transmitted.
+
+
+-----------------------------------------------------------------------------
+
+::
+
+ void pop();
+
+Pop an element off the local queue. The queue must not be ``empty()``.
+
+-----------------------------------------------------------------------------
+
+::
+
+ value_type& top();
+ const value_type& top();
+
+Returns the top element in the local queue. The queue must not be
+``empty()``.
+
+-----------------------------------------------------------------------------
+
+::
+
+ bool empty() const;
+
+Determines if the queue is empty.
+
+When the local queue is nonempty, returns true. If the local queue is
+empty, synchronizes with all other processes in the process group
+until either (1) the local queue is nonempty (returns true) (2) the
+entire distributed queue is empty (returns false).
+
+-----------------------------------------------------------------------------
+
+::
+
+ size_type size() const;
+
+
+Determines the size of the local queue.
+
+The behavior of this routine is equivalent to the behavior of
+``empty``, except that when ``empty`` returns true this
+function returns the size of the local queue and when ``empty``
+returns false this function returns zero.
+
+Free Functions
+--------------
+
+::
+
+ template<typename ProcessGroup, typename Buffer>
+ inline distributed_queue<ProcessGroup, Buffer>
+ make_distributed_queue(const ProcessGroup& process_group, const Buffer& buffer,
+ bool polling = false);
+
+Constructs a distributed queue.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004, 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Global descriptor: GlobalDescriptor.html
+.. _Buffer: http://www.boost.org/libs/graph/doc/Buffer.html

Added: trunk/libs/graph_parallel/doc/fruchterman_reingold.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/fruchterman_reingold.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,20 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===========================
+|Logo| Fruchterman Reingold
+===========================
+
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl

Added: trunk/libs/graph_parallel/doc/graph.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/html/DistributedEdgeListGraph.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/DistributedEdgeListGraph.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Concept Distributed Edge List Graph</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-concept-distributed-edge-list-graph">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Concept Distributed Edge List Graph</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#description" id="id1">Description</a></li>
+<li><a class="reference internal" href="#notation" id="id2">Notation</a></li>
+<li><a class="reference internal" href="#refinement-of" id="id3">Refinement of</a></li>
+<li><a class="reference internal" href="#associated-types" id="id4">Associated types</a></li>
+<li><a class="reference internal" href="#valid-expressions" id="id5">Valid Expressions</a></li>
+<li><a class="reference internal" href="#models" id="id6">Models</a></li>
+</ul>
+</div>
+<div class="section" id="description">
+<h1><a class="toc-backref" href="#id1">Description</a></h1>
+<p>A Distributed Edge List Graph is a graph whose vertices are
+distributed across multiple processes or address spaces. The
+<tt class="docutils literal"><span class="pre">vertices</span></tt> and <tt class="docutils literal"><span class="pre">num_vertices</span></tt> functions retain the same
+signatures as in the <a class="reference external" href="http://www.boost.org/libs/graph/doc/EdgeListGraph.html">Edge List Graph</a> concept, but return only
+the local set (and size of the local set) of vertices.</p>
+</div>
+<div class="section" id="notation">
+<h1><a class="toc-backref" href="#id2">Notation</a></h1>
+<dl class="docutils">
+<dt>G</dt>
+<dd>A type that models the Distributed Edge List Graph concept.</dd>
+<dt>g</dt>
+<dd>An object of type <tt class="docutils literal"><span class="pre">G</span></tt>.</dd>
+</dl>
+</div>
+<div class="section" id="refinement-of">
+<h1><a class="toc-backref" href="#id3">Refinement of</a></h1>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="http://www.boost.org/libs/graph/doc/Graph.html">Graph</a></li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="associated-types">
+<h1><a class="toc-backref" href="#id4">Associated types</a></h1>
+<table border="1" class="docutils">
+<colgroup>
+<col width="18%" />
+<col width="44%" />
+<col width="38%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>Edge
+descriptor type</td>
+<td><tt class="docutils literal"><span class="pre">graph_traits&lt;G&gt;::edge_descriptor</span></tt></td>
+<td>Must model the
+<a class="reference external" href="GlobalDescriptor.html">Global Descriptor</a> concept.</td>
+</tr>
+<tr><td>Edge iterator
+type</td>
+<td><tt class="docutils literal"><span class="pre">graph_traits&lt;G&gt;::edge_iterator</span></tt></td>
+<td>Iterates over edges stored
+locally. The value type must be
+<tt class="docutils literal"><span class="pre">edge_descriptor</span></tt>.</td>
+</tr>
+<tr><td>Edges size
+type</td>
+<td><tt class="docutils literal"><span class="pre">graph_traits&lt;G&gt;::edges_size_type</span></tt></td>
+<td>The unsigned integral type used
+to store the number of edges
+in the local subgraph.</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="valid-expressions">
+<h1><a class="toc-backref" href="#id5">Valid Expressions</a></h1>
+<table border="1" class="docutils">
+<colgroup>
+<col width="17%" />
+<col width="22%" />
+<col width="23%" />
+<col width="39%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Name</th>
+<th class="head">Expression</th>
+<th class="head">Type</th>
+<th class="head">Semantics</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>Local edge set</td>
+<td><tt class="docutils literal"><span class="pre">edges(g)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">std::pair&lt;</span></tt>
+<tt class="docutils literal"><span class="pre">edge_iterator,</span></tt>
+<tt class="docutils literal"><span class="pre">edge_iterator&gt;</span></tt></td>
+<td>Returns an iterator range
+providing access to the local
+edges in the graph.</td>
+</tr>
+<tr><td>Number of local
+edges.</td>
+<td><tt class="docutils literal"><span class="pre">num_edges(g)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">edges_size_type</span></tt></td>
+<td>Returns the number of edges
+stored locally in the graph.</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="models">
+<h1><a class="toc-backref" href="#id6">Models</a></h1>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="distributed_adjacency_list.html">Distributed adjacency list</a></li>
+</ul>
+</blockquote>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/DistributedGraph.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/DistributedGraph.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Concept Distributed Graph</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-concept-distributed-graph">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Concept Distributed Graph</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#description" id="id1">Description</a></li>
+<li><a class="reference internal" href="#notation" id="id2">Notation</a></li>
+<li><a class="reference internal" href="#refinement-of" id="id3">Refinement of</a></li>
+<li><a class="reference internal" href="#associated-types" id="id4">Associated types</a></li>
+<li><a class="reference internal" href="#models" id="id5">Models</a></li>
+</ul>
+</div>
+<div class="section" id="description">
+<h1><a class="toc-backref" href="#id1">Description</a></h1>
+<p>A Distributed Graph is a graph whose vertices or edges are
+distributed across multiple processes or address spaces. The
+descriptors of a Distributed Graph must model the <a class="reference external" href="GlobalDescriptor.html">Global
+Descriptor</a> concept.</p>
+</div>
+<div class="section" id="notation">
+<h1><a class="toc-backref" href="#id2">Notation</a></h1>
+<dl class="docutils">
+<dt>G</dt>
+<dd>A type that models the Distributed Graph concept.</dd>
+</dl>
+</div>
+<div class="section" id="refinement-of">
+<h1><a class="toc-backref" href="#id3">Refinement of</a></h1>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="http://www.boost.org/libs/graph/doc/Graph.html">Graph</a></li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="associated-types">
+<h1><a class="toc-backref" href="#id4">Associated types</a></h1>
+<table border="1" class="docutils">
+<colgroup>
+<col width="18%" />
+<col width="44%" />
+<col width="38%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>Vertex
+descriptor type</td>
+<td><tt class="docutils literal"><span class="pre">graph_traits&lt;G&gt;::vertex_descriptor</span></tt></td>
+<td>Must model the
+<a class="reference external" href="GlobalDescriptor.html">Global Descriptor</a> concept.</td>
+</tr>
+<tr><td>Edge
+descriptor type</td>
+<td><tt class="docutils literal"><span class="pre">graph_traits&lt;G&gt;::edge_descriptor</span></tt></td>
+<td>Must model the
+<a class="reference external" href="GlobalDescriptor.html">Global Descriptor</a> concept.</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="models">
+<h1><a class="toc-backref" href="#id5">Models</a></h1>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="distributed_adjacency_list.html">Distributed adjacency list</a></li>
+</ul>
+</blockquote>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:13 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/DistributedVertexListGraph.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/DistributedVertexListGraph.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Concept Distributed Vertex List Graph</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-concept-distributed-vertex-list-graph">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Concept Distributed Vertex List Graph</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#description" id="id1">Description</a></li>
+<li><a class="reference internal" href="#notation" id="id2">Notation</a></li>
+<li><a class="reference internal" href="#refinement-of" id="id3">Refinement of</a></li>
+<li><a class="reference internal" href="#associated-types" id="id4">Associated types</a></li>
+<li><a class="reference internal" href="#valid-expressions" id="id5">Valid Expressions</a></li>
+<li><a class="reference internal" href="#models" id="id6">Models</a></li>
+</ul>
+</div>
+<div class="section" id="description">
+<h1><a class="toc-backref" href="#id1">Description</a></h1>
+<p>A Distributed Vertex List Graph is a graph whose vertices are
+distributed across multiple processes or address spaces. The
+<tt class="docutils literal"><span class="pre">vertices</span></tt> and <tt class="docutils literal"><span class="pre">num_vertices</span></tt> functions retain the same
+signatures as in the <a class="reference external" href="http://www.boost.org/libs/graph/doc/VertexListGraph.html">Vertex List Graph</a> concept, but return only
+the local set (and size of the local set) of vertices.</p>
+</div>
+<div class="section" id="notation">
+<h1><a class="toc-backref" href="#id2">Notation</a></h1>
+<dl class="docutils">
+<dt>G</dt>
+<dd>A type that models the Distributed Vertex List Graph concept.</dd>
+<dt>g</dt>
+<dd>An object of type <tt class="docutils literal"><span class="pre">G</span></tt>.</dd>
+</dl>
+</div>
+<div class="section" id="refinement-of">
+<h1><a class="toc-backref" href="#id3">Refinement of</a></h1>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="http://www.boost.org/libs/graph/doc/Graph.html">Graph</a></li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="associated-types">
+<h1><a class="toc-backref" href="#id4">Associated types</a></h1>
+<table border="1" class="docutils">
+<colgroup>
+<col width="18%" />
+<col width="44%" />
+<col width="38%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>Vertex
+descriptor type</td>
+<td><tt class="docutils literal"><span class="pre">graph_traits&lt;G&gt;::vertex_descriptor</span></tt></td>
+<td>Must model the
+<a class="reference external" href="GlobalDescriptor.html">Global Descriptor</a> concept.</td>
+</tr>
+<tr><td>Vertex iterator
+type</td>
+<td><tt class="docutils literal"><span class="pre">graph_traits&lt;G&gt;::vertex_iterator</span></tt></td>
+<td>Iterates over vertices stored
+locally. The value type must be
+<tt class="docutils literal"><span class="pre">vertex_descriptor</span></tt>.</td>
+</tr>
+<tr><td>Vertices size
+type</td>
+<td><tt class="docutils literal"><span class="pre">graph_traits&lt;G&gt;::vertices_size_type</span></tt></td>
+<td>The unsigned integral type used
+to store the number of vertices
+in the local subgraph.</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="valid-expressions">
+<h1><a class="toc-backref" href="#id5">Valid Expressions</a></h1>
+<table border="1" class="docutils">
+<colgroup>
+<col width="17%" />
+<col width="22%" />
+<col width="23%" />
+<col width="39%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Name</th>
+<th class="head">Expression</th>
+<th class="head">Type</th>
+<th class="head">Semantics</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>Local vertex set</td>
+<td><tt class="docutils literal"><span class="pre">vertices(g)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">std::pair&lt;</span></tt>
+<tt class="docutils literal"><span class="pre">vertex_iterator,</span></tt>
+<tt class="docutils literal"><span class="pre">vertex_iterator&gt;</span></tt></td>
+<td>Returns an iterator range
+providing access to the local
+vertices in the graph.</td>
+</tr>
+<tr><td>Number of local
+vertices.</td>
+<td><tt class="docutils literal"><span class="pre">num_vertices(g)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">vertices_size_type</span></tt></td>
+<td>Returns the number of vertices
+stored locally in the graph.</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="models">
+<h1><a class="toc-backref" href="#id6">Models</a></h1>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="distributed_adjacency_list.html">Distributed adjacency list</a></li>
+</ul>
+</blockquote>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/GlobalDescriptor.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/GlobalDescriptor.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Concept Global Descriptor</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-concept-global-descriptor">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Concept Global Descriptor</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#description" id="id1">Description</a></li>
+<li><a class="reference internal" href="#refinement-of" id="id2">Refinement of</a></li>
+<li><a class="reference internal" href="#notation" id="id3">Notation</a></li>
+<li><a class="reference internal" href="#associated-types" id="id4">Associated types</a></li>
+<li><a class="reference internal" href="#valid-expressions" id="id5">Valid Expressions</a></li>
+</ul>
+</div>
+<div class="section" id="description">
+<h1><a class="toc-backref" href="#id1">Description</a></h1>
+<p>A global descriptor is an object that represents an entity that is
+owned by some process and may reside in an address space not
+accessible to the currently-executing process. The global descriptor
+consists of two parts: the <em>owner</em> of the entity, which is the
+identifier of that process in which the entity resides, and a <em>local
+descriptor</em>, that uniquely identifies the entity with the address
+space of the owner.</p>
+</div>
+<div class="section" id="refinement-of">
+<h1><a class="toc-backref" href="#id2">Refinement of</a></h1>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</a></li>
+<li><a class="reference external" href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a></li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="notation">
+<h1><a class="toc-backref" href="#id3">Notation</a></h1>
+<dl class="docutils">
+<dt>X</dt>
+<dd>A type that models the Global Descriptor concept.</dd>
+<dt>x</dt>
+<dd>Object of type X</dd>
+</dl>
+</div>
+<div class="section" id="associated-types">
+<h1><a class="toc-backref" href="#id4">Associated types</a></h1>
+<table border="1" class="docutils">
+<colgroup>
+<col width="23%" />
+<col width="29%" />
+<col width="48%" />
+</colgroup>
+<tbody valign="top">
+<tr><td>Process ID type</td>
+<td><tt class="docutils literal"><span class="pre">process_id_type</span></tt></td>
+<td>Determined by the process group
+associated with type X.</td>
+</tr>
+<tr><td>Local descriptor
+type</td>
+<td><tt class="docutils literal"><span class="pre">local_type</span></tt></td>
+<td>Determined by the data structure
+the descriptor accesses.
+Must model <a class="reference external" href="http://www.sgi.com/tech/stl/EqualityComparable.html">Equality Comparable</a>
+and <a class="reference external" href="http://www.sgi.com/tech/stl/CopyConstructible.html">Copy Constructible</a>.</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="valid-expressions">
+<h1><a class="toc-backref" href="#id5">Valid Expressions</a></h1>
+<table border="1" class="docutils">
+<colgroup>
+<col width="17%" />
+<col width="22%" />
+<col width="22%" />
+<col width="39%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Name</th>
+<th class="head">Expression</th>
+<th class="head">Type</th>
+<th class="head">Semantics</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>Owner</td>
+<td><tt class="docutils literal"><span class="pre">owner(x)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">process_id_type</span></tt></td>
+<td>Returns the owner of <tt class="docutils literal"><span class="pre">x</span></tt>.</td>
+</tr>
+<tr><td>Local descriptor</td>
+<td><tt class="docutils literal"><span class="pre">local(x)</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">local_type</span></tt></td>
+<td>Returns the local descriptor
+uniquely identifying <tt class="docutils literal"><span class="pre">x</span></tt>.</td>
+</tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:13 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/betweenness_centrality.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/betweenness_centrality.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Betweenness Centrality</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-betweenness-centrality">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Betweenness Centrality</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/boman_et_al_graph_coloring.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/boman_et_al_graph_coloring.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Boman et al graph coloring</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-boman-et-al-graph-coloring">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Boman et al graph coloring</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+namespace graph {
+ template&lt;typename DistributedGraph, typename ColorMap&gt;
+ typename property_traits&lt;ColorMap&gt;::value_type
+ boman_et_al_graph_coloring
+ (const DistributedGraph&amp; g,
+ ColorMap color,
+ typename graph_traits&lt;DistributedGraph&gt;::vertices_size_type s = 100);
+
+ template&lt;typename DistributedGraph, typename ColorMap, typename ChooseColor&gt;
+ typename property_traits&lt;ColorMap&gt;::value_type
+ boman_et_al_graph_coloring
+ (const DistributedGraph&amp; g,
+ ColorMap color,
+ typename graph_traits&lt;DistributedGraph&gt;::vertices_size_type s,
+ ChooseColor choose_color);
+
+ template&lt;typename DistributedGraph, typename ColorMap, typename ChooseColor,
+ typename VertexOrdering&gt;
+ typename property_traits&lt;ColorMap&gt;::value_type
+ boman_et_al_graph_coloring
+ (const DistributedGraph&amp; g, ColorMap color,
+ typename graph_traits&lt;DistributedGraph&gt;::vertices_size_type s,
+ ChooseColor choose_color, VertexOrdering ordering);
+
+ template&lt;typename DistributedGraph, typename ColorMap, typename ChooseColor,
+ typename VertexOrdering, typename VertexIndexMap&gt;
+ typename property_traits&lt;ColorMap&gt;::value_type
+ boman_et_al_graph_coloring
+ (const DistributedGraph&amp; g,
+ ColorMap color,
+ typename graph_traits&lt;DistributedGraph&gt;::vertices_size_type s,
+ ChooseColor choose_color,
+ VertexOrdering ordering, VertexIndexMap vertex_index);
+}
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">boman_et_al_graph_coloring</span></tt> function colors the vertices of an
+undirected, distributed graph such that no two adjacent vertices have
+the same color. All of the vertices of a given color form an
+independent set in the graph. Graph coloring has been used to solve
+various problems, including register allocation in compilers,
+optimization problems, and scheduling problems.</p>
+<img align="right" alt="Vertex coloring example" class="align-right" src="vertex_coloring.png" style="width: 462px; height: 269px;" />
+<p>The problem of coloring a graph with the fewest possible number of
+colors is NP-complete, so many algorithms (including the one
+implemented here) are heuristic algorithms that try to minimize the
+number of colors but are not guaranteed to provide an optimal
+solution. This algorithm <a class="citation-reference" href="#bbc05" id="id1">[BBC05]</a> is similar to the
+<tt class="docutils literal"><span class="pre">sequential_vertex_coloring</span></tt> algorithm, that iterates through the
+vertices once and selects the lowest-numbered color that the current
+vertex can have. The coloring and the number of colors is therefore
+related to the ordering of the vertices in the sequential case.</p>
+<p>The distributed <tt class="docutils literal"><span class="pre">boman_et_al_graph_coloring</span></tt> algorithm will produce
+different colorings depending on the ordering and distribution of the
+vertices and the number of parallel processes cooperating to perform
+the coloring.</p>
+<p>The algorithm returns the number of colors <tt class="docutils literal"><span class="pre">num_colors</span></tt> used to
+color the graph.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id2">Where Defined</a></li>
+<li><a class="reference internal" href="#parameters" id="id3">Parameters</a></li>
+<li><a class="reference internal" href="#complexity" id="id4">Complexity</a></li>
+<li><a class="reference internal" href="#performance" id="id5">Performance</a></li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id2">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/boman_et_al_graph_coloring.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="parameters">
+<h1><a class="toc-backref" href="#id3">Parameters</a></h1>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph type must be a model of <a class="reference external" href="DistributedVertexListGraph.html">Distributed Vertex List Graph</a> and
+<a class="reference external" href="DistributedEdgeListGraph.html">Distributed Edge List Graph</a>.</dd>
+<dt>UTIL/OUT: <tt class="docutils literal"><span class="pre">ColorMap</span> <span class="pre">color</span></tt></dt>
+<dd>Stores the color of each vertex, which will be a value in the range
+[0, <tt class="docutils literal"><span class="pre">num_colors</span></tt>). The type <tt class="docutils literal"><span class="pre">ColorMap</span></tt> must model the
+<a class="reference external" href="http://www.boost.org/libs/property_map/ReadWritePropertyMap.html">Read/Write Property Map</a> concept and must be a <a class="reference external" href="distributed_property_map.html">distributed
+property map</a>.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">vertices_size_type</span> <span class="pre">s</span></tt></dt>
+<dd><p class="first">The number of vertices to color within each superstep. After
+<tt class="docutils literal"><span class="pre">s</span></tt> vertices have been colored, the colors of boundary vertices
+will be sent to their out-of-process neighbors. Smaller values
+communicate more often but may reduce the risk of conflicts,
+whereas larger values do more work in between communication steps
+but may create many conflicts.</p>
+<p class="last"><strong>Default</strong>: 100</p>
+</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">ChooseColor</span> <span class="pre">choose_color</span></tt></dt>
+<dd><p class="first">A function object that chooses the color for a vertex given the
+colors of its neighbors. The function object will be passed a vector
+of values (<tt class="docutils literal"><span class="pre">marked</span></tt>) and a <tt class="docutils literal"><span class="pre">marked_true</span></tt> value, and should
+return a <tt class="docutils literal"><span class="pre">color</span></tt> value such that <tt class="docutils literal"><span class="pre">color</span> <span class="pre">&gt;=</span> <span class="pre">marked.size()</span></tt> or
+<tt class="docutils literal"><span class="pre">marked[color]</span> <span class="pre">!=</span> <span class="pre">marked_true</span></tt>.</p>
+<p class="last"><strong>Default</strong>:
+<tt class="docutils literal"><span class="pre">boost::graph::distributed::first_fit_color&lt;color_type&gt;()</span></tt>, where
+<tt class="docutils literal"><span class="pre">color_type</span></tt> is the value type of the <tt class="docutils literal"><span class="pre">ColorMap</span></tt> property map.</p>
+</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">VertexOrdering</span> <span class="pre">ordering</span></tt></dt>
+<dd><p class="first">A binary predicate function object that provides total ordering on
+the vertices in the graph. Whenever a conflict arises, only one of
+the processes involved will recolor the vertex in the next round,
+and this ordering determines which vertex should be considered
+conflicting (its owning process will then handle the
+conflict). Ideally, this predicate should order vertices so that
+conflicting vertices will be spread uniformly across
+processes. However, this predicate <em>must</em> resolve the same way on
+both processors.</p>
+<p class="last"><strong>Default</strong>: <em>unspecified</em></p>
+</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">VertexIndexMap</span> <span class="pre">index</span></tt></dt>
+<dd><p class="first">A mapping from vertex descriptors to indices in the range <em>[0,
+num_vertices(g))</em>. This must be a <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable Property Map</a> whose
+key type is a vertex descriptor and whose value type is an integral
+type, typically the <tt class="docutils literal"><span class="pre">vertices_size_type</span></tt> of the graph.</p>
+<p class="last"><strong>Default:</strong> <tt class="docutils literal"><span class="pre">get(vertex_index,</span> <span class="pre">g)</span></tt></p>
+</dd>
+</dl>
+</div>
+<div class="section" id="complexity">
+<h1><a class="toc-backref" href="#id4">Complexity</a></h1>
+<p>The complexity of this algorithm is hard to characterize,
+because it depends greatly on the number of <em>conflicts</em> that occur
+during the algorithm. A conflict occurs when a <em>boundary vertex</em>
+(i.e., a vertex that is adjacent to a vertex stored on a different
+processor) is given the same color is a boundary vertex adjacency to
+it (but on another processor). Conflicting vertices must be assigned
+new colors, requiring additional work and communication. The work
+involved in reassigning a color for a conflicting vertex is <em>O(d)</em>,
+where <em>d</em> is the degree of the vertex and <em>O(1)</em> messages of <em>O(1)</em>
+size are needed to resolve the conflict. Note that the number of
+conflicts grows with (1) the number of processes and (2) the number
+of inter-process edges.</p>
+</div>
+<div class="section" id="performance">
+<h1><a class="toc-backref" href="#id5">Performance</a></h1>
+<p>The performance of this implementation of Bomen et al's graph coloring
+algorithm is illustrated by the following charts. Scaling and
+performance is reasonable for all of the graphs we have tried.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;cluster=Odin&amp;columns=11" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;cluster=Odin&amp;columns=11" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;cluster=Odin&amp;columns=11&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;cluster=Odin&amp;columns=11&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;cluster=Odin&amp;columns=11" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;cluster=Odin&amp;columns=11" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;cluster=Odin&amp;columns=11&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;cluster=Odin&amp;columns=11&amp;speedup=1" />
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+<table class="docutils citation" frame="void" id="bbc05" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[BBC05]</a></td><td>Erik G. Boman, Doruk Bozdag, Umit Catalyurek, Assefaw
+H. Gebremedhin, and Fredrik Manne. A Scalable Parallel Graph Coloring
+Algorithm for Distributed Memory Computers. [preprint]</td></tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/breadth_first_search.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/breadth_first_search.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Breadth-First Search</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-breadth-first-search">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Breadth-First Search</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+// named parameter version
+template &lt;class Graph, class P, class T, class R&gt;
+void breadth_first_search(Graph&amp; G,
+ typename graph_traits&lt;Graph&gt;::vertex_descriptor s,
+ const bgl_named_params&lt;P, T, R&gt;&amp; params);
+
+// non-named parameter version
+template &lt;class Graph, class Buffer, class BFSVisitor,
+ class ColorMap&gt;
+void breadth_first_search(const Graph&amp; g,
+ typename graph_traits&lt;Graph&gt;::vertex_descriptor s,
+ Buffer&amp; Q, BFSVisitor vis, ColorMap color);
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">breadth_first_search()</span></tt> function performs a distributed breadth-first
+traversal of a directed or undirected graph. The distributed BFS is
+syntactically equivalent to its <a class="reference external" href="http://www.boost.org/libs/graph/doc/breadth_first_search.html">sequential counterpart</a>, which
+provides additional background and discussion. Differences in
+semantics are highlighted here, and we refer the reader to the
+documentation of the <a class="reference external" href="http://www.boost.org/libs/graph/doc/breadth_first_search.html">sequential breadth-first search</a> for the
+remainder of the details.</p>
+<p>This distributed breadth-first search algorithm implements a
+<em>level-synchronized</em> breadth-first search, meaning that all vertices
+in a given level of the BFS tree will be processed (potentially in
+parallel) before any vertices from a successive level in the tree are
+processed. Distributed breadth-first search visitors should account
+for this behavior, a topic discussed further in <a class="reference internal" href="#visitor-event-points">Visitor Event
+Points</a>.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id1">Where Defined</a></li>
+<li><a class="reference internal" href="#parameter-defaults" id="id2">Parameter Defaults</a></li>
+<li><a class="reference internal" href="#complexity" id="id3">Complexity</a></li>
+<li><a class="reference internal" href="#visitor-event-points" id="id4">Visitor Event Points</a><ul>
+<li><a class="reference internal" href="#making-visitors-safe-for-distributed-bfs" id="id5">Making Visitors Safe for Distributed BFS</a></li>
+<li><a class="reference internal" href="#distributed-bfs-visitor-example" id="id6">Distributed BFS Visitor Example</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#performance" id="id7">Performance</a></li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id1">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/breadth_first_search.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="parameter-defaults">
+<h1><a class="toc-backref" href="#id2">Parameter Defaults</a></h1>
+<p>All parameters of the <a class="reference external" href="http://www.boost.org/libs/graph/doc/breadth_first_search.html">sequential breadth-first search</a> are supported
+and have essentially the same meaning. Only differences are documented
+here.</p>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph type must be a model of <a class="reference external" href="DistributedGraph.html">Distributed Graph</a>.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">vertex_descriptor</span> <span class="pre">s</span></tt></dt>
+<dd>The start vertex must be the same in every process.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">visitor(BFSVisitor</span> <span class="pre">vis)</span></tt></dt>
+<dd>The visitor must be a distributed BFS visitor. The suble differences
+between sequential and distributed BFS visitors are discussed in the
+section <a class="reference internal" href="#visitor-event-points">Visitor Event Points</a>.</dd>
+<dt>UTIL/OUT: <tt class="docutils literal"><span class="pre">color_map(ColorMap</span> <span class="pre">color)</span></tt></dt>
+<dd>The color map must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> with the same
+process group as the graph <tt class="docutils literal"><span class="pre">g</span></tt> whose colors must monotonically
+darken (white -&gt; gray -&gt; black). The default value is a distributed
+<tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> created from a <tt class="docutils literal"><span class="pre">std::vector</span></tt> of
+<tt class="docutils literal"><span class="pre">default_color_type</span></tt>.</dd>
+<dt>UTIL: <tt class="docutils literal"><span class="pre">buffer(Buffer&amp;</span> <span class="pre">Q)</span></tt></dt>
+<dd><p class="first">The queue must be a distributed queue that passes vertices to their
+owning process. If already-visited vertices should not be visited
+again (as is typical for BFS), the queue must filter duplicates
+itself. The queue controls synchronization within the algorithm: its
+<tt class="docutils literal"><span class="pre">empty()</span></tt> method must not return <tt class="docutils literal"><span class="pre">true</span></tt> until all local queues
+are empty.</p>
+<dl class="last docutils">
+<dt><strong>Default:</strong> A <tt class="docutils literal"><span class="pre">distributed_queue</span></tt> of a <tt class="docutils literal"><span class="pre">filtered_queue</span></tt> over a</dt>
+<dd>standard <tt class="docutils literal"><span class="pre">boost::queue</span></tt>. This queue filters out duplicate
+vertices and distributes vertices appropriately.</dd>
+</dl>
+</dd>
+</dl>
+</div>
+<div class="section" id="complexity">
+<h1><a class="toc-backref" href="#id3">Complexity</a></h1>
+<p>This algorithm performs <em>O(V + E)</em> work in <em>d + 1</em> BSP supersteps,
+where <em>d</em> is the diameter of the connected component being
+searched. Over all supersteps, <em>O(E)</em> messages of constant size will
+be transmitted.</p>
+</div>
+<div class="section" id="visitor-event-points">
+<h1><a class="toc-backref" href="#id4">Visitor Event Points</a></h1>
+<p>The <a class="reference external" href="http://www.boost.org/libs/graph/doc/BFSVisitor.html">BFS Visitor</a> concept defines 9 event points that will be
+triggered by the <a class="reference external" href="http://www.boost.org/libs/graph/doc/breadth_first_search.html">sequential breadth-first search</a>. The distributed
+BFS retains these nine event points, but the sequence of events
+triggered and the process in which each event occurs will change
+depending on the distribution of the graph.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">initialize_vertex(s,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by every process for each local vertex.</dd>
+<dt><tt class="docutils literal"><span class="pre">discover_vertex(u,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked each time a process discovers a new vertex
+<tt class="docutils literal"><span class="pre">u</span></tt>. Due to incomplete information in distributed property maps,
+this event may be triggered many times for the same vertex <tt class="docutils literal"><span class="pre">u</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">examine_vertex(u,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by the process owning the vertex <tt class="docutils literal"><span class="pre">u</span></tt>. If the
+distributed queue prevents duplicates, it will be invoked only
+once for a particular vertex <tt class="docutils literal"><span class="pre">u</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">examine_edge(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by the process owning the source vertex of
+<tt class="docutils literal"><span class="pre">e</span></tt>. If the distributed queue prevents duplicates, it will be
+invoked only once for a particular edge <tt class="docutils literal"><span class="pre">e</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">tree_edge(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>Similar to <tt class="docutils literal"><span class="pre">examine_edge</span></tt>, this will be invoked by the process
+owning the source vertex and may be invoked only once. Unlike the
+sequential BFS, this event may be triggered even when the target has
+already been discovered (but by a different process). Thus, some
+<tt class="docutils literal"><span class="pre">non_tree_edge</span></tt> events in a sequential BFS may become
+<tt class="docutils literal"><span class="pre">tree_edge</span></tt> in a distributed BFS.</dd>
+<dt><tt class="docutils literal"><span class="pre">non_tree_edge(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>Some <tt class="docutils literal"><span class="pre">non_tree_edge</span></tt> events in a sequential BFS may become
+<tt class="docutils literal"><span class="pre">tree_edge</span></tt> events in a distributed BFS. See the description of
+<tt class="docutils literal"><span class="pre">tree_edge</span></tt> for additional details.</dd>
+<dt><tt class="docutils literal"><span class="pre">gray_target(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>As with <tt class="docutils literal"><span class="pre">tree_edge</span></tt> not knowing when another process has already
+discovered a vertex, <tt class="docutils literal"><span class="pre">gray_target</span></tt> events may occur in a
+distributed BFS when <tt class="docutils literal"><span class="pre">black_target</span></tt> events may occur in a
+sequential BFS, due to a lack of information on a given
+processor. The source of edge <tt class="docutils literal"><span class="pre">e</span></tt> will be local to the process
+executing this event.</dd>
+<dt><tt class="docutils literal"><span class="pre">black_target(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>See documentation for <tt class="docutils literal"><span class="pre">gray_target</span></tt></dd>
+<dt><tt class="docutils literal"><span class="pre">finish_vertex(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>See documentation for <tt class="docutils literal"><span class="pre">examine_vertex</span></tt>.</dd>
+</dl>
+<div class="section" id="making-visitors-safe-for-distributed-bfs">
+<h2><a class="toc-backref" href="#id5">Making Visitors Safe for Distributed BFS</a></h2>
+<p>The three most important things to remember when updating an existing
+BFS visitor for distributed BFS or writing a new distributed BFS
+visitor are:</p>
+<ol class="arabic simple">
+<li>Be sure that all state is either entirely local or in a
+distributed data structure (most likely a property map!) using
+the same process group as the graph.</li>
+<li>Be sure that the visitor doesn't require precise event sequences
+that cannot be guaranteed by distributed BFS, e.g., requiring
+<tt class="docutils literal"><span class="pre">tree_edge</span></tt> and <tt class="docutils literal"><span class="pre">non_tree_edge</span></tt> events to be completely
+distinct.</li>
+<li>Be sure that the visitor can operate on incomplete
+information. This often includes using an appropriate reduction
+operation in a <a class="reference external" href="distributed_property_map.html">distributed property map</a> and verifying that
+results written are &quot;better&quot; that what was previously written.</li>
+</ol>
+</div>
+<div class="section" id="distributed-bfs-visitor-example">
+<h2><a class="toc-backref" href="#id6">Distributed BFS Visitor Example</a></h2>
+<p>To illustrate the differences between sequential and distributed BFS
+visitors, we consider a BFS visitor that places the distance from the
+source vertex to every other vertex in a property map. The sequential
+visitor is very simple:</p>
+<pre class="literal-block">
+template&lt;typename DistanceMap&gt;
+struct bfs_discovery_visitor : bfs_visitor&lt;&gt;
+{
+ bfs_discovery_visitor(DistanceMap distance) : distance(distance) {}
+
+ template&lt;typename Edge, typename Graph&gt;
+ void tree_edge(Edge e, const Graph&amp; g)
+ {
+ std::size_t new_distance = get(distance, source(e, g)) + 1;
+ put(distance, target(e, g), new_distance);
+ }
+
+ private:
+ DistanceMap distance;
+};
+</pre>
+<p>To revisit this code for distributed BFS, we consider the three points
+in the section <a class="reference internal" href="#making-visitors-safe-for-distributed-bfs">Making Visitors Safe for Distributed BFS</a>:</p>
+<ol class="arabic">
+<li><p class="first">The distance map will need to become distributed, because the
+distance to each vertex should be stored in the process owning the
+vertex. This is actually a requirement on the user to provide such
+a distributed property map, although in many cases the property map
+will automatically be distributed and no syntactic changes will be
+required.</p>
+</li>
+<li><p class="first">This visitor <em>does</em> require a precise sequence of events that may
+change with a distributed BFS. The extraneous <tt class="docutils literal"><span class="pre">tree_edge</span></tt> events
+that may occur could result in attempts to put distances into the
+distance map multiple times for a single vertex. We therefore need
+to consider bullet #3.</p>
+</li>
+<li><p class="first">Since multiple distance values may be written for each vertex, we
+must always choose the best value we can find to update the
+distance map. The distributed property map <tt class="docutils literal"><span class="pre">distance</span></tt> needs to
+resolve distances to the smallest distance it has seen. For
+instance, process 0 may find vertex <tt class="docutils literal"><span class="pre">u</span></tt> at level 3 but process 1
+finds it at level 5: the distance must remain at 3. To do this, we
+state that the property map's <em>role</em> is as a distance map, which
+introduces an appropriate reduction operation:</p>
+<pre class="literal-block">
+set_property_map_role(vertex_distance, distance);
+</pre>
+</li>
+</ol>
+<p>The resulting distributed BFS visitor (which also applies, with no
+changes, in the sequential BFS) is very similar to our original
+sequential BFS visitor. Note the single-line difference in the
+constructor:</p>
+<pre class="literal-block">
+template&lt;typename DistanceMap&gt;
+struct bfs_discovery_visitor : bfs_visitor&lt;&gt;
+{
+ bfs_discovery_visitor(DistanceMap distance) : distance(distance)
+ {
+ set_property_map_role(vertex_distance, distance);
+ }
+
+ template&lt;typename Edge, typename Graph&gt;
+ void tree_edge(Edge e, const Graph&amp; g)
+ {
+ std::size_t new_distance = get(distance, source(e, g)) + 1;
+ put(distance, target(e, g), new_distance);
+ }
+
+ private:
+ DistanceMap distance;
+};
+</pre>
+</div>
+</div>
+<div class="section" id="performance">
+<h1><a class="toc-backref" href="#id7">Performance</a></h1>
+<p>The performance of Breadth-First Search is illustrated by the
+following charts. Scaling and performance is reasonable for all of the
+graphs we have tried.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=4" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=4" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=4&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=4&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=4" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=4" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=4&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=4&amp;speedup=1" />
+<hr class="docutils" />
+<p>Copyright (C) 2004 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/connected_components.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/connected_components.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Connected Components</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-connected-components">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Connected Components</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+namespace graph {
+ // Default constructed ParentMap
+ template&lt;typename Graph, typename ComponentMap, typename ParentMap&gt;
+ typename property_traits&lt;ComponentMap&gt;::value_type
+ connected_components( const Graph&amp; g, ComponentMap c);
+
+ // User supplied ParentMap
+ template&lt;typename Graph, typename ComponentMap, typename ParentMap&gt;
+ typename property_traits&lt;ComponentMap&gt;::value_type
+ connected_components( const Graph&amp; g, ComponentMap c, ParentMap p);
+}
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">connected_components()</span></tt> function computes the connected
+components of an undirected graph. The distributed connected
+components algorithm uses the sequential version of the connected
+components algorithm to compute the connected components of the local
+subgraph, then executes the parallel phase of the algorithm. The
+parallel portion of the connected components algorithm is loosely
+based on the work of Goddard, Kumar, and Prins. The interface is a
+superset of the interface to the BGL <a class="reference external" href="http://www.boost.org/libs/graph/doc/connected_components.html">sequential connected
+components</a> algorithm.</p>
+<p>Prior to executing the sequential phase of the algorithm, each process
+identifies the roots of its local components. An adjacency list of
+all vertices adjacent to members of the component is then constructed
+at the root vertex of each component.</p>
+<p>The parallel phase of the distributed connected components algorithm
+consists of a series of supersteps. In each superstep, each root
+attempts to hook to a member of it's adjacency list by assigning it's
+parent pointer to that vertex. Hooking is restricted to vertices
+which are logically less than the current vertex to prevent looping.
+Vertices which hook successfully are removed from the list of roots
+and placed on another list of completed vertices. All completed
+vertices now execute a pointer jumping step until every completed
+vertex has as its parent the root of a component. This pointer
+jumping step may be further optimized by the addition of Cycle
+Reduction (CR) rules developed by Johnson and Metaxas, however current
+performance evaluations indicate that this would have a negligible
+impact on the overall performance of the algorithm. These CR rules
+reduce the number of pointer jumping steps from <em>O(n)</em> to <em>O(log n)</em>.
+Following this pointer jumping step, roots which have hooked in this
+phase transmit their adjacency list to their new parent. The
+remaining roots receive these edges and execute a pruning step on
+their adjacency lists to remove vertices that are now members of their
+component. The parallel phase of the algorithm is complete when no
+root successfully hooks. Once the parallel phase is complete a final
+pointer jumping step is performed on all vertices to assign the parent
+pointers of the leaves of the initial local subgraph components to
+their final parent which has now been determined.</p>
+<p>The single largest performance bottleneck in the distributed connected
+components algorithm is the effect of poor vertex distribution on the
+algorithm. For sparse graphs with a single large component, many
+roots may hook to the same component, resulting in severe load
+imbalance at the process owning this component. Several methods of
+modifying the hooking strategy to avoid this behavior have been
+implemented but none has been successful as of yet.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id1">Where Defined</a></li>
+<li><a class="reference internal" href="#parameters" id="id2">Parameters</a></li>
+<li><a class="reference internal" href="#complexity" id="id3">Complexity</a></li>
+<li><a class="reference internal" href="#performance" id="id4">Performance</a></li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id1">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/connected_components.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="parameters">
+<h1><a class="toc-backref" href="#id2">Parameters</a></h1>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph typed must be a model of <a class="reference external" href="DistributedGraph.html">Distributed Graph</a>.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">ComponentMap</span> <span class="pre">c</span></tt></dt>
+<dd>The algorithm computes how many connected components are in the
+graph, and assigns each component an integer label. The algorithm
+then records to which component each vertex in the graph belongs by
+recording the component number in the component property map. The
+<tt class="docutils literal"><span class="pre">ComponentMap</span></tt> type must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a>. The
+value type must be the <tt class="docutils literal"><span class="pre">vertices_size_type</span></tt> of the graph. The key
+type must be the graph's vertex descriptor type. If you do not wish
+to compute component numbers, pass <tt class="docutils literal"><span class="pre">dummy_property_map</span></tt> as the
+component map and parent information will be provided in the parent
+map.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">ParentMap</span> <span class="pre">p</span></tt></dt>
+<dd>A parent map may be supplied to the algorithm, if not supplied the
+parent map will be constructed automatically. The <tt class="docutils literal"><span class="pre">ParentMap</span></tt> type
+must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a>. The value type and key type
+must be the graph's vertex descriptor type.</dd>
+<dt>OUT: <tt class="docutils literal"><span class="pre">property_traits&lt;ComponentMap&gt;::value_type</span></tt></dt>
+<dd>The number of components found will be returned as the value type of
+the component map.</dd>
+</dl>
+</div>
+<div class="section" id="complexity">
+<h1><a class="toc-backref" href="#id3">Complexity</a></h1>
+<p>The local phase of the algorithm is <em>O(V + E)</em>. The parallel phase of
+the algorithm requires at most <em>O(d)</em> supersteps where <em>d</em> is the
+number of initial roots. <em>d</em> is at most <em>O(V)</em> but becomes
+significantly smaller as <em>E</em> increases. The pointer jumping phase
+within each superstep requires at most <em>O(c)</em> steps on each of the
+completed roots where <em>c</em> is the length of the longest cycle.
+Application of CR rules can reduce this to <em>O(log c)</em>.</p>
+</div>
+<div class="section" id="performance">
+<h1><a class="toc-backref" href="#id4">Performance</a></h1>
+<p>The following charts illustrate the performance of the Parallel BGL
+connected components algorithm. It performs well on very sparse and
+very dense graphs. However, for cases where the graph has a medium
+density with a giant connected component, the algorithm will perform
+poorly. This is a known problem with the algorithm and as far as we
+know all implemented algorithms have this degenerate behavior.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=9" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=9" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=9&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=9&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=9" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=9" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=9&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=9&amp;speedup=1" />
+<hr class="docutils" />
+<p>Copyright (C) 2004 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds, Douglas Gregor, and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:13 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/connected_components_parallel_search.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/connected_components_parallel_search.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Connected Components Parallel Search</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-connected-components-parallel-search">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Connected Components Parallel Search</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/dehne_gotz_min_spanning_tree.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/dehne_gotz_min_spanning_tree.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Minimum Spanning Tree</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-minimum-spanning-tree">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Minimum Spanning Tree</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<p>The Parallel BGL contains four <a class="reference external" href="http://www.boost.org/libs/graph/doc/graph_theory_review.html#sec:minimum-spanning-tree">minimum spanning tree</a> (MST)
+algorithms <a class="citation-reference" href="#dg98" id="id1">[DG98]</a> for use on undirected, weighted, distributed
+graphs. The graphs need not be connected: each algorithm will compute
+a minimum spanning forest (MSF) when provided with a disconnected
+graph.</p>
+<p>The interface to each of the four algorithms is similar to the
+implementation of 'Kruskal's algorithm'_ in the sequential BGL. Each
+accepts, at a minimum, a graph, a weight map, and an output
+iterator. The edges of the MST (or MSF) will be output via the output
+iterator on process 0: other processes may receive edges on their
+output iterators, but the set may not be complete, depending on the
+algorithm. The algorithm parameters are documented together, because
+they do not vary greatly. See the section <a class="reference internal" href="#selecting-an-mst-algorithm">Selecting an MST
+algorithm</a> for advice on algorithm selection.</p>
+<p>The graph itself must model the <a class="reference external" href="http://www.boost.org/libs/graph/doc/VertexListGraph.html">Vertex List Graph</a> concept and the
+Distributed Edge List Graph concept. Since the most common
+distributed graph structure, the <a class="reference external" href="distributed_adjacency_list.html">distributed adjacency list</a>, only
+models the Distributed Vertex List Graph concept, it may only be used
+with these algorithms when wrapped in a suitable adaptor, such as the
+<a class="reference external" href="vertex_list_adaptor.html">vertex_list_adaptor</a>.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id12">Where Defined</a></li>
+<li><a class="reference internal" href="#parameters" id="id13">Parameters</a></li>
+<li><a class="reference internal" href="#dense-boruvka-minimum-spanning-tree" id="id14"><tt class="docutils literal"><span class="pre">dense_boruvka_minimum_spanning_tree</span></tt></a><ul>
+<li><a class="reference internal" href="#description" id="id15">Description</a></li>
+<li><a class="reference internal" href="#complexity" id="id16">Complexity</a></li>
+<li><a class="reference internal" href="#performance" id="id17">Performance</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#merge-local-minimum-spanning-trees" id="id18"><tt class="docutils literal"><span class="pre">merge_local_minimum_spanning_trees</span></tt></a><ul>
+<li><a class="reference internal" href="#id2" id="id19">Description</a></li>
+<li><a class="reference internal" href="#id3" id="id20">Complexity</a></li>
+<li><a class="reference internal" href="#id4" id="id21">Performance</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#boruvka-then-merge" id="id22"><tt class="docutils literal"><span class="pre">boruvka_then_merge</span></tt></a><ul>
+<li><a class="reference internal" href="#id5" id="id23">Description</a></li>
+<li><a class="reference internal" href="#id6" id="id24">Complexity</a></li>
+<li><a class="reference internal" href="#id7" id="id25">Performance</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#boruvka-mixed-merge" id="id26"><tt class="docutils literal"><span class="pre">boruvka_mixed_merge</span></tt></a><ul>
+<li><a class="reference internal" href="#id8" id="id27">Description</a></li>
+<li><a class="reference internal" href="#id9" id="id28">Complexity</a></li>
+<li><a class="reference internal" href="#id10" id="id29">Performance</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#selecting-an-mst-algorithm" id="id30">Selecting an MST algorithm</a><ul>
+<li><a class="reference internal" href="#performance-on-sparse-graphs" id="id31">Performance on Sparse Graphs</a></li>
+<li><a class="reference internal" href="#performance-on-dense-graphs" id="id32">Performance on Dense Graphs</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id12">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="parameters">
+<h1><a class="toc-backref" href="#id13">Parameters</a></h1>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph type must be a model of <a class="reference external" href="http://www.boost.org/libs/graph/doc/VertexListGraph.html">Vertex List Graph</a> and
+<a class="reference external" href="DistributedEdgeListGraph.html">Distributed Edge List Graph</a>.</dd>
+<dt>IN/OUT: <tt class="docutils literal"><span class="pre">WeightMap</span> <span class="pre">weight</span></tt></dt>
+<dd>The weight map must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> and a <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable
+Property Map</a> whose key type is the edge descriptor of the graph
+and whose value type is numerical.</dd>
+<dt>IN/OUT: <tt class="docutils literal"><span class="pre">OutputIterator</span> <span class="pre">out</span></tt></dt>
+<dd>The output iterator through which the edges of the MSF will be
+written. Must be capable of accepting edge descriptors for output.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">VertexIndexMap</span> <span class="pre">index</span></tt></dt>
+<dd><p class="first">A mapping from vertex descriptors to indices in the range <em>[0,
+num_vertices(g))</em>. This must be a <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable Property Map</a> whose
+key type is a vertex descriptor and whose value type is an integral
+type, typically the <tt class="docutils literal"><span class="pre">vertices_size_type</span></tt> of the graph.</p>
+<p class="last"><strong>Default:</strong> <tt class="docutils literal"><span class="pre">get(vertex_index,</span> <span class="pre">g)</span></tt></p>
+</dd>
+<dt>IN/UTIL: <tt class="docutils literal"><span class="pre">RankMap</span> <span class="pre">rank_map</span></tt></dt>
+<dd><p class="first">Stores the rank of each vertex, which is used for maintaining
+union-find data structures. This must be a <a class="reference external" href="http://www.boost.org/libs/property_map/ReadWritePropertyMap.html">Read/Write Property Map</a>
+whose key type is a vertex descriptor and whose value type is an
+integral type.</p>
+<p class="last"><strong>Default:</strong> An <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> built from an STL vector
+of the <tt class="docutils literal"><span class="pre">vertices_size_type</span></tt> of the graph and the vertex index map.</p>
+</dd>
+<dt>IN/UTIL: <tt class="docutils literal"><span class="pre">ParentMap</span> <span class="pre">parent_map</span></tt></dt>
+<dd><p class="first">Stores the parent (representative) of each vertex, which is used for
+maintaining union-find data structures. This must be a <a class="reference external" href="http://www.boost.org/libs/property_map/ReadWritePropertyMap.html">Read/Write
+Property Map</a> whose key type is a vertex descriptor and whose value
+type is also a vertex descriptor.</p>
+<p class="last"><strong>Default:</strong> An <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> built from an STL vector
+of the <tt class="docutils literal"><span class="pre">vertex_descriptor</span></tt> of the graph and the vertex index map.</p>
+</dd>
+<dt>IN/UTIL: <tt class="docutils literal"><span class="pre">SupervertexMap</span> <span class="pre">supervertex_map</span></tt></dt>
+<dd><p class="first">Stores the supervertex index of each vertex, which is used for
+maintaining the supervertex list data structures. This must be a
+<a class="reference external" href="http://www.boost.org/libs/property_map/ReadWritePropertyMap.html">Read/Write Property Map</a> whose key type is a vertex descriptor and
+whose value type is an integral type.</p>
+<p class="last"><strong>Default:</strong> An <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> built from an STL vector
+of the <tt class="docutils literal"><span class="pre">vertices_size_type</span></tt> of the graph and the vertex index map.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="dense-boruvka-minimum-spanning-tree">
+<h1><a class="toc-backref" href="#id14"><tt class="docutils literal"><span class="pre">dense_boruvka_minimum_spanning_tree</span></tt></a></h1>
+<pre class="literal-block">
+namespace graph {
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap, typename RankMap, typename ParentMap,
+ typename SupervertexMap&gt;
+ OutputIterator
+ dense_boruvka_minimum_spanning_tree(const Graph&amp; g, WeightMap weight_map,
+ OutputIterator out,
+ VertexIndexMap index,
+ RankMap rank_map, ParentMap parent_map,
+ SupervertexMap supervertex_map);
+
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndex&gt;
+ OutputIterator
+ dense_boruvka_minimum_spanning_tree(const Graph&amp; g, WeightMap weight_map,
+ OutputIterator out, VertexIndex index);
+
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator&gt;
+ OutputIterator
+ dense_boruvka_minimum_spanning_tree(const Graph&amp; g, WeightMap weight_map,
+ OutputIterator out);
+}
+</pre>
+<div class="section" id="description">
+<h2><a class="toc-backref" href="#id15">Description</a></h2>
+<p>The dense Boruvka distributed minimum spanning tree algorithm is a
+direct parallelization of the sequential MST algorithm by
+Boruvka. The algorithm first creates a <em>supervertex</em> out of each
+vertex. Then, in each iteration, it finds the smallest-weight edge
+incident to each vertex, collapses supervertices along these edges,
+and removals all self loops. The only difference between the
+sequential and parallel algorithms is that the parallel algorithm
+performs an all-reduce operation so that all processes have the
+global minimum set of edges.</p>
+<p>Unlike the other three algorithms, this algorithm emits the complete
+list of edges in the minimum spanning forest via the output iterator
+on all processes. It may therefore be more useful than the others
+when parallelizing sequential BGL programs.</p>
+</div>
+<div class="section" id="complexity">
+<h2><a class="toc-backref" href="#id16">Complexity</a></h2>
+<p>The distributed algorithm requires <em>O(log n)</em> BSP supersteps, each of
+which requires <em>O(m/p + n)</em> time and <em>O(n)</em> communication per
+process.</p>
+</div>
+<div class="section" id="performance">
+<h2><a class="toc-backref" href="#id17">Performance</a></h2>
+<p>The following charts illustrate the performance of this algorithm on
+various random graphs. We see that the algorithm scales well up to 64
+or 128 processors, depending on the type of graph, for dense
+graphs. However, for sparse graphs performance tapers off as the
+number of processors surpases <em>m/n</em>, i.e., the average degree (which
+is 30 for this graph). This behavior is expected from the algorithm.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=5" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=5" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=5&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=5&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=5" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=5" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=5&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=5&amp;speedup=1" />
+</div>
+</div>
+<div class="section" id="merge-local-minimum-spanning-trees">
+<h1><a class="toc-backref" href="#id18"><tt class="docutils literal"><span class="pre">merge_local_minimum_spanning_trees</span></tt></a></h1>
+<pre class="literal-block">
+namespace graph {
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap&gt;
+ OutputIterator
+ merge_local_minimum_spanning_trees(const Graph&amp; g, WeightMap weight,
+ OutputIterator out,
+ VertexIndexMap index);
+
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator&gt;
+ inline OutputIterator
+ merge_local_minimum_spanning_trees(const Graph&amp; g, WeightMap weight,
+ OutputIterator out);
+}
+</pre>
+<div class="section" id="id2">
+<h2><a class="toc-backref" href="#id19">Description</a></h2>
+<p>The merging local MSTs algorithm operates by computing minimum
+spanning forests from the edges stored on each process. Then the
+processes merge their edge lists along a tree. The child nodes cease
+participating in the computation, but the parent nodes recompute MSFs
+from the newly acquired edges. In the final round, the root of the
+tree computes the global MSFs, having received candidate edges from
+every other process via the tree.</p>
+</div>
+<div class="section" id="id3">
+<h2><a class="toc-backref" href="#id20">Complexity</a></h2>
+<p>This algorithm requires <em>O(log_D p)</em> BSP supersteps (where <em>D</em> is the
+number of children in the tree, and is currently fixed at 3). Each
+superstep requires <em>O((m/p) log (m/p) + n)</em> time and <em>O(m/p)</em>
+communication per process.</p>
+</div>
+<div class="section" id="id4">
+<h2><a class="toc-backref" href="#id21">Performance</a></h2>
+<p>The following charts illustrate the performance of this algorithm on
+various random graphs. The algorithm only scales well for very dense
+graphs, where most of the work is performed in the initial stage and
+there is very little work in the later stages.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=6" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=6" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=6&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=6&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=6" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=6" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=6&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=6&amp;speedup=1" />
+</div>
+</div>
+<div class="section" id="boruvka-then-merge">
+<h1><a class="toc-backref" href="#id22"><tt class="docutils literal"><span class="pre">boruvka_then_merge</span></tt></a></h1>
+<pre class="literal-block">
+namespace graph {
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap, typename RankMap, typename ParentMap,
+ typename SupervertexMap&gt;
+ OutputIterator
+ boruvka_then_merge(const Graph&amp; g, WeightMap weight, OutputIterator out,
+ VertexIndexMap index, RankMap rank_map,
+ ParentMap parent_map, SupervertexMap
+ supervertex_map);
+
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap&gt;
+ inline OutputIterator
+ boruvka_then_merge(const Graph&amp; g, WeightMap weight, OutputIterator out,
+ VertexIndexMap index);
+
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator&gt;
+ inline OutputIterator
+ boruvka_then_merge(const Graph&amp; g, WeightMap weight, OutputIterator out);
+}
+</pre>
+<div class="section" id="id5">
+<h2><a class="toc-backref" href="#id23">Description</a></h2>
+<p>This algorithm applies both Boruvka steps and local MSF merging steps
+together to achieve better asymptotic performance than either
+algorithm alone. It first executes Boruvka steps until only <em>n/(log_d
+p)^2</em> supervertices remain, then completes the MSF computation by
+performing local MSF merging on the remaining edges and
+supervertices.</p>
+</div>
+<div class="section" id="id6">
+<h2><a class="toc-backref" href="#id24">Complexity</a></h2>
+<p>This algorithm requires <em>log_D p</em> + <em>log log_D p</em> BSP supersteps. The
+time required by each superstep depends on the type of superstep
+being performed; see the distributed Boruvka or merging local MSFS
+algorithms for details.</p>
+</div>
+<div class="section" id="id7">
+<h2><a class="toc-backref" href="#id25">Performance</a></h2>
+<p>The following charts illustrate the performance of this algorithm on
+various random graphs. We see that the algorithm scales well up to 64
+or 128 processors, depending on the type of graph, for dense
+graphs. However, for sparse graphs performance tapers off as the
+number of processors surpases <em>m/n</em>, i.e., the average degree (which
+is 30 for this graph). This behavior is expected from the algorithm.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=7" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=7" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=7&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=7&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=7" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=7" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=7&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=7&amp;speedup=1" />
+</div>
+</div>
+<div class="section" id="boruvka-mixed-merge">
+<h1><a class="toc-backref" href="#id26"><tt class="docutils literal"><span class="pre">boruvka_mixed_merge</span></tt></a></h1>
+<pre class="literal-block">
+namespace {
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap, typename RankMap, typename ParentMap,
+ typename SupervertexMap&gt;
+ OutputIterator
+ boruvka_mixed_merge(const Graph&amp; g, WeightMap weight, OutputIterator out,
+ VertexIndexMap index, RankMap rank_map,
+ ParentMap parent_map, SupervertexMap
+ supervertex_map);
+
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator,
+ typename VertexIndexMap&gt;
+ inline OutputIterator
+ boruvka_mixed_merge(const Graph&amp; g, WeightMap weight, OutputIterator out,
+ VertexIndexMap index);
+
+ template&lt;typename Graph, typename WeightMap, typename OutputIterator&gt;
+ inline OutputIterator
+ boruvka_mixed_merge(const Graph&amp; g, WeightMap weight, OutputIterator out);
+}
+</pre>
+<div class="section" id="id8">
+<h2><a class="toc-backref" href="#id27">Description</a></h2>
+<p>This algorithm applies both Boruvka steps and local MSF merging steps
+together to achieve better asymptotic performance than either method
+alone. In each iteration, the algorithm first performs a Boruvka step
+and then merges the local MSFs computed based on the supervertex
+graph.</p>
+</div>
+<div class="section" id="id9">
+<h2><a class="toc-backref" href="#id28">Complexity</a></h2>
+<p>This algorithm requires <em>log_D p</em> BSP supersteps. The
+time required by each superstep depends on the type of superstep
+being performed; see the distributed Boruvka or merging local MSFS
+algorithms for details. However, the algorithm is
+communication-optional (requiring <em>O(n)</em> communication overall) when
+the graph is sufficiently dense, i.e., <em>m/n &gt;= p</em>.</p>
+</div>
+<div class="section" id="id10">
+<h2><a class="toc-backref" href="#id29">Performance</a></h2>
+<p>The following charts illustrate the performance of this algorithm on
+various random graphs. We see that the algorithm scales well up to 64
+or 128 processors, depending on the type of graph, for dense
+graphs. However, for sparse graphs performance tapers off as the
+number of processors surpases <em>m/n</em>, i.e., the average degree (which
+is 30 for this graph). This behavior is expected from the algorithm.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=8" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=8" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=8&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=8&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=8" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=8" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=8&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=8&amp;speedup=1" />
+</div>
+</div>
+<div class="section" id="selecting-an-mst-algorithm">
+<h1><a class="toc-backref" href="#id30">Selecting an MST algorithm</a></h1>
+<p>Dehne and Gotz reported <a class="citation-reference" href="#dg98" id="id11">[DG98]</a> mixed results when evaluating these
+four algorithms. No particular algorithm was clearly better than the
+others in all cases. However, the asymptotically best algorithm
+(<tt class="docutils literal"><span class="pre">boruvka_mixed_merge</span></tt>) seemed to perform more poorly in their tests
+than the other merging-based algorithms. The following performance
+charts illustrate the performance of these four minimum spanning tree
+implementations.</p>
+<p>Overall, <tt class="docutils literal"><span class="pre">dense_boruvka_minimum_spanning_tree</span></tt> gives the most
+consistent performance and scalability for the graphs we
+tested. Additionally, it may be more suitable for sequential programs
+that are being parallelized, because it emits complete MSF edge lists
+via the output iterators in every process.</p>
+<div class="section" id="performance-on-sparse-graphs">
+<h2><a class="toc-backref" href="#id31">Performance on Sparse Graphs</a></h2>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&amp;dataset=TimeSparse&amp;columns=5,6,7,8" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&amp;dataset=TimeSparse&amp;columns=5,6,7,8" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&amp;dataset=TimeSparse&amp;columns=5,6,7,8&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&amp;dataset=TimeSparse&amp;columns=5,6,7,8&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&amp;dataset=TimeSparse&amp;columns=5,6,7,8" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&amp;dataset=TimeSparse&amp;columns=5,6,7,8" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&amp;dataset=TimeSparse&amp;columns=5,6,7,8&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&amp;dataset=TimeSparse&amp;columns=5,6,7,8&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&amp;dataset=TimeSparse&amp;columns=5,6,7,8" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&amp;dataset=TimeSparse&amp;columns=5,6,7,8" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&amp;dataset=TimeSparse&amp;columns=5,6,7,8&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&amp;dataset=TimeSparse&amp;columns=5,6,7,8&amp;speedup=1" />
+</div>
+<div class="section" id="performance-on-dense-graphs">
+<h2><a class="toc-backref" href="#id32">Performance on Dense Graphs</a></h2>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&amp;dataset=TimeDense&amp;columns=5,6,7,8" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&amp;dataset=TimeDense&amp;columns=5,6,7,8" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&amp;dataset=TimeDense&amp;columns=5,6,7,8&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=ER&amp;dataset=TimeDense&amp;columns=5,6,7,8&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&amp;dataset=TimeDense&amp;columns=5,6,7,8" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&amp;dataset=TimeDense&amp;columns=5,6,7,8" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&amp;dataset=TimeDense&amp;columns=5,6,7,8&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SF&amp;dataset=TimeDense&amp;columns=5,6,7,8&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&amp;dataset=TimeDense&amp;columns=5,6,7,8" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&amp;dataset=TimeDense&amp;columns=5,6,7,8" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&amp;dataset=TimeDense&amp;columns=5,6,7,8&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?generator=SW&amp;dataset=TimeDense&amp;columns=5,6,7,8&amp;speedup=1" />
+<hr class="docutils" />
+<p>Copyright (C) 2004 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+<table class="docutils citation" frame="void" id="dg98" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[DG98]</td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id11">2</a>)</em> Frank Dehne and Silvia Gotz. <em>Practical Parallel Algorithms
+for Minimum Spanning Trees</em>. In Symposium on Reliable Distributed Systems,
+pages 366--371, 1998.</td></tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/dijkstra_example.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/dijkstra_example.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel Shortest Paths</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="parallel-shortest-paths">
+<h1 class="title">Parallel Shortest Paths</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<p>To illustrate the use of the Parallel Boost Graph Library, we
+illustrate the use of both the sequential and parallel BGL to find
+the shortest paths from vertex A to every other vertex in the
+following simple graph:</p>
+<img alt="dijkstra_seq_graph.png" src="dijkstra_seq_graph.png" />
+<p>With the sequential <a class="reference external" href="http://www.boost.org/libs/graph/doc">BGL</a>, the program to calculate shortest paths has
+three stages. Readers familiar with the BGL may wish to skip ahead to
+the section <a class="reference internal" href="#distributing-the-graph">Distributing the graph</a>.</p>
+<blockquote>
+<ul class="simple">
+<li><a class="reference internal" href="#define-the-graph-type">Define the graph type</a></li>
+<li><a class="reference internal" href="#construct-the-graph">Construct the graph</a></li>
+<li><a class="reference internal" href="#invoke-dijkstra-s-algorithm">Invoke Dijkstra's algorithm</a></li>
+</ul>
+</blockquote>
+<div class="section" id="define-the-graph-type">
+<h1>Define the graph type</h1>
+<p>For this problem we use an adjacency list representation of the graph,
+using the BGL <tt class="docutils literal"><span class="pre">adjacency_list``_</span> <span class="pre">class</span> <span class="pre">template.</span> <span class="pre">It</span> <span class="pre">will</span> <span class="pre">be</span> <span class="pre">a</span> <span class="pre">directed</span>
+<span class="pre">graph</span> <span class="pre">(``directedS</span></tt> parameter ) whose vertices are stored in an
+<tt class="docutils literal"><span class="pre">std::vector</span></tt> (<tt class="docutils literal"><span class="pre">vecS</span></tt> parameter) where the outgoing edges of each
+vertex are stored in an <tt class="docutils literal"><span class="pre">std::list</span></tt> (<tt class="docutils literal"><span class="pre">listS</span></tt> parameter). To each
+of the edges we attach an integral weight.</p>
+<pre class="literal-block">
+typedef adjacency_list&lt;listS, vecS, directedS,
+ no_property, // Vertex properties
+ property&lt;edge_weight_t, int&gt; // Edge properties
+ &gt; graph_t;
+typedef graph_traits &lt; graph_t &gt;::vertex_descriptor vertex_descriptor;
+typedef graph_traits &lt; graph_t &gt;::edge_descriptor edge_descriptor;
+</pre>
+</div>
+<div class="section" id="construct-the-graph">
+<h1>Construct the graph</h1>
+<p>To build the graph, we declare an enumeration containing the node
+names (for our own use) and create two arrays: the first,
+<tt class="docutils literal"><span class="pre">edge_array</span></tt>, contains the source and target of each edge, whereas
+the second, <tt class="docutils literal"><span class="pre">weights</span></tt>, contains the integral weight of each
+edge. We pass the contents of the arrays via pointers (used here as
+iterators) to the graph constructor to build our graph:</p>
+<pre class="literal-block">
+typedef std::pair&lt;int, int&gt; Edge;
+const int num_nodes = 5;
+enum nodes { A, B, C, D, E };
+char name[] = &quot;ABCDE&quot;;
+Edge edge_array[] = { Edge(A, C), Edge(B, B), Edge(B, D), Edge(B, E),
+ Edge(C, B), Edge(C, D), Edge(D, E), Edge(E, A), Edge(E, B)
+};
+int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1 };
+int num_arcs = sizeof(edge_array) / sizeof(Edge);
+
+graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes);
+</pre>
+</div>
+<div class="section" id="invoke-dijkstra-s-algorithm">
+<h1>Invoke Dijkstra's algorithm</h1>
+<p>To invoke Dijkstra's algorithm, we need to first decide how we want
+to receive the results of the algorithm, namely the distance to each
+vertex and the predecessor of each vertex (allowing reconstruction of
+the shortest paths themselves). In our case, we will create two
+vectors, <tt class="docutils literal"><span class="pre">p</span></tt> for predecessors and <tt class="docutils literal"><span class="pre">d</span></tt> for distances.</p>
+<p>Next, we determine our starting vertex <tt class="docutils literal"><span class="pre">s</span></tt> using the <tt class="docutils literal"><span class="pre">vertex</span></tt>
+operation on the <tt class="docutils literal"><span class="pre">adjacency_list``_</span> <span class="pre">and</span> <span class="pre">call</span>
+<span class="pre">``dijkstra_shortest_paths``_</span> <span class="pre">with</span> <span class="pre">the</span> <span class="pre">graph</span> <span class="pre">``g</span></tt>, starting vertex
+<tt class="docutils literal"><span class="pre">s</span></tt>, and two <tt class="docutils literal"><span class="pre">property</span> <span class="pre">maps``_</span> <span class="pre">that</span> <span class="pre">instruct</span> <span class="pre">the</span> <span class="pre">algorithm</span> <span class="pre">to</span>
+<span class="pre">store</span> <span class="pre">predecessors</span> <span class="pre">in</span> <span class="pre">the</span> <span class="pre">``p</span></tt> vector and distances in the <tt class="docutils literal"><span class="pre">d</span></tt>
+vector. The algorithm automatically uses the edge weights stored
+within the graph, although this capability can be overridden.</p>
+<pre class="literal-block">
+// Keeps track of the predecessor of each vertex
+std::vector&lt;vertex_descriptor&gt; p(num_vertices(g));
+// Keeps track of the distance to each vertex
+std::vector&lt;int&gt; d(num_vertices(g));
+
+vertex_descriptor s = vertex(A, g);
+dijkstra_shortest_paths
+ (g, s,
+ predecessor_map(
+ make_iterator_property_map(p.begin(), get(vertex_index, g))).
+ distance_map(
+ make_iterator_property_map(d.begin(), get(vertex_index, g)))
+ );
+</pre>
+</div>
+<div class="section" id="distributing-the-graph">
+<h1>Distributing the graph</h1>
+<p>The prior computation is entirely sequential, with the graph stored
+within a single address space. To distribute the graph across several
+processors without a shared address space, we need to represent the
+processors and communication among them and alter the graph type.</p>
+<p>Processors and their interactions are abstracted via a <em>process
+group</em>. In our case, we will use <a class="reference external" href="http://www-unix.mcs.anl.gov/mpi/">MPI</a> for communication with
+inter-processor messages sent immediately:</p>
+<pre class="literal-block">
+typedef mpi::process_group&lt;mpi::immediateS&gt; process_group_type;
+</pre>
+<p>Next, we instruct the <tt class="docutils literal"><span class="pre">adjacency_list</span></tt> template
+to distribute the vertices of the graph across our process group,
+storing the local vertices in an <tt class="docutils literal"><span class="pre">std::vector</span></tt>:</p>
+<pre class="literal-block">
+typedef adjacency_list&lt;listS,
+ distributedS&lt;process_group_type, vecS&gt;,
+ directedS,
+ no_property, // Vertex properties
+ property&lt;edge_weight_t, int&gt; // Edge properties
+ &gt; graph_t;
+typedef graph_traits &lt; graph_t &gt;::vertex_descriptor vertex_descriptor;
+typedef graph_traits &lt; graph_t &gt;::edge_descriptor edge_descriptor;
+</pre>
+<p>Note that the only difference from the sequential BGL is the use of
+the <tt class="docutils literal"><span class="pre">distributedS</span></tt> selector, which identifies a distributed
+graph. The vertices of the graph will be distributed among the
+various processors, and the processor that owns a vertex also stores
+the edges outgoing from that vertex and any properties associated
+with that vertex or its edges. With three processors and the default
+block distribution, the graph would be distributed in this manner:</p>
+<img alt="dijkstra_dist3_graph.png" src="dijkstra_dist3_graph.png" />
+<p>Processor 0 (red) owns vertices A and B, including all edges outoing
+from those vertices, processor 1 (green) owns vertices C and D (and
+their edges), and processor 2 (blue) owns vertex E. Constructing this
+graph uses the same syntax is the sequential graph, as in the section
+<a class="reference internal" href="#construct-the-graph">Construct the graph</a>.</p>
+<p>The call to <tt class="docutils literal"><span class="pre">dijkstra_shortest_paths</span></tt> is syntactically equivalent to
+the sequential call, but the mechanisms used are very different. The
+property maps passed to <tt class="docutils literal"><span class="pre">dijkstra_shortest_paths</span></tt> are actually
+<em>distributed</em> property maps, which store properties for local edges
+or vertices and perform implicit communication to access properties
+of remote edges or vertices when needed. The formulation of Dijkstra's
+algorithm is also slightly different, because each processor can
+only attempt to relax edges outgoing from local vertices: as shorter
+paths to a vertex are discovered, messages to the processor owning
+that vertex indicate that the vertex may require reprocessing.</p>
+<hr class="docutils" />
+<p>Return to the <a class="reference external" href="index.html">Parallel BGL home page</a></p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:13 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/dijkstra_shortest_paths.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/dijkstra_shortest_paths.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,400 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Dijkstra's Single-Source Shortest Paths</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-dijkstra-s-single-source-shortest-paths">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Dijkstra's Single-Source Shortest Paths</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+// named parameter version
+template &lt;typename Graph, typename P, typename T, typename R&gt;
+void
+dijkstra_shortest_paths(Graph&amp; g,
+ typename graph_traits&lt;Graph&gt;::vertex_descriptor s,
+ const bgl_named_params&lt;P, T, R&gt;&amp; params);
+
+// non-named parameter version
+template &lt;typename Graph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap,
+ typename WeightMap, typename VertexIndexMap, typename CompareFunction, typename CombineFunction,
+ typename DistInf, typename DistZero&gt;
+void dijkstra_shortest_paths
+ (const Graph&amp; g,
+ typename graph_traits&lt;Graph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
+ VertexIndexMap index_map,
+ CompareFunction compare, CombineFunction combine, DistInf inf, DistZero zero,
+ DijkstraVisitor vis);
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">dijkstra_shortest_paths()</span></tt> function solves the single-source
+shortest paths problem on a weighted, undirected or directed
+distributed graph. There are two implementations of distributed
+Dijkstra's algorithm, which offer different performance
+tradeoffs. Both are accessible via the <tt class="docutils literal"><span class="pre">dijkstra_shortest_paths()</span></tt>
+function (for compatibility with sequential BGL programs). The
+distributed Dijkstra algorithms are very similar to their sequential
+counterparts. Only the differences are highlighted here; please refer
+to the <a class="reference external" href="http://www.boost.org/libs/graph/doc/dijkstra_shortest_paths.html">sequential Dijkstra implementation</a> for additional
+details. The best-performing implementation for most cases is the
+<a class="reference internal" href="#delta-stepping-algorithm">Delta-Stepping algorithm</a>; however, one can also employ the more
+conservative <a class="reference internal" href="#crauser-et-al-s-algorithm">Crauser et al.'s algorithm</a> or the simlistic <a class="reference internal" href="#eager-dijkstra-s-algorithm">Eager
+Dijkstra's algorithm</a>.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id10">Where Defined</a></li>
+<li><a class="reference internal" href="#parameters" id="id11">Parameters</a></li>
+<li><a class="reference internal" href="#visitor-event-points" id="id12">Visitor Event Points</a></li>
+<li><a class="reference internal" href="#crauser-et-al-s-algorithm" id="id13">Crauser et al.'s algorithm</a><ul>
+<li><a class="reference internal" href="#id2" id="id14">Where Defined</a></li>
+<li><a class="reference internal" href="#complexity" id="id15">Complexity</a></li>
+<li><a class="reference internal" href="#performance" id="id16">Performance</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#eager-dijkstra-s-algorithm" id="id17">Eager Dijkstra's algorithm</a><ul>
+<li><a class="reference internal" href="#id5" id="id18">Where Defined</a></li>
+<li><a class="reference internal" href="#id6" id="id19">Complexity</a></li>
+<li><a class="reference internal" href="#id7" id="id20">Performance</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#delta-stepping-algorithm" id="id21">Delta-Stepping algorithm</a><ul>
+<li><a class="reference internal" href="#id9" id="id22">Where Defined</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#example" id="id23">Example</a></li>
+<li><a class="reference internal" href="#bibliography" id="id24">Bibliography</a></li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id10">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/dijkstra_shortest_paths.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="parameters">
+<h1><a class="toc-backref" href="#id11">Parameters</a></h1>
+<p>All parameters of the <a class="reference external" href="http://www.boost.org/libs/graph/doc/dijkstra_shortest_paths.html">sequential Dijkstra implementation</a> are
+supported and have essentially the same meaning. The distributed
+Dijkstra implementations introduce a new parameter that allows one to
+select <a class="reference internal" href="#eager-dijkstra-s-algorithm">Eager Dijkstra's algorithm</a> and control the amount of work it
+performs. Only differences and new parameters are documented here.</p>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph type must be a model of <a class="reference external" href="DistributedGraph.html">Distributed Graph</a>.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">vertex_descriptor</span> <span class="pre">s</span></tt></dt>
+<dd>The start vertex must be the same in every process.</dd>
+<dt>OUT: <tt class="docutils literal"><span class="pre">predecessor_map(PredecessorMap</span> <span class="pre">p_map)</span></tt></dt>
+<dd><p class="first">The predecessor map must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> or
+<tt class="docutils literal"><span class="pre">dummy_property_map</span></tt>, although only the local portions of the map
+will be written.</p>
+<p class="last"><strong>Default:</strong> <tt class="docutils literal"><span class="pre">dummy_property_map</span></tt></p>
+</dd>
+<dt>UTIL/OUT: <tt class="docutils literal"><span class="pre">distance_map(DistanceMap</span> <span class="pre">d_map)</span></tt></dt>
+<dd>The distance map must be either a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> or
+<tt class="docutils literal"><span class="pre">dummy_property_map</span></tt>. It will be given the <tt class="docutils literal"><span class="pre">vertex_distance</span></tt>
+role.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">visitor(DijkstraVisitor</span> <span class="pre">vis)</span></tt></dt>
+<dd>The visitor must be a distributed Dijkstra visitor. The suble differences
+between sequential and distributed Dijkstra visitors are discussed in the
+section <a class="reference internal" href="#visitor-event-points">Visitor Event Points</a>.</dd>
+<dt>UTIL/OUT: <tt class="docutils literal"><span class="pre">color_map(ColorMap</span> <span class="pre">color)</span></tt></dt>
+<dd>The color map must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> with the same
+process group as the graph <tt class="docutils literal"><span class="pre">g</span></tt> whose colors must monotonically
+darken (white -&gt; gray -&gt; black). The default value is a distributed
+<tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> created from a <tt class="docutils literal"><span class="pre">std::vector</span></tt> of
+<tt class="docutils literal"><span class="pre">default_color_type</span></tt>.</dd>
+</dl>
+<p>IN: <tt class="docutils literal"><span class="pre">lookahead(distance_type</span> <span class="pre">look)</span></tt></p>
+<blockquote>
+<p>When this parameter is supplied, the implementation will use the
+<a class="reference internal" href="#eager-dijkstra-s-algorithm">Eager Dijkstra's algorithm</a> with the given lookahead value.
+Lookahead permits distributed Dijkstra's algorithm to speculatively
+process vertices whose shortest distance from the source may not
+have been found yet. When the distance found is the shortest
+distance, parallelism is improved and the algorithm may terminate
+more quickly. However, if the distance is not the shortest distance,
+the vertex will need to be reprocessed later, resulting in more
+work.</p>
+<p>The type <tt class="docutils literal"><span class="pre">distance_type</span></tt> is the value type of the <tt class="docutils literal"><span class="pre">DistanceMap</span></tt>
+property map. It is a nonnegative value specifying how far ahead
+Dijkstra's algorithm may process values.</p>
+<p><strong>Default:</strong> no value (lookahead is not employed; uses <a class="reference internal" href="#crauser-et-al-s-algorithm">Crauser et
+al.'s algorithm</a>).</p>
+</blockquote>
+</div>
+<div class="section" id="visitor-event-points">
+<h1><a class="toc-backref" href="#id12">Visitor Event Points</a></h1>
+<p>The <a class="reference external" href="http://www.boost.org/libs/graph/doc/DijkstraVisitor.html">Dijkstra Visitor</a> concept defines 7 event points that will be
+triggered by the <a class="reference external" href="http://www.boost.org/libs/graph/doc/dijkstra_shortest_paths.html">sequential Dijkstra implementation</a>. The distributed
+Dijkstra retains these event points, but the sequence of events
+triggered and the process in which each event occurs will change
+depending on the distribution of the graph, lookahead, and edge
+weights.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">initialize_vertex(s,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by every process for each local vertex.</dd>
+<dt><tt class="docutils literal"><span class="pre">discover_vertex(u,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked each type a process discovers a new vertex
+<tt class="docutils literal"><span class="pre">u</span></tt>. Due to incomplete information in distributed property maps,
+this event may be triggered many times for the same vertex <tt class="docutils literal"><span class="pre">u</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">examine_vertex(u,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by the process owning the vertex <tt class="docutils literal"><span class="pre">u</span></tt>. This
+event may be invoked multiple times for the same vertex when the
+graph contains negative edges or lookahead is employed.</dd>
+<dt><tt class="docutils literal"><span class="pre">examine_edge(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by the process owning the source vertex of
+<tt class="docutils literal"><span class="pre">e</span></tt>. As with <tt class="docutils literal"><span class="pre">examine_vertex</span></tt>, this event may be invoked
+multiple times for the same edge.</dd>
+<dt><tt class="docutils literal"><span class="pre">edge_relaxed(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>Similar to <tt class="docutils literal"><span class="pre">examine_edge</span></tt>, this will be invoked by the process
+owning the source vertex and may be invoked multiple times (even
+without lookahead or negative edges).</dd>
+<dt><tt class="docutils literal"><span class="pre">edge_not_relaxed(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>Similar to <tt class="docutils literal"><span class="pre">edge_relaxed</span></tt>. Some <tt class="docutils literal"><span class="pre">edge_not_relaxed</span></tt> events that
+would be triggered by sequential Dijkstra's will become
+<tt class="docutils literal"><span class="pre">edge_relaxed</span></tt> events in distributed Dijkstra's algorithm.</dd>
+<dt><tt class="docutils literal"><span class="pre">finish_vertex(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>See documentation for <tt class="docutils literal"><span class="pre">examine_vertex</span></tt>. Note that a &quot;finished&quot;
+vertex is not necessarily finished if lookahead is permitted or
+negative edges exist in the graph.</dd>
+</dl>
+</div>
+<div class="section" id="crauser-et-al-s-algorithm">
+<h1><a class="toc-backref" href="#id13">Crauser et al.'s algorithm</a></h1>
+<pre class="literal-block">
+namespace graph {
+ template&lt;typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap, typename WeightMap,
+ typename IndexMap, typename ColorMap, typename Compare,
+ typename Combine, typename DistInf, typename DistZero&gt;
+ void
+ crauser_et_al_shortest_paths
+ (const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
+ IndexMap index_map, ColorMap color_map,
+ Compare compare, Combine combine, DistInf inf, DistZero zero,
+ DijkstraVisitor vis);
+
+ template&lt;typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap, typename WeightMap&gt;
+ void
+ crauser_et_al_shortest_paths
+ (const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight);
+
+ template&lt;typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap&gt;
+ void
+ crauser_et_al_shortest_paths
+ (const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance);
+}
+</pre>
+<p>The formulation of Dijkstra's algorithm by Crauser, Mehlhorn, Meyer,
+and Sanders <a class="citation-reference" href="#cmms98a" id="id1">[CMMS98a]</a> improves the scalability of parallel Dijkstra's
+algorithm by increasing the number of vertices that can be processed
+in a given superstep. This algorithm adapts well to various graph
+types, and is a simple algorithm to use, requiring no additional user
+input to achieve reasonable performance. The disadvantage of this
+algorithm is that the implementation is required to manage three
+priority queues, which creates a large amount of work at each node.</p>
+<p>This algorithm is used by default in distributed
+<tt class="docutils literal"><span class="pre">dijkstra_shortest_paths()</span></tt>.</p>
+<div class="section" id="id2">
+<h2><a class="toc-backref" href="#id14">Where Defined</a></h2>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/crauser_et_al_shortest_paths.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="complexity">
+<h2><a class="toc-backref" href="#id15">Complexity</a></h2>
+<p>This algorithm performs <em>O(V log V)</em> work in <em>d + 1</em> BSP supersteps,
+where <em>d</em> is at most <em>O(V)</em> but is generally much smaller. On directed
+Erdos-Renyi graphs with edge weights in [0, 1), the expected number of
+supersteps <em>d</em> is <em>O(n^(1/3))</em> with high probability.</p>
+</div>
+<div class="section" id="performance">
+<h2><a class="toc-backref" href="#id16">Performance</a></h2>
+<p>The following charts illustrate the performance of the Parallel BGL implementation of Crauser et al.'s
+algorithm on graphs with edge weights uniformly selected from the
+range <em>[0, 1)</em>.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=4" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=4" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=4&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=4&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=4" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=4" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=4&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=4&amp;speedup=1" />
+</div>
+</div>
+<div class="section" id="eager-dijkstra-s-algorithm">
+<h1><a class="toc-backref" href="#id17">Eager Dijkstra's algorithm</a></h1>
+<pre class="literal-block">
+namespace graph {
+ template&lt;typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap, typename WeightMap,
+ typename IndexMap, typename ColorMap, typename Compare,
+ typename Combine, typename DistInf, typename DistZero&gt;
+ void
+ eager_dijkstra_shortest_paths
+ (const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance,
+ typename property_traits&lt;DistanceMap&gt;::value_type lookahead,
+ WeightMap weight, IndexMap index_map, ColorMap color_map,
+ Compare compare, Combine combine, DistInf inf, DistZero zero,
+ DijkstraVisitor vis);
+
+ template&lt;typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap, typename WeightMap&gt;
+ void
+ eager_dijkstra_shortest_paths
+ (const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance,
+ typename property_traits&lt;DistanceMap&gt;::value_type lookahead,
+ WeightMap weight);
+
+ template&lt;typename DistributedGraph, typename DijkstraVisitor,
+ typename PredecessorMap, typename DistanceMap&gt;
+ void
+ eager_dijkstra_shortest_paths
+ (const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance,
+ typename property_traits&lt;DistanceMap&gt;::value_type lookahead);
+}
+</pre>
+<p>In each superstep, parallel Dijkstra's algorithm typically only
+processes nodes whose distances equivalent to the global minimum
+distance, because these distances are guaranteed to be correct. This
+variation on the algorithm allows the algorithm to process all
+vertices whose distances are within some constant value of the
+minimum distance. The value is called the &quot;lookahead&quot; value and is
+provided by the user as the fifth parameter to the function. Small
+values of the lookahead parameter will likely result in limited
+parallelization opportunities, whereas large values will expose more
+parallelism but may introduce (non-infinite) looping and result in
+extra work. The optimal value for the lookahead parameter depends on
+the input graph; see <a class="citation-reference" href="#cmms98b" id="id3">[CMMS98b]</a> and <a class="citation-reference" href="#ms98" id="id4">[MS98]</a>.</p>
+<p>This algorithm will be used by <tt class="docutils literal"><span class="pre">dijkstra_shortest_paths()</span></tt> when it
+is provided with a lookahead value.</p>
+<div class="section" id="id5">
+<h2><a class="toc-backref" href="#id18">Where Defined</a></h2>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/eager_dijkstra_shortest_paths.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="id6">
+<h2><a class="toc-backref" href="#id19">Complexity</a></h2>
+<p>This algorithm performs <em>O(V log V)</em> work in <em>d
++ 1</em> BSP supersteps, where <em>d</em> is at most <em>O(V)</em> but may be smaller
+depending on the lookahead value. the algorithm may perform more work
+when a large lookahead is provided, because vertices will be
+reprocessed.</p>
+</div>
+<div class="section" id="id7">
+<h2><a class="toc-backref" href="#id20">Performance</a></h2>
+<p>The performance of the eager Dijkstra's algorithm varies greatly
+depending on the lookahead value. The following charts illustrate the
+performance of the Parallel BGL on graphs with edge weights uniformly
+selected from the range <em>[0, 1)</em> and a constant lookahead of 0.1.</p>
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=5" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=5" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=5&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeSparse&amp;columns=5&amp;speedup=1" />
+<img align="left" alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=5" class="align-left" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=5" />
+<img alt="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=5&amp;speedup=1" src="http://www.osl.iu.edu/research/pbgl/performance/chart.php?cluster=Odin&amp;generator=ER,SF,SW&amp;dataset=TimeDense&amp;columns=5&amp;speedup=1" />
+</div>
+</div>
+<div class="section" id="delta-stepping-algorithm">
+<h1><a class="toc-backref" href="#id21">Delta-Stepping algorithm</a></h1>
+<pre class="literal-block">
+namespace boost { namespace graph { namespace distributed {
+
+ template &lt;typename Graph, typename PredecessorMap,
+ typename DistanceMap, typename WeightMap&gt;
+ void delta_stepping_shortest_paths
+ (const Graph&amp; g,
+ typename graph_traits&lt;Graph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
+ typename property_traits&lt;WeightMap&gt;::value_type delta)
+
+
+ template &lt;typename Graph, typename PredecessorMap,
+ typename DistanceMap, typename WeightMap&gt;
+ void delta_stepping_shortest_paths
+ (const Graph&amp; g,
+ typename graph_traits&lt;Graph&gt;::vertex_descriptor s,
+ PredecessorMap predecessor, DistanceMap distance, WeightMap weight)
+ }
+
+} } }
+</pre>
+<p>The delta-stepping algorithm <a class="citation-reference" href="#ms98" id="id8">[MS98]</a> is another variant of the parallel
+Dijkstra algorithm. Like the eager Dijkstra algorithm, it employs a
+lookahead (<tt class="docutils literal"><span class="pre">delta</span></tt>) value that allows processors to process vertices
+before we are guaranteed to find their minimum distances, permitting
+more parallelism than a conservative strategy. Delta-stepping also
+introduces a multi-level bucket data structure that provides more
+relaxed ordering constraints than the priority queues employed by the
+other Dijkstra variants, reducing the complexity of insertions,
+relaxations, and removals from the central data structure. The
+delta-stepping algorithm is the best-performing of the Dijkstra
+variants.</p>
+<p>The lookahead value <tt class="docutils literal"><span class="pre">delta</span></tt> determines how large each of the
+&quot;buckets&quot; within the delta-stepping queue will be, where the ith
+bucket contains edges within tentative distances between <tt class="docutils literal"><span class="pre">delta``*i</span>
+<span class="pre">and</span> <span class="pre">``delta``*(i+1).</span> <span class="pre">``delta</span></tt> must be a positive value. When omitted,
+<tt class="docutils literal"><span class="pre">delta</span></tt> will be set to the maximum edge weight divided by the
+maximum degree.</p>
+<div class="section" id="id9">
+<h2><a class="toc-backref" href="#id22">Where Defined</a></h2>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/delta_stepping_shortest_paths.hpp</span></tt>&gt;</p>
+</div>
+</div>
+<div class="section" id="example">
+<h1><a class="toc-backref" href="#id23">Example</a></h1>
+<p>See the separate <a class="reference external" href="dijkstra_example.html">Dijkstra example</a>.</p>
+</div>
+<div class="section" id="bibliography">
+<h1><a class="toc-backref" href="#id24">Bibliography</a></h1>
+<table class="docutils citation" frame="void" id="cmms98a" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[CMMS98a]</a></td><td>Andreas Crauser, Kurt Mehlhorn, Ulrich Meyer, and Peter Sanders. A
+Parallelization of Dijkstra's Shortest Path Algorithm. In
+<em>Mathematical Foundations of Computer Science (MFCS)</em>, volume 1450 of
+Lecture Notes in Computer Science, pages 722--731, 1998. Springer.</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="cmms98b" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id3">[CMMS98b]</a></td><td>Andreas Crauser, Kurt Mehlhorn, Ulrich Meyer, and Peter
+Sanders. Parallelizing Dijkstra's shortest path algorithm. Technical
+report, MPI-Informatik, 1998.</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="ms98" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[MS98]</td><td><em>(<a class="fn-backref" href="#id4">1</a>, <a class="fn-backref" href="#id8">2</a>)</em> Ulrich Meyer and Peter Sanders. Delta-stepping: A parallel
+shortest path algorithm. In <em>6th ESA</em>, LNCS. Springer, 1998.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2004, 2005, 2006, 2007, 2008 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/distributedS.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/distributedS.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>distributedS Distribution Selector</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="distributeds-distribution-selector">
+<h1 class="title"><tt class="docutils literal"><span class="pre">distributedS</span></tt> Distribution Selector</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<p>The Boost Graph Library's class template <a class="reference external" href="http://www.boost.org/libs/graph/doc/adjacency_list.html">adjacency_list</a> supports
+several selectors that indicate what data structure should be used for
+the storage of edges or vertices. The selector <tt class="docutils literal"><span class="pre">vecS</span></tt>, for instance,
+indicates storage in a <tt class="docutils literal"><span class="pre">std::vector</span></tt> whereas <tt class="docutils literal"><span class="pre">listS</span></tt> indicates
+storage in a <tt class="docutils literal"><span class="pre">std::list</span></tt>. The Parallel BGL's <a class="reference external" href="distributed_adjacency_list.html">distributed
+adjacency list</a> supports an additional selector, <tt class="docutils literal"><span class="pre">distributedS</span></tt>,
+that indicates that the storage should be distributed across multiple
+processes. This selector can transform a sequential adjacency list
+into a distributed adjacency list.</p>
+<pre class="literal-block">
+template&lt;typename ProcessGroup, typename LocalSelector = vecS&gt;
+struct distributedS;
+</pre>
+<div class="section" id="template-parameters">
+<h1>Template parameters</h1>
+<dl class="docutils">
+<dt><strong>ProcessGroup</strong>:</dt>
+<dd>The type of the process group over which the property map is
+distributed and also the medium for communication. This type must
+model the <a class="reference external" href="../parallel/ProcessGroup.html">Process Group</a> concept, but certain data structures may
+place additional requirements on this parameter.</dd>
+<dt><strong>LocalSelector</strong>:</dt>
+<dd>A selector type (e.g., <tt class="docutils literal"><span class="pre">vecS</span></tt>) that indicates how vertices or
+edges should be stored in each process.</dd>
+</dl>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:13 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/distributed_adjacency_list.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/distributed_adjacency_list.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,804 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Distributed Adjacency List</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-distributed-adjacency-list">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Distributed Adjacency List</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#introduction" id="id1">Introduction</a><ul>
+<li><a class="reference internal" href="#defining-a-distributed-adjacency-list" id="id2">Defining a Distributed Adjacency List</a></li>
+<li><a class="reference internal" href="#distributed-vertex-and-edge-properties" id="id3">Distributed Vertex and Edge Properties</a></li>
+<li><a class="reference internal" href="#named-vertices" id="id4">Named Vertices</a></li>
+<li><a class="reference internal" href="#building-a-distributed-graph" id="id5">Building a Distributed Graph</a></li>
+<li><a class="reference internal" href="#graph-concepts" id="id6">Graph Concepts</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#reference" id="id7">Reference</a><ul>
+<li><a class="reference internal" href="#where-defined" id="id8">Where Defined</a></li>
+<li><a class="reference internal" href="#associated-types" id="id9">Associated Types</a></li>
+<li><a class="reference internal" href="#member-functions" id="id10">Member Functions</a></li>
+<li><a class="reference internal" href="#non-member-functions" id="id11">Non-Member Functions</a></li>
+<li><a class="reference internal" href="#structure-modification" id="id12">Structure Modification</a></li>
+<li><a class="reference internal" href="#property-map-accessors" id="id13">Property Map Accessors</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="introduction">
+<h1><a class="toc-backref" href="#id1">Introduction</a></h1>
+<p>The distributed adjacency list implements a graph data structure using
+an adjacency list representation. Its interface and behavior are
+roughly equivalent to the Boost Graph Library's <a class="reference external" href="http://www.boost.org/libs/graph/doc/adjacency_list.html">adjacency_list</a>
+class template. However, the distributed adjacency list partitions the
+vertices of the graph across several processes (which need not share
+an address space). Edges outgoing from any vertex stored by a process
+are also stored on that process, except in the case of undirected
+graphs, where either the source or the target may store the edge.</p>
+<pre class="literal-block">
+template&lt;typename OutEdgeListS, typename ProcessGroup, typename VertexListS,
+ typename DirectedS, typename VertexProperty, typename EdgeProperty,
+ typename GraphProperty, typename EdgeListS&gt;
+class adjacency_list&lt;OutEdgeListS,
+ distributedS&lt;ProcessGroup, VertexListS&gt;,
+ DirectedS, VertexProperty,
+ EdgeProperty, GraphProperty, EdgeListS&gt;;
+</pre>
+<div class="section" id="defining-a-distributed-adjacency-list">
+<h2><a class="toc-backref" href="#id2">Defining a Distributed Adjacency List</a></h2>
+<p>To create a distributed adjacency list, first determine the
+representation of the graph in a single address space using these
+<a class="reference external" href="http://www.boost.org/libs/graph/doc/using_adjacency_list.html">guidelines</a>. Next, replace the vertex list selector (<tt class="docutils literal"><span class="pre">VertexListS</span></tt>)
+with an instantiation of <a class="reference external" href="distributedS.html">distributedS</a>, which includes:</p>
+<ul class="simple">
+<li>Selecting a <a class="reference external" href="process_group.html">process group</a> type that represents the various
+coordinating processes that will store the distributed graph. For
+example, the <a class="reference external" href="process_group.html">MPI process group</a>.</li>
+<li>A selector indicating how the vertex lists in each process will be
+stored. Only the <tt class="docutils literal"><span class="pre">vecS</span></tt> and <tt class="docutils literal"><span class="pre">listS</span></tt> selectors are well-supported
+at this time.</li>
+</ul>
+<p>The following <tt class="docutils literal"><span class="pre">typedef</span></tt> defines a distributed adjacency list
+containing directed edges. The vertices in the graph will be
+distributed over several processes, using the MPI process group
+for communication. In each process, the vertices and outgoing edges
+will be stored in STL vectors. There are no properties attached to the
+vertices or edges of the graph.</p>
+<pre class="literal-block">
+using namespace boost;
+typedef adjacency_list&lt;vecS,
+ distributedS&lt;parallel::mpi::bsp_process_group, vecS&gt;,
+ directedS&gt;
+ Graph;
+</pre>
+</div>
+<div class="section" id="distributed-vertex-and-edge-properties">
+<h2><a class="toc-backref" href="#id3">Distributed Vertex and Edge Properties</a></h2>
+<p>Vertex and edge properties for distributed graphs mirror their
+counterparts for non-distributed graphs. With a distributed graph,
+however, vertex and edge properties are stored only in the process
+that owns the vertex or edge.</p>
+<p>The most direct way to attach properties to a distributed graph is to
+create a structure that will be attached to each of the vertices and
+edges of the graph. For example, if we wish to model a simplistic map
+of the United States interstate highway system, we might state that
+the vertices of the graph are cities and the edges are highways, then
+define the information that we maintain for each city and highway:</p>
+<pre class="literal-block">
+struct City {
+ City() { }
+ City(const std::string&amp; name, const std::string&amp; mayor = &quot;Unknown&quot;, int population = 0)
+ : name(name), mayor(mayor), population(population) { }
+
+ std::string name;
+ std::string mayor;
+ int population;
+
+ // Serialization support is required!
+ template&lt;typename Archiver&gt;
+ void serialize(Archiver&amp; ar, const unsigned int /*version*/) {
+ ar &amp; name &amp; mayor &amp; population;
+ }
+};
+
+struct Highway {
+ Highway() { }
+ Highway(const std::string&amp; name, int lanes, int miles_per_hour, int length)
+ : name(name), lanes(lanes), miles_per_hour(miles_per_hour), length(length) { }
+
+ std::string name;
+ int lanes;
+ int miles_per_hour;
+ int length;
+
+ // Serialization support is required!
+ template&lt;typename Archiver&gt;
+ void serialize(Archiver&amp; ar, const unsigned int /*version*/) {
+ ar &amp; name &amp; lanes &amp; miles_per_hour &amp; length;
+ }
+};
+</pre>
+<p>To create a distributed graph for a road map, we supply <tt class="docutils literal"><span class="pre">City</span></tt> and
+<tt class="docutils literal"><span class="pre">Highway</span></tt> as the fourth and fifth parameters to <tt class="docutils literal"><span class="pre">adjacency_list</span></tt>,
+respectively:</p>
+<pre class="literal-block">
+typedef adjacency_list&lt;vecS,
+ distributedS&lt;parallel::mpi::bsp_process_group, vecS&gt;,
+ directedS,
+ City, Highway&gt;
+ RoadMap;
+</pre>
+<p>Property maps for internal properties retain their behavior with
+distributed graphs via <a class="reference external" href="distributed_property_map.html">distributed property maps</a>, which automate
+communication among processes so that <tt class="docutils literal"><span class="pre">put</span></tt> and <tt class="docutils literal"><span class="pre">get</span></tt> operations
+may be applied to non-local vertices and edges. However, for
+distributed adjacency lists that store vertices in a vector
+(<tt class="docutils literal"><span class="pre">VertexListS</span></tt> is <tt class="docutils literal"><span class="pre">vecS</span></tt>), the automatic <tt class="docutils literal"><span class="pre">vertex_index</span></tt>
+property map restricts the domain of <tt class="docutils literal"><span class="pre">put</span></tt> and <tt class="docutils literal"><span class="pre">get</span></tt> operations
+to vertices local to the process executing the operation. For example,
+we can create a property map that accesses the length of each highway
+as follows:</p>
+<pre class="literal-block">
+RoadMap map; // distributed graph instance
+
+typedef property_map&lt;RoadMap, int Highway::*&gt;::type
+ road_length = get(&amp;Highway::length, map);
+</pre>
+<p>Now, one can access the length of any given road based on its edge
+descriptor <tt class="docutils literal"><span class="pre">e</span></tt> with the expression <tt class="docutils literal"><span class="pre">get(road_length,</span> <span class="pre">e)</span></tt>,
+regardless of which process stores the edge <tt class="docutils literal"><span class="pre">e</span></tt>.</p>
+</div>
+<div class="section" id="named-vertices">
+<h2><a class="toc-backref" href="#id4">Named Vertices</a></h2>
+<p>The vertices of a graph typically correspond to named entities within
+the application domain. In the road map example from the previous
+section, the vertices in the graph represent cities. The distributed
+adjacency list supports named vertices, which provides an implicit
+mapping from the names of the vertices in the application domain
+(e.g., the name of a city, such as &quot;Bloomington&quot;) to the actual vertex
+descriptor stored within the distributed graph (e.g., the third vertex
+on processor 1). By enabling support for named vertices, one can refer
+to vertices by name when manipulating the graph. For example, one can
+add a highway from Indianapolis to Chicago:</p>
+<pre class="literal-block">
+add_edge(&quot;Indianapolis&quot;, &quot;Chicago&quot;, Highway(&quot;I-65&quot;, 4, 65, 151), map);
+</pre>
+<p>The distributed adjacency list will find vertices associated with the
+names &quot;Indianapolis&quot; and &quot;Chicago&quot;, then add an edge between these
+vertices that represents I-65. The vertices may be stored on any
+processor, local or remote.</p>
+<p>To enable named vertices, specialize the <tt class="docutils literal"><span class="pre">internal_vertex_name</span></tt>
+property for the structure attached to the vertices in your
+graph. <tt class="docutils literal"><span class="pre">internal_vertex_name</span></tt> contains a single member, <tt class="docutils literal"><span class="pre">type</span></tt>,
+which is the type of a function object that accepts a vertex property
+and returns the name stored within that vertex property. In the case
+of our road map, the <tt class="docutils literal"><span class="pre">name</span></tt> field contains the name of each city, so
+we use the <tt class="docutils literal"><span class="pre">member</span></tt> function object from the <a class="reference external" href="http://www.boost.org/libs/multi_index/doc/index.html">Boost.MultiIndex</a>
+library to extract the name, e.g.,</p>
+<pre class="literal-block">
+namespace boost { namespace graph {
+
+template&lt;&gt;
+struct internal_vertex_name&lt;City&gt;
+{
+ typedef multi_index::member&lt;City, std::string, &amp;City::name&gt; type;
+};
+
+} }
+</pre>
+<p>That's it! One can now refer to vertices by name when interacting with
+the distributed adjacency list.</p>
+<p>What happens when one uses the name of a vertex that does not exist?
+For example, in our <tt class="docutils literal"><span class="pre">add_edge</span></tt> call above, what happens if the
+vertex named &quot;Indianapolis&quot; has not yet been added to the graph? By
+default, the distributed adjacency list will throw an exception if a
+named vertex does not yet exist. However, one can customize this
+behavior by specifying a function object that constructs an instance
+of the vertex property (e.g., <tt class="docutils literal"><span class="pre">City</span></tt>) from just the name of the
+vertex. This customization occurs via the
+<tt class="docutils literal"><span class="pre">internal_vertex_constructor</span></tt> trait. For example, using the
+<tt class="docutils literal"><span class="pre">vertex_from_name</span></tt> template (provided with the Parallel BGL), we can
+state that a <tt class="docutils literal"><span class="pre">City</span></tt> can be constructed directly from the name of the
+city using its second constructor:</p>
+<pre class="literal-block">
+namespace boost { namespace graph {
+
+template&lt;&gt;
+struct internal_vertex_constructor&lt;City&gt;
+{
+ typedef vertex_from_name&lt;City&gt; type;
+};
+
+} }
+</pre>
+<p>Now, one can add edges by vertex name freely, without worrying about
+the explicit addition of vertices. The <tt class="docutils literal"><span class="pre">mayor</span></tt> and <tt class="docutils literal"><span class="pre">population</span></tt>
+fields will have default values, but the graph structure will be
+correct.</p>
+</div>
+<div class="section" id="building-a-distributed-graph">
+<h2><a class="toc-backref" href="#id5">Building a Distributed Graph</a></h2>
+<p>Once you have determined the layout of your graph type, including the
+specific data structures and properties, it is time to construct an
+instance of the graph by adding the appropriate vertices and
+edges. Construction of distributed graphs can be slightly more
+complicated than construction of normal, non-distributed graph data
+structures, because one must account for both the distribution of the
+vertices and edges and the multiple processes executing
+concurrently. There are three main ways to construct distributed
+graphs:</p>
+<p>1. <em>Sequence constructors</em>: if your data can easily be generated by a
+pair of iterators that produce (source, target) pairs, you can use the
+sequence constructors to build the distributed graph in parallel. This
+method is often preferred when creating benchmarks, because random
+graph generators like the <a class="reference external" href="http://www.boost.org/libs/graph/doc/sorted_erdos_renyi_gen.html">sorted_erdos_renyi_iterator</a> create the
+appropriate input sequence. Note that one must provide the same input
+iterator sequence on all processes. This method has the advantage that
+the sequential graph-building code is identical to the parallel
+graph-building code. An example constructing a random graph this way:</p>
+<blockquote>
+<pre class="literal-block">
+typedef boost::sorted_erdos_renyi_iterator&lt;boost::minstd_rand, Graph&gt; ERIter;
+boost::minstd_rand gen;
+unsigned long n = 1000000; // 1M vertices
+Graph g(ERIter(gen, n, 0.00005), ERIter(), n);
+</pre>
+</blockquote>
+<p>2. <em>Adding edges by vertex number</em>: if you are able to map your
+vertices into values in the random [0, <em>n</em>), where <em>n</em> is the number
+of vertices in the distributed graph. Use this method rather than the
+sequence constructors when your algorithm cannot easily be moved into
+input iterators, or if you can't replicate the input sequence. For
+example, you might be reading the graph from an input file:</p>
+<blockquote>
+<pre class="literal-block">
+Graph g(n); // initialize with the total number of vertices, n
+if (process_id(g.process_group()) == 0) {
+ // Only process 0 loads the graph, which is distributed automatically
+ int source, target;
+ for (std::cin &gt;&gt; source &gt;&gt; target)
+ add_edge(vertex(source, g), vertex(target, g), g);
+}
+
+// All processes synchronize at this point, then the graph is complete
+synchronize(g.process_group());
+</pre>
+</blockquote>
+<p>3. <em>Adding edges by name</em>: if you are using named vertices, you can
+construct your graph just by calling <tt class="docutils literal"><span class="pre">add_edge</span></tt> with the names of
+the source and target vertices. Be careful to make sure that each edge
+is added by only one process (it doesn't matter which process it is),
+otherwise you will end up with multiple edges. For example, in the
+following program we read edges from the standard input of process 0,
+adding those edges by name. Vertices and edges will be created and
+distributed automatically.</p>
+<blockquote>
+<pre class="literal-block">
+Graph g;
+if (process_id(g.process_group()) == 0) {
+ // Only process 0 loads the graph, which is distributed automatically
+ std:string source, target;
+ for(std::cin &gt;&gt; source &gt;&gt; target)
+ add_edge(source, target, g);
+}
+
+// All processes synchronize at this point, then the graph is complete
+synchronize(g.process_group());
+</pre>
+</blockquote>
+</div>
+<div class="section" id="graph-concepts">
+<h2><a class="toc-backref" href="#id6">Graph Concepts</a></h2>
+<p>The distributed adjacency list models the <a class="reference external" href="http://www.boost.org/libs/graph/doc/Graph.html">Graph</a> concept, and in
+particular the <a class="reference external" href="DistributedGraph.html">Distributed Graph</a> concept. It also models the
+<a class="reference external" href="http://www.boost.org/libs/graph/doc/IncidenceGraph.html">Incidence Graph</a> and <a class="reference external" href="http://www.boost.org/libs/graph/doc/AdjacencyGraph.html">Adjacency Graph</a> concept, but restricts the
+input domain of the operations to correspond to local vertices
+only. For instance, a process may only access the outgoing edges of a
+vertex if that vertex is stored in that process. Undirected and
+bidirectional distributed adjacency lists model the <a class="reference external" href="http://www.boost.org/libs/graph/doc/BidirectionalGraph.html">Bidirectional
+Graph</a> concept, with the same domain restrictions. Distributed
+adjacency lists also model the <a class="reference external" href="http://www.boost.org/libs/graph/doc/MutableGraph.html">Mutable Graph</a> concept (with domain
+restrictions; see the <a class="reference internal" href="#reference">Reference</a> section), <a class="reference external" href="http://www.boost.org/libs/graph/doc/PropertyGraph.html">Property Graph</a> concept,
+and <a class="reference external" href="http://www.boost.org/libs/graph/doc/MutablePropertyGraph.html">Mutable Property Graph</a> concept.</p>
+<p>Unlike its non-distributed counterpart, the distributed adjacency
+list does <strong>not</strong> model the <a class="reference external" href="http://www.boost.org/libs/graph/doc/VertexListGraph.html">Vertex List Graph</a> or <a class="reference external" href="http://www.boost.org/libs/graph/doc/EdgeListGraph.html">Edge List
+Graph</a> concepts, because one cannot enumerate all vertices or edges
+within a distributed graph. Instead, it models the weaker
+<a class="reference external" href="DistributedVertexListGraph.html">Distributed Vertex List Graph</a> and <a class="reference external" href="DistributedEdgeListGraph.html">Distributed Edge List Graph</a>
+concepts, which permit access to the local edges and vertices on each
+processor. Note that if all processes within the process group over
+which the graph is distributed iterator over their respective vertex
+or edge lists, all vertices and edges will be covered once.</p>
+</div>
+</div>
+<div class="section" id="reference">
+<h1><a class="toc-backref" href="#id7">Reference</a></h1>
+<p>Since the distributed adjacency list closely follows the
+non-distributed <a class="reference external" href="http://www.boost.org/libs/graph/doc/adjacency_list.html">adjacency_list</a>, this reference documentation
+only describes where the two implementations differ.</p>
+<div class="section" id="where-defined">
+<h2><a class="toc-backref" href="#id8">Where Defined</a></h2>
+<p>&lt;boost/graph/distributed/adjacency_list.hpp&gt;</p>
+</div>
+<div class="section" id="associated-types">
+<h2><a class="toc-backref" href="#id9">Associated Types</a></h2>
+<pre class="literal-block">
+adjacency_list::process_group_type
+</pre>
+<p>The type of the process group over which the graph will be
+distributed.</p>
+<hr class="docutils" />
+<blockquote>
+adjacency_list::distribution_type</blockquote>
+<p>The type of distribution used to partition vertices in the graph.</p>
+<hr class="docutils" />
+<blockquote>
+adjacency_list::vertex_name_type</blockquote>
+<p>If the graph supports named vertices, this is the type used to name
+vertices. Otherwise, this type is not present within the distributed
+adjacency list.</p>
+</div>
+<div class="section" id="member-functions">
+<h2><a class="toc-backref" href="#id10">Member Functions</a></h2>
+<pre class="literal-block">
+adjacency_list(const ProcessGroup&amp; pg = ProcessGroup());
+
+adjacency_list(const GraphProperty&amp; g,
+ const ProcessGroup&amp; pg = ProcessGroup());
+</pre>
+<p>Construct an empty distributed adjacency list with the given process
+group (or default) and graph property (or default).</p>
+<hr class="docutils" />
+<pre class="literal-block">
+adjacency_list(vertices_size_type n, const GraphProperty&amp; p,
+ const ProcessGroup&amp; pg, const Distribution&amp; distribution);
+
+adjacency_list(vertices_size_type n, const ProcessGroup&amp; pg,
+ const Distribution&amp; distribution);
+
+adjacency_list(vertices_size_type n, const GraphProperty&amp; p,
+ const ProcessGroup&amp; pg = ProcessGroup());
+
+adjacency_list(vertices_size_type n,
+ const ProcessGroup&amp; pg = ProcessGroup());
+</pre>
+<p>Construct a distributed adjacency list with <tt class="docutils literal"><span class="pre">n</span></tt> vertices,
+optionally providing the graph property, process group, or
+distribution. The <tt class="docutils literal"><span class="pre">n</span></tt> vertices will be distributed via the given
+(or default-constructed) distribution. This operation is collective,
+requiring all processes with the process group to execute it
+concurrently.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template &lt;class EdgeIterator&gt;
+adjacency_list(EdgeIterator first, EdgeIterator last,
+ vertices_size_type n,
+ const ProcessGroup&amp; pg = ProcessGroup(),
+ const GraphProperty&amp; p = GraphProperty());
+
+template &lt;class EdgeIterator, class EdgePropertyIterator&gt;
+adjacency_list(EdgeIterator first, EdgeIterator last,
+ EdgePropertyIterator ep_iter,
+ vertices_size_type n,
+ const ProcessGroup&amp; pg = ProcessGroup(),
+ const GraphProperty&amp; p = GraphProperty());
+
+template &lt;class EdgeIterator&gt;
+adjacency_list(EdgeIterator first, EdgeIterator last,
+ vertices_size_type n,
+ const ProcessGroup&amp; process_group,
+ const Distribution&amp; distribution,
+ const GraphProperty&amp; p = GraphProperty());
+
+template &lt;class EdgeIterator, class EdgePropertyIterator&gt;
+adjacency_list(EdgeIterator first, EdgeIterator last,
+ EdgePropertyIterator ep_iter,
+ vertices_size_type n,
+ const ProcessGroup&amp; process_group,
+ const Distribution&amp; distribution,
+ const GraphProperty&amp; p = GraphProperty());
+</pre>
+<p>Construct a distributed adjacency list with <tt class="docutils literal"><span class="pre">n</span></tt> vertices and with
+edges specified in the edge list given by the range <tt class="docutils literal"><span class="pre">[first,</span> <span class="pre">last)</span></tt>. The
+<tt class="docutils literal"><span class="pre">EdgeIterator</span></tt> must be a model of <a class="reference external" href="http://www.boost.org/doc/html/InputIterator.html">InputIterator</a>. The value type of the
+<tt class="docutils literal"><span class="pre">EdgeIterator</span></tt> must be a <tt class="docutils literal"><span class="pre">std::pair</span></tt>, where the type in the pair is an
+integer type. The integers will correspond to vertices, and they must
+all fall in the range of <tt class="docutils literal"><span class="pre">[0,</span> <span class="pre">n)</span></tt>. When provided, <tt class="docutils literal"><span class="pre">ep_iter</span></tt>
+refers to an edge property list <tt class="docutils literal"><span class="pre">[ep_iter,</span> <span class="pre">ep_iter</span> <span class="pre">+</span> <span class="pre">m)</span></tt> contains
+properties for each of the edges.</p>
+<p>This constructor is a collective operation and must be executed
+concurrently by each process with the same argument list. Most
+importantly, the edge lists provided to the constructor in each process
+should be equivalent. The vertices will be partitioned among the
+processes according to the <tt class="docutils literal"><span class="pre">distribution</span></tt>, with edges placed on the
+process owning the source of the edge. Note that this behavior
+permits sequential graph construction code to be parallelized
+automatically, regardless of the underlying distribution.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void clear()
+</pre>
+<p>Removes all of the edges and vertices from the local graph. To
+eliminate all vertices and edges from the graph, this routine must be
+executed in all processes.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+process_group_type&amp; process_group();
+const process_group_type&amp; process_group() const;
+</pre>
+<p>Returns the process group over which this graph is distributed.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+distribution_type&amp; distribution();
+const distribution_type&amp; distribution() const;
+</pre>
+<p>Returns the distribution used for initial placement of vertices.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename VertexProcessorMap&gt;
+ void redistribute(VertexProcessorMap vertex_to_processor);
+</pre>
+<p>Redistributes the vertices (and, therefore, the edges) of the
+graph. The property map <tt class="docutils literal"><span class="pre">vertex_to_processor</span></tt> provides, for each
+vertex, the process identifier indicating where the vertex should be
+moved. Once this collective routine has completed, the distributed
+graph will reflect the new distribution. All vertex and edge
+descsriptors and internal and external property maps are invalidated
+by this operation.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename OStreamConstructibleArchive&gt;
+ void save(std::string const&amp; filename) const;
+
+template&lt;typename IStreamConstructibleArchive&gt;
+ void load(std::string const&amp; filename);
+</pre>
+<p>Serializes the graph to a Boost.Serialization archive.
+<tt class="docutils literal"><span class="pre">OStreamConstructibleArchive</span></tt> and <tt class="docutils literal"><span class="pre">IStreamConstructibleArchive</span></tt>
+are models of Boost.Serialization <em>Archive</em> with the extra
+requirement that they can be constructed from a <tt class="docutils literal"><span class="pre">std::ostream</span></tt>
+and <tt class="docutils literal"><span class="pre">std::istream</span></tt>.
+<tt class="docutils literal"><span class="pre">filename</span></tt> names a directory that will hold files for
+the different processes.</p>
+</div>
+<div class="section" id="non-member-functions">
+<h2><a class="toc-backref" href="#id11">Non-Member Functions</a></h2>
+<pre class="literal-block">
+std::pair&lt;vertex_iterator, vertex_iterator&gt;
+vertices(const adjacency_list&amp; g);
+</pre>
+<p>Returns an iterator-range providing access to the vertex set of graph
+<tt class="docutils literal"><span class="pre">g</span></tt> stored in this process. Each of the processes that contain <tt class="docutils literal"><span class="pre">g</span></tt>
+will get disjoint sets of vertices.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+std::pair&lt;edge_iterator, edge_iterator&gt;
+edges(const adjacency_list&amp; g);
+</pre>
+<p>Returns an iterator-range providing access to the edge set of graph
+<tt class="docutils literal"><span class="pre">g</span></tt> stored in this process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+std::pair&lt;adjacency_iterator, adjacency_iterator&gt;
+adjacent_vertices(vertex_descriptor u, const adjacency_list&amp; g);
+</pre>
+<p>Returns an iterator-range providing access to the vertices adjacent to
+vertex <tt class="docutils literal"><span class="pre">u</span></tt> in graph <tt class="docutils literal"><span class="pre">g</span></tt>. The vertex <tt class="docutils literal"><span class="pre">u</span></tt> must be local to this process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+std::pair&lt;out_edge_iterator, out_edge_iterator&gt;
+out_edges(vertex_descriptor u, const adjacency_list&amp; g);
+</pre>
+<p>Returns an iterator-range providing access to the out-edges of vertex
+<tt class="docutils literal"><span class="pre">u</span></tt> in graph <tt class="docutils literal"><span class="pre">g</span></tt>. If the graph is undirected, this iterator-range
+provides access to all edges incident on vertex <tt class="docutils literal"><span class="pre">u</span></tt>. For both
+directed and undirected graphs, for an out-edge <tt class="docutils literal"><span class="pre">e</span></tt>, <tt class="docutils literal"><span class="pre">source(e,</span> <span class="pre">g)</span>
+<span class="pre">==</span> <span class="pre">u</span></tt> and <tt class="docutils literal"><span class="pre">target(e,</span> <span class="pre">g)</span> <span class="pre">==</span> <span class="pre">v</span></tt> where <tt class="docutils literal"><span class="pre">v</span></tt> is a vertex adjacent to
+<tt class="docutils literal"><span class="pre">u</span></tt>. The vertex <tt class="docutils literal"><span class="pre">u</span></tt> must be local to this process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+std::pair&lt;in_edge_iterator, in_edge_iterator&gt;
+in_edges(vertex_descriptor v, const adjacency_list&amp; g);
+</pre>
+<p>Returns an iterator-range providing access to the in-edges of vertex
+<tt class="docutils literal"><span class="pre">v</span></tt> in graph <tt class="docutils literal"><span class="pre">g</span></tt>. This operation is only available if
+<tt class="docutils literal"><span class="pre">bidirectionalS</span></tt> was specified for the <tt class="docutils literal"><span class="pre">Directed</span></tt> template
+parameter. For an in-edge <tt class="docutils literal"><span class="pre">e</span></tt>, <tt class="docutils literal"><span class="pre">target(e,</span> <span class="pre">g)</span> <span class="pre">==</span> <span class="pre">v</span></tt> and <tt class="docutils literal"><span class="pre">source(e,</span>
+<span class="pre">g)</span> <span class="pre">==</span> <span class="pre">u</span></tt> for some vertex <tt class="docutils literal"><span class="pre">u</span></tt> that is adjacent to <tt class="docutils literal"><span class="pre">v</span></tt>, whether the
+graph is directed or undirected. The vertex <tt class="docutils literal"><span class="pre">v</span></tt> must be local to
+this process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+degree_size_type
+out_degree(vertex_descriptor u, const adjacency_list&amp; g);
+</pre>
+<p>Returns the number of edges leaving vertex <tt class="docutils literal"><span class="pre">u</span></tt>. Vertex <tt class="docutils literal"><span class="pre">u</span></tt> must
+be local to the executing process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+degree_size_type
+in_degree(vertex_descriptor u, const adjacency_list&amp; g);
+</pre>
+<p>Returns the number of edges entering vertex <tt class="docutils literal"><span class="pre">u</span></tt>. This operation is
+only available if <tt class="docutils literal"><span class="pre">bidirectionalS</span></tt> was specified for the
+<tt class="docutils literal"><span class="pre">Directed</span></tt> template parameter. Vertex <tt class="docutils literal"><span class="pre">u</span></tt> must be local to the
+executing process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+vertices_size_type
+num_vertices(const adjacency_list&amp; g);
+</pre>
+<p>Returns the number of vertices in the graph <tt class="docutils literal"><span class="pre">g</span></tt> that are stored in
+the executing process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+edges_size_type
+num_edges(const adjacency_list&amp; g);
+</pre>
+<p>Returns the number of edges in the graph <tt class="docutils literal"><span class="pre">g</span></tt> that are stored in the
+executing process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+vertex_descriptor
+vertex(vertices_size_type n, const adjacency_list&amp; g);
+</pre>
+<p>Returns the <tt class="docutils literal"><span class="pre">n``th</span> <span class="pre">vertex</span> <span class="pre">in</span> <span class="pre">the</span> <span class="pre">graph's</span> <span class="pre">vertex</span> <span class="pre">list,</span> <span class="pre">according</span> <span class="pre">to</span> <span class="pre">the</span>
+<span class="pre">distribution</span> <span class="pre">used</span> <span class="pre">to</span> <span class="pre">partition</span> <span class="pre">the</span> <span class="pre">graph.</span> <span class="pre">``n</span></tt> must be a value
+between zero and the sum of <tt class="docutils literal"><span class="pre">num_vertices(g)</span></tt> in each process (minus
+one). Note that it is not necessarily the case that <tt class="docutils literal"><span class="pre">vertex(0,</span> <span class="pre">g)</span> <span class="pre">==</span>
+<span class="pre">*num_vertices(g).first</span></tt>. This function is only guaranteed to be
+accurate when no vertices have been added to or removed from the
+graph after its initial construction.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+std::pair&lt;edge_descriptor, bool&gt;
+edge(vertex_descriptor u, vertex_descriptor v,
+ const adjacency_list&amp; g);
+</pre>
+<p>Returns an edge connecting vertex <tt class="docutils literal"><span class="pre">u</span></tt> to vertex <tt class="docutils literal"><span class="pre">v</span></tt> in graph
+<tt class="docutils literal"><span class="pre">g</span></tt>. For bidirectional and undirected graphs, either vertex <tt class="docutils literal"><span class="pre">u</span></tt> or
+vertex <tt class="docutils literal"><span class="pre">v</span></tt> must be local; for directed graphs, vertex <tt class="docutils literal"><span class="pre">u</span></tt> must be
+local.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+std::pair&lt;out_edge_iterator, out_edge_iterator&gt;
+edge_range(vertex_descriptor u, vertex_descriptor v,
+ const adjacency_list&amp; g);
+</pre>
+<p>TODO: Not implemented. Returns a pair of out-edge iterators that give
+the range for all the parallel edges from <tt class="docutils literal"><span class="pre">u</span></tt> to <tt class="docutils literal"><span class="pre">v</span></tt>. This function only
+works when the <tt class="docutils literal"><span class="pre">OutEdgeList</span></tt> for the <tt class="docutils literal"><span class="pre">adjacency_list</span></tt> is a container that
+sorts the out edges according to target vertex, and allows for
+parallel edges. The <tt class="docutils literal"><span class="pre">multisetS</span></tt> selector chooses such a
+container. Vertex <tt class="docutils literal"><span class="pre">u</span></tt> must be stored in the executing process.</p>
+</div>
+<div class="section" id="structure-modification">
+<h2><a class="toc-backref" href="#id12">Structure Modification</a></h2>
+<pre class="literal-block">
+unspecified add_edge(vertex_descriptor u, vertex_descriptor v, adjacency_list&amp; g);
+unspecified add_edge(vertex_name_type u, vertex_descriptor v, adjacency_list&amp; g);
+unspecified add_edge(vertex_descriptor u, vertex_name_type v, adjacency_list&amp; g);
+unspecified add_edge(vertex_name_type u, vertex_name_type v, adjacency_list&amp; g);
+</pre>
+<p>Adds edge <tt class="docutils literal"><span class="pre">(u,v)</span></tt> to the graph. The return type itself is
+unspecified, but the type can be copy-constructed and implicitly
+converted into a <tt class="docutils literal"><span class="pre">std::pair&lt;edge_descriptor,bool&gt;</span></tt>. The edge
+descriptor describes the added (or found) edge. For graphs that do not
+allow parallel edges, if the edge
+is already in the graph then a duplicate will not be added and the
+<tt class="docutils literal"><span class="pre">bool</span></tt> flag will be <tt class="docutils literal"><span class="pre">false</span></tt>. Also, if u and v are descriptors for
+the same vertex (creating a self loop) and the graph is undirected,
+then the edge will not be added and the flag will be <tt class="docutils literal"><span class="pre">false</span></tt>. When
+the flag is <tt class="docutils literal"><span class="pre">false</span></tt>, the returned edge descriptor points to the
+already existing edge.</p>
+<p>The parameters <tt class="docutils literal"><span class="pre">u</span></tt> and <tt class="docutils literal"><span class="pre">v</span></tt> can be either vertex descriptors or, if
+the graph uses named vertices, the names of vertices. If no vertex
+with the given name exists, the internal vertex constructor will be
+invoked to create a new vertex property and a vertex with that
+property will be added to the graph implicitly. The default internal
+vertex constructor throws an exception.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+unspecified add_edge(vertex_descriptor u, vertex_descriptor v, const EdgeProperties&amp; p, adjacency_list&amp; g);
+unspecified add_edge(vertex_name_type u, vertex_descriptor v, const EdgeProperties&amp; p, adjacency_list&amp; g);
+unspecified add_edge(vertex_descriptor u, vertex_name_type v, const EdgeProperties&amp; p, adjacency_list&amp; g);
+unspecified add_edge(vertex_name_type u, vertex_name_type v, const EdgeProperties&amp; p, adjacency_list&amp; g);
+</pre>
+<p>Adds edge <tt class="docutils literal"><span class="pre">(u,v)</span></tt> to the graph and attaches <tt class="docutils literal"><span class="pre">p</span></tt> as the value of the edge's
+internal property storage. See the previous <tt class="docutils literal"><span class="pre">add_edge()</span></tt> member
+function for more details.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void
+remove_edge(vertex_descriptor u, vertex_descriptor v,
+ adjacency_list&amp; g);
+</pre>
+<p>Removes the edge <tt class="docutils literal"><span class="pre">(u,v)</span></tt> from the graph. If the directed selector is
+<tt class="docutils literal"><span class="pre">bidirectionalS</span></tt> or <tt class="docutils literal"><span class="pre">undirectedS</span></tt>, either the source or target
+vertex of the graph must be local. If the directed selector is
+<tt class="docutils literal"><span class="pre">directedS</span></tt>, then the source vertex must be local.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void
+remove_edge(edge_descriptor e, adjacency_list&amp; g);
+</pre>
+<p>Removes the edge <tt class="docutils literal"><span class="pre">e</span></tt> from the graph. If the directed selector is
+<tt class="docutils literal"><span class="pre">bidirectionalS</span></tt> or <tt class="docutils literal"><span class="pre">undirectedS</span></tt>, either the source or target
+vertex of the graph must be local. If the directed selector is
+<tt class="docutils literal"><span class="pre">directedS</span></tt>, then the source vertex must be local.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void remove_edge(out_edge_iterator iter, adjacency_list&amp; g);
+</pre>
+<p>This has the same effect as <tt class="docutils literal"><span class="pre">remove_edge(*iter,</span> <span class="pre">g)</span></tt>. For directed
+(but not bidirectional) graphs, this will be more efficient than
+<tt class="docutils literal"><span class="pre">remove_edge(*iter,</span> <span class="pre">g)</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template &lt;class Predicate &gt;
+void remove_out_edge_if(vertex_descriptor u, Predicate predicate,
+ adjacency_list&amp; g);
+</pre>
+<p>Removes all out-edges of vertex <tt class="docutils literal"><span class="pre">u</span></tt> from the graph that satisfy the
+predicate. That is, if the predicate returns <tt class="docutils literal"><span class="pre">true</span></tt> when applied to an
+edge descriptor, then the edge is removed. The vertex <tt class="docutils literal"><span class="pre">u</span></tt> must be local.</p>
+<p>The affect on descriptor and iterator stability is the same as that of
+invoking remove_edge() on each of the removed edges.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template &lt;class Predicate &gt;
+void remove_in_edge_if(vertex_descriptor v, Predicate predicate,
+ adjacency_list&amp; g);
+</pre>
+<p>Removes all in-edges of vertex <tt class="docutils literal"><span class="pre">v</span></tt> from the graph that satisfy the
+predicate. That is, if the predicate returns true when applied to an
+edge descriptor, then the edge is removed. The vertex <tt class="docutils literal"><span class="pre">v</span></tt> must be local.</p>
+<p>The affect on descriptor and iterator stability is the same as that of
+invoking <tt class="docutils literal"><span class="pre">remove_edge()</span></tt> on each of the removed edges.</p>
+<p>This operation is available for undirected and bidirectional
+adjacency_list graphs, but not for directed.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template &lt;class Predicate&gt;
+void remove_edge_if(Predicate predicate, adjacency_list&amp; g);
+</pre>
+<p>Removes all edges from the graph that satisfy the predicate. That is,
+if the predicate returns true when applied to an edge descriptor, then
+the edge is removed.</p>
+<p>The affect on descriptor and iterator stability is the same as that
+of invoking <tt class="docutils literal"><span class="pre">remove_edge()</span></tt> on each of the removed edges.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+vertex_descriptor add_vertex(adjacency_list&amp; g);
+</pre>
+<p>Adds a vertex to the graph and returns the vertex descriptor for the
+new vertex. The vertex will be stored in the local process. This
+function is not available when using named vertices.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+unspecified add_vertex(const VertexProperties&amp; p, adjacency_list&amp; g);
+unspecified add_vertex(const vertex_name_type&amp; p, adjacency_list&amp; g);
+</pre>
+<p>Adds a vertex to the graph with the specified properties. If the graph
+is using vertex names, the vertex will be added on whichever process
+&quot;owns&quot; that name. Otherwise, the vertex will be stored in the local
+process. Note that the second constructor will invoke the
+user-customizable internal vertex constructor, which (by default)
+throws an exception when it sees an unknown vertex.</p>
+<p>The return type is of unspecified type, but can be copy-constructed
+and can be implicitly converted into a vertex descriptor.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void clear_vertex(vertex_descriptor u, adjacency_list&amp; g);
+</pre>
+<p>Removes all edges to and from vertex <tt class="docutils literal"><span class="pre">u</span></tt>. The vertex still appears
+in the vertex set of the graph.</p>
+<p>The affect on descriptor and iterator stability is the same as that of
+invoking <tt class="docutils literal"><span class="pre">remove_edge()</span></tt> for all of the edges that have <tt class="docutils literal"><span class="pre">u</span></tt> as the source
+or target.</p>
+<p>This operation is not applicable to directed graphs, because the
+incoming edges to vertex <tt class="docutils literal"><span class="pre">u</span></tt> are not known.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void clear_out_edges(vertex_descriptor u, adjacency_list&amp; g);
+</pre>
+<p>Removes all out-edges from vertex <tt class="docutils literal"><span class="pre">u</span></tt>. The vertex still appears in
+the vertex set of the graph.</p>
+<p>The affect on descriptor and iterator stability is the same as that of
+invoking <tt class="docutils literal"><span class="pre">remove_edge()</span></tt> for all of the edges that have <tt class="docutils literal"><span class="pre">u</span></tt> as the
+source.</p>
+<p>This operation is not applicable to undirected graphs (use
+<tt class="docutils literal"><span class="pre">clear_vertex()</span></tt> instead).</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void clear_in_edges(vertex_descriptor u, adjacency_list&amp; g);
+</pre>
+<p>Removes all in-edges from vertex <tt class="docutils literal"><span class="pre">u</span></tt>. The vertex still appears in
+the vertex set of the graph.</p>
+<p>The affect on descriptor and iterator stability is the same as that of
+invoking <tt class="docutils literal"><span class="pre">remove_edge()</span></tt> for all of the edges that have <tt class="docutils literal"><span class="pre">u</span></tt> as the
+target.</p>
+<p>This operation is only applicable to bidirectional graphs.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void remove_vertex(vertex_descriptor u, adjacency_list&amp; g);
+</pre>
+<p>Remove vertex <tt class="docutils literal"><span class="pre">u</span></tt> from the vertex set of the graph. It is assumed
+that there are no edges to or from vertex <tt class="docutils literal"><span class="pre">u</span></tt> when it is
+removed. One way to make sure of this is to invoke <tt class="docutils literal"><span class="pre">clear_vertex()</span></tt>
+beforehand. The vertex <tt class="docutils literal"><span class="pre">u</span></tt> must be stored locally.</p>
+</div>
+<div class="section" id="property-map-accessors">
+<h2><a class="toc-backref" href="#id13">Property Map Accessors</a></h2>
+<pre class="literal-block">
+template &lt;class PropertyTag&gt;
+property_map&lt;adjacency_list, PropertyTag&gt;::type
+get(PropertyTag, adjacency_list&amp; g);
+
+template &lt;class PropertyTag&gt;
+property_map&lt;adjacency_list, Tag&gt;::const_type
+get(PropertyTag, const adjacency_list&amp; g);
+</pre>
+<p>Returns the property map object for the vertex property specified by
+<tt class="docutils literal"><span class="pre">PropertyTag</span></tt>. The <tt class="docutils literal"><span class="pre">PropertyTag</span></tt> must match one of the properties
+specified in the graph's <tt class="docutils literal"><span class="pre">VertexProperty</span></tt> template argument. The
+returned property map will be a <a class="reference external" href="distributed_property_map.html">distributed property map</a>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template &lt;class PropertyTag , class X&gt;
+typename property_traits&lt;property_map&lt;adjacency_list, PropertyTag&gt;::const_type&gt;::value_type
+get(PropertyTag, const adjacency_list&amp; g, X x);
+</pre>
+<p>This returns the property value for <tt class="docutils literal"><span class="pre">x</span></tt>, where <tt class="docutils literal"><span class="pre">x</span></tt> is either a vertex or
+edge descriptor. The entity referred to by descriptor <tt class="docutils literal"><span class="pre">x</span></tt> must be
+stored in the local process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template &lt;class PropertyTag , class X, class Value&gt;
+void put(PropertyTag, const adjacency_list&amp; g, X x, const Value&amp; value);
+</pre>
+<p>This sets the property value for <tt class="docutils literal"><span class="pre">x</span></tt> to value. <tt class="docutils literal"><span class="pre">x</span></tt> is either a
+vertex or edge descriptor. <tt class="docutils literal"><span class="pre">Value</span></tt> must be convertible to <tt class="docutils literal"><span class="pre">typename</span>
+<span class="pre">property_traits&lt;property_map&lt;adjacency_list,</span>
+<span class="pre">PropertyTag&gt;::type&gt;::value_type</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template &lt;class GraphProperties, class GraphPropertyTag&gt;
+typename graph_property&lt;adjacency_list, GraphPropertyTag&gt;::type&amp;
+get_property(adjacency_list&amp; g, GraphPropertyTag);
+
+template &lt;class GraphProperties, class GraphPropertyTag &gt;
+const typename graph_property&lt;adjacency_list, GraphPropertyTag&gt;::type&amp;
+get_property(const adjacency_list&amp; g, GraphPropertyTag);
+</pre>
+<p>TODO: not implemented.</p>
+<p>Return the property specified by <tt class="docutils literal"><span class="pre">GraphPropertyTag</span></tt> that is attached
+to the graph object <tt class="docutils literal"><span class="pre">g</span></tt>. The <tt class="docutils literal"><span class="pre">graph_property</span></tt> traits class is
+defined in <tt class="docutils literal"><span class="pre">boost/graph/adjacency_list.hpp</span></tt>.</p>
+<hr class="docutils" />
+<p>Copyright (C) 2004 The Trustees of Indiana University.</p>
+<p>Copyright (C) 2007 Douglas Gregor</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/distributed_property_map.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/distributed_property_map.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,649 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Distributed Property Map</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-distributed-property-map">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Distributed Property Map</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<p>A distributed property map adaptor is a property map whose stored
+values are distributed across multiple non-overlapping memory spaces
+on different processes. Values local to the current process are stored
+within a local property map and may be immediately accessed via
+<tt class="docutils literal"><span class="pre">get</span></tt> and <tt class="docutils literal"><span class="pre">put</span></tt>. Values stored on remote processes may also be
+accessed via <tt class="docutils literal"><span class="pre">get</span></tt> and <tt class="docutils literal"><span class="pre">put</span></tt>, but the behavior differs slightly:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">put</span></tt> operations update a local ghost cell and send a &quot;put&quot;
+message to the process that owns the value. The owner is free to
+update its own &quot;official&quot; value or may ignore the put request.</li>
+<li><tt class="docutils literal"><span class="pre">get</span></tt> operations returns the contents of the local ghost
+cell. If no ghost cell is available, one is created using a
+(customizable) default value.</li>
+</ul>
+</blockquote>
+<p>Using distributed property maps requires a bit more care than using
+local, sequential property maps. While the syntax and semantics are
+similar, distributed property maps may contain out-of-date
+information that can only be guaranteed to be synchronized by
+calling the <tt class="docutils literal"><span class="pre">synchronize</span></tt> function in all processes.</p>
+<p>To address the issue of out-of-date values, distributed property
+maps support multiple <a class="reference internal" href="#consistency-models">consistency models</a> and may be supplied with a
+<a class="reference internal" href="#reduction-operation">reduction operation</a>.</p>
+<p>Distributed property maps meet the requirements of the <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable
+Property Map</a> and, potentially, the <a class="reference external" href="http://www.boost.org/libs/property_map/WritablePropertyMap.html">Writable Property Map</a> and
+<a class="reference external" href="http://www.boost.org/libs/property_map/ReadWritePropertyMap.html">Read/Write Property Map</a> concepts. Distributed property maps do
+<em>not</em>, however, meet the requirements of the <a class="reference external" href="http://www.boost.org/libs/property_map/LvaluePropertyMap.html">Lvalue Property Map</a>
+concept, because elements residing in another process are not
+directly addressible. There are several forms of distributed property
+maps:</p>
+<blockquote>
+<ul class="simple">
+<li><a class="reference internal" href="#distributed-property-map-adaptor">Distributed property map adaptor</a></li>
+<li><a class="reference internal" href="#distributed-iterator-property-map">Distributed iterator property map</a></li>
+<li><a class="reference internal" href="#distributed-safe-iterator-property-map">Distributed safe iterator property map</a></li>
+<li><a class="reference internal" href="#local-property-map">Local property map</a></li>
+</ul>
+</blockquote>
+<div class="section" id="consistency-models">
+<h1>Consistency models</h1>
+<p>Distributed property maps offer many consistency models, which affect
+how the values read from and written to remote keys relate to the
+&quot;official&quot; value for that key stored in the owning process. The
+consistency model of a distributed property map can be set with the
+member function <tt class="docutils literal"><span class="pre">set_consistency_model</span></tt> to a bitwise-OR of the
+flags in the <tt class="docutils literal"><span class="pre">boost::parallel::consistency_model</span></tt> enumeration. The
+individual flags are:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">cm_forward</span></tt>: The default consistency model, which propagates
+values forward from <tt class="docutils literal"><span class="pre">put</span></tt> operations on remote processors to
+the owner of the value being changed.</li>
+<li><tt class="docutils literal"><span class="pre">cm_backward</span></tt>: After all values have been forwarded or flushed
+to the owning processes, each process receives updates values for
+each of its ghost cells. After synchronization, the values in
+ghost cells are guaranteed to match the values stored on the
+owning processor.</li>
+<li><tt class="docutils literal"><span class="pre">cm_bidirectional</span></tt>: A combination of both <tt class="docutils literal"><span class="pre">cm_forward</span></tt> and
+<tt class="docutils literal"><span class="pre">cm_backward</span></tt>.</li>
+<li><tt class="docutils literal"><span class="pre">cm_flush</span></tt>: At the beginning of synchronization, all of the
+values stored locally in ghost cells are sent to their owning
+processors.</li>
+<li><tt class="docutils literal"><span class="pre">cm_reset</span></tt>: Executes a <tt class="docutils literal"><span class="pre">reset()</span></tt> operation after
+synchronization, setting the values in each ghost cell to their
+default value.</li>
+<li><tt class="docutils literal"><span class="pre">cm_clear</span></tt>: Executes a <tt class="docutils literal"><span class="pre">clear()</span></tt> operation after
+synchronizing, eliminating all ghost cells.</li>
+</ul>
+</blockquote>
+<p>There are several common combinations of flags that result in
+interesting consistency models. Some of these combinations are:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">cm_forward</span></tt>: By itself, the forward consistency model enables
+algorithms such as <a class="reference external" href="dijkstra_shortest_paths.html">Dijkstra's shortest paths</a> and
+<a class="reference external" href="breadth_first_search.html">Breadth-First Search</a> to operate correctly.</li>
+<li><tt class="docutils literal"><span class="pre">cm_flush</span> <span class="pre">&amp;</span> <span class="pre">cm_reset</span></tt>: All updates values are queued locally,
+then flushed during the synchronization step. Once the flush has
+occurred, the ghost cells are restored to their default
+values. This consistency model is used by the <a class="reference external" href="page_rank.html">PageRank</a>
+implementation to locally accumulate rank for each node.</li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="reduction-operation">
+<h1>Reduction operation</h1>
+<p>The reduction operation maintains consistency by determining how
+multiple writes to a property map are resolved and what the property
+map should do if unknown values are requested. More specifically, a
+reduction operation is used in two cases:</p>
+<blockquote>
+<ol class="arabic simple">
+<li>When a value is needed for a remote key but no value is
+immediately available, the reduction operation provides a
+suitable default. For instance, a distributed property map
+storing distances may have a reduction operation that returns
+an infinite value as the default, whereas a distributed
+property map for vertex colors may return white as the
+default.</li>
+<li>When a value is received from a remote process, the process
+owning the key associated with that value must determine which
+value---the locally stored value, the value received from a
+remote process, or some combination of the two---will be
+stored as the &quot;official&quot; value in the property map. The
+reduction operation transforms the local and remote values
+into the &quot;official&quot; value to be stored.</li>
+</ol>
+</blockquote>
+<p>The reduction operation of a distributed property map can be set with
+the <tt class="docutils literal"><span class="pre">set_reduce</span></tt> method of <tt class="docutils literal"><span class="pre">distributed_property_map</span></tt>. The reduce
+operation is a function object with two signatures. The first
+signature takes a (remote) key and returns a default value for it,
+whereas the second signatures takes a key and two values (local first,
+then remote) and will return the combined value that will be stored in
+the local property map. Reduction operations must also contain a
+static constant <tt class="docutils literal"><span class="pre">non_default_resolver&quot;,</span> <span class="pre">which</span> <span class="pre">states</span> <span class="pre">whether</span> <span class="pre">the</span>
+<span class="pre">reduction</span> <span class="pre">operation's</span> <span class="pre">default</span> <span class="pre">value</span> <span class="pre">actually</span> <span class="pre">acts</span> <span class="pre">like</span> <span class="pre">a</span> <span class="pre">default</span>
+<span class="pre">value.</span> <span class="pre">It</span> <span class="pre">should</span> <span class="pre">be</span> <span class="pre">``true</span></tt> when the default is meaningful (e.g.,
+infinity for a distance) and <tt class="docutils literal"><span class="pre">false</span></tt> when the default should not be
+used.</p>
+<p>The following reduction operation is used by the distributed PageRank
+algorithm. The default rank for a remote node is 0. Rank is
+accumulated locally, and then the reduction operation combines local
+and remote values by adding them. Combined with a consistency model
+that flushes all values to the owner and then resets the values
+locally in each step, the resulting property map will compute partial
+sums on each processor and then accumulate the results on the owning
+processor. The PageRank reduction operation is defined as follows.</p>
+<pre class="literal-block">
+template&lt;typename T&gt;
+struct rank_accumulate_reducer {
+ static const bool non_default_resolver = true;
+
+ // The default rank of an unknown node
+ template&lt;typename K&gt;
+ T operator()(const K&amp;) const { return T(0); }
+
+ template&lt;typename K&gt;
+ T operator()(const K&amp;, const T&amp; x, const T&amp; y) const { return x + y; }
+};
+</pre>
+</div>
+<div class="section" id="distributed-property-map-adaptor">
+<h1>Distributed property map adaptor</h1>
+<p>The distributed property map adaptor creates a distributed property
+map from a local property map, a <a class="reference external" href="process_group.html">process group</a> over which
+distribution should occur, and a <a class="reference external" href="GlobalDescriptor.html">global descriptor</a> type that
+indexes the distributed property map.</p>
+<div class="section" id="synopsis">
+<h2>Synopsis</h2>
+<pre class="literal-block">
+template&lt;typename ProcessGroup, typename LocalPropertyMap, typename Key,
+ typename GhostCellS = gc_mapS&gt;
+class distributed_property_map
+{
+public:
+ typedef ... ghost_regions_type;
+
+ distributed_property_map();
+
+ distributed_property_map(const ProcessGroup&amp; pg,
+ const LocalPropertyMap&amp; pm);
+
+ template&lt;typename Reduce&gt;
+ distributed_property_map(const ProcessGroup&amp; pg,
+ const LocalPropertyMap&amp; pm,
+ const Reduce&amp; reduce);
+
+ template&lt;typename Reduce&gt; void set_reduce(const Reduce&amp; reduce);
+ void set_consistency_model(int model);
+
+ void flush();
+ void reset();
+ void clear();
+};
+
+reference get(distributed_property_map pm, const key_type&amp; key);
+
+void
+put(distributed_property_map pm, const key_type&amp; key, const value_type&amp; value);
+local_put(distributed_property_map pm, const key_type&amp; key, const value_type&amp; value);
+
+void request(distributed_property_map pm, const key_type&amp; key);
+
+void synchronize(distributed_property_map&amp; pm);
+
+template&lt;typename Key, typename ProcessGroup, typename LocalPropertyMap&gt;
+distributed_property_map&lt;ProcessGroup, LocalPropertyMap, Key&gt;
+make_distributed_property_map(const ProcessGroup&amp; pg, LocalPropertyMap pmap);
+
+template&lt;typename Key, typename ProcessGroup, typename LocalPropertyMap,
+ typename Reduce&gt;
+distributed_property_map&lt;ProcessGroup, LocalPropertyMap, Key&gt;
+make_distributed_property_map(const ProcessGroup&amp; pg, LocalPropertyMap pmap,
+ Reduce reduce);
+</pre>
+</div>
+<div class="section" id="template-parameters">
+<h2>Template parameters</h2>
+<dl class="docutils">
+<dt><strong>ProcessGroup</strong>:</dt>
+<dd>The type of the process group over which the
+property map is distributed and is also the medium for
+communication.</dd>
+<dt><strong>LocalPropertyMap</strong>:</dt>
+<dd>The type of the property map that will store values
+for keys local to this processor. The <tt class="docutils literal"><span class="pre">value_type</span></tt> of this
+property map will become the <tt class="docutils literal"><span class="pre">value_type</span></tt> of the distributed
+property map. The distributed property map models the same property
+map concepts as the <tt class="docutils literal"><span class="pre">LocalPropertyMap</span></tt>, with one exception: a
+distributed property map cannot be an <a class="reference external" href="http://www.boost.org/libs/property_map/LvaluePropertyMap.html">Lvalue Property Map</a>
+(because remote values are not addressable), and is therefore
+limited to <a class="reference external" href="http://www.boost.org/libs/property_map/ReadWritePropertyMap.html">Read/Write Property Map</a>.</dd>
+<dt><strong>Key</strong>:</dt>
+<dd>The <tt class="docutils literal"><span class="pre">key_type</span></tt> of the distributed property map, which
+must model the <a class="reference external" href="GlobalDescriptor.html">Global Descriptor</a> concept. The process ID type of
+the <tt class="docutils literal"><span class="pre">Key</span></tt> parameter must match the process ID type of the
+<tt class="docutils literal"><span class="pre">ProcessGroup</span></tt>, and the local descriptor type of the <tt class="docutils literal"><span class="pre">Key</span></tt> must
+be convertible to the <tt class="docutils literal"><span class="pre">key_type</span></tt> of the <tt class="docutils literal"><span class="pre">LocalPropertyMap</span></tt>.</dd>
+<dt><strong>GhostCellS</strong>:</dt>
+<dd><p class="first">A selector type that indicates how ghost cells should be stored in
+the distributed property map. There are either two or three
+options, depending on your compiler:</p>
+<blockquote class="last">
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">boost::parallel::gc_mapS</span></tt> (default): Uses an STL <tt class="docutils literal"><span class="pre">map</span></tt> to
+store the ghost cells for each process.</li>
+<li><tt class="docutils literal"><span class="pre">boost::parallel::gc_vector_mapS</span></tt>: Uses a sorted STL
+<tt class="docutils literal"><span class="pre">vector</span></tt> to store the ghost cells for each process. This
+option works well when there are likely to be few insertions
+into the ghost cells; for instance, if the only ghost cells used
+are for neighboring vertices, the property map can be
+initialized with cells for each neighboring vertex, providing
+faster lookups than a <tt class="docutils literal"><span class="pre">map</span></tt> and using less space.</li>
+<li><tt class="docutils literal"><span class="pre">boost::parallel::gc_hash_mapS</span></tt>: Uses the GCC <tt class="docutils literal"><span class="pre">hash_map</span></tt> to
+store ghost cells. This option may improve performance over
+<tt class="docutils literal"><span class="pre">map</span></tt> for large problems sizes, where the set of ghost cells
+cannot be predetermined.</li>
+</ul>
+</blockquote>
+</dd>
+</dl>
+</div>
+<div class="section" id="member-functions">
+<h2>Member functions</h2>
+<pre class="literal-block">
+distributed_property_map();
+</pre>
+<p>Default-construct a distributed property map. The property map is in
+an invalid state, and may only be used if it is reassigned to a valid
+property map.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+distributed_property_map(const ProcessGroup&amp; pg,
+ const LocalPropertyMap&amp; pm);
+
+template&lt;typename Reduce&gt;
+distributed_property_map(const ProcessGroup&amp; pg,
+ const LocalPropertyMap&amp; pm,
+ const Reduce&amp; reduce);
+</pre>
+<p>Construct a property map from a process group and a local property
+map. If a <tt class="docutils literal"><span class="pre">reduce</span></tt> operation is not supplied, a default of
+<tt class="docutils literal"><span class="pre">basic_reduce&lt;value_type&gt;</span></tt> will be used.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename Reduce&gt; void set_reduce(const Reduce&amp; reduce);
+</pre>
+<p>Replace the current reduction operation with the new operation
+<tt class="docutils literal"><span class="pre">reduce</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void set_consistency_model(int model);
+</pre>
+<p>Sets the consistency model of the distributed property map, which will
+take effect on the next synchronization step. See the section
+<a class="reference internal" href="#consistency-models">Consistency models</a> for a description of the effect of various
+consistency model flags.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void flush();
+</pre>
+<p>Emits a message sending the contents of all local ghost cells to the
+owners of those cells.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void reset();
+</pre>
+<p>Replaces the values stored in each of the ghost cells with the default
+value generated by the reduction operation.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void clear();
+</pre>
+<p>Removes all ghost cells from the property map.</p>
+</div>
+<div class="section" id="free-functions">
+<h2>Free functions</h2>
+<pre class="literal-block">
+reference get(distributed_property_map pm, const key_type&amp; key);
+</pre>
+<p>Retrieves the element in <tt class="docutils literal"><span class="pre">pm</span></tt> associated with the given <tt class="docutils literal"><span class="pre">key</span></tt>. If
+the key refers to data stored locally, returns the actual value
+associated with the key. If the key refers to nonlocal data, returns
+the value of the ghost cell. If no ghost cell exists, the behavior
+depends on the current reduction operation: if a reduction operation
+has been set and has <tt class="docutils literal"><span class="pre">non_default_resolver</span></tt> set <tt class="docutils literal"><span class="pre">true</span></tt>, then a
+ghost cell will be created according to the default value provided by
+the reduction operation. Otherwise, the call to <tt class="docutils literal"><span class="pre">get</span></tt> will abort
+because no value exists for this remote cell. To avoid this problem,
+either set a reduction operation that generates default values,
+<tt class="docutils literal"><span class="pre">request()</span></tt> the value and then perform a synchronization step, or
+<tt class="docutils literal"><span class="pre">put</span></tt> a value into the cell before reading it.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void
+put(distributed_property_map pm, const key_type&amp; key, const value_type&amp; value);
+</pre>
+<p>Places the given <tt class="docutils literal"><span class="pre">value</span></tt> associated with <tt class="docutils literal"><span class="pre">key</span></tt> into property map
+<tt class="docutils literal"><span class="pre">pm</span></tt>. If the key refers to data stored locally, the value is
+immediately updates. If the key refers to data stored in a remote
+process, updates (or creates) a local ghost cell containing this
+value for the key and sends the new value to the owning process. Note
+that the owning process may reject this value based on the reduction
+operation, but this will not be detected until the next
+synchronization step.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void
+local_put(distributed_property_map pm, const key_type&amp; key, const value_type&amp; value);
+</pre>
+<p>Equivalent to <tt class="docutils literal"><span class="pre">put(pm,</span> <span class="pre">key,</span> <span class="pre">value)</span></tt>, except that no message is sent
+to the owning process when the value is changed for a nonlocal key.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void synchronize(distributed_property_map&amp; pm);
+</pre>
+<p>Synchronize the values stored in the distributed property maps. Each
+process much execute <tt class="docutils literal"><span class="pre">synchronize</span></tt> at the same time, after which
+the ghost cells in every process will reflect the actual value stored
+in the owning process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void request(distributed_property_map pm, const key_type&amp; key);
+</pre>
+<p>Request that the element &quot;key&quot; be available after the next
+synchronization step. For a non-local key, this means establishing a
+ghost cell and requesting.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename Key, typename ProcessGroup, typename LocalPropertyMap&gt;
+distributed_property_map&lt;ProcessGroup, LocalPropertyMap, Key&gt;
+make_distributed_property_map(const ProcessGroup&amp; pg, LocalPropertyMap pmap);
+
+template&lt;typename Key, typename ProcessGroup, typename LocalPropertyMap,
+ typename Reduce&gt;
+distributed_property_map&lt;ProcessGroup, LocalPropertyMap, Key&gt;
+make_distributed_property_map(const ProcessGroup&amp; pg, LocalPropertyMap pmap,
+ Reduce reduce);
+</pre>
+<p>Create a distributed property map over process group <tt class="docutils literal"><span class="pre">pg</span></tt> and local
+property map <tt class="docutils literal"><span class="pre">pmap</span></tt>. A default reduction operation will be generated
+if it is not provided.</p>
+</div>
+</div>
+<div class="section" id="distributed-iterator-property-map">
+<h1>Distributed iterator property map</h1>
+<p>The distributed iterator property map adaptor permits the creation of
+distributed property maps from random access iterators using the same
+syntax as non-distributed iterator property maps. The specialization
+is based on a <a class="reference internal" href="#local-property-map">local property map</a>, which contains the
+indices for local descriptors and is typically returned to describe
+the vertex indices of a distributed graph.</p>
+<div class="section" id="id1">
+<h2>Synopsis</h2>
+<pre class="literal-block">
+template&lt;typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference&gt;
+class iterator_property_map&lt;RandomAccessIterator,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt;,
+ ValueType, Reference&gt;
+{
+public:
+ typedef local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt; index_map_type;
+
+ iterator_property_map();
+ iterator_property_map(RandomAccessIterator iter, const index_map_type&amp; id);
+};
+
+reference get(iterator_property_map pm, const key_type&amp; key);
+void put(iterator_property_map pm, const key_type&amp; key, const value_type&amp; value);
+
+template&lt;typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap&gt;
+iterator_property_map&lt;RandomAccessIterator,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt; &gt;
+make_iterator_property_map(RandomAccessIterator iter,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt; id);
+</pre>
+</div>
+<div class="section" id="id2">
+<h2>Member functions</h2>
+<pre class="literal-block">
+iterator_property_map();
+</pre>
+<p>Default-constructs a distributed iterator property map. The property
+map is in an invalid state, and must be reassigned before it may be
+used.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+iterator_property_map(RandomAccessIterator iter, const index_map_type&amp; id);
+</pre>
+<p>Constructs a distributed iterator property map using the property map
+<tt class="docutils literal"><span class="pre">id</span></tt> to map global descriptors to local indices. The random access
+iterator sequence <tt class="docutils literal"><span class="pre">[iter,</span> <span class="pre">iter</span> <span class="pre">+</span> <span class="pre">n)</span></tt> must be a valid range, where
+<tt class="docutils literal"><span class="pre">[0,</span> <span class="pre">n)</span></tt> is the range of local indices.</p>
+</div>
+<div class="section" id="id3">
+<h2>Free functions</h2>
+<pre class="literal-block">
+reference get(iterator_property_map pm, const key_type&amp; key);
+</pre>
+<p>Returns the value associated with the given <tt class="docutils literal"><span class="pre">key</span></tt> from the
+distributed property map.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void put(iterator_property_map pm, const key_type&amp; key, const value_type&amp; value);
+</pre>
+<p>Associates the value with the given key in the distributed property map.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference&gt;
+iterator_property_map&lt;RandomAccessIterator,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt;,
+ ValueType, Reference&gt;
+make_iterator_property_map(RandomAccessIterator iter,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt;,
+ ValueType, Reference&gt; id);
+</pre>
+<p>Creates a distributed iterator property map using the given iterator
+<tt class="docutils literal"><span class="pre">iter</span></tt> and local index property map <tt class="docutils literal"><span class="pre">id</span></tt>.</p>
+</div>
+</div>
+<div class="section" id="distributed-safe-iterator-property-map">
+<h1>Distributed safe iterator property map</h1>
+<p>The distributed safe iterator property map adaptor permits the
+creation of distributed property maps from random access iterators
+using the same syntax as non-distributed safe iterator property
+maps. The specialization is based on a <a class="reference internal" href="#local-property-map">local property map</a>, which
+contains the indices for local descriptors and is typically returned
+to describe the vertex indices of a distributed graph. Safe iterator
+property maps check the indices of accesses to ensure that they are
+not out-of-bounds before attempting to access an value.</p>
+<div class="section" id="id4">
+<h2>Synopsis</h2>
+<pre class="literal-block">
+template&lt;typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference&gt;
+class safe_iterator_property_map&lt;RandomAccessIterator,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt;,
+ ValueType, Reference&gt;
+{
+public:
+ typedef local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt; index_map_type;
+
+ safe_iterator_property_map();
+ safe_iterator_property_map(RandomAccessIterator iter, std::size_t n,
+ const index_map_type&amp; id);
+};
+
+reference get(safe_iterator_property_map pm, const key_type&amp; key);
+void put(safe_iterator_property_map pm, const key_type&amp; key, const value_type&amp; value);
+
+template&lt;typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference&gt;
+safe_iterator_property_map&lt;RandomAccessIterator,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt;,
+ ValueType, Reference&gt;
+make_safe_iterator_property_map(RandomAccessIterator iter,
+ std::size_t n,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt;,
+ ValueType, Reference&gt; id);
+</pre>
+</div>
+<div class="section" id="id5">
+<h2>Member functions</h2>
+<pre class="literal-block">
+safe_iterator_property_map();
+</pre>
+<p>Default-constructs a distributed safe iterator property map. The property
+map is in an invalid state, and must be reassigned before it may be
+used.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+safe_iterator_property_map(RandomAccessIterator iter, std::size_t n,
+ const index_map_type&amp; id);
+</pre>
+<p>Constructs a distributed safe iterator property map using the property map
+<tt class="docutils literal"><span class="pre">id</span></tt> to map global descriptors to local indices. The random access
+iterator sequence <tt class="docutils literal"><span class="pre">[iter,</span> <span class="pre">iter</span> <span class="pre">+</span> <span class="pre">n)</span></tt>.</p>
+</div>
+<div class="section" id="id6">
+<h2>Free functions</h2>
+<pre class="literal-block">
+reference get(safe_iterator_property_map pm, const key_type&amp; key);
+</pre>
+<p>Returns the value associated with the given <tt class="docutils literal"><span class="pre">key</span></tt> from the
+distributed property map.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void put(safe_iterator_property_map pm, const key_type&amp; key, const value_type&amp; value);
+</pre>
+<p>Associates the value with the given key in the distributed property map.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename RandomAccessIterator, typename ProcessGroup,
+ typename GlobalKey, typename LocalMap, typename ValueType,
+ typename Reference&gt;
+safe_iterator_property_map&lt;RandomAccessIterator,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt;,
+ ValueType, Reference&gt;
+make_safe_iterator_property_map(RandomAccessIterator iter,
+ std::size_t n,
+ local_property_map&lt;ProcessGroup, GlobalKey, LocalMap&gt;,
+ ValueType, Reference&gt; id);
+</pre>
+<p>Creates a distributed safe iterator property map using the given iterator
+<tt class="docutils literal"><span class="pre">iter</span></tt> and local index property map <tt class="docutils literal"><span class="pre">id</span></tt>. The indices in <tt class="docutils literal"><span class="pre">id</span></tt> must</p>
+</div>
+</div>
+<div class="section" id="local-property-map">
+<h1>Local property map</h1>
+<p>A property map adaptor that accesses an underlying property map whose
+key type is the local part of the <tt class="docutils literal"><span class="pre">Key</span></tt> type for the local subset
+of keys. Local property maps are typically used by distributed graph
+types for vertex index properties.</p>
+<div class="section" id="id7">
+<h2>Synopsis</h2>
+<pre class="literal-block">
+template&lt;typename ProcessGroup, typename GlobalKey, typename LocalMap&gt;
+ class local_property_map
+ {
+ public:
+ typedef typename property_traits&lt;LocalMap&gt;::value_type value_type;
+ typedef GlobalKey key_type;
+ typedef typename property_traits&lt;LocalMap&gt;::reference reference;
+ typedef typename property_traits&lt;LocalMap&gt;::category category;
+
+ explicit
+ local_property_map(const ProcessGroup&amp; process_group = ProcessGroup(),
+ const LocalMap&amp; local_map = LocalMap());
+
+ reference operator[](const key_type&amp; key);
+};
+
+reference get(const local_property_map&amp; pm, key_type key);
+void put(local_property_map pm, const key_type&amp; key, const value_type&amp; value);
+</pre>
+</div>
+<div class="section" id="id8">
+<h2>Template parameters</h2>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">ProcessGroup:</th><td class="field-body">the type of the process group over which the global
+keys are distributed.</td>
+</tr>
+<tr class="field"><th class="field-name">GlobalKey:</th><td class="field-body">The <tt class="docutils literal"><span class="pre">key_type</span></tt> of the local property map, which
+must model the <a class="reference external" href="GlobalDescriptor.html">Global Descriptor</a> concept. The process ID type of
+the <tt class="docutils literal"><span class="pre">GlobalKey</span></tt> parameter must match the process ID type of the
+<tt class="docutils literal"><span class="pre">ProcessGroup</span></tt>, and the local descriptor type of the <tt class="docutils literal"><span class="pre">GlobalKey</span></tt>
+must be convertible to the <tt class="docutils literal"><span class="pre">key_type</span></tt> of the <tt class="docutils literal"><span class="pre">LocalMap</span></tt>.</td>
+</tr>
+<tr class="field"><th class="field-name">LocalMap:</th><td class="field-body">the type of the property map that will store values
+for keys local to this processor. The <tt class="docutils literal"><span class="pre">value_type</span></tt> of this
+property map will become the <tt class="docutils literal"><span class="pre">value_type</span></tt> of the local
+property map. The local property map models the same property
+map concepts as the <tt class="docutils literal"><span class="pre">LocalMap</span></tt>.</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="id9">
+<h2>Member functions</h2>
+<pre class="literal-block">
+explicit
+local_property_map(const ProcessGroup&amp; process_group = ProcessGroup(),
+ const LocalMap&amp; local_map = LocalMap());
+</pre>
+<p>Constructs a local property map whose keys are distributed across the
+given process group and which accesses the given local map.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+reference operator[](const key_type&amp; key);
+</pre>
+<p>Access the value associated with the given key, which must be local
+to this process.</p>
+</div>
+<div class="section" id="id10">
+<h2>Free functions</h2>
+<pre class="literal-block">
+reference get(const local_property_map&amp; pm, key_type key);
+</pre>
+<p>Return the value associated with the given key, which must be local
+to this process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void put(local_property_map pm, const key_type&amp; key, const value_type&amp; value);
+</pre>
+<p>Set the value associated with the given key, which must be local to
+this process.</p>
+<hr class="docutils" />
+<p>Copyright (C) 2004, 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/distributed_queue.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/distributed_queue.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Distributed queue adaptor</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-distributed-queue-adaptor">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Distributed queue adaptor</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+template&lt;typename ProcessGroup, typename Buffer&gt;
+class distributed_queue
+{
+public:
+ typedef ProcessGroup process_group_type;
+ typedef Buffer buffer_type;
+ typedef typename buffer_type::value_type value_type;
+ typedef typename buffer_type::size_type size_type;
+
+ explicit
+ distributed_queue(const ProcessGroup&amp; process_group = ProcessGroup(),
+ const Buffer&amp; buffer = Buffer(),
+ bool polling = false);
+
+ distributed_queue(const ProcessGroup&amp; process_group, bool polling);
+
+ void push(const value_type&amp; x);
+ void pop();
+ value_type&amp; top();
+ const value_type&amp; top() const;
+ bool empty() const;
+ size_type size() const;
+};
+
+template&lt;typename ProcessGroup, typename Buffer&gt;
+inline distributed_queue&lt;ProcessGroup, Buffer&gt;
+make_distributed_queue(const ProcessGroup&amp; process_group, const Buffer&amp; buffer,
+ bool polling = false);
+</pre>
+<p>Class template <tt class="docutils literal"><span class="pre">distributed_queue</span></tt> implements a distributed queue
+across a process group. The distributed queue is an adaptor over an
+existing (local) queue, which must model the <a class="reference external" href="http://www.boost.org/libs/graph/doc/Buffer.html">Buffer</a> concept. Each
+process stores a distinct copy of the local queue, from which it draws
+or removes elements via the <tt class="docutils literal"><span class="pre">pop</span></tt> and <tt class="docutils literal"><span class="pre">top</span></tt> members.</p>
+<p>The value type of the local queue must be a model of the
+<a class="reference external" href="GlobalDescriptor.html">Global Descriptor</a> concept. The <tt class="docutils literal"><span class="pre">push</span></tt> operation of the
+distributed queue passes (via a message) the value to its owning
+processor. Thus, the elements within a particular local queue are
+guaranteed to have the process owning that local queue as an owner.</p>
+<p>Synchronization of distributed queues occurs in the <tt class="docutils literal"><span class="pre">empty</span></tt> and
+<tt class="docutils literal"><span class="pre">size</span></tt> functions, which will only return &quot;empty&quot; values (true or 0,
+respectively) when the entire distributed queue is empty. If the local
+queue is empty but the distributed queue is not, the operation will
+block until either condition changes. When the <tt class="docutils literal"><span class="pre">size</span></tt> function of a
+nonempty queue returns, it returns the size of the local queue. These
+semantics were selected so that sequential code that processes
+elements in the queue via the following idiom can be parallelized via
+introduction of a distributed queue:</p>
+<pre class="literal-block">
+distributed_queue&lt;...&gt; Q;
+Q.push(x);
+while (!Q.empty()) {
+ // do something, that may push a value onto Q
+}
+</pre>
+<p>In the parallel version, the initial <tt class="docutils literal"><span class="pre">push</span></tt> operation will place
+the value <tt class="docutils literal"><span class="pre">x</span></tt> onto its owner's queue. All processes will
+synchronize at the call to empty, and only the process owning <tt class="docutils literal"><span class="pre">x</span></tt>
+will be allowed to execute the loop (<tt class="docutils literal"><span class="pre">Q.empty()</span></tt> returns
+false). This iteration may in turn push values onto other remote
+queues, so when that process finishes execution of the loop body
+and all processes synchronize again in <tt class="docutils literal"><span class="pre">empty</span></tt>, more processes
+may have nonempty local queues to execute. Once all local queues
+are empty, <tt class="docutils literal"><span class="pre">Q.empty()</span></tt> returns <tt class="docutils literal"><span class="pre">false</span></tt> for all processes.</p>
+<p>The distributed queue can receive messages at two different times:
+during synchronization and when polling <tt class="docutils literal"><span class="pre">empty</span></tt>. Messages are
+always received during synchronization, to ensure that accurate
+local queue sizes can be determines. However, whether <tt class="docutils literal"><span class="pre">empty</span></tt>
+should poll for messages is specified as an option to the
+constructor. Polling may be desired when the order in which
+elements in the queue are processed is not important, because it
+permits fewer synchronization steps and less communication
+overhead. However, when more strict ordering guarantees are
+required, polling may be semantically incorrect. By disabling
+polling, one ensures that parallel execution using the idiom above
+will not process an element at a later &quot;level&quot; before an earlier
+&quot;level&quot;.</p>
+<p>The distributed queue nearly models the <a class="reference external" href="http://www.boost.org/libs/graph/doc/Buffer.html">Buffer</a>
+concept. However, the <tt class="docutils literal"><span class="pre">push</span></tt> routine does not necessarily
+increase the result of <tt class="docutils literal"><span class="pre">size()</span></tt> by one (although the size of the
+global queue does increase by one).</p>
+<div class="section" id="member-functions">
+<h1>Member Functions</h1>
+<pre class="literal-block">
+explicit
+distributed_queue(const ProcessGroup&amp; process_group = ProcessGroup(),
+ const Buffer&amp; buffer = Buffer(),
+ bool polling = false);
+</pre>
+<p>Build a new distributed queue that communicates over the given
+<tt class="docutils literal"><span class="pre">process_group</span></tt>, whose local queue is initialized via <tt class="docutils literal"><span class="pre">buffer</span></tt> and
+which may or may not poll for messages.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+distributed_queue(const ProcessGroup&amp; process_group, bool polling);
+</pre>
+<p>Build a new distributed queue that communicates over the given
+<tt class="docutils literal"><span class="pre">process_group</span></tt>, whose local queue is default-initalized and which
+may or may not poll for messages.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void push(const value_type&amp; x);
+</pre>
+<p>Push an element onto the distributed queue.</p>
+<p>The element will be sent to its owner process to be added to that
+process's local queue. If polling is enabled for this queue and
+the owner process is the current process, the value will be
+immediately pushed onto the local queue.</p>
+<p>Complexity: O(1) messages of size O(<tt class="docutils literal"><span class="pre">sizeof(value_type)</span></tt>) will be
+transmitted.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+void pop();
+</pre>
+<p>Pop an element off the local queue. The queue must not be <tt class="docutils literal"><span class="pre">empty()</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+value_type&amp; top();
+const value_type&amp; top();
+</pre>
+<p>Returns the top element in the local queue. The queue must not be
+<tt class="docutils literal"><span class="pre">empty()</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+bool empty() const;
+</pre>
+<p>Determines if the queue is empty.</p>
+<p>When the local queue is nonempty, returns true. If the local queue is
+empty, synchronizes with all other processes in the process group
+until either (1) the local queue is nonempty (returns true) (2) the
+entire distributed queue is empty (returns false).</p>
+<hr class="docutils" />
+<pre class="literal-block">
+size_type size() const;
+</pre>
+<p>Determines the size of the local queue.</p>
+<p>The behavior of this routine is equivalent to the behavior of
+<tt class="docutils literal"><span class="pre">empty</span></tt>, except that when <tt class="docutils literal"><span class="pre">empty</span></tt> returns true this
+function returns the size of the local queue and when <tt class="docutils literal"><span class="pre">empty</span></tt>
+returns false this function returns zero.</p>
+</div>
+<div class="section" id="free-functions">
+<h1>Free Functions</h1>
+<pre class="literal-block">
+template&lt;typename ProcessGroup, typename Buffer&gt;
+inline distributed_queue&lt;ProcessGroup, Buffer&gt;
+make_distributed_queue(const ProcessGroup&amp; process_group, const Buffer&amp; buffer,
+ bool polling = false);
+</pre>
+<p>Constructs a distributed queue.</p>
+<hr class="docutils" />
+<p>Copyright (C) 2004, 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/fruchterman_reingold.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/fruchterman_reingold.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Fruchterman Reingold</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-fruchterman-reingold">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Fruchterman Reingold</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/index.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/index.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Parallel Boost Graph Library</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-parallel-boost-graph-library">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Parallel Boost Graph Library</h1>
+<h2 class="subtitle" id="overview">Overview</h2>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<p>The Parallel Boost Graph Library is an extension to the <a class="reference external" href="http://www.boost.org/libs/graph/doc">Boost Graph
+Library</a> (BGL) for parallel and distributed computing. It offers
+distributed graphs and graph algorithms to exploit coarse-grained
+parallelism along with parallel algorithms that exploit fine-grained
+parallelism, while retaining the same interfaces as the (sequential)
+BGL. Code written using the sequential BGL should be easy to
+parallelize with the parallel BGL. Visitors new to the Parallel BGL
+should read our <a class="reference external" href="overview.html">architectural overview</a>.</p>
+<ol class="arabic simple">
+<li><a class="reference external" href="process_group.html">Process groups</a></li>
+</ol>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="process_group.html">MPI process group</a></li>
+<li><a class="reference external" href="simple_trigger.html">Simple trigger interface</a></li>
+</ul>
+</blockquote>
+<ol class="arabic simple" start="2">
+<li>Auxiliary data structures</li>
+</ol>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="distributed_queue.html">Distributed queue</a></li>
+<li><a class="reference external" href="distributed_property_map.html">Distributed property map</a></li>
+</ul>
+</blockquote>
+<ol class="arabic simple" start="3">
+<li>Distributed graph concepts</li>
+</ol>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="DistributedGraph.html">Distributed Graph</a></li>
+<li><a class="reference external" href="DistributedVertexListGraph.html">Distributed Vertex List Graph</a></li>
+<li><a class="reference external" href="DistributedEdgeListGraph.html">Distributed Edge List Graph</a></li>
+<li><a class="reference external" href="GlobalDescriptor.html">Global Descriptor</a></li>
+</ul>
+</blockquote>
+<ol class="arabic simple" start="4">
+<li>Graph data structures</li>
+</ol>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="distributed_adjacency_list.html">Distributed adjacency list</a></li>
+</ul>
+</blockquote>
+<ol class="arabic simple" start="5">
+<li>Graph adaptors</li>
+</ol>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="local_subgraph.html">Local subgraph adaptor</a></li>
+<li><a class="reference external" href="vertex_list_adaptor.html">Vertex list graph adaptor</a></li>
+</ul>
+</blockquote>
+<ol class="arabic simple" start="6">
+<li>Graph input/output</li>
+</ol>
+<blockquote>
+<ul class="simple">
+<li>Graphviz output</li>
+<li><a class="reference external" href="metis.html">METIS input</a></li>
+</ul>
+</blockquote>
+<ol class="arabic simple" start="7">
+<li>Synthetic data generators</li>
+</ol>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="rmat_generator.html">R-MAT generator</a></li>
+<li><a class="reference external" href="sorted_rmat_generator.html">Sorted R-MAT generator</a></li>
+<li><a class="reference external" href="unique_rmat_generator.html">Unique R-MAT generator</a></li>
+<li><a class="reference external" href="scalable_rmat_generator.html">Scalable R-MAT generator</a></li>
+<li><a class="reference external" href="http://www.boost.org/libs/graph/doc/erdos_renyi_generator.html">Erdos-Renyi generator</a></li>
+<li><a class="reference external" href="http://www.boost.org/libs/graph/doc/sorted_erdos_renyi_gen.html">Sorted Erdos-Renyi generator</a></li>
+<li><a class="reference external" href="http://www.boost.org/libs/graph/doc/small_world_generator.html">Small world generator</a></li>
+<li><a class="reference external" href="ssca_generator.html">SSCA generator</a></li>
+<li><a class="reference external" href="mesh_generator.html">Mesh generator</a></li>
+</ul>
+</blockquote>
+<ol class="arabic simple" start="8">
+<li>Algorithms</li>
+</ol>
+<blockquote>
+<ul class="simple">
+<li>Distributed algorithms<ul>
+<li><a class="reference external" href="breadth_first_search.html">Breadth-first search</a></li>
+<li><a class="reference external" href="dijkstra_shortest_paths.html">Dijkstra's single-source shortest paths</a><ul>
+<li><a class="reference external" href="dijkstra_shortest_paths.html#eager-dijkstra-s-algorithm">Eager Dijkstra shortest paths</a></li>
+<li><a class="reference external" href="dijkstra_shortest_paths.html#crauser-et-al-s-algorithm">Crauser et al. Dijkstra shortest paths</a></li>
+<li><a class="reference external" href="dijkstra_shortest_paths.html#delta-stepping-algorithm">Delta-Stepping shortest paths</a></li>
+</ul>
+</li>
+<li><a class="reference external" href="tsin_depth_first_visit.html">Depth-first search</a></li>
+<li><a class="reference external" href="dehne_gotz_min_spanning_tree.html">Minimum spanning tree</a><ul>
+<li><a class="reference external" href="dehne_gotz_min_spanning_tree.html#dense-boruvka-minimum-spanning-tree">Boruvka's minimum spanning tree</a></li>
+<li><a class="reference external" href="dehne_gotz_min_spanning_tree.html#merge-local-minimum-spanning-trees">Merging local minimum spanning forests</a></li>
+<li><a class="reference external" href="dehne_gotz_min_spanning_tree.html#boruvka-then-merge">Boruvka-then-merge</a></li>
+<li><a class="reference external" href="dehne_gotz_min_spanning_tree.html#boruvka-mixed-merge">Boruvka-mixed-merge</a></li>
+</ul>
+</li>
+<li>Connected components<ul>
+<li><a class="reference external" href="connected_components.html">Connected components</a></li>
+<li><a class="reference external" href="connected_components_parallel_search.html">Connected components parallel search</a></li>
+<li><a class="reference external" href="strong_components.html">Strongly-connected components</a></li>
+</ul>
+</li>
+<li><a class="reference external" href="page_rank.html">PageRank</a></li>
+<li><a class="reference external" href="boman_et_al_graph_coloring.html">Boman et al. Graph coloring</a></li>
+<li><a class="reference external" href="fruchterman_reingold.html">Fruchterman Reingold force-directed layout</a></li>
+<li><a class="reference external" href="st_connected.html">s-t connectivity</a></li>
+<li><a class="reference external" href="betweenness_centrality.html">Betweenness centrality</a></li>
+</ul>
+</li>
+</ul>
+</blockquote>
+<hr class="docutils" />
+<p>Copyright (C) 2005-2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds, Douglas Gregor, and Andrew Lumsdaine</p>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/local_subgraph.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/local_subgraph.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Local Subgraph Adaptor</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-local-subgraph-adaptor">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Local Subgraph Adaptor</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<p>The local subgraph adaptor takes an existing <cite>Distributed Graph</cite> and
+filters out all of the nonlocal edges and vertices, presenting only
+the local portion of the distributed graph to the user. The behavior
+is equivalent to (and implemented with) a <a class="reference external" href="http://www.boost.org/libs/graph/doc/filtered_graph.html">filtered graph</a>, and is a
+noncopying view into the graph itself. Changes made through the
+filtered graph will be reflected in the original graph and vice-versa.</p>
+<pre class="literal-block">
+template&lt;typename DistributedGraph&gt; class local_subgraph;
+
+template&lt;typename DistributedGraph&gt;
+local_subgraph&lt;DistributedGraph&gt; make_local_subgraph(DistributedGraph&amp; g);
+</pre>
+<div class="section" id="where-defined">
+<h1>Where Defined</h1>
+<p>&lt;boost/graph/distributed/local_subgraph.hpp&gt;</p>
+</div>
+<div class="section" id="reference">
+<h1>Reference</h1>
+<p>The local subgraph adaptor adapts and forwards all operations of
+distributed graphs, the signatures of which will be omitted. Only
+operations unique to the local subgraph adaptor are presented.</p>
+<div class="section" id="member-functions">
+<h2>Member Functions</h2>
+<pre class="literal-block">
+local_subgraph(DistributedGraph&amp; g);
+</pre>
+<p>Constructs a local subgraph presenting the local portion of the
+distributed graph <tt class="docutils literal"><span class="pre">g</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+DistributedGraph&amp; base() { return g; }
+const DistributedGraph&amp; base() const { return g; }
+</pre>
+<p>Returns the underlying distributed graph.</p>
+</div>
+<div class="section" id="free-functions">
+<h2>Free Functions</h2>
+<pre class="literal-block">
+template&lt;typename DistributedGraph&gt;
+local_subgraph&lt;DistributedGraph&gt; make_local_subgraph(DistributedGraph&amp; g);
+</pre>
+<p>Constructs a local subgraph presenting the local portion of the
+distributed graph <tt class="docutils literal"><span class="pre">g</span></tt>.</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/mesh_generator.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/mesh_generator.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Mesh Generator</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-mesh-generator">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Mesh Generator</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/metis.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/metis.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,274 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL METIS Input Routines</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-metis-input-routines">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> METIS Input Routines</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+namespace boost {
+ namespace graph {
+ class metis_reader;
+ class metis_exception;
+ class metis_input_exception;
+ class metis_distribution;
+ }
+}
+</pre>
+<p><a class="reference external" href="http://www-users.cs.umn.edu/~karypis/metis/metis/">METIS</a> is a set of programs for partitioning graphs (among other
+things). The Parallel BGL can read the METIS graph format and
+partition format, allowing one to easily load METIS-partitioned
+graphs into the Parallel BGL's data structures.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id3">Where Defined</a><ul>
+<li><a class="reference internal" href="#graph-reader" id="id4">Graph Reader</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#usage" id="id5">Usage</a></li>
+<li><a class="reference internal" href="#associated-types" id="id6">Associated Types</a></li>
+<li><a class="reference internal" href="#member-functions" id="id7">Member Functions</a><ul>
+<li><a class="reference internal" href="#partition-reader" id="id8">Partition Reader</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#id1" id="id9">Usage</a></li>
+<li><a class="reference internal" href="#id2" id="id10">Member Functions</a></li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id3">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/metis.hpp</span></tt>&gt;</p>
+<div class="section" id="graph-reader">
+<h2><a class="toc-backref" href="#id4">Graph Reader</a></h2>
+<pre class="literal-block">
+class metis_reader
+{
+ public:
+ typedef std::size_t vertices_size_type;
+ typedef std::size_t edges_size_type;
+ typedef double vertex_weight_type;
+ typedef double edge_weight_type;
+
+ class edge_iterator;
+ class edge_weight_iterator;
+
+ metis_reader(std::istream&amp; in);
+
+ edge_iterator begin();
+ edge_iterator end();
+ edge_weight_iterator weight_begin();
+
+ vertices_size_type num_vertices() const;
+ edges_size_type num_edges() const;
+
+ std::size_t num_vertex_weights() const;
+
+ vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n);
+
+ bool has_edge_weights() const;
+};
+</pre>
+</div>
+</div>
+<div class="section" id="usage">
+<h1><a class="toc-backref" href="#id5">Usage</a></h1>
+<p>The METIS reader provides an iterator interface to the METIS graph
+file. The iterator interface is most useful when constructing Parallel
+BGL graphs on-the-fly. For instance, the following code builds a graph
+<tt class="docutils literal"><span class="pre">g</span></tt> from a METIS graph stored in <tt class="docutils literal"><span class="pre">argv[1]</span></tt>.</p>
+<pre class="literal-block">
+std::ifstream in_graph(argv[1]);
+metis_reader reader(in_graph);
+Graph g(reader.begin(), reader.end(),
+ reader.weight_begin(),
+ reader.num_vertices());
+</pre>
+<p>The calls to <tt class="docutils literal"><span class="pre">begin()</span></tt> and <tt class="docutils literal"><span class="pre">end()</span></tt> return an iterator range for
+the edges in the graph; the call to <tt class="docutils literal"><span class="pre">weight_begin()</span></tt> returns an
+iterator that will enumerate the weights of the edges in the
+graph. For a distributed graph, the distribution will be determined
+automatically by the graph; to use a METIS partitioning, see the
+section <a class="reference internal" href="#partition-reader">Partition Reader</a>.</p>
+</div>
+<div class="section" id="associated-types">
+<h1><a class="toc-backref" href="#id6">Associated Types</a></h1>
+<pre class="literal-block">
+metis_reader::edge_iterator
+</pre>
+<p>An <a class="reference external" href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> that enumerates the edges in the METIS graph, and
+is suitable for use as the <tt class="docutils literal"><span class="pre">EdgeIterator</span></tt> of an <a class="reference external" href="http://www.boost.org/libs/graph/doc/adjacency_list.html">adjacency_list</a>.
+The <tt class="docutils literal"><span class="pre">value_type</span></tt> of this iterator is a pair of vertex numbers.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+metis_reader::edge_weight_iterator
+</pre>
+<p>An <a class="reference external" href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> that enumerates the edge weights in the METIS
+graph. The <tt class="docutils literal"><span class="pre">value_type</span></tt> of this iterator is <tt class="docutils literal"><span class="pre">edge_weight_type</span></tt>. If
+the edges in the METIS graph are unweighted, the result of
+dereferencing this iterator will always be zero.</p>
+</div>
+<div class="section" id="member-functions">
+<h1><a class="toc-backref" href="#id7">Member Functions</a></h1>
+<pre class="literal-block">
+metis_reader(std::istream&amp; in);
+</pre>
+<p>Constructs a new METIS reader that will retrieve edges from the input
+stream <tt class="docutils literal"><span class="pre">in</span></tt>. If any errors are encountered while initially parsing
+<tt class="docutils literal"><span class="pre">in</span></tt>, <tt class="docutils literal"><span class="pre">metis_input_exception</span></tt> will be thrown.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+edge_iterator begin();
+</pre>
+<p>Returns an iterator to the first edge in the METIS file.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+edge_iterator end();
+</pre>
+<p>Returns an iterator one past the last edge in the METIS file.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+edge_weight_iterator weight_begin();
+</pre>
+<p>Returns an iterator to the first edge weight in the METIS file. The
+weight iterator should be moved in concert with the edge iterator;
+when the edge iterator moves, the edge weight changes. If the edges
+in the graph are unweighted, the weight returned will always be zero.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+vertices_size_type num_vertices() const;
+</pre>
+<p>Returns the number of vertices in the graph.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+edges_size_type num_edges() const;
+</pre>
+<p>Returns the number of edges in the graph.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+std::size_t num_vertex_weights() const;
+</pre>
+<p>Returns the number of weights attached to each vertex.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n);
+</pre>
+<hr class="docutils" />
+<pre class="literal-block">
+bool has_edge_weights() const;
+</pre>
+<p>Returns <tt class="docutils literal"><span class="pre">true</span></tt> when the edges of the graph have weights, <tt class="docutils literal"><span class="pre">false</span></tt>
+otherwise. When <tt class="docutils literal"><span class="pre">false</span></tt>, the edge weight iterator is still valid
+but returns zero for the weight of each edge.</p>
+<div class="section" id="partition-reader">
+<h2><a class="toc-backref" href="#id8">Partition Reader</a></h2>
+<pre class="literal-block">
+class metis_distribution
+{
+ public:
+ typedef int process_id_type;
+ typedef std::size_t size_type;
+
+ metis_distribution(std::istream&amp; in, process_id_type my_id);
+
+ size_type block_size(process_id_type id, size_type) const;
+ process_id_type operator()(size_type n);
+ size_type local(size_type n) const;
+ size_type global(size_type n) const;
+ size_type global(process_id_type id, size_type n) const;
+
+ private:
+ std::istream&amp; in;
+ process_id_type my_id;
+ std::vector&lt;process_id_type&gt; vertices;
+};
+</pre>
+</div>
+</div>
+<div class="section" id="id1">
+<h1><a class="toc-backref" href="#id9">Usage</a></h1>
+<p>The class <tt class="docutils literal"><span class="pre">metis_distribution</span></tt> loads a METIS partition file and
+makes it available as a Distribution suitable for use with the
+<a class="reference external" href="distributed_adjacency_list.html">distributed adjacency list</a> graph type. To load a METIS graph using
+a METIS partitioning, use a <tt class="docutils literal"><span class="pre">metis_reader</span></tt> object for the graph and
+a <tt class="docutils literal"><span class="pre">metis_distribution</span></tt> object for the distribution, as in the
+following example.</p>
+<pre class="literal-block">
+std::ifstream in_graph(argv[1]);
+metis_reader reader(in_graph);
+
+std::ifstream in_partitions(argv[2]);
+metis_distribution dist(in_partitions, process_id(pg));
+Graph g(reader.begin(), reader.end(),
+ reader.weight_begin(),
+ reader.num_vertices(),
+ pg,
+ dist);
+</pre>
+<p>In this example, <tt class="docutils literal"><span class="pre">argv[1]</span></tt> is the graph and <tt class="docutils literal"><span class="pre">argv[2]</span></tt> is the
+partition file generated by <tt class="docutils literal"><span class="pre">pmetis</span></tt>. The <tt class="docutils literal"><span class="pre">dist</span></tt> object loads the
+partitioning information from the input stream it is given and uses
+that to distributed the adjacency list. Note that the input stream
+must be in the METIS partition file format and must have been
+partitioned for the same number of processes are there are in the
+process group <tt class="docutils literal"><span class="pre">pg</span></tt>.</p>
+</div>
+<div class="section" id="id2">
+<h1><a class="toc-backref" href="#id10">Member Functions</a></h1>
+<pre class="literal-block">
+metis_distribution(std::istream&amp; in, process_id_type my_id);
+</pre>
+<p>Creates a new METIS distribution from the input stream
+<tt class="docutils literal"><span class="pre">in</span></tt>. <tt class="docutils literal"><span class="pre">my_id</span></tt> is the process ID of the current process in the
+process group over which the graph will be distributed.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+size_type block_size(process_id_type id, size_type) const;
+</pre>
+<p>Returns the number of vertices to be stored in the process
+<tt class="docutils literal"><span class="pre">id</span></tt>. The second parameter, <tt class="docutils literal"><span class="pre">size_type</span></tt>, is unused and may be any
+value.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+process_id_type operator()(size_type n);
+</pre>
+<p>Returns the ID for the process that will store vertex number <tt class="docutils literal"><span class="pre">n</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+size_type local(size_type n) const;
+</pre>
+<p>Returns the local index of vertex number <tt class="docutils literal"><span class="pre">n</span></tt> within its owning
+process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+size_type global(size_type n) const;
+</pre>
+<p>Returns the global index of the current processor's local vertex <tt class="docutils literal"><span class="pre">n</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+size_type global(process_id_type id, size_type n) const;
+</pre>
+<p>Returns the global index of the process <tt class="docutils literal"><span class="pre">id</span></tt>'s local vertex <tt class="docutils literal"><span class="pre">n</span></tt>.</p>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/overview.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/overview.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>An Overview of the Parallel Boost Graph Library</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="an-overview-of-the-parallel-boost-graph-library">
+<h1 class="title">An Overview of the Parallel Boost Graph Library</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<img align="right" alt="An example graph" class="align-right" src="graph.png" style="width: 206px; height: 184px;" />
+<p>The Parallel Boost Graph Library (Parallel BGL) is a C++ library for
+parallel, distributed computation on graphs. The Parallel BGL contains
+distributed graph data structures, distributed graph algorithms,
+abstractions over the communication medium (such as MPI), and
+supporting data structures. A graph (also called a <em>network</em>) consists
+of a set of <em>vertices</em> and a set of relationships between vertices,
+called <em>edges</em>. The edges may be <em>undirected</em>, meaning that the
+relationship between vertices is mutual, e.g., &quot;X is related to Y&quot;, or
+they can be <em>directed</em>, meaning that the relationship goes only one
+way, e.g., &quot;X is the child of Y&quot;. The following figure illustrates a
+typical directed graph, where <em>a-i</em> are the vertices and the arrows
+represent edges.</p>
+<img align="right" alt="A distributed graph" class="align-right" src="distributed-graph.png" style="width: 229px; height: 199px;" />
+<p>The Parallel BGL is primarily concerned with <em>distributed</em>
+graphs. Distributed graphs are conceptually graphs, but their storage
+is spread across multiple processors. The following figure
+demonstrates a distributed version of the graph above, where the graph
+has been divided among three processors (represented by the grey
+rectangles). Edges in the graph may be either local (with both
+endpoints stored on the same processor) or remote (the target of the
+edge is stored on a different processor).</p>
+<p>The Parallel BGL is a generic library. At its core are <em>generic</em>
+distributed graph algorithms, which can operate on any distributed
+graph data structure provided that data structure meets certain
+requirements. For instance, the algorithm may need to enumerate the
+set of vertices stored on the current processor, enumerate the set of
+outgoing edges from a particular vertex, and determine on which
+processor the target of each edge resides. The graph algorithms in the
+Parallel BGL are also generic with respect to the <em>properties</em>
+attached to edges and vertices in a graph; for instance, the weight of
+each edge can be stored as part of the graph or allocated in a
+completely separate data structure.</p>
+<p>The genericity available in the algorithms of the Parallel BGL allows
+them to be applied to existing graph data structures. However, most
+users will instead be writing new code that takes advantage of the
+Parallel BGL. The Parallel BGL provides distributed graph data
+structures that meet the requirements of the Parallel BGL
+algorithms. The primary data structure is the <a class="reference external" href="distributed_adjacency_list.html">distributed adjacency
+list</a>, which allows storage and manipulation of a (distributed)
+graph. The vertices in the graph are divided among the various
+processors, and each of the edges outgoing from a vertex are stored on
+the processor that &quot;owns&quot; (stores) that vertex. The following figure
+illustrates the distributed adjacency list representation.</p>
+<div align="center" class="align-center"><img alt="A distributed adjacency list" class="align-center" src="dist-adjlist.png" style="width: 446px; height: 154px;" /></div>
+<img align="right" alt="A distributed property map" class="align-right" src="dist-pmap.png" style="width: 271px; height: 175px;" />
+<p>The <a class="reference external" href="distributed_adjacency_list.html">distributed adjacency list</a> distributes the structure of a graph
+over multiple processors. While graph structure is in important part
+of many graph problems, there are typically other properties attached
+to the vertices and edges, such as edge weights or the position of
+vertices within a grid. These properties are stored in <em>property
+maps</em>, which associate a single piece of data with each edge or vertex
+in a graph. Distributed property maps extend this notion to
+distributed computing, where properties are stored on the same
+processor as the vertex or edge. The following figure illustrates the
+distribution of a property map storing colors (white, gray, black) for
+each vertex. In addition to the storage for each vertex, the
+processors store some &quot;ghost cells&quot; that cache values actually stored
+on other processors, represented by the dashed boxes.</p>
+<p>Tying together all of the distributed data structures of the Parallel
+BGL are its process groups and distributed graph algorithms. Process
+groups coordinate the interactions between multiple processes and
+distributed data structures by abstracting the communication
+mechanism. The algorithms are typically written using the SPMD model
+(Single Program, Multiple Data) and interact with both the distributed
+data structures and the process group itself. At various points in the
+algorithm's execution, all processes execute a synchronization point,
+which allows all of the distributed data structures to ensure an
+appropriate degree of consistency across processes. The following
+diagram illustrates the communication patterns within the the
+execution of a distributed algorithm in the Parallel BGL. In
+particular, the diagram illustrates the distributed data structures
+used in a distributed breadth-first search, from the top-left and
+proceeding clockwise:</p>
+<blockquote>
+<ul class="simple">
+<li>a user-defined property map that tracks the distance from the
+source vertex to all other vertices,</li>
+<li>an automatically-generated property map that tracks the &quot;color&quot;
+of vertices in the (distributed) graph, to determine which
+vertices have been seen before,</li>
+<li>a distributed queue, which coordinates the breadth-first search
+and distributes new vertices to search, and</li>
+<li>a distributed graph, on which the breadth-first search is
+operating.</li>
+</ul>
+</blockquote>
+<div align="center" class="align-center"><img alt="Parallel Boost Graph Library architecture" class="align-center" src="architecture.png" style="width: 485px; height: 410px;" /></div>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+<span class="target" id="process-groups"></span>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:13 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/page_rank.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/page_rank.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL PageRank</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-pagerank">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> PageRank</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+namespace graph {
+ template&lt;typename Graph, typename RankMap, typename Done&gt;
+ inline void
+ page_rank(const Graph&amp; g, RankMap rank_map, Done done,
+ typename property_traits&lt;RankMap&gt;::value_type damping = 0.85);
+
+ template&lt;typename Graph, typename RankMap&gt;
+ inline void
+ page_rank(const Graph&amp; g, RankMap rank_map);
+}
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">page_rank</span></tt> algorithm computes the ranking of vertices in a
+graph, based on the connectivity of a directed graph <a class="citation-reference" href="#pbmw98" id="id1">[PBMW98]</a>. The
+idea of PageRank is based on a random model of a Web surfer, who
+starts a random web page and then either follows a link from that web
+page (choosing from the links randomly) or jumps to a completely
+different web page (not necessarily linked from the current
+page). The PageRank of each page is the probability of the random web
+surfer visiting that page.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id2">Where Defined</a></li>
+<li><a class="reference internal" href="#parameters" id="id3">Parameters</a></li>
+<li><a class="reference internal" href="#complexity" id="id4">Complexity</a><ul>
+<li><a class="reference internal" href="#bibliography" id="id5">Bibliography</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id2">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/page_rank.hpp</span></tt>&gt;</p>
+<p>also accessible from</p>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/page_rank.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="parameters">
+<h1><a class="toc-backref" href="#id3">Parameters</a></h1>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph type must be a model of <a class="reference external" href="DistributedVertexListGraph.html">Distributed Vertex List Graph</a> and
+<a class="reference external" href="DistributedEdgeListGraph.html">Distributed Edge List Graph</a>. The graph must be directed.</dd>
+<dt>OUT: <tt class="docutils literal"><span class="pre">RankMap</span> <span class="pre">rank</span></tt></dt>
+<dd>Stores the rank of each vertex. The type <tt class="docutils literal"><span class="pre">RankMap</span></tt> must model the
+<a class="reference external" href="http://www.boost.org/libs/property_map/ReadWritePropertyMap.html">Read/Write Property Map</a> concept and must be a <a class="reference external" href="distributed_property_map.html">distributed
+property map</a>. Its key type must be the vertex descriptor of the
+graph type and its value type must be a floating-point or rational
+type.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">Done</span> <span class="pre">done</span></tt></dt>
+<dd><p class="first">A function object that determines when the PageRank algorithm
+should complete. It will be passed two parameters, the rank map and
+a reference to the graph, and should return <tt class="docutils literal"><span class="pre">true</span></tt> when the
+algorithm should terminate.</p>
+<p class="last"><strong>Default</strong>: <tt class="docutils literal"><span class="pre">graph::n_iterations(20)</span></tt></p>
+</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">typename</span> <span class="pre">property_traits&lt;RankMap&gt;::value_type</span> <span class="pre">damping</span></tt></dt>
+<dd><p class="first">The damping factor is the probability that the Web surfer will
+select an outgoing link from the current page instead of jumping to
+a random page.</p>
+<p class="last"><strong>Default</strong>: 0.85</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="complexity">
+<h1><a class="toc-backref" href="#id4">Complexity</a></h1>
+<p>Each iteration of PageRank requires <em>O((V + E)/p)</em> time on <em>p</em>
+processors and performs <em>O(V)</em> communication. The number of
+iterations is dependent on the input to the algorithm.</p>
+<div class="section" id="bibliography">
+<h2><a class="toc-backref" href="#id5">Bibliography</a></h2>
+<table class="docutils citation" frame="void" id="pbmw98" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[PBMW98]</a></td><td>Lawrence Page, Sergey Brin, Rajeev Motwani, and Terry
+Winograd. The PageRank Citation Ranking: Bringing Order to the
+Web. Technical report, Stanford Digital Library Technologies Project,
+November 1998.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/process_group.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/process_group.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,450 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Parallel BGL Process Groups</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-parallel-bgl-process-groups">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Parallel BGL Process Groups</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#introduction" id="id1">Introduction</a></li>
+<li><a class="reference internal" href="#communication-model" id="id2">Communication model</a><ul>
+<li><a class="reference internal" href="#distributed-data-structures" id="id3">Distributed data structures</a></li>
+<li><a class="reference internal" href="#asynchronous-receives" id="id4">Asynchronous receives</a></li>
+<li><a class="reference internal" href="#out-of-band-messaging" id="id5">Out-of-band messaging</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#reference" id="id6">Reference</a><ul>
+<li><a class="reference internal" href="#process-group-constructors" id="id7">Process group constructors</a></li>
+<li><a class="reference internal" href="#triggers" id="id8">Triggers</a></li>
+<li><a class="reference internal" href="#helper-operations" id="id9">Helper operations</a></li>
+<li><a class="reference internal" href="#process-query" id="id10">Process query</a></li>
+<li><a class="reference internal" href="#message-transmission" id="id11">Message transmission</a></li>
+<li><a class="reference internal" href="#synchronization" id="id12">Synchronization</a></li>
+<li><a class="reference internal" href="#out-of-band-communication" id="id13">Out-of-band communication</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="introduction">
+<h1><a class="toc-backref" href="#id1">Introduction</a></h1>
+<p>Process groups are an abstraction of a set of communicating processes
+that coordinate to solve the same problem. Process groups contain
+facilities for identifying the processes within that group, sending
+and receiving messages between the processes in that group, and
+performing collective communications involving all processes in the
+group simultaneously.</p>
+</div>
+<div class="section" id="communication-model">
+<h1><a class="toc-backref" href="#id2">Communication model</a></h1>
+<p>Process groups are based on an extended version of the Bulk
+Synchronous Parallel (BSP) model of computation. Parallel computations
+in the BSP model are organized into <em>supersteps</em>, each of which
+consists of a computation phase followed by a communication
+phase. During the computation phase, all processes in the process
+group work exclusively on local data, and there is no inter-process
+communication. During the communication phase, all of the processes
+exchange message with each other. Messages sent in the communication
+phase of a superstep will be received in the next superstep.</p>
+<p>The boundary between supersteps in the Parallel BGL corresponds to the
+<tt class="docutils literal"><span class="pre">synchronize</span></tt> operation. Whenever a process has completed its local
+computation phase and sent all of the messages required for that
+superstep, it invokes the <tt class="docutils literal"><span class="pre">synchronize</span></tt> operation on the process
+group. Once all processes in the process group have entered
+<tt class="docutils literal"><span class="pre">synchronize</span></tt>, they exchange messages and then continue with the
+next superstep.</p>
+<p>The Parallel BGL loosens the BSP model significantly, to provide a
+more natural programming model that also provides some performance
+benefits over the strict BSP model. The primary extension is the
+ability to receive messages sent within the same superstep
+&quot;asynchronously&quot;, either to free up message buffers or to respond to
+an immediate request for information. For particularly unstructured
+computations, the ability to send a message and get an immediate reply
+can simplify many computations that would otherwise need to be split
+into two separate supersteps. Additionally, the Parallel BGL augments
+the BSP model with support for multiple distributed data structures,
+each of which are provided with a different communication space but
+whose messages will all be synchronized concurrently.</p>
+<div class="section" id="distributed-data-structures">
+<h2><a class="toc-backref" href="#id3">Distributed data structures</a></h2>
+<p>A typical computation with the Parallel BGL involves several
+distributed data structures working in concern. For example, a simple
+breadth-first search involves the distributed graph data structure
+containing the graph itself, a distributed queue that manages the
+traversal through the graph, and a distributed property map that
+tracks which vertices have already been visited as part of the
+search.</p>
+<p>The Parallel BGL manages these distributed data structures by allowing
+each of the data structures to attach themselves to the process group
+itself. When a distributed data structure attaches to the process
+group, it receives its own copy of the process group that allows the
+distributed data structure to communicate without colliding with the
+communications from other distributed data structures. When the
+process group is synchronized, all of the distributed data structures
+attached to that process group are automatically synchronized, so that
+all of the distributed data structures in a computation remain
+synchronized.</p>
+<p>A distributed data structure attaches itself to the process group by
+creating a copy of the process group and passing an
+<tt class="docutils literal"><span class="pre">attach_distributed_object</span></tt> flag to the process group
+constructor. So long as this copy of the process group persists, the
+distributed data structure is attached the process group. For this
+reason, most distributed data structures keep a copy of the process
+group as member data, constructing the member with
+<tt class="docutils literal"><span class="pre">attach_distributed_object</span></tt>, e.g.,</p>
+<pre class="literal-block">
+template&lt;typename ProcessGroup&gt;
+struct distributed_data_structure
+{
+ explicit distributed_data_structure(const ProcessGroup&amp; pg)
+ : process_group(pg, boost::parallel::attach_distributed_object())
+ { }
+
+private:
+ ProcessGroup process_group;
+};
+</pre>
+</div>
+<div class="section" id="asynchronous-receives">
+<h2><a class="toc-backref" href="#id4">Asynchronous receives</a></h2>
+<p>Distributed data structures in the Parallel BGL can &quot;asynchronously&quot;
+receive and process messages before the end of a BSP
+superstep. Messages can be received any time that a process is inside
+the process group operations, and the scheduling of message receives
+is entirely managed by the process group.</p>
+<p>Distributed data structures receive messages through
+&quot;triggers&quot;. Triggers are function objects responsible for processing a
+received message. Each trigger is registered with the <tt class="docutils literal"><span class="pre">trigger</span></tt>
+method of the process group using a specific message
+tag (an integer) and the type of data that is expected to be
+contained within that message. Whenever a message with that tag
+becomes available, the progress group will call the trigger with the
+source of the message, the message tag, the data contained in the
+message, and the &quot;context&quot; of the message.</p>
+<p>The majority of triggers have no return value, although it is common
+that the triggers send messages back to the source process. In certain
+cases where the trigger's purpose is to immediately reply with a
+value, the trigger should be registered with the
+<tt class="docutils literal"><span class="pre">trigger_with_reply</span></tt> method and should return the value that will be
+sent back to the caller. The <tt class="docutils literal"><span class="pre">trigger_with_reply</span></tt> facility is only
+useful in conjunction with out-of-band messaging, discussed next.</p>
+</div>
+<div class="section" id="out-of-band-messaging">
+<h2><a class="toc-backref" href="#id5">Out-of-band messaging</a></h2>
+<p>The majority of messages sent by the Parallel BGL are sent through the
+normal send operations, to be received in the next superstep or, in
+some cases, received &quot;early&quot; by a trigger. These messages are not
+time-sensitive, so they will be delivered whenever the process group
+processes them.</p>
+<p>Some messages, however, require immediate responses. For example, if a
+process needs to determine the current value associated with a vertex
+owned by another process, the first process must send a request to the
+second process and block while waiting for a response. For such
+messages, the Parallel BGL's process groups provide an out-of-band
+messaging mechanism. Out-of-band messages are transmitted immediately,
+with a much higher priority than other messages. The sending of
+out-of-band messages can be coupled with a receive operation that
+waits until the remote process has received the message and sent its
+reply. For example, in the following code the process sends a message
+containing the string <tt class="docutils literal"><span class="pre">name</span></tt> to process <tt class="docutils literal"><span class="pre">owner</span></tt> with tag
+<tt class="docutils literal"><span class="pre">msg_get_descriptor_by_name</span></tt> via an out-of-band message. The
+receiver of that message will immediately deliver the message via a
+trigger, that returns the resulting value--a
+<tt class="docutils literal"><span class="pre">vertex_descriptor</span></tt>--that will be passed back to the process that
+initiated the communication. The full communication happens
+immediately, within the current superstep.</p>
+<pre class="literal-block">
+std::string name;
+vertex_descriptor descriptor;
+send_oob_with_reply(process_group, owner, msg_get_descriptor_by_name,
+ name, descriptor);
+</pre>
+</div>
+</div>
+<div class="section" id="reference">
+<h1><a class="toc-backref" href="#id6">Reference</a></h1>
+<p>The Parallel BGL process groups specify an interface that can be
+implemented by various communication subsystems. In this reference
+section, we use the placeholder type <tt class="docutils literal"><span class="pre">ProcessGroup</span></tt> to stand in for
+the various process group implementations that exist. There is only
+one implementation of the process group interface at this time:</p>
+<blockquote>
+<ul class="simple">
+<li><a class="reference external" href="mpi_bsp_process_group.html">MPI BSP process group</a></li>
+</ul>
+</blockquote>
+<pre class="literal-block">
+enum trigger_receive_context {
+ trc_none,
+ trc_in_synchronization,
+ trc_early_receive,
+ trc_out_of_band
+};
+
+class ProcessGroup
+{
+ // Process group constructors
+ ProcessGroup();
+ ProcessGroup(const ProcessGroup&amp;, boost::parallel::attach_distributed_object);
+
+ // Triggers
+ template&lt;typename Type, typename Handler&gt;
+ void trigger(int tag, const Handler&amp; handler);
+
+ template&lt;typename Type, typename Handler&gt;
+ void trigger_with_reply(int tag, const Handler&amp; handler);
+
+ trigger_receive_context trigger_context() const;
+
+ // Helper operations
+ void poll();
+ ProcessGroup base() const;
+};
+
+// Process query
+int process_id(const ProcessGroup&amp;);
+int num_processes(const ProcessGroup&amp;);
+
+// Message transmission
+template&lt;typename T&gt;
+ void send(const ProcessGroup&amp; pg, int dest, int tag, const T&amp; value);
+
+template&lt;typename T&gt;
+ void receive(const ProcessGroup&amp; pg, int source, int tag, T&amp; value);
+
+optional&lt;std::pair&lt;int, int&gt; &gt; probe(const ProcessGroup&amp; pg);
+
+// Synchronization
+void synchronize(const ProcessGroup&amp; pg);
+
+// Out-of-band communication
+template&lt;typename T&gt;
+ void send_oob(const ProcessGroup&amp; pg, int dest, int tag, const T&amp; value);
+
+template&lt;typename T, typename U&gt;
+ void
+ send_oob_with_reply(const ProcessGroup&amp; pg, int dest, int
+ tag, const T&amp; send_value, U&amp; receive_value);
+
+template&lt;typename T&gt;
+ void receive_oob(const ProcessGroup&amp; pg, int source, int tag, T&amp; value);
+</pre>
+<div class="section" id="process-group-constructors">
+<h2><a class="toc-backref" href="#id7">Process group constructors</a></h2>
+<pre class="literal-block">
+ProcessGroup();
+</pre>
+<p>Constructs a new process group with a different communication space
+from any other process group.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+ProcessGroup(const ProcessGroup&amp; pg, boost::parallel::attach_distributed_object);
+</pre>
+<p>Attaches a new distributed data structure to the process group
+<tt class="docutils literal"><span class="pre">pg</span></tt>. The resulting process group can be used for communication
+within that new distributed data structure. When the newly-constructed
+process group is eventually destroyed, the distributed data structure
+is detached from the process group.</p>
+</div>
+<div class="section" id="triggers">
+<h2><a class="toc-backref" href="#id8">Triggers</a></h2>
+<pre class="literal-block">
+template&lt;typename Type, typename Handler&gt;
+ void trigger(int tag, const Handler&amp; handler);
+</pre>
+<p>Registers a trigger with the given process group. The trigger will
+watch for messages with the given <tt class="docutils literal"><span class="pre">tag</span></tt>. When such a message is
+available, it will be received into a value of type <tt class="docutils literal"><span class="pre">Type</span></tt>, and the
+function object <tt class="docutils literal"><span class="pre">handler</span></tt> will be invoked with four parameters:</p>
+<dl class="docutils">
+<dt>source</dt>
+<dd>The rank of the source process (an <tt class="docutils literal"><span class="pre">int</span></tt>)</dd>
+<dt>tag</dt>
+<dd>The tag used to send the message (also an <tt class="docutils literal"><span class="pre">int</span></tt>)</dd>
+<dt>data:</dt>
+<dd>The data transmitted with the message. The data will have the type
+specified when the trigger was registered.</dd>
+<dt>context:</dt>
+<dd>The context in which the trigger is executed. This will be a value of
+type <tt class="docutils literal"><span class="pre">trigger_receive_context</span></tt>, which stages whether the trigger
+is being executed during synchronization, asynchronously in response
+to an &quot;early&quot; receive (often to free up communication buffers), or
+in response to an &quot;out-of-band&quot; message.</dd>
+</dl>
+<p>Triggers can only be registered by process groups that result from
+attaching a distributed data structure. A trigger can be invoked in
+response to either a normal send operation or an out-of-band send
+operation. There is also a <a class="reference external" href="simple_trigger.html">simple trigger interface</a> for defining
+triggers in common cases.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename Type, typename Handler&gt;
+ void trigger_with_reply(int tag, const Handler&amp; handler);
+</pre>
+<p>Like the <tt class="docutils literal"><span class="pre">trigger</span></tt> method, registers a trigger with the given
+process group. The trigger will watch for messages with the given
+<tt class="docutils literal"><span class="pre">tag</span></tt>. When such a message is available, it will be received into a
+value of type <tt class="docutils literal"><span class="pre">Type</span></tt> and <tt class="docutils literal"><span class="pre">handler</span></tt> will be invoked, just as with a
+normal trigger. However, a trigger registered with
+<tt class="docutils literal"><span class="pre">trigger_with_reply</span></tt> must return a value, which will be immediately
+sent back to the process that initiated the send resulting in this
+trigger. Thus, <tt class="docutils literal"><span class="pre">trigger_with_reply</span></tt> should only be used for messages
+that need immediate responses. These triggers can only be invoked via
+the out-of-band sends that wait for the reply, via
+<tt class="docutils literal"><span class="pre">send_oob_with_reply</span></tt>. There is also a <a class="reference external" href="simple_trigger.html">simple trigger interface</a>
+for defining triggers in common cases.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+trigger_receive_context trigger_context() const;
+</pre>
+<p>Retrieves the current context of the process group with respect to the
+invocation of triggers. When <tt class="docutils literal"><span class="pre">trc_none</span></tt>, the process group is not
+currently invoking any triggers. Otherwise, this value describes in
+what context the currently executing trigger is being invoked.</p>
+</div>
+<div class="section" id="helper-operations">
+<h2><a class="toc-backref" href="#id9">Helper operations</a></h2>
+<pre class="literal-block">
+void poll();
+</pre>
+<p>Permits the process group to receive any incomining messages,
+processing them via triggers. If you have a long-running computation
+that does not invoke any of the process group's communication
+routines, you should call <tt class="docutils literal"><span class="pre">poll</span></tt> occasionally to along incoming
+messages to be processed.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+ProcessGroup base() const;
+</pre>
+<p>Retrieves the &quot;base&quot; process group for this process group, which is a
+copy of the underlying process group that does not reference any
+specific distributed data structure.</p>
+</div>
+<div class="section" id="process-query">
+<h2><a class="toc-backref" href="#id10">Process query</a></h2>
+<pre class="literal-block">
+int process_id(const ProcessGroup&amp; pg);
+</pre>
+<p>Retrieves the ID (or &quot;rank&quot;) of the calling process within the process
+group. Process IDs are values in the range [0, <tt class="docutils literal"><span class="pre">num_processes(pg)</span></tt>)
+that uniquely identify the process. Process IDs can be used to
+initiate communication with another process.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+int num_processes(const ProcessGroup&amp; pg);
+</pre>
+<p>Returns the number of processes within the process group.</p>
+</div>
+<div class="section" id="message-transmission">
+<h2><a class="toc-backref" href="#id11">Message transmission</a></h2>
+<pre class="literal-block">
+template&lt;typename T&gt;
+ void send(const ProcessGroup&amp; pg, int dest, int tag, const T&amp; value);
+</pre>
+<p>Sends a message with the given <tt class="docutils literal"><span class="pre">tag</span></tt> and carrying the given
+<tt class="docutils literal"><span class="pre">value</span></tt> to the process with ID <tt class="docutils literal"><span class="pre">dest</span></tt> in the given process
+group. All message sends are non-blocking, meaning that this send
+operation will not block while waiting for the communication to
+complete. There is no guarantee when the message will be received,
+except that it will become available to the destination process by the
+end of the superstep, in the collective call to <tt class="docutils literal"><span class="pre">synchronize</span></tt>.</p>
+<p>Any type of value can be transmitted via <tt class="docutils literal"><span class="pre">send</span></tt>, so long as it
+provides the appropriate functionality to be serialized with the
+Boost.Serialization library.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename T&gt;
+ void receive(const ProcessGroup&amp; pg, int source, int tag, T&amp; value);
+</pre>
+<p>Receives a message with the given <tt class="docutils literal"><span class="pre">tag</span></tt> sent from the process
+<tt class="docutils literal"><span class="pre">source</span></tt>, updating <tt class="docutils literal"><span class="pre">value</span></tt> with the payload of the message. This
+receive operation can only receive messages sent within the previous
+superstep via the <tt class="docutils literal"><span class="pre">send</span></tt> operation. If no such message is available
+at the time <tt class="docutils literal"><span class="pre">receive</span></tt> is called, the program is ill-formed.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+optional&lt;std::pair&lt;int, int&gt; &gt; probe(const ProcessGroup&amp; pg);
+</pre>
+<p>Determines whether a message is available. The probe operation checks
+for any messages that were sent in the previous superstep but have not
+yet been received. If such a message exists, <tt class="docutils literal"><span class="pre">probe</span></tt> returns a
+(source, tag) pair describing the message. Otherwise, <tt class="docutils literal"><span class="pre">probe</span></tt> will
+return an empty <tt class="docutils literal"><span class="pre">boost::optional</span></tt>.</p>
+<p>A typical use of <tt class="docutils literal"><span class="pre">probe</span></tt> is to continually probe for messages at the
+beginning of the superstep, receiving and processing those messages
+until no messages remain.</p>
+</div>
+<div class="section" id="synchronization">
+<h2><a class="toc-backref" href="#id12">Synchronization</a></h2>
+<pre class="literal-block">
+void synchronize(const ProcessGroup&amp; pg);
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">synchronize</span></tt> function is a collective operation that must be
+invoked by all of the processes within the process group. A call to
+<tt class="docutils literal"><span class="pre">synchronize</span></tt> marks the end of a superstep in the parallel
+computation. All messages sent before the end of the superstep will be
+received into message buffers, and can be processed by the program in
+the next superstep. None of the processes will leave the
+<tt class="docutils literal"><span class="pre">synchronize</span></tt> function until all of the processes have entered the
+function and exchanged messages, so that all processes are always on
+the same superstep.</p>
+</div>
+<div class="section" id="out-of-band-communication">
+<h2><a class="toc-backref" href="#id13">Out-of-band communication</a></h2>
+<pre class="literal-block">
+template&lt;typename T&gt;
+ void send_oob(const ProcessGroup&amp; pg, int dest, int tag, const T&amp; value);
+</pre>
+<p>Sends and out-of-band message. This out-of-band send operation acts
+like the normal <tt class="docutils literal"><span class="pre">send</span></tt> operation, except that out-of-band messages
+are delivered immediately through a high-priority channel.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename T, typename U&gt;
+ void
+ send_oob_with_reply(const ProcessGroup&amp; pg, int dest, int
+ tag, const T&amp; send_value, U&amp; receive_value);
+</pre>
+<p>Sends an out-of-band message and waits for a reply. The
+<tt class="docutils literal"><span class="pre">send_oob_with_reply</span></tt> function can only be invoked with message tags
+that correspond to triggers registered with
+<tt class="docutils literal"><span class="pre">trigger_with_reply</span></tt>. This operation will send the message
+immediately (through the high-priority, out-of-band channel), then
+wait until the remote process sends a reply. The data from the reply
+is stored into <tt class="docutils literal"><span class="pre">receive_value</span></tt>.</p>
+<hr class="docutils" />
+<pre class="literal-block">
+template&lt;typename T&gt;
+ void receive_oob(const ProcessGroup&amp; pg, int source, int tag, T&amp; value);
+</pre>
+<p>Receives an out-of-band message with the given <tt class="docutils literal"><span class="pre">source</span></tt> and
+<tt class="docutils literal"><span class="pre">tag</span></tt>. As with the normal <tt class="docutils literal"><span class="pre">receive</span></tt> operation, it is an error to
+call <tt class="docutils literal"><span class="pre">receive_oob</span></tt> if no message matching the source and tag is
+available. This routine is used only rarely; for most circumstances,
+use <tt class="docutils literal"><span class="pre">send_oob_with_reply</span></tt> to perform an immediate send with a
+reply.</p>
+<hr class="docutils" />
+<p>Copyright (C) 2007 Douglas Gregor</p>
+<p>Copyright (C) 2007 Matthias Troyer</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:13 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/rmat_generator.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/rmat_generator.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL R-MAT generator</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-r-mat-generator">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> R-MAT generator</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+ template&lt;typename RandomGenerator, typename Graph&gt;
+ class rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair&lt;vertices_size_type, vertices_size_type&gt; value_type;
+ typedef const value_type&amp; reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ rmat_iterator();
+ rmat_iterator(RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+ // Iterator operations
+ reference operator*() const;
+ pointer operator-&gt;() const;
+ rmat_iterator&amp; operator++();
+ rmat_iterator operator++(int);
+ bool operator==(const rmat_iterator&amp; other) const;
+ bool operator!=(const rmat_iterator&amp; other) const;
+};
+</pre>
+<p>This class template implements a generator for R-MAT graphs <a class="citation-reference" href="#czf04" id="id1">[CZF04]</a>,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning.</p>
+<div class="section" id="where-defined">
+<h1>Where Defined</h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/rmat_graph_generator.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="constructors">
+<h1>Constructors</h1>
+<pre class="literal-block">
+rmat_iterator();
+</pre>
+<p>Constructs a past-the-end iterator.</p>
+<pre class="literal-block">
+rmat_iterator(RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+</pre>
+<p>Constructs an R-MAT generator iterator that creates a graph with <tt class="docutils literal"><span class="pre">n</span></tt>
+vertices and <tt class="docutils literal"><span class="pre">m</span></tt> edges. <tt class="docutils literal"><span class="pre">a</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, <tt class="docutils literal"><span class="pre">c</span></tt>, and <tt class="docutils literal"><span class="pre">d</span></tt> represent
+the probability that a generated edge is placed of each of the 4
+quadrants of the partitioned adjacency matrix. Probabilities are
+drawn from the random number generator gen. Vertex indices are
+permuted to eliminate locality when <tt class="docutils literal"><span class="pre">permute_vertices</span></tt> is true.</p>
+</div>
+<div class="section" id="example">
+<h1>Example</h1>
+<pre class="literal-block">
+#include &lt;boost/graph/adjacency_list.hpp&gt;
+#include &lt;boost/graph/rmat_graph_generator.hpp&gt;
+#include &lt;boost/random/linear_congruential.hpp&gt;
+
+typedef boost::adjacency_list&lt;&gt; Graph;
+typedef boost::rmat_iterator&lt;boost::minstd_rand, Graph&gt; RMATGen;
+
+int main()
+{
+ boost::minstd_rand gen;
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(gen, 100, 400, 0.57, 0.19, 0.19, 0.05), RMATGen(), 100);
+ return 0;
+}
+</pre>
+</div>
+<div class="section" id="bibliography">
+<h1>Bibliography</h1>
+<table class="docutils citation" frame="void" id="czf04" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[CZF04]</a></td><td>D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+Model for Graph Mining. In Proceedings of 4th International Conference
+on Data Mining, pages 442--446, 2004.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/scalable_rmat_generator.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/scalable_rmat_generator.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Scalable R-MAT generator</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-scalable-r-mat-generator">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Scalable R-MAT generator</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+ template&lt;typename ProcessGroup, typename Distribution,
+ typename RandomGenerator, typename Graph&gt;
+ class scalable_rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair&lt;vertices_size_type, vertices_size_type&gt; value_type;
+ typedef const value_type&amp; reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ scalable_rmat_iterator();
+ scalable_rmat_iterator(ProcessGroup pg, Distribution distrib,
+ RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+
+ // Iterator operations
+ reference operator*() const;
+ pointer operator-&gt;() const;
+ scalable_rmat_iterator&amp; operator++();
+ scalable_rmat_iterator operator++(int);
+ bool operator==(const scalable_rmat_iterator&amp; other) const;
+ bool operator!=(const scalable_rmat_iterator&amp; other) const;
+};
+</pre>
+<p>This class template implements a generator for R-MAT graphs <a class="citation-reference" href="#czf04" id="id1">[CZF04]</a>,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning.</p>
+<div class="section" id="where-defined">
+<h1>Where Defined</h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/rmat_graph_generator.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="constructors">
+<h1>Constructors</h1>
+<pre class="literal-block">
+scalable_rmat_iterator();
+</pre>
+<p>Constructs a past-the-end iterator.</p>
+<pre class="literal-block">
+scalable_rmat_iterator(ProcessGroup pg, Distribution distrib,
+ RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+</pre>
+<p>Constructs an R-MAT generator iterator that creates a graph with <tt class="docutils literal"><span class="pre">n</span></tt>
+vertices and <tt class="docutils literal"><span class="pre">m</span></tt> edges. Inside the <tt class="docutils literal"><span class="pre">scalable_rmat_iterator</span></tt>
+processes communicate using <tt class="docutils literal"><span class="pre">pg</span></tt> to generate their local edges as
+defined by <tt class="docutils literal"><span class="pre">distrib</span></tt>. <tt class="docutils literal"><span class="pre">a</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, <tt class="docutils literal"><span class="pre">c</span></tt>, and <tt class="docutils literal"><span class="pre">d</span></tt> represent the
+probability that a generated edge is placed of each of the 4 quadrants
+of the partitioned adjacency matrix. Probabilities are drawn from the
+random number generator <tt class="docutils literal"><span class="pre">gen</span></tt>. Vertex indices are permuted to
+eliminate locality when <tt class="docutils literal"><span class="pre">permute_vertices</span></tt> is true.</p>
+</div>
+<div class="section" id="example">
+<h1>Example</h1>
+<pre class="literal-block">
+#include &lt;boost/graph/distributed/mpi_process_group.hpp&gt;
+#include &lt;boost/graph/compressed_sparse_row_graph.hpp&gt;
+#include &lt;boost/graph/rmat_graph_generator.hpp&gt;
+#include &lt;boost/random/linear_congruential.hpp&gt;
+
+using boost::graph::distributed::mpi_process_group;
+
+typedef compressed_sparse_row_graph&lt;directedS, no_property, no_property, no_property,
+ distributedS&lt;mpi_process_group&gt; &gt; Graph;
+typedef boost::scalable_rmat_iterator&lt;boost::minstd_rand, Graph&gt; RMATGen;
+
+int main()
+{
+ boost::minstd_rand gen;
+ mpi_process_group pg;
+
+ int N = 100;
+
+ boost::parallel::variant_distribution&lt;ProcessGroup&gt; distrib
+ = boost::parallel::block(pg, N);
+
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(pg, distrib, gen, N, 400, 0.57, 0.19, 0.19, 0.05),
+ RMATGen(), N, pg, distrib);
+ return 0;
+}
+</pre>
+</div>
+<div class="section" id="bibliography">
+<h1>Bibliography</h1>
+<table class="docutils citation" frame="void" id="czf04" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[CZF04]</a></td><td>D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+Model for Graph Mining. In Proceedings of 4th International Conference
+on Data Mining, pages 442--446, 2004.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds, Brian Barrett, and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/simple_trigger.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/simple_trigger.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Simple Triggers</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-simple-triggers">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Simple Triggers</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#introduction" id="id1">Introduction</a></li>
+<li><a class="reference internal" href="#where-defined" id="id2">Where Defined</a></li>
+<li><a class="reference internal" href="#reference" id="id3">Reference</a></li>
+</ul>
+</div>
+<div class="section" id="introduction">
+<h1><a class="toc-backref" href="#id1">Introduction</a></h1>
+<p>Triggers in the <a class="reference external" href="process_group.html">process group</a> interface are used to asynchronously
+receive and process messages destined for distributed data
+structures. The trigger interface is relatively versatile, permitting
+one to attach any function object to handle requests. The
+<tt class="docutils literal"><span class="pre">simple_trigger</span></tt> function simplifies a common case for triggers:
+attaching a trigger that invokes a specific member function of the
+distributed data structure.</p>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id2">Where Defined</a></h1>
+<p>Header <tt class="docutils literal"><span class="pre">&lt;boost/graph/parallel/simple_trigger.hpp&gt;</span></tt></p>
+</div>
+<div class="section" id="reference">
+<h1><a class="toc-backref" href="#id3">Reference</a></h1>
+<blockquote>
+<pre class="literal-block">
+template&lt;typename ProcessGroup, typename Class, typename T&gt;
+ void
+ simple_trigger(ProcessGroup&amp; pg, int tag, Class* self,
+ void (Class::*pmf)(int source, int tag, const T&amp; data,
+ trigger_receive_context context))
+
+template&lt;typename ProcessGroup, typename Class, typename T, typename Result&gt;
+ void
+ simple_trigger(ProcessGroup&amp; pg, int tag, Class* self,
+ Result (Class::*pmf)(int source, int tag, const T&amp; data,
+ trigger_receive_context context))
+</pre>
+</blockquote>
+<p>The <tt class="docutils literal"><span class="pre">simple_trigger</span></tt> function registers a trigger that invokes the
+given member function (<tt class="docutils literal"><span class="pre">pmf</span></tt>) on the object <tt class="docutils literal"><span class="pre">self</span></tt> whenever a
+message is received. If the member function has a return value, then
+the trigger has a reply, and can only be used via out-of-band sends
+that expect a reply. Otherwise, the member function returns <tt class="docutils literal"><span class="pre">void</span></tt>,
+and the function is registered as a normal trigger.</p>
+<hr class="docutils" />
+<p>Copyright (C) 2007 Douglas Gregor</p>
+<p>Copyright (C) 2007 Matthias Troyer</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/sorted_rmat_generator.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/sorted_rmat_generator.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Sorted R-MAT generator</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-sorted-r-mat-generator">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Sorted R-MAT generator</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+ template&lt;typename RandomGenerator, typename Graph,
+ typename EdgePredicate = keep_all_edges&gt;
+ class sorted_rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair&lt;vertices_size_type, vertices_size_type&gt; value_type;
+ typedef const value_type&amp; reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ sorted_rmat_iterator();
+ sorted_rmat_iterator(RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+ // Iterator operations
+ reference operator*() const;
+ pointer operator-&gt;() const;
+ sorted_rmat_iterator&amp; operator++();
+ sorted_rmat_iterator operator++(int);
+ bool operator==(const sorted_rmat_iterator&amp; other) const;
+ bool operator!=(const sorted_rmat_iterator&amp; other) const;
+};
+</pre>
+<p>This class template implements a generator for R-MAT graphs <a class="citation-reference" href="#czf04" id="id1">[CZF04]</a>,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning. The output of this generator is sorted
+for use with <a class="reference external" href="http://www.boost.org/libs/graph/doc/compressed_sparse_row.html">compressed sparse row graph</a>.</p>
+<div class="section" id="where-defined">
+<h1>Where Defined</h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/rmat_graph_generator.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="constructors">
+<h1>Constructors</h1>
+<pre class="literal-block">
+sorted_rmat_iterator();
+</pre>
+<p>Constructs a past-the-end iterator.</p>
+<pre class="literal-block">
+sorted_rmat_iterator(RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true,
+ EdgePredicate ep = keep_all_edges());
+</pre>
+<p>Constructs an R-MAT generator iterator that creates a graph with <tt class="docutils literal"><span class="pre">n</span></tt>
+vertices and <tt class="docutils literal"><span class="pre">m</span></tt> edges. <tt class="docutils literal"><span class="pre">a</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, <tt class="docutils literal"><span class="pre">c</span></tt>, and <tt class="docutils literal"><span class="pre">d</span></tt> represent
+the probability that a generated edge is placed of each of the 4
+quadrants of the partitioned adjacency matrix. Probabilities are
+drawn from the random number generator <tt class="docutils literal"><span class="pre">gen</span></tt>. Vertex indices are
+permuted to eliminate locality when <tt class="docutils literal"><span class="pre">permute_vertices</span></tt> is true.
+<tt class="docutils literal"><span class="pre">ep</span></tt> allows the user to specify which edges are retained, this is
+useful in the case where the user wishes to refrain from storing
+remote edges locally during generation to reduce memory consumption.</p>
+</div>
+<div class="section" id="example">
+<h1>Example</h1>
+<pre class="literal-block">
+#include &lt;boost/graph/compressed_sparse_row_graph.hpp&gt;
+#include &lt;boost/graph/rmat_graph_generator.hpp&gt;
+#include &lt;boost/random/linear_congruential.hpp&gt;
+
+typedef boost::compressed_sparse_row_graph&lt;&gt; Graph;
+typedef boost::sorted_rmat_iterator&lt;boost::minstd_rand, Graph&gt;
+ RMATGen;
+
+int main()
+{
+ boost::minstd_rand gen;
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(gen, 100, 400, 0.57, 0.19, 0.19, 0.05),
+ RMATGen(), 100);
+ return 0;
+}
+</pre>
+</div>
+<div class="section" id="bibliography">
+<h1>Bibliography</h1>
+<table class="docutils citation" frame="void" id="czf04" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[CZF04]</a></td><td>D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+Model for Graph Mining. In Proceedings of 4th International Conference
+on Data Mining, pages 442--446, 2004.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/sorted_unique_rmat_generator.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/sorted_unique_rmat_generator.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Sorted unique R-MAT generator</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-sorted-unique-r-mat-generator">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Sorted unique R-MAT generator</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+ template&lt;typename RandomGenerator, typename Graph,
+ typename EdgePredicate = keep_all_edges&gt;
+ class sorted_unique_rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair&lt;vertices_size_type, vertices_size_type&gt; value_type;
+ typedef const value_type&amp; reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ sorted_unique_rmat_iterator();
+ sorted_unique_rmat_iterator(RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool bidirectional = true,
+ bool permute_vertices = true,
+ EdgePredicate ep = keep_all_edges());
+ // Iterator operations
+ reference operator*() const;
+ pointer operator-&gt;() const;
+ sorted_unique_rmat_iterator&amp; operator++();
+ sorted_unique_rmat_iterator operator++(int);
+ bool operator==(const sorted_unique_rmat_iterator&amp; other) const;
+ bool operator!=(const sorted_unique_rmat_iterator&amp; other) const;
+};
+</pre>
+<p>This class template implements a generator for R-MAT graphs <a class="citation-reference" href="#czf04" id="id1">[CZF04]</a>,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning. The output of this generator is sorted
+for use with a <a class="reference external" href="http://www.boost.org/libs/graph/doc/compressed_sparse_row.html">compressed sparse row graph</a>. The edge list produced by
+this iterator is guaranteed not to contain parallel edges.</p>
+<div class="section" id="where-defined">
+<h1>Where Defined</h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/rmat_graph_generator.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="constructors">
+<h1>Constructors</h1>
+<pre class="literal-block">
+sorted_unique_rmat_iterator();
+</pre>
+<p>Constructs a past-the-end iterator.</p>
+<pre class="literal-block">
+sorted_unique_rmat_iterator(RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool bidirectional = false,
+ bool permute_vertices = true,
+ EdgePredicate ep = keep_all_edges());
+</pre>
+<p>Constructs an R-MAT generator iterator that creates a graph with <tt class="docutils literal"><span class="pre">n</span></tt>
+vertices and <tt class="docutils literal"><span class="pre">m</span></tt> edges. <tt class="docutils literal"><span class="pre">a</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, <tt class="docutils literal"><span class="pre">c</span></tt>, and <tt class="docutils literal"><span class="pre">d</span></tt> represent
+the probability that a generated edge is placed of each of the 4
+quadrants of the partitioned adjacency matrix. Probabilities are
+drawn from the random number generator <tt class="docutils literal"><span class="pre">gen</span></tt>. Vertex indices are
+permuted to eliminate locality when <tt class="docutils literal"><span class="pre">permute_vertices</span></tt> is true.
+When <tt class="docutils literal"><span class="pre">bidirectional</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for every edge s-t, the
+corresponding anti-edge t-s is added as well, these anti-edges are not
+counted towards <tt class="docutils literal"><span class="pre">m</span></tt>. <tt class="docutils literal"><span class="pre">ep</span></tt> allows the user to specify which edges
+are retained, this is useful in the case where the user wishes to
+refrain from storing remote edges locally during generation to reduce
+memory consumption.</p>
+</div>
+<div class="section" id="example">
+<h1>Example</h1>
+<pre class="literal-block">
+#include &lt;boost/graph/distributed/mpi_process_group.hpp&gt;
+#include &lt;boost/graph/compressed_sparse_row_graph.hpp&gt;
+#include &lt;boost/graph/rmat_graph_generator.hpp&gt;
+#include &lt;boost/random/linear_congruential.hpp&gt;
+
+using boost::graph::distributed::mpi_process_group;
+
+typedef compressed_sparse_row_graph&lt;directedS, no_property, no_property, no_property,
+ distributedS&lt;mpi_process_group&gt; &gt; Graph;
+typedef keep_local_edges&lt;boost::parallel::variant_distribution&lt;mpi_process_group&gt;,
+ mpi_process_group::process_id_type&gt; EdgeFilter;
+typedef boost::sorted_unique_rmat_iterator&lt;boost::minstd_rand, Graph&gt; RMATGen;
+
+int main()
+{
+ boost::minstd_rand gen;
+ mpi_process_group pg;
+
+ int N = 100;
+
+ boost::parallel::variant_distribution&lt;ProcessGroup&gt; distrib
+ = boost::parallel::block(pg, N);
+
+ mpi_process_group::process_id_type id = process_id(pg);
+
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(gen, N, 400, 0.57, 0.19, 0.19, 0.05, true,
+ true, EdgeFilter(distrib, id)),
+ RMATGen(), N, pg, distrib);
+ return 0;
+}
+</pre>
+</div>
+<div class="section" id="bibliography">
+<h1>Bibliography</h1>
+<table class="docutils citation" frame="void" id="czf04" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[CZF04]</a></td><td>D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+Model for Graph Mining. In Proceedings of 4th International Conference
+on Data Mining, pages 442--446, 2004.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/ssca_generator.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/ssca_generator.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL SSCA Generator</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-ssca-generator">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> SSCA Generator</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<p>Generator from the Scalable Synthetic Compact Application #2 Graph Analysis benchmark.</p>
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/st_connected.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/st_connected.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL s-t Connectivity</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-s-t-connectivity">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> s-t Connectivity</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/strong_components.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/strong_components.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Connected Components</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-connected-components">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Connected Components</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+template&lt;typename Graph, typename ComponentMap&gt;
+inline typename property_traits&lt;ComponentMap&gt;::value_type
+strong_components( const Graph&amp; g, ComponentMap c);
+
+namespace graph {
+ template&lt;typename Graph, typename VertexComponentMap&gt;
+ void
+ fleischer_hendrickson_pinar_strong_components(const Graph&amp; g, VertexComponentMap r);
+
+ template&lt;typename Graph, typename ReverseGraph,
+ typename ComponentMap, typename IsoMapFR, typename IsoMapRF&gt;
+ inline typename property_traits&lt;ComponentMap&gt;::value_type
+ fleischer_hendrickson_pinar_strong_components(const Graph&amp; g,
+ ComponentMap c,
+ const ReverseGraph&amp; gr,
+ IsoMapFR fr, IsoMapRF rf);
+}
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">strong_components()</span></tt> function computes the strongly connected
+components of a directed graph. The distributed strong components
+algorithm uses the <a class="reference external" href="http://www.boost.org/libs/graph/doc/strong_components.html">sequential strong components</a> algorithm to
+identify components local to a processor. The distributed portion of
+the algorithm is built on the <a class="reference external" href="breadth_first_search.html">distributed breadth first search</a>
+algorithm and is based on the work of Fleischer, Hendrickson, and
+Pinar <a class="citation-reference" href="#fhp00" id="id1">[FHP00]</a>. The interface is a superset of the interface to the
+BGL <a class="reference external" href="http://www.boost.org/libs/graph/doc/strong_components.html">sequential strong components</a> algorithm. The number of
+strongly-connected components in the graph is returned to all
+processes.</p>
+<p>The distributed strong components algorithm works on both <tt class="docutils literal"><span class="pre">directed</span></tt>
+and <tt class="docutils literal"><span class="pre">bidirectional</span></tt> graphs. In the bidirectional case, a reverse
+graph adapter is used to produce the required reverse graph. In
+the directed case, a separate graph is constructed in which all the
+edges are reversed.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id2">Where Defined</a></li>
+<li><a class="reference internal" href="#parameters" id="id3">Parameters</a></li>
+<li><a class="reference internal" href="#complexity" id="id4">Complexity</a></li>
+<li><a class="reference internal" href="#algorithm-description" id="id5">Algorithm Description</a></li>
+<li><a class="reference internal" href="#bibliography" id="id6">Bibliography</a></li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id2">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/strong_components.hpp</span></tt>&gt;</p>
+<p>also accessible from</p>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/strong_components.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="parameters">
+<h1><a class="toc-backref" href="#id3">Parameters</a></h1>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">const</span> <span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph type must be a model of <a class="reference external" href="DistributedGraph.html">Distributed Graph</a>. The graph
+type must also model the <a class="reference external" href="http://www.boost.org/libs/graph/doc/IncidenceGraph.html">Incidence Graph</a> and be directed.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">ComponentMap</span> <span class="pre">c</span></tt></dt>
+<dd>The algorithm computes how many strongly connected components are in the
+graph, and assigns each component an integer label. The algorithm
+then records to which component each vertex in the graph belongs by
+recording the component number in the component property map. The
+<tt class="docutils literal"><span class="pre">ComponentMap</span></tt> type must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a>. The
+value type must be the <tt class="docutils literal"><span class="pre">vertices_size_type</span></tt> of the graph. The key
+type must be the graph's vertex descriptor type.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">VertexComponentMap</span> <span class="pre">r</span></tt></dt>
+<dd>The algorithm computes a mapping from each vertex to the
+representative of the strong component, stored in this property map.
+The <tt class="docutils literal"><span class="pre">VertexComponentMap</span></tt> type must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a>.
+The value and key types must be the vertex descriptor of the graph.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">const</span> <span class="pre">ReverseGraph&amp;</span> <span class="pre">gr</span></tt></dt>
+<dd><p class="first">The reverse (or transpose) graph of <tt class="docutils literal"><span class="pre">g</span></tt>, such that for each
+directed edge <em>(u, v)</em> in <tt class="docutils literal"><span class="pre">g</span></tt> there exists a directed edge
+<em>(fr(v), fr(u))</em> in <tt class="docutils literal"><span class="pre">gr</span></tt> and for each edge <em>(v', u')</em> in <em>gr</em>
+there exists an edge <em>(rf(u'), rf(v'))</em> in <tt class="docutils literal"><span class="pre">g</span></tt>. The functions
+<em>fr</em> and <em>rf</em> map from vertices in the graph to the reverse graph
+and vice-verse, and are represented as property map arguments. The
+concept requirements on this graph type are equivalent to those on
+the <tt class="docutils literal"><span class="pre">Graph</span></tt> type, but the types need not be the same.</p>
+<p class="last"><strong>Default</strong>: Either a <tt class="docutils literal"><span class="pre">reverse_graph</span></tt> adaptor over the original
+graph (if the graph type is bidirectional, i.e., models the
+<a class="reference external" href="http://www.boost.org/libs/graph/doc/BidirectionalGraph.html">Bidirectional Graph</a> concept) or a <a class="reference external" href="distributed_adjacency_list.html">distributed adjacency list</a>
+constructed from the input graph.</p>
+</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">IsoMapFR</span> <span class="pre">fr</span></tt></dt>
+<dd><p class="first">A property map that maps from vertices in the input graph <tt class="docutils literal"><span class="pre">g</span></tt> to
+vertices in the reversed graph <tt class="docutils literal"><span class="pre">gr</span></tt>. The type <tt class="docutils literal"><span class="pre">IsoMapFR</span></tt> must
+model the <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable Property Map</a> concept and have the graph's
+vertex descriptor as its key type and the reverse graph's vertex
+descriptor as its value type.</p>
+<p class="last"><strong>Default</strong>: An identity property map (if the graph type is
+bidirectional) or a distributed <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> (if the
+graph type is directed).</p>
+</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">IsoMapRF</span> <span class="pre">rf</span></tt></dt>
+<dd><p class="first">A property map that maps from vertices in the reversed graph <tt class="docutils literal"><span class="pre">gr</span></tt>
+to vertices in the input graph <tt class="docutils literal"><span class="pre">g</span></tt>. The type <tt class="docutils literal"><span class="pre">IsoMapRF</span></tt> must
+model the <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable Property Map</a> concept and have the reverse
+graph's vertex descriptor as its key type and the graph's vertex
+descriptor as its value type.</p>
+<p class="last"><strong>Default</strong>: An identity property map (if the graph type is
+bidirectional) or a distributed <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> (if the
+graph type is directed).</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="complexity">
+<h1><a class="toc-backref" href="#id4">Complexity</a></h1>
+<p>The local phase of the algorithm is <em>O(V + E)</em>. The parallel phase of
+the algorithm requires at most <em>O(V)</em> supersteps each containing two
+breadth first searches which are <em>O(V + E)</em> each.</p>
+</div>
+<div class="section" id="algorithm-description">
+<h1><a class="toc-backref" href="#id5">Algorithm Description</a></h1>
+<p>Prior to executing the sequential phase of the algorithm, each process
+identifies any completely local strong components which it labels and
+removes from the vertex set considered in the parallel phase of the
+algorithm.</p>
+<p>The parallel phase of the distributed strong components algorithm
+consists of series of supersteps. Each superstep starts with one
+or more vertex sets which are guaranteed to completely contain
+any remaining strong components. A <a class="reference external" href="breadth_first_search.html">distributed breadth first search</a>
+is performed starting from the first vertex in each vertex set.
+All of these breadth first searches are performed in parallel by having
+each processor call <tt class="docutils literal"><span class="pre">breadth_first_search()</span></tt> with a different starting
+vertex, and if necessary inserting additional vertices into the
+<tt class="docutils literal"><span class="pre">distributed</span> <span class="pre">queue</span></tt> used for breadth first search before invoking
+the algorithm. A second <a class="reference external" href="breadth_first_search.html">distributed breadth first search</a> is
+performed on the reverse graph in the same fashion. For each initial
+vertex set, the successor set (the vertices reached in the forward
+breadth first search), and the predecessor set (the vertices reached
+in the backward breadth first search) is computed. The intersection
+of the predecessor and successor sets form a strongly connected
+component which is labeled as such. The remaining vertices in the
+initial vertex set are partitioned into three subsets each guaranteed
+to completely contain any remaining strong components. These three sets
+are the vertices in the predecessor set not contained in the identified
+strongly connected component, the vertices in the successor set not
+in the strongly connected component, and the remaing vertices in the
+initial vertex set not in the predecessor or successor sets. Once
+new vertex sets are identified, the algorithm begins a new superstep.
+The algorithm halts when no vertices remain.</p>
+<p>To boost performance in sparse graphs when identifying small components,
+when less than a given portion of the initial number of vertices
+remain in active vertex sets, a filtered graph adapter is used
+to limit the graph seen by the breadth first search algorithm to the
+active vertices.</p>
+</div>
+<div class="section" id="bibliography">
+<h1><a class="toc-backref" href="#id6">Bibliography</a></h1>
+<table class="docutils citation" frame="void" id="fhp00" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[FHP00]</a></td><td>Lisa Fleischer, Bruce Hendrickson, and Ali Pinar. On
+Identifying Strongly Connected Components in Parallel. In Parallel and
+Distributed Processing (IPDPS), volume 1800 of Lecture Notes in
+Computer Science, pages 505--511, 2000. Springer.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2004, 2005 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds, Douglas Gregor, and Andrew Lumsdaine</p>
+<!-- -->
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/tsin_depth_first_visit.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/tsin_depth_first_visit.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Depth-First Visit</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-depth-first-visit">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Depth-First Visit</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+template&lt;typename DistributedGraph, typename DFSVisitor&gt;
+void
+depth_first_visit(const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ DFSVisitor vis);
+
+namespace graph {
+ template&lt;typename DistributedGraph, typename DFSVisitor,
+ typename VertexIndexMap&gt;
+ void
+ tsin_depth_first_visit(const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ DFSVisitor vis);
+
+ template&lt;typename DistributedGraph, typename DFSVisitor,
+ typename VertexIndexMap&gt;
+ void
+ tsin_depth_first_visit(const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ DFSVisitor vis, VertexIndexMap index_map);
+
+ template&lt;typename DistributedGraph, typename ColorMap, typename ParentMap,
+ typename ExploreMap, typename NextOutEdgeMap, typename DFSVisitor&gt;
+ void
+ tsin_depth_first_visit(const DistributedGraph&amp; g,
+ typename graph_traits&lt;DistributedGraph&gt;::vertex_descriptor s,
+ DFSVisitor vis, ColorMap color, ParentMap parent, ExploreMap explore,
+ NextOutEdgeMap next_out_edge);
+}
+</pre>
+<p>The <tt class="docutils literal"><span class="pre">depth_first_visit()</span></tt> function performs a distributed
+depth-first traversal of an undirected graph using Tsin's corrections
+<a class="citation-reference" href="#tsin02" id="id1">[Tsin02]</a> to Cidon's algorithm <a class="citation-reference" href="#cidon88" id="id2">[Cidon88]</a>. The distributed DFS is
+syntactically similar to its <a class="reference external" href="http://www.boost.org/libs/graph/doc/depth_first_visit.html">sequential counterpart</a>, which provides
+additional background and discussion. Differences in semantics are
+highlighted here, and we refer the reader to the documentation of the
+<a class="reference external" href="http://www.boost.org/libs/graph/doc/depth_first_visit.html">sequential depth-first search</a> for the remainder of the
+details. Visitors passed to depth-first search need to account for the
+distribution of vertices across processes, because events will be
+triggered on certain processes but not others. See the section
+<a class="reference internal" href="#visitor-event-points">Visitor Event Points</a> for details.</p>
+<div class="section" id="where-defined">
+<h1>Where Defined</h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/depth_first_search.hpp</span></tt>&gt;</p>
+<p>also available in</p>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/depth_first_search.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="parameters">
+<h1>Parameters</h1>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">const</span> <span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph type must be a model of <a class="reference external" href="DistributedGraph.html">Distributed Graph</a>. The graph
+must be undirected.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">vertex_descriptor</span> <span class="pre">s</span></tt></dt>
+<dd>The start vertex must be the same in every process.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">DFSVisitor</span> <span class="pre">vis</span></tt></dt>
+<dd>The visitor must be a distributed DFS visitor. The suble differences
+between sequential and distributed DFS visitors are discussed in the
+section <a class="reference internal" href="#visitor-event-points">Visitor Event Points</a>.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">VertexIndexMap</span> <span class="pre">map</span></tt></dt>
+<dd><p class="first">A model of <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable Property Map</a> whose key type is the vertex
+descriptor type of the graph <tt class="docutils literal"><span class="pre">g</span></tt> and whose value type is an
+integral type. The property map should map from vertices to their
+(local) indices in the range <em>[0, num_vertices(g))</em>.</p>
+<p class="last"><strong>Default</strong>: <tt class="docutils literal"><span class="pre">get(vertex_index,</span> <span class="pre">g)</span></tt></p>
+</dd>
+<dt>UTIL/OUT: <tt class="docutils literal"><span class="pre">ColorMap</span> <span class="pre">color</span></tt></dt>
+<dd><p class="first">The color map must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> with the same
+process group as the graph <tt class="docutils literal"><span class="pre">g</span></tt> whose colors must monotonically
+darken (white -&gt; gray -&gt; black).</p>
+<p class="last"><strong>Default</strong>: A distributed <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> created from a
+<tt class="docutils literal"><span class="pre">std::vector</span></tt> of <tt class="docutils literal"><span class="pre">default_color_type</span></tt>.</p>
+</dd>
+<dt>UTIL/OUT: <tt class="docutils literal"><span class="pre">ParentMap</span> <span class="pre">parent</span></tt></dt>
+<dd><p class="first">The parent map must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> with the same
+process group as the graph <tt class="docutils literal"><span class="pre">g</span></tt> whose key and values types are the
+same as the vertex descriptor type of the graph <tt class="docutils literal"><span class="pre">g</span></tt>. This
+property map holds the parent of each vertex in the depth-first
+search tree.</p>
+<p class="last"><strong>Default</strong>: A distributed <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> created from a
+<tt class="docutils literal"><span class="pre">std::vector</span></tt> of the vertex descriptor type of the graph.</p>
+</dd>
+<dt>UTIL: <tt class="docutils literal"><span class="pre">ExploreMap</span> <span class="pre">explore</span></tt></dt>
+<dd><p class="first">The explore map must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> with the same
+process group as the graph <tt class="docutils literal"><span class="pre">g</span></tt> whose key and values types are the
+same as the vertex descriptor type of the graph <tt class="docutils literal"><span class="pre">g</span></tt>.</p>
+<p class="last"><strong>Default</strong>: A distributed <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> created from a
+<tt class="docutils literal"><span class="pre">std::vector</span></tt> of the vertex descriptor type of the graph.</p>
+</dd>
+<dt>UTIL: <tt class="docutils literal"><span class="pre">NextOutEdgeMap</span> <span class="pre">next_out_edge</span></tt></dt>
+<dd><p class="first">The next out-edge map must be a <a class="reference external" href="distributed_property_map.html">Distributed Property Map</a> with the
+same process group as the graph <tt class="docutils literal"><span class="pre">g</span></tt> whose key type is the vertex
+descriptor of the graph <tt class="docutils literal"><span class="pre">g</span></tt> and whose value type is the
+<tt class="docutils literal"><span class="pre">out_edge_iterator</span></tt> type of the graph. It is used internally to
+keep track of the next edge that should be traversed from each
+vertex.</p>
+<p class="last"><strong>Default</strong>: A distributed <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> created from a
+<tt class="docutils literal"><span class="pre">std::vector</span></tt> of the <tt class="docutils literal"><span class="pre">out_edge_iterator</span></tt> type of the graph.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="complexity">
+<h1>Complexity</h1>
+<p>Depth-first search is inherently sequential, so parallel speedup is
+very poor. Regardless of the number of processors, the algorithm will
+not be faster than <em>O(V)</em>; see <a class="citation-reference" href="#tsin02" id="id3">[Tsin02]</a> for more details.</p>
+</div>
+<div class="section" id="visitor-event-points">
+<h1>Visitor Event Points</h1>
+<p>The <a class="reference external" href="http://www.boost.org/libs/graph/doc/DFSVisitor.html">DFS Visitor</a> concept defines 8 event points that will be
+triggered by the <a class="reference external" href="http://www.boost.org/libs/graph/doc/depth_first_visit.html">sequential depth-first search</a>. The distributed
+DFS retains these event points, but the sequence of events
+triggered and the process in which each event occurs will change
+depending on the distribution of the graph.</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">initialize_vertex(s,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by every process for each local vertex.</dd>
+<dt><tt class="docutils literal"><span class="pre">discover_vertex(u,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked each time a process discovers a new vertex
+<tt class="docutils literal"><span class="pre">u</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">examine_vertex(u,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by the process owning the vertex <tt class="docutils literal"><span class="pre">u</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">examine_edge(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>This will be invoked by the process owning the source vertex of
+<tt class="docutils literal"><span class="pre">e</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">tree_edge(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>Similar to <tt class="docutils literal"><span class="pre">examine_edge</span></tt>, this will be invoked by the process
+owning the source vertex and may be invoked only once.</dd>
+<dt><tt class="docutils literal"><span class="pre">back_edge(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>Some edges that would be forward or cross edges in the sequential
+DFS may be detected as back edges by the distributed DFS, so extra
+<tt class="docutils literal"><span class="pre">back_edge</span></tt> events may be received.</dd>
+<dt><tt class="docutils literal"><span class="pre">forward_or_cross_edge(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>Some edges that would be forward or cross edges in the sequential
+DFS may be detected as back edges by the distributed DFS, so fewer
+<tt class="docutils literal"><span class="pre">forward_or_cross_edge</span></tt> events may be received in the distributed
+algorithm than in the sequential case.</dd>
+<dt><tt class="docutils literal"><span class="pre">finish_vertex(e,</span> <span class="pre">g)</span></tt></dt>
+<dd>See documentation for <tt class="docutils literal"><span class="pre">examine_vertex</span></tt>.</dd>
+</dl>
+<div class="section" id="making-visitors-safe-for-distributed-dfs">
+<h2>Making Visitors Safe for Distributed DFS</h2>
+<p>The three most important things to remember when updating an existing
+DFS visitor for distributed DFS or writing a new distributed DFS
+visitor are:</p>
+<ol class="arabic simple">
+<li>Be sure that all state is either entirely local or in a
+distributed data structure (most likely a property map!) using
+the same process group as the graph.</li>
+<li>Be sure that the visitor doesn't require precise event sequences
+that cannot be guaranteed by distributed DFS, e.g., requiring
+<tt class="docutils literal"><span class="pre">back_edge</span></tt> and <tt class="docutils literal"><span class="pre">forward_or_cross_edge</span></tt> events to be completely
+distinct.</li>
+<li>Be sure that the visitor can operate on incomplete
+information. This often includes using an appropriate reduction
+operation in a <a class="reference external" href="distributed_property_map.html">distributed property map</a> and verifying that
+results written are &quot;better&quot; that what was previously written.</li>
+</ol>
+</div>
+</div>
+<div class="section" id="bibliography">
+<h1>Bibliography</h1>
+<table class="docutils citation" frame="void" id="cidon88" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2">[Cidon88]</a></td><td>Isreal Cidon. Yet another distributed depth-first-search
+algorithm. Information Processing Letters, 26(6):301--305, 1988.</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="tsin02" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[Tsin02]</td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id3">2</a>)</em> Y. H. Tsin. Some remarks on distributed depth-first
+search. Information Processing Letters, 82(4):173--178, 2002.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2005 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/unique_rmat_generator.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/unique_rmat_generator.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Unique R-MAT generator</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-unique-r-mat-generator">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Unique R-MAT generator</h1>
+
+<!-- Copyright (C) 2004-2009 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+ template&lt;typename RandomGenerator, typename Graph&gt;
+ class unique_rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair&lt;vertices_size_type, vertices_size_type&gt; value_type;
+ typedef const value_type&amp; reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ unique_rmat_iterator();
+ unique_rmat_iterator(RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+ // Iterator operations
+ reference operator*() const;
+ pointer operator-&gt;() const;
+ unique_rmat_iterator&amp; operator++();
+ unique_rmat_iterator operator++(int);
+ bool operator==(const unique_rmat_iterator&amp; other) const;
+ bool operator!=(const unique_rmat_iterator&amp; other) const;
+};
+</pre>
+<p>This class template implements a generator for R-MAT graphs <a class="citation-reference" href="#czf04" id="id1">[CZF04]</a>,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning. The edge list produced by this iterator
+is guaranteed not to contain parallel edges.</p>
+<div class="section" id="where-defined">
+<h1>Where Defined</h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/rmat_graph_generator.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="constructors">
+<h1>Constructors</h1>
+<pre class="literal-block">
+unique_rmat_iterator();
+</pre>
+<p>Constructs a past-the-end iterator.</p>
+<pre class="literal-block">
+unique_rmat_iterator(RandomGenerator&amp; gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true,
+ EdgePredicate ep = keep_all_edges());
+</pre>
+<p>Constructs an R-MAT generator iterator that creates a graph with <tt class="docutils literal"><span class="pre">n</span></tt>
+vertices and <tt class="docutils literal"><span class="pre">m</span></tt> edges. <tt class="docutils literal"><span class="pre">a</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, <tt class="docutils literal"><span class="pre">c</span></tt>, and <tt class="docutils literal"><span class="pre">d</span></tt> represent
+the probability that a generated edge is placed of each of the 4
+quadrants of the partitioned adjacency matrix. Probabilities are
+drawn from the random number generator <tt class="docutils literal"><span class="pre">gen</span></tt>. Vertex indices are
+permuted to eliminate locality when <tt class="docutils literal"><span class="pre">permute_vertices</span></tt> is true.
+<tt class="docutils literal"><span class="pre">ep</span></tt> allows the user to specify which edges are retained, this is
+useful in the case where the user wishes to refrain from storing
+remote edges locally during generation to reduce memory consumption.</p>
+</div>
+<div class="section" id="example">
+<h1>Example</h1>
+<pre class="literal-block">
+#include &lt;boost/graph/adjacency_list.hpp&gt;
+#include &lt;boost/graph/rmat_graph_generator.hpp&gt;
+#include &lt;boost/random/linear_congruential.hpp&gt;
+
+typedef boost::adjacency_list&lt;&gt; Graph;
+typedef boost::unique_rmat_iterator&lt;boost::minstd_rand, Graph&gt; RMATGen;
+
+int main()
+{
+ boost::minstd_rand gen;
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(gen, 100, 400, 0.57, 0.19, 0.19, 0.05,),
+ RMATGen(), 100);
+ return 0;
+}
+</pre>
+</div>
+<div class="section" id="bibliography">
+<h1>Bibliography</h1>
+<table class="docutils citation" frame="void" id="czf04" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1">[CZF04]</a></td><td>D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+Model for Graph Mining. In Proceedings of 4th International Conference
+on Data Mining, pages 442--446, 2004.</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<p>Copyright (C) 2009 The Trustees of Indiana University.</p>
+<p>Authors: Nick Edmonds and Andrew Lumsdaine</p>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:13 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/html/vertex_list_adaptor.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/html/vertex_list_adaptor.html 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>Parallel BGL Vertex List Graph Adaptor</title>
+<link rel="stylesheet" href="rst.css" type="text/css" />
+</head>
+<body>
+<div class="document" id="logo-vertex-list-graph-adaptor">
+<h1 class="title"><a class="reference external" href="http://www.osl.iu.edu/research/pbgl"><img align="middle" alt="Parallel BGL" class="align-middle" src="http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png" /></a> Vertex List Graph Adaptor</h1>
+
+<!-- Copyright (C) 2004-2008 The Trustees of Indiana University.
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) -->
+<pre class="literal-block">
+template&lt;typename Graph, typename GlobalIndexMap&gt;
+class vertex_list_adaptor
+{
+public:
+ vertex_list_adaptor(const Graph&amp; g,
+ const GlobalIndexMap&amp; index_map = GlobalIndexMap());
+};
+
+template&lt;typename Graph, typename GlobalIndexMap&gt;
+vertex_list_adaptor&lt;Graph, GlobalIndexMap&gt;
+make_vertex_list_adaptor(const Graph&amp; g, const GlobalIndexMap&amp; index_map);
+
+template&lt;typename Graph&gt;
+vertex_list_adaptor&lt;Graph, *unspecified*&gt;
+make_vertex_list_adaptor(const Graph&amp; g);
+</pre>
+<p>The vertex list graph adaptor adapts any model of <a class="reference external" href="DistributedVertexListGraph.html">Distributed Vertex List
+Graph</a> in a <a class="reference external" href="http://www.boost.org/libs/graph/doc/VertexListGraph.html">Vertex List Graph</a>. In the former type of graph, the
+set of vertices is distributed across the process group, so no
+process has access to all vertices. In the latter type of graph,
+however, every process has access to every vertex in the graph. This
+is required by some distributed algorithms, such as the
+implementations of <a class="reference external" href="dehne_gotz_min_spanning_tree.html">Minimum spanning tree</a> algorithms.</p>
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#where-defined" id="id1">Where Defined</a></li>
+<li><a class="reference internal" href="#class-template-vertex-list-adaptor" id="id2">Class template <tt class="docutils literal"><span class="pre">vertex_list_adaptor</span></tt></a></li>
+<li><a class="reference internal" href="#function-templates-make-vertex-list-adaptor" id="id3">Function templates <tt class="docutils literal"><span class="pre">make_vertex_list_adaptor</span></tt></a><ul>
+<li><a class="reference internal" href="#parameters" id="id4">Parameters</a></li>
+<li><a class="reference internal" href="#complexity" id="id5">Complexity</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="where-defined">
+<h1><a class="toc-backref" href="#id1">Where Defined</a></h1>
+<p>&lt;<tt class="docutils literal"><span class="pre">boost/graph/distributed/vertex_list_adaptor.hpp</span></tt>&gt;</p>
+</div>
+<div class="section" id="class-template-vertex-list-adaptor">
+<h1><a class="toc-backref" href="#id2">Class template <tt class="docutils literal"><span class="pre">vertex_list_adaptor</span></tt></a></h1>
+<p>The <tt class="docutils literal"><span class="pre">vertex_list_adaptor</span></tt> class template takes a <a class="reference external" href="DistributedVertexListGraph.html">Distributed
+Vertex List Graph</a> and a mapping from vertex descriptors to global
+vertex indices, which must be in the range <em>[0, n)</em>, where <em>n</em> is the
+number of vertices in the entire graph. The mapping is a <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable
+Property Map</a> whose key type is a vertex descriptor.</p>
+<p>The vertex list adaptor stores only a reference to the underlying
+graph, forwarding all operations not related to the vertex list on to
+the underlying graph. For instance, if the underlying graph models
+<a class="reference external" href="http://www.boost.org/libs/graph/doc/AdjacencyGraph.html">Adjacency Graph</a>, then the adaptor will also model <a class="reference external" href="http://www.boost.org/libs/graph/doc/AdjacencyGraph.html">Adjacency
+Graph</a>. Note, however, that no modifications to the underlying graph
+can occur through the vertex list adaptor. Modifications made to the
+underlying graph directly will be reflected in the vertex list
+adaptor, but modifications that add or remove vertices invalidate the
+vertex list adaptor. Additionally, the vertex list adaptor provides
+access to the global index map via the <tt class="docutils literal"><span class="pre">vertex_index</span></tt> property.</p>
+<p>On construction, the vertex list adaptor performs an all-gather
+operation to create a list of all vertices in the graph within each
+process. It is this list that is accessed via <em>vertices</em> and the
+length of this list that is accessed via <em>num_vertices</em>. Due to the
+all-gather operation, the creation of this adaptor is a collective
+operation.</p>
+</div>
+<div class="section" id="function-templates-make-vertex-list-adaptor">
+<h1><a class="toc-backref" href="#id3">Function templates <tt class="docutils literal"><span class="pre">make_vertex_list_adaptor</span></tt></a></h1>
+<p>These function templates construct a vertex list adaptor from a graph
+and, optionally, a property map that maps vertices to global index
+numbers.</p>
+<div class="section" id="parameters">
+<h2><a class="toc-backref" href="#id4">Parameters</a></h2>
+<dl class="docutils">
+<dt>IN: <tt class="docutils literal"><span class="pre">Graph&amp;</span> <span class="pre">g</span></tt></dt>
+<dd>The graph type must be a model of <a class="reference external" href="DistributedVertexListGraph.html">Distributed Vertex List Graph</a>.</dd>
+<dt>IN: <tt class="docutils literal"><span class="pre">GlobalIndexMap</span> <span class="pre">index_map</span></tt></dt>
+<dd><p class="first">A <a class="reference external" href="distributed_property_map.html">Distributed property map</a> whose type must model <a class="reference external" href="http://www.boost.org/libs/property_map/ReadablePropertyMap.html">Readable
+property map</a> that maps from vertices to a global index. If
+provided, this map must be initialized prior to be passed to the
+vertex list adaptor.</p>
+<p class="last"><strong>Default:</strong> A property map of unspecified type constructed from a
+distributed <tt class="docutils literal"><span class="pre">iterator_property_map</span></tt> that uses the
+<tt class="docutils literal"><span class="pre">vertex_index</span></tt> property map of the underlying graph and a vector
+of <tt class="docutils literal"><span class="pre">vertices_size_type</span></tt>.</p>
+</dd>
+</dl>
+</div>
+<div class="section" id="complexity">
+<h2><a class="toc-backref" href="#id5">Complexity</a></h2>
+<p>These operations require <em>O(n)</em> time, where <em>n</em> is the number of
+vertices in the graph, and <em>O(n)</em> communication per node in the BSP model.</p>
+<hr class="docutils" />
+<p>Copyright (C) 2004 The Trustees of Indiana University.</p>
+<p>Authors: Douglas Gregor and Andrew Lumsdaine</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+Generated on: 2009-04-11 01:12 UTC.
+Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>

Added: trunk/libs/graph_parallel/doc/index.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/index.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,156 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===================================
+|Logo| Parallel Boost Graph Library
+===================================
+
+Overview
+--------
+
+The Parallel Boost Graph Library is an extension to the `Boost Graph
+Library`_ (BGL) for parallel and distributed computing. It offers
+distributed graphs and graph algorithms to exploit coarse-grained
+parallelism along with parallel algorithms that exploit fine-grained
+parallelism, while retaining the same interfaces as the (sequential)
+BGL. Code written using the sequential BGL should be easy to
+parallelize with the parallel BGL. Visitors new to the Parallel BGL
+should read our `architectural overview`_.
+
+1. `Process groups`_
+
+ - `MPI process group`_
+ - `Simple trigger interface`_
+
+2. Auxiliary data structures
+
+ - `Distributed queue`_
+ - `Distributed property map`_
+
+3. Distributed graph concepts
+
+ - `Distributed Graph`_
+ - `Distributed Vertex List Graph`_
+ - `Distributed Edge List Graph`_
+ - `Global Descriptor`_
+
+4. Graph data structures
+
+ - `Distributed adjacency list`_
+
+5. Graph adaptors
+
+ - `Local subgraph adaptor`_
+ - `Vertex list graph adaptor`_
+
+6. Graph input/output
+
+ - Graphviz output
+ - `METIS input`_
+
+7. Synthetic data generators
+
+ - `R-MAT generator`_
+ - `Sorted R-MAT generator`_
+ - `Unique R-MAT generator`_
+ - `Scalable R-MAT generator`_
+ - `Erdos-Renyi generator`_
+ - `Sorted Erdos-Renyi generator`_
+ - `Small world generator`_
+ - `SSCA generator`_
+ - `Mesh generator`_
+
+8. Algorithms
+
+ - Distributed algorithms
+
+ - `Breadth-first search`_
+ - `Dijkstra's single-source shortest paths`_
+
+ - `Eager Dijkstra shortest paths`_
+ - `Crauser et al. Dijkstra shortest paths`_
+ - `Delta-Stepping shortest paths`_
+
+ - `Depth-first search`_
+ - `Minimum spanning tree`_
+
+ - `Boruvka's minimum spanning tree`_
+ - `Merging local minimum spanning forests`_
+ - `Boruvka-then-merge`_
+ - `Boruvka-mixed-merge`_
+
+ - Connected components
+
+ - `Connected components`_
+ - `Connected components parallel search`_
+ - `Strongly-connected components`_
+
+ - PageRank_
+ - `Boman et al. Graph coloring`_
+ - `Fruchterman Reingold force-directed layout`_
+ - `s-t connectivity`_
+ - `Betweenness centrality`_
+
+----------------------------------------------------------------------------
+
+Copyright (C) 2005-2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds, Douglas Gregor, and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Parallel Dijkstra example: dijkstra_example.html
+.. _Boost Graph Library: http://www.boost.org/libs/graph/doc
+.. _adjacency_list: http://www.boost.org/libs/graph/doc/adjacency_list.html
+.. _local subgraph adaptor: local_subgraph.html
+.. _vertex list graph adaptor: vertex_list_adaptor.html
+.. _MPI: http://www-unix.mcs.anl.gov/mpi/
+.. _generic programming: http://www.cs.rpi.edu/~musser/gp/
+.. _development page: design/index.html
+.. _process groups: process_group.html
+.. _MPI process group: process_group.html
+.. _Simple trigger interface: simple_trigger.html
+.. _Open Systems Laboratory: http://www.osl.iu.edu
+.. _Indiana University: http://www.indiana.edu
+.. _Distributed adjacency list: distributed_adjacency_list.html
+.. _Distributed queue: distributed_queue.html
+.. _Distributed property map: distributed_property_map.html
+.. _R-MAT generator: rmat_generator.html
+.. _Sorted R-MAT generator: sorted_rmat_generator.html
+.. _Unique R-MAT generator: unique_rmat_generator.html
+.. _Scalable R-MAT generator: scalable_rmat_generator.html
+.. _Erdos-Renyi generator: http://www.boost.org/libs/graph/doc/erdos_renyi_generator.html
+.. _Sorted Erdos-Renyi generator: http://www.boost.org/libs/graph/doc/sorted_erdos_renyi_gen.html
+.. _Small world generator: http://www.boost.org/libs/graph/doc/small_world_generator.html
+.. _SSCA generator: ssca_generator.html
+.. _Mesh generator: mesh_generator.html
+.. _Breadth-first search: breadth_first_search.html
+.. _Depth-first search: tsin_depth_first_visit.html
+.. _Dijkstra's single-source shortest paths: dijkstra_shortest_paths.html
+.. _Eager Dijkstra shortest paths: dijkstra_shortest_paths.html#eager-dijkstra-s-algorithm
+.. _Crauser et al. Dijkstra shortest paths: dijkstra_shortest_paths.html#crauser-et-al-s-algorithm
+.. _Delta-Stepping shortest paths: dijkstra_shortest_paths.html#delta-stepping-algorithm
+.. _Minimum spanning tree: dehne_gotz_min_spanning_tree.html
+.. _Boruvka's minimum spanning tree: dehne_gotz_min_spanning_tree.html#dense-boruvka-minimum-spanning-tree
+.. _Merging local minimum spanning forests: dehne_gotz_min_spanning_tree.html#merge-local-minimum-spanning-trees
+.. _Boruvka-then-merge: dehne_gotz_min_spanning_tree.html#boruvka-then-merge
+.. _Boruvka-mixed-merge: dehne_gotz_min_spanning_tree.html#boruvka-mixed-merge
+.. _PageRank: page_rank.html
+.. _Boman et al. Graph coloring: boman_et_al_graph_coloring.html
+.. _Connected components: connected_components.html
+.. _Connected components parallel search: connected_components_parallel_search.html
+.. _Strongly-connected components: strong_components.html
+.. _Distributed Graph: DistributedGraph.html
+.. _Distributed Vertex List Graph: DistributedVertexListGraph.html
+.. _Distributed Edge List Graph: DistributedEdgeListGraph.html
+.. _Global Descriptor: GlobalDescriptor.html
+.. _METIS Input: metis.html
+.. _architectural overview: overview.html
+.. _Fruchterman Reingold force-directed layout: fruchterman_reingold.html
+.. _s-t connectivity: st_connected.html
+.. _Betweenness centrality: betweenness_centrality.html

Added: trunk/libs/graph_parallel/doc/local_subgraph.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/local_subgraph.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,69 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+=============================
+|Logo| Local Subgraph Adaptor
+=============================
+
+The local subgraph adaptor takes an existing `Distributed Graph` and
+filters out all of the nonlocal edges and vertices, presenting only
+the local portion of the distributed graph to the user. The behavior
+is equivalent to (and implemented with) a `filtered graph`_, and is a
+noncopying view into the graph itself. Changes made through the
+filtered graph will be reflected in the original graph and vice-versa.
+
+::
+
+ template<typename DistributedGraph> class local_subgraph;
+
+ template<typename DistributedGraph>
+ local_subgraph<DistributedGraph> make_local_subgraph(DistributedGraph& g);
+
+Where Defined
+-------------
+<boost/graph/distributed/local_subgraph.hpp>
+
+Reference
+---------
+The local subgraph adaptor adapts and forwards all operations of
+distributed graphs, the signatures of which will be omitted. Only
+operations unique to the local subgraph adaptor are presented.
+
+Member Functions
+~~~~~~~~~~~~~~~~
+
+::
+
+ local_subgraph(DistributedGraph& g);
+
+Constructs a local subgraph presenting the local portion of the
+distributed graph ``g``.
+
+--------------------------------------------------------------------------
+
+::
+
+ DistributedGraph& base() { return g; }
+ const DistributedGraph& base() const { return g; }
+
+Returns the underlying distributed graph.
+
+Free Functions
+~~~~~~~~~~~~~~
+
+::
+
+ template<typename DistributedGraph>
+ local_subgraph<DistributedGraph> make_local_subgraph(DistributedGraph& g);
+
+Constructs a local subgraph presenting the local portion of the
+distributed graph ``g``.
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _filtered graph: http://www.boost.org/libs/graph/doc/filtered_graph.html

Added: trunk/libs/graph_parallel/doc/mesh_generator.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/mesh_generator.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,20 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===========================
+|Logo| Mesh Generator
+===========================
+
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl

Added: trunk/libs/graph_parallel/doc/metis.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/metis.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,320 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+=========================================
+|Logo| METIS Input Routines
+=========================================
+
+::
+
+ namespace boost {
+ namespace graph {
+ class metis_reader;
+ class metis_exception;
+ class metis_input_exception;
+ class metis_distribution;
+ }
+ }
+
+
+METIS_ is a set of programs for partitioning graphs (among other
+things). The Parallel BGL can read the METIS graph format and
+partition format, allowing one to easily load METIS-partitioned
+graphs into the Parallel BGL's data structures.
+
+.. contents::
+
+Where Defined
+~~~~~~~~~~~~~
+<``boost/graph/metis.hpp``>
+
+
+Graph Reader
+------------------
+
+::
+
+ class metis_reader
+ {
+ public:
+ typedef std::size_t vertices_size_type;
+ typedef std::size_t edges_size_type;
+ typedef double vertex_weight_type;
+ typedef double edge_weight_type;
+
+ class edge_iterator;
+ class edge_weight_iterator;
+
+ metis_reader(std::istream& in);
+
+ edge_iterator begin();
+ edge_iterator end();
+ edge_weight_iterator weight_begin();
+
+ vertices_size_type num_vertices() const;
+ edges_size_type num_edges() const;
+
+ std::size_t num_vertex_weights() const;
+
+ vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n);
+
+ bool has_edge_weights() const;
+ };
+
+
+Usage
+~~~~~
+
+The METIS reader provides an iterator interface to the METIS graph
+file. The iterator interface is most useful when constructing Parallel
+BGL graphs on-the-fly. For instance, the following code builds a graph
+``g`` from a METIS graph stored in ``argv[1]``.
+
+::
+
+ std::ifstream in_graph(argv[1]);
+ metis_reader reader(in_graph);
+ Graph g(reader.begin(), reader.end(),
+ reader.weight_begin(),
+ reader.num_vertices());
+
+
+The calls to ``begin()`` and ``end()`` return an iterator range for
+the edges in the graph; the call to ``weight_begin()`` returns an
+iterator that will enumerate the weights of the edges in the
+graph. For a distributed graph, the distribution will be determined
+automatically by the graph; to use a METIS partitioning, see the
+section `Partition Reader`_.
+
+Associated Types
+~~~~~~~~~~~~~~~~
+
+::
+
+ metis_reader::edge_iterator
+
+An `Input Iterator`_ that enumerates the edges in the METIS graph, and
+is suitable for use as the ``EdgeIterator`` of an adjacency_list_.
+The ``value_type`` of this iterator is a pair of vertex numbers.
+
+-----------------------------------------------------------------------------
+
+::
+
+ metis_reader::edge_weight_iterator
+
+An `Input Iterator`_ that enumerates the edge weights in the METIS
+graph. The ``value_type`` of this iterator is ``edge_weight_type``. If
+the edges in the METIS graph are unweighted, the result of
+dereferencing this iterator will always be zero.
+
+Member Functions
+~~~~~~~~~~~~~~~~
+
+::
+
+ metis_reader(std::istream& in);
+
+Constructs a new METIS reader that will retrieve edges from the input
+stream ``in``. If any errors are encountered while initially parsing
+``in``, ``metis_input_exception`` will be thrown.
+
+-----------------------------------------------------------------------------
+
+::
+
+ edge_iterator begin();
+
+Returns an iterator to the first edge in the METIS file.
+
+-----------------------------------------------------------------------------
+
+::
+
+ edge_iterator end();
+
+Returns an iterator one past the last edge in the METIS file.
+
+-----------------------------------------------------------------------------
+
+::
+
+ edge_weight_iterator weight_begin();
+
+Returns an iterator to the first edge weight in the METIS file. The
+weight iterator should be moved in concert with the edge iterator;
+when the edge iterator moves, the edge weight changes. If the edges
+in the graph are unweighted, the weight returned will always be zero.
+
+-----------------------------------------------------------------------------
+
+::
+
+ vertices_size_type num_vertices() const;
+
+Returns the number of vertices in the graph.
+
+
+-----------------------------------------------------------------------------
+
+::
+
+ edges_size_type num_edges() const;
+
+Returns the number of edges in the graph.
+
+-----------------------------------------------------------------------------
+
+::
+
+ std::size_t num_vertex_weights() const;
+
+Returns the number of weights attached to each vertex.
+
+-----------------------------------------------------------------------------
+
+::
+
+ vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n);
+
+-----------------------------------------------------------------------------
+
+::
+
+ bool has_edge_weights() const;
+
+Returns ``true`` when the edges of the graph have weights, ``false``
+otherwise. When ``false``, the edge weight iterator is still valid
+but returns zero for the weight of each edge.
+
+
+Partition Reader
+----------------
+
+::
+
+ class metis_distribution
+ {
+ public:
+ typedef int process_id_type;
+ typedef std::size_t size_type;
+
+ metis_distribution(std::istream& in, process_id_type my_id);
+
+ size_type block_size(process_id_type id, size_type) const;
+ process_id_type operator()(size_type n);
+ size_type local(size_type n) const;
+ size_type global(size_type n) const;
+ size_type global(process_id_type id, size_type n) const;
+
+ private:
+ std::istream& in;
+ process_id_type my_id;
+ std::vector<process_id_type> vertices;
+ };
+
+
+Usage
+~~~~~
+
+The class ``metis_distribution`` loads a METIS partition file and
+makes it available as a Distribution suitable for use with the
+`distributed adjacency list`_ graph type. To load a METIS graph using
+a METIS partitioning, use a ``metis_reader`` object for the graph and
+a ``metis_distribution`` object for the distribution, as in the
+following example.
+
+::
+
+ std::ifstream in_graph(argv[1]);
+ metis_reader reader(in_graph);
+
+ std::ifstream in_partitions(argv[2]);
+ metis_distribution dist(in_partitions, process_id(pg));
+ Graph g(reader.begin(), reader.end(),
+ reader.weight_begin(),
+ reader.num_vertices(),
+ pg,
+ dist);
+
+In this example, ``argv[1]`` is the graph and ``argv[2]`` is the
+partition file generated by ``pmetis``. The ``dist`` object loads the
+partitioning information from the input stream it is given and uses
+that to distributed the adjacency list. Note that the input stream
+must be in the METIS partition file format and must have been
+partitioned for the same number of processes are there are in the
+process group ``pg``.
+
+Member Functions
+~~~~~~~~~~~~~~~~
+
+::
+
+ metis_distribution(std::istream& in, process_id_type my_id);
+
+Creates a new METIS distribution from the input stream
+``in``. ``my_id`` is the process ID of the current process in the
+process group over which the graph will be distributed.
+
+-----------------------------------------------------------------------------
+
+::
+
+ size_type block_size(process_id_type id, size_type) const;
+
+Returns the number of vertices to be stored in the process
+``id``. The second parameter, ``size_type``, is unused and may be any
+value.
+
+-----------------------------------------------------------------------------
+
+::
+
+ process_id_type operator()(size_type n);
+
+Returns the ID for the process that will store vertex number ``n``.
+
+-----------------------------------------------------------------------------
+
+::
+
+ size_type local(size_type n) const;
+
+Returns the local index of vertex number ``n`` within its owning
+process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ size_type global(size_type n) const;
+
+Returns the global index of the current processor's local vertex ``n``.
+
+-----------------------------------------------------------------------------
+
+
+::
+
+ size_type global(process_id_type id, size_type n) const;
+
+Returns the global index of the process ``id``'s local vertex ``n``.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. _METIS: http://www-users.cs.umn.edu/~karypis/metis/metis/
+.. _distributed adjacency list: distributed_adjacency_list.html
+.. _adjacency_list: http://www.boost.org/libs/graph/doc/adjacency_list.html
+.. _input iterator: http://www.sgi.com/tech/stl/InputIterator.html
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+

Added: trunk/libs/graph_parallel/doc/overview.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/overview.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,136 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===============================================
+An Overview of the Parallel Boost Graph Library
+===============================================
+
+.. image:: graph.png
+ :width: 206
+ :height: 184
+ :alt: An example graph
+ :align: right
+
+The Parallel Boost Graph Library (Parallel BGL) is a C++ library for
+parallel, distributed computation on graphs. The Parallel BGL contains
+distributed graph data structures, distributed graph algorithms,
+abstractions over the communication medium (such as MPI), and
+supporting data structures. A graph (also called a *network*) consists
+of a set of *vertices* and a set of relationships between vertices,
+called *edges*. The edges may be *undirected*, meaning that the
+relationship between vertices is mutual, e.g., "X is related to Y", or
+they can be *directed*, meaning that the relationship goes only one
+way, e.g., "X is the child of Y". The following figure illustrates a
+typical directed graph, where *a-i* are the vertices and the arrows
+represent edges.
+
+.. image:: distributed-graph.png
+ :width: 229
+ :height: 199
+ :alt: A distributed graph
+ :align: right
+
+The Parallel BGL is primarily concerned with *distributed*
+graphs. Distributed graphs are conceptually graphs, but their storage
+is spread across multiple processors. The following figure
+demonstrates a distributed version of the graph above, where the graph
+has been divided among three processors (represented by the grey
+rectangles). Edges in the graph may be either local (with both
+endpoints stored on the same processor) or remote (the target of the
+edge is stored on a different processor).
+
+The Parallel BGL is a generic library. At its core are *generic*
+distributed graph algorithms, which can operate on any distributed
+graph data structure provided that data structure meets certain
+requirements. For instance, the algorithm may need to enumerate the
+set of vertices stored on the current processor, enumerate the set of
+outgoing edges from a particular vertex, and determine on which
+processor the target of each edge resides. The graph algorithms in the
+Parallel BGL are also generic with respect to the *properties*
+attached to edges and vertices in a graph; for instance, the weight of
+each edge can be stored as part of the graph or allocated in a
+completely separate data structure.
+
+The genericity available in the algorithms of the Parallel BGL allows
+them to be applied to existing graph data structures. However, most
+users will instead be writing new code that takes advantage of the
+Parallel BGL. The Parallel BGL provides distributed graph data
+structures that meet the requirements of the Parallel BGL
+algorithms. The primary data structure is the `distributed adjacency
+list`_, which allows storage and manipulation of a (distributed)
+graph. The vertices in the graph are divided among the various
+processors, and each of the edges outgoing from a vertex are stored on
+the processor that "owns" (stores) that vertex. The following figure
+illustrates the distributed adjacency list representation.
+
+.. image:: dist-adjlist.png
+ :width: 446
+ :height: 154
+ :alt: A distributed adjacency list
+ :align: center
+
+.. image:: dist-pmap.png
+ :width: 271
+ :height: 175
+ :alt: A distributed property map
+ :align: right
+
+The `distributed adjacency list`_ distributes the structure of a graph
+over multiple processors. While graph structure is in important part
+of many graph problems, there are typically other properties attached
+to the vertices and edges, such as edge weights or the position of
+vertices within a grid. These properties are stored in *property
+maps*, which associate a single piece of data with each edge or vertex
+in a graph. Distributed property maps extend this notion to
+distributed computing, where properties are stored on the same
+processor as the vertex or edge. The following figure illustrates the
+distribution of a property map storing colors (white, gray, black) for
+each vertex. In addition to the storage for each vertex, the
+processors store some "ghost cells" that cache values actually stored
+on other processors, represented by the dashed boxes.
+
+Tying together all of the distributed data structures of the Parallel
+BGL are its process groups and distributed graph algorithms. Process
+groups coordinate the interactions between multiple processes and
+distributed data structures by abstracting the communication
+mechanism. The algorithms are typically written using the SPMD model
+(Single Program, Multiple Data) and interact with both the distributed
+data structures and the process group itself. At various points in the
+algorithm's execution, all processes execute a synchronization point,
+which allows all of the distributed data structures to ensure an
+appropriate degree of consistency across processes. The following
+diagram illustrates the communication patterns within the the
+execution of a distributed algorithm in the Parallel BGL. In
+particular, the diagram illustrates the distributed data structures
+used in a distributed breadth-first search, from the top-left and
+proceeding clockwise:
+
+ - a user-defined property map that tracks the distance from the
+ source vertex to all other vertices,
+
+ - an automatically-generated property map that tracks the "color"
+ of vertices in the (distributed) graph, to determine which
+ vertices have been seen before,
+
+ - a distributed queue, which coordinates the breadth-first search
+ and distributes new vertices to search, and
+
+ - a distributed graph, on which the breadth-first search is
+ operating.
+
+.. image:: architecture.png
+ :width: 485
+ :height: 410
+ :alt: Parallel Boost Graph Library architecture
+ :align: center
+
+----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. _Distributed adjacency list: distributed_adjacency_list.html
+.. _Process groups:
\ No newline at end of file

Added: trunk/libs/graph_parallel/doc/page_rank.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/page_rank.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,101 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===============
+|Logo| PageRank
+===============
+
+::
+
+ namespace graph {
+ template<typename Graph, typename RankMap, typename Done>
+ inline void
+ page_rank(const Graph& g, RankMap rank_map, Done done,
+ typename property_traits<RankMap>::value_type damping = 0.85);
+
+ template<typename Graph, typename RankMap>
+ inline void
+ page_rank(const Graph& g, RankMap rank_map);
+ }
+
+The ``page_rank`` algorithm computes the ranking of vertices in a
+graph, based on the connectivity of a directed graph [PBMW98]_. The
+idea of PageRank is based on a random model of a Web surfer, who
+starts a random web page and then either follows a link from that web
+page (choosing from the links randomly) or jumps to a completely
+different web page (not necessarily linked from the current
+page). The PageRank of each page is the probability of the random web
+surfer visiting that page.
+
+.. contents::
+
+Where Defined
+~~~~~~~~~~~~~
+<``boost/graph/distributed/page_rank.hpp``>
+
+also accessible from
+
+<``boost/graph/page_rank.hpp``>
+
+Parameters
+~~~~~~~~~~
+
+IN: ``Graph& g``
+ The graph type must be a model of `Distributed Vertex List Graph`_ and
+ `Distributed Edge List Graph`_. The graph must be directed.
+
+OUT: ``RankMap rank``
+ Stores the rank of each vertex. The type ``RankMap`` must model the
+ `Read/Write Property Map`_ concept and must be a `distributed
+ property map`_. Its key type must be the vertex descriptor of the
+ graph type and its value type must be a floating-point or rational
+ type.
+
+IN: ``Done done``
+ A function object that determines when the PageRank algorithm
+ should complete. It will be passed two parameters, the rank map and
+ a reference to the graph, and should return ``true`` when the
+ algorithm should terminate.
+
+ **Default**: ``graph::n_iterations(20)``
+
+IN: ``typename property_traits<RankMap>::value_type damping``
+ The damping factor is the probability that the Web surfer will
+ select an outgoing link from the current page instead of jumping to
+ a random page.
+
+ **Default**: 0.85
+
+Complexity
+~~~~~~~~~~
+Each iteration of PageRank requires *O((V + E)/p)* time on *p*
+processors and performs *O(V)* communication. The number of
+iterations is dependent on the input to the algorithm.
+
+Bibliography
+------------
+
+.. [PBMW98] Lawrence Page, Sergey Brin, Rajeev Motwani, and Terry
+ Winograd. The PageRank Citation Ranking: Bringing Order to the
+ Web. Technical report, Stanford Digital Library Technologies Project,
+ November 1998.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Distributed Vertex List Graph: DistributedVertexListGraph.html
+.. _Distributed Edge List Graph: DistributedEdgeListGraph.html
+.. _Distributed property map: distributed_property_map.html
+.. _Readable Property Map: http://www.boost.org/libs/property_map/ReadablePropertyMap.html
+.. _Read/Write Property Map: http://www.boost.org/libs/property_map/ReadWritePropertyMap.html
+

Added: trunk/libs/graph_parallel/doc/process_group.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/process_group.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,487 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+==================================
+|Logo| Parallel BGL Process Groups
+==================================
+
+.. contents::
+
+Introduction
+------------
+
+Process groups are an abstraction of a set of communicating processes
+that coordinate to solve the same problem. Process groups contain
+facilities for identifying the processes within that group, sending
+and receiving messages between the processes in that group, and
+performing collective communications involving all processes in the
+group simultaneously.
+
+Communication model
+-------------------
+
+Process groups are based on an extended version of the Bulk
+Synchronous Parallel (BSP) model of computation. Parallel computations
+in the BSP model are organized into *supersteps*, each of which
+consists of a computation phase followed by a communication
+phase. During the computation phase, all processes in the process
+group work exclusively on local data, and there is no inter-process
+communication. During the communication phase, all of the processes
+exchange message with each other. Messages sent in the communication
+phase of a superstep will be received in the next superstep.
+
+The boundary between supersteps in the Parallel BGL corresponds to the
+``synchronize`` operation. Whenever a process has completed its local
+computation phase and sent all of the messages required for that
+superstep, it invokes the ``synchronize`` operation on the process
+group. Once all processes in the process group have entered
+``synchronize``, they exchange messages and then continue with the
+next superstep.
+
+The Parallel BGL loosens the BSP model significantly, to provide a
+more natural programming model that also provides some performance
+benefits over the strict BSP model. The primary extension is the
+ability to receive messages sent within the same superstep
+"asynchronously", either to free up message buffers or to respond to
+an immediate request for information. For particularly unstructured
+computations, the ability to send a message and get an immediate reply
+can simplify many computations that would otherwise need to be split
+into two separate supersteps. Additionally, the Parallel BGL augments
+the BSP model with support for multiple distributed data structures,
+each of which are provided with a different communication space but
+whose messages will all be synchronized concurrently.
+
+Distributed data structures
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A typical computation with the Parallel BGL involves several
+distributed data structures working in concern. For example, a simple
+breadth-first search involves the distributed graph data structure
+containing the graph itself, a distributed queue that manages the
+traversal through the graph, and a distributed property map that
+tracks which vertices have already been visited as part of the
+search.
+
+The Parallel BGL manages these distributed data structures by allowing
+each of the data structures to attach themselves to the process group
+itself. When a distributed data structure attaches to the process
+group, it receives its own copy of the process group that allows the
+distributed data structure to communicate without colliding with the
+communications from other distributed data structures. When the
+process group is synchronized, all of the distributed data structures
+attached to that process group are automatically synchronized, so that
+all of the distributed data structures in a computation remain
+synchronized.
+
+A distributed data structure attaches itself to the process group by
+creating a copy of the process group and passing an
+``attach_distributed_object`` flag to the process group
+constructor. So long as this copy of the process group persists, the
+distributed data structure is attached the process group. For this
+reason, most distributed data structures keep a copy of the process
+group as member data, constructing the member with
+``attach_distributed_object``, e.g.,
+
+::
+
+ template<typename ProcessGroup>
+ struct distributed_data_structure
+ {
+ explicit distributed_data_structure(const ProcessGroup& pg)
+ : process_group(pg, boost::parallel::attach_distributed_object())
+ { }
+
+ private:
+ ProcessGroup process_group;
+ };
+
+
+Asynchronous receives
+~~~~~~~~~~~~~~~~~~~~~
+
+Distributed data structures in the Parallel BGL can "asynchronously"
+receive and process messages before the end of a BSP
+superstep. Messages can be received any time that a process is inside
+the process group operations, and the scheduling of message receives
+is entirely managed by the process group.
+
+Distributed data structures receive messages through
+"triggers". Triggers are function objects responsible for processing a
+received message. Each trigger is registered with the ``trigger``
+method of the process group using a specific message
+tag (an integer) and the type of data that is expected to be
+contained within that message. Whenever a message with that tag
+becomes available, the progress group will call the trigger with the
+source of the message, the message tag, the data contained in the
+message, and the "context" of the message.
+
+The majority of triggers have no return value, although it is common
+that the triggers send messages back to the source process. In certain
+cases where the trigger's purpose is to immediately reply with a
+value, the trigger should be registered with the
+``trigger_with_reply`` method and should return the value that will be
+sent back to the caller. The ``trigger_with_reply`` facility is only
+useful in conjunction with out-of-band messaging, discussed next.
+
+Out-of-band messaging
+~~~~~~~~~~~~~~~~~~~~~
+
+The majority of messages sent by the Parallel BGL are sent through the
+normal send operations, to be received in the next superstep or, in
+some cases, received "early" by a trigger. These messages are not
+time-sensitive, so they will be delivered whenever the process group
+processes them.
+
+Some messages, however, require immediate responses. For example, if a
+process needs to determine the current value associated with a vertex
+owned by another process, the first process must send a request to the
+second process and block while waiting for a response. For such
+messages, the Parallel BGL's process groups provide an out-of-band
+messaging mechanism. Out-of-band messages are transmitted immediately,
+with a much higher priority than other messages. The sending of
+out-of-band messages can be coupled with a receive operation that
+waits until the remote process has received the message and sent its
+reply. For example, in the following code the process sends a message
+containing the string ``name`` to process ``owner`` with tag
+``msg_get_descriptor_by_name`` via an out-of-band message. The
+receiver of that message will immediately deliver the message via a
+trigger, that returns the resulting value--a
+``vertex_descriptor``--that will be passed back to the process that
+initiated the communication. The full communication happens
+immediately, within the current superstep.
+
+::
+
+ std::string name;
+ vertex_descriptor descriptor;
+ send_oob_with_reply(process_group, owner, msg_get_descriptor_by_name,
+ name, descriptor);
+
+Reference
+---------
+
+The Parallel BGL process groups specify an interface that can be
+implemented by various communication subsystems. In this reference
+section, we use the placeholder type ``ProcessGroup`` to stand in for
+the various process group implementations that exist. There is only
+one implementation of the process group interface at this time:
+
+ - `MPI BSP process group`_
+
+::
+
+ enum trigger_receive_context {
+ trc_none,
+ trc_in_synchronization,
+ trc_early_receive,
+ trc_out_of_band
+ };
+
+ class ProcessGroup
+ {
+ // Process group constructors
+ ProcessGroup();
+ ProcessGroup(const ProcessGroup&, boost::parallel::attach_distributed_object);
+
+ // Triggers
+ template<typename Type, typename Handler>
+ void trigger(int tag, const Handler& handler);
+
+ template<typename Type, typename Handler>
+ void trigger_with_reply(int tag, const Handler& handler);
+
+ trigger_receive_context trigger_context() const;
+
+ // Helper operations
+ void poll();
+ ProcessGroup base() const;
+ };
+
+ // Process query
+ int process_id(const ProcessGroup&);
+ int num_processes(const ProcessGroup&);
+
+ // Message transmission
+ template<typename T>
+ void send(const ProcessGroup& pg, int dest, int tag, const T& value);
+
+ template<typename T>
+ void receive(const ProcessGroup& pg, int source, int tag, T& value);
+
+ optional<std::pair<int, int> > probe(const ProcessGroup& pg);
+
+ // Synchronization
+ void synchronize(const ProcessGroup& pg);
+
+ // Out-of-band communication
+ template<typename T>
+ void send_oob(const ProcessGroup& pg, int dest, int tag, const T& value);
+
+ template<typename T, typename U>
+ void
+ send_oob_with_reply(const ProcessGroup& pg, int dest, int
+ tag, const T& send_value, U& receive_value);
+
+ template<typename T>
+ void receive_oob(const ProcessGroup& pg, int source, int tag, T& value);
+
+
+Process group constructors
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ ProcessGroup();
+
+Constructs a new process group with a different communication space
+from any other process group.
+
+-----------------------------------------------------------------------------
+
+::
+
+ ProcessGroup(const ProcessGroup& pg, boost::parallel::attach_distributed_object);
+
+Attaches a new distributed data structure to the process group
+``pg``. The resulting process group can be used for communication
+within that new distributed data structure. When the newly-constructed
+process group is eventually destroyed, the distributed data structure
+is detached from the process group.
+
+Triggers
+~~~~~~~~
+
+::
+
+ template<typename Type, typename Handler>
+ void trigger(int tag, const Handler& handler);
+
+Registers a trigger with the given process group. The trigger will
+watch for messages with the given ``tag``. When such a message is
+available, it will be received into a value of type ``Type``, and the
+function object ``handler`` will be invoked with four parameters:
+
+source
+ The rank of the source process (an ``int``)
+
+tag
+ The tag used to send the message (also an ``int``)
+
+data:
+ The data transmitted with the message. The data will have the type
+ specified when the trigger was registered.
+
+context:
+ The context in which the trigger is executed. This will be a value of
+ type ``trigger_receive_context``, which stages whether the trigger
+ is being executed during synchronization, asynchronously in response
+ to an "early" receive (often to free up communication buffers), or
+ in response to an "out-of-band" message.
+
+Triggers can only be registered by process groups that result from
+attaching a distributed data structure. A trigger can be invoked in
+response to either a normal send operation or an out-of-band send
+operation. There is also a `simple trigger interface`_ for defining
+triggers in common cases.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template<typename Type, typename Handler>
+ void trigger_with_reply(int tag, const Handler& handler);
+
+Like the ``trigger`` method, registers a trigger with the given
+process group. The trigger will watch for messages with the given
+``tag``. When such a message is available, it will be received into a
+value of type ``Type`` and ``handler`` will be invoked, just as with a
+normal trigger. However, a trigger registered with
+``trigger_with_reply`` must return a value, which will be immediately
+sent back to the process that initiated the send resulting in this
+trigger. Thus, ``trigger_with_reply`` should only be used for messages
+that need immediate responses. These triggers can only be invoked via
+the out-of-band sends that wait for the reply, via
+``send_oob_with_reply``. There is also a `simple trigger interface`_
+for defining triggers in common cases.
+
+-----------------------------------------------------------------------------
+
+::
+
+ trigger_receive_context trigger_context() const;
+
+Retrieves the current context of the process group with respect to the
+invocation of triggers. When ``trc_none``, the process group is not
+currently invoking any triggers. Otherwise, this value describes in
+what context the currently executing trigger is being invoked.
+
+
+Helper operations
+~~~~~~~~~~~~~~~~~
+
+::
+
+ void poll();
+
+Permits the process group to receive any incomining messages,
+processing them via triggers. If you have a long-running computation
+that does not invoke any of the process group's communication
+routines, you should call ``poll`` occasionally to along incoming
+messages to be processed.
+
+-----------------------------------------------------------------------------
+
+::
+
+ ProcessGroup base() const;
+
+Retrieves the "base" process group for this process group, which is a
+copy of the underlying process group that does not reference any
+specific distributed data structure.
+
+Process query
+~~~~~~~~~~~~~
+
+::
+
+ int process_id(const ProcessGroup& pg);
+
+Retrieves the ID (or "rank") of the calling process within the process
+group. Process IDs are values in the range [0, ``num_processes(pg)``)
+that uniquely identify the process. Process IDs can be used to
+initiate communication with another process.
+
+-----------------------------------------------------------------------------
+
+::
+
+ int num_processes(const ProcessGroup& pg);
+
+Returns the number of processes within the process group.
+
+
+Message transmission
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ template<typename T>
+ void send(const ProcessGroup& pg, int dest, int tag, const T& value);
+
+Sends a message with the given ``tag`` and carrying the given
+``value`` to the process with ID ``dest`` in the given process
+group. All message sends are non-blocking, meaning that this send
+operation will not block while waiting for the communication to
+complete. There is no guarantee when the message will be received,
+except that it will become available to the destination process by the
+end of the superstep, in the collective call to ``synchronize``.
+
+Any type of value can be transmitted via ``send``, so long as it
+provides the appropriate functionality to be serialized with the
+Boost.Serialization library.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template<typename T>
+ void receive(const ProcessGroup& pg, int source, int tag, T& value);
+
+Receives a message with the given ``tag`` sent from the process
+``source``, updating ``value`` with the payload of the message. This
+receive operation can only receive messages sent within the previous
+superstep via the ``send`` operation. If no such message is available
+at the time ``receive`` is called, the program is ill-formed.
+
+-----------------------------------------------------------------------------
+
+::
+
+ optional<std::pair<int, int> > probe(const ProcessGroup& pg);
+
+Determines whether a message is available. The probe operation checks
+for any messages that were sent in the previous superstep but have not
+yet been received. If such a message exists, ``probe`` returns a
+(source, tag) pair describing the message. Otherwise, ``probe`` will
+return an empty ``boost::optional``.
+
+A typical use of ``probe`` is to continually probe for messages at the
+beginning of the superstep, receiving and processing those messages
+until no messages remain.
+
+
+Synchronization
+~~~~~~~~~~~~~~~
+
+::
+
+ void synchronize(const ProcessGroup& pg);
+
+The ``synchronize`` function is a collective operation that must be
+invoked by all of the processes within the process group. A call to
+``synchronize`` marks the end of a superstep in the parallel
+computation. All messages sent before the end of the superstep will be
+received into message buffers, and can be processed by the program in
+the next superstep. None of the processes will leave the
+``synchronize`` function until all of the processes have entered the
+function and exchanged messages, so that all processes are always on
+the same superstep.
+
+Out-of-band communication
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ template<typename T>
+ void send_oob(const ProcessGroup& pg, int dest, int tag, const T& value);
+
+Sends and out-of-band message. This out-of-band send operation acts
+like the normal ``send`` operation, except that out-of-band messages
+are delivered immediately through a high-priority channel.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template<typename T, typename U>
+ void
+ send_oob_with_reply(const ProcessGroup& pg, int dest, int
+ tag, const T& send_value, U& receive_value);
+
+Sends an out-of-band message and waits for a reply. The
+``send_oob_with_reply`` function can only be invoked with message tags
+that correspond to triggers registered with
+``trigger_with_reply``. This operation will send the message
+immediately (through the high-priority, out-of-band channel), then
+wait until the remote process sends a reply. The data from the reply
+is stored into ``receive_value``.
+
+-----------------------------------------------------------------------------
+
+::
+
+ template<typename T>
+ void receive_oob(const ProcessGroup& pg, int source, int tag, T& value);
+
+Receives an out-of-band message with the given ``source`` and
+``tag``. As with the normal ``receive`` operation, it is an error to
+call ``receive_oob`` if no message matching the source and tag is
+available. This routine is used only rarely; for most circumstances,
+use ``send_oob_with_reply`` to perform an immediate send with a
+reply.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2007 Douglas Gregor
+
+Copyright (C) 2007 Matthias Troyer
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _MPI BSP process group: mpi_bsp_process_group.html
+.. _Simple trigger interface: simple_trigger.html

Added: trunk/libs/graph_parallel/doc/rmat_generator.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/rmat_generator.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,104 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===================================
+|Logo| R-MAT generator
+===================================
+
+::
+
+ template<typename RandomGenerator, typename Graph>
+ class rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair<vertices_size_type, vertices_size_type> value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ rmat_iterator();
+ rmat_iterator(RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+ // Iterator operations
+ reference operator*() const;
+ pointer operator->() const;
+ rmat_iterator& operator++();
+ rmat_iterator operator++(int);
+ bool operator==(const rmat_iterator& other) const;
+ bool operator!=(const rmat_iterator& other) const;
+ };
+
+This class template implements a generator for R-MAT graphs [CZF04]_,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning.
+
+Where Defined
+-------------
+<``boost/graph/rmat_graph_generator.hpp``>
+
+Constructors
+------------
+
+::
+
+ rmat_iterator();
+
+Constructs a past-the-end iterator.
+
+::
+
+ rmat_iterator(RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+
+Constructs an R-MAT generator iterator that creates a graph with ``n``
+vertices and ``m`` edges. ``a``, ``b``, ``c``, and ``d`` represent
+the probability that a generated edge is placed of each of the 4
+quadrants of the partitioned adjacency matrix. Probabilities are
+drawn from the random number generator gen. Vertex indices are
+permuted to eliminate locality when ``permute_vertices`` is true.
+
+Example
+-------
+
+::
+
+ #include <boost/graph/adjacency_list.hpp>
+ #include <boost/graph/rmat_graph_generator.hpp>
+ #include <boost/random/linear_congruential.hpp>
+
+ typedef boost::adjacency_list<> Graph;
+ typedef boost::rmat_iterator<boost::minstd_rand, Graph> RMATGen;
+
+ int main()
+ {
+ boost::minstd_rand gen;
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(gen, 100, 400, 0.57, 0.19, 0.19, 0.05), RMATGen(), 100);
+ return 0;
+ }
+
+
+Bibliography
+------------
+
+.. [CZF04] D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+ Model for Graph Mining. In Proceedings of 4th International Conference
+ on Data Mining, pages 442--446, 2004.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl

Added: trunk/libs/graph_parallel/doc/scalable_rmat_generator.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/scalable_rmat_generator.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,123 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===================================
+|Logo| Scalable R-MAT generator
+===================================
+
+::
+
+ template<typename ProcessGroup, typename Distribution,
+ typename RandomGenerator, typename Graph>
+ class scalable_rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair<vertices_size_type, vertices_size_type> value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ scalable_rmat_iterator();
+ scalable_rmat_iterator(ProcessGroup pg, Distribution distrib,
+ RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+
+ // Iterator operations
+ reference operator*() const;
+ pointer operator->() const;
+ scalable_rmat_iterator& operator++();
+ scalable_rmat_iterator operator++(int);
+ bool operator==(const scalable_rmat_iterator& other) const;
+ bool operator!=(const scalable_rmat_iterator& other) const;
+ };
+
+This class template implements a generator for R-MAT graphs [CZF04]_,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning.
+
+Where Defined
+-------------
+<``boost/graph/rmat_graph_generator.hpp``>
+
+Constructors
+------------
+
+::
+
+ scalable_rmat_iterator();
+
+Constructs a past-the-end iterator.
+
+::
+
+ scalable_rmat_iterator(ProcessGroup pg, Distribution distrib,
+ RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+
+Constructs an R-MAT generator iterator that creates a graph with ``n``
+vertices and ``m`` edges. Inside the ``scalable_rmat_iterator``
+processes communicate using ``pg`` to generate their local edges as
+defined by ``distrib``. ``a``, ``b``, ``c``, and ``d`` represent the
+probability that a generated edge is placed of each of the 4 quadrants
+of the partitioned adjacency matrix. Probabilities are drawn from the
+random number generator ``gen``. Vertex indices are permuted to
+eliminate locality when ``permute_vertices`` is true.
+
+Example
+-------
+
+::
+
+ #include <boost/graph/distributed/mpi_process_group.hpp>
+ #include <boost/graph/compressed_sparse_row_graph.hpp>
+ #include <boost/graph/rmat_graph_generator.hpp>
+ #include <boost/random/linear_congruential.hpp>
+
+ using boost::graph::distributed::mpi_process_group;
+
+ typedef compressed_sparse_row_graph<directedS, no_property, no_property, no_property,
+ distributedS<mpi_process_group> > Graph;
+ typedef boost::scalable_rmat_iterator<boost::minstd_rand, Graph> RMATGen;
+
+ int main()
+ {
+ boost::minstd_rand gen;
+ mpi_process_group pg;
+
+ int N = 100;
+
+ boost::parallel::variant_distribution<ProcessGroup> distrib
+ = boost::parallel::block(pg, N);
+
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(pg, distrib, gen, N, 400, 0.57, 0.19, 0.19, 0.05),
+ RMATGen(), N, pg, distrib);
+ return 0;
+ }
+
+Bibliography
+------------
+
+.. [CZF04] D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+ Model for Graph Mining. In Proceedings of 4th International Conference
+ on Data Mining, pages 442--446, 2004.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds, Brian Barrett, and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Sequential connected components: http://www.boost.org/libs/graph/doc/connected_components.html

Added: trunk/libs/graph_parallel/doc/simple_trigger.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/simple_trigger.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,64 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+============================
+|Logo| Simple Triggers
+============================
+
+.. contents::
+
+Introduction
+------------
+
+Triggers in the `process group`_ interface are used to asynchronously
+receive and process messages destined for distributed data
+structures. The trigger interface is relatively versatile, permitting
+one to attach any function object to handle requests. The
+``simple_trigger`` function simplifies a common case for triggers:
+attaching a trigger that invokes a specific member function of the
+distributed data structure.
+
+Where Defined
+-------------
+
+Header ``<boost/graph/parallel/simple_trigger.hpp>``
+
+Reference
+---------
+
+ ::
+
+ template<typename ProcessGroup, typename Class, typename T>
+ void
+ simple_trigger(ProcessGroup& pg, int tag, Class* self,
+ void (Class::*pmf)(int source, int tag, const T& data,
+ trigger_receive_context context))
+
+ template<typename ProcessGroup, typename Class, typename T, typename Result>
+ void
+ simple_trigger(ProcessGroup& pg, int tag, Class* self,
+ Result (Class::*pmf)(int source, int tag, const T& data,
+ trigger_receive_context context))
+
+The ``simple_trigger`` function registers a trigger that invokes the
+given member function (``pmf``) on the object ``self`` whenever a
+message is received. If the member function has a return value, then
+the trigger has a reply, and can only be used via out-of-band sends
+that expect a reply. Otherwise, the member function returns ``void``,
+and the function is registered as a normal trigger.
+
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2007 Douglas Gregor
+
+Copyright (C) 2007 Matthias Troyer
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _process group: process_group.html

Added: trunk/libs/graph_parallel/doc/small_world_1_70_6_0p02.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/sorted_rmat_generator.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/sorted_rmat_generator.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,114 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===================================
+|Logo| Sorted R-MAT generator
+===================================
+
+::
+
+ template<typename RandomGenerator, typename Graph,
+ typename EdgePredicate = keep_all_edges>
+ class sorted_rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair<vertices_size_type, vertices_size_type> value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ sorted_rmat_iterator();
+ sorted_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+ // Iterator operations
+ reference operator*() const;
+ pointer operator->() const;
+ sorted_rmat_iterator& operator++();
+ sorted_rmat_iterator operator++(int);
+ bool operator==(const sorted_rmat_iterator& other) const;
+ bool operator!=(const sorted_rmat_iterator& other) const;
+ };
+
+This class template implements a generator for R-MAT graphs [CZF04]_,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning. The output of this generator is sorted
+for use with `compressed sparse row graph`_.
+
+Where Defined
+-------------
+<``boost/graph/rmat_graph_generator.hpp``>
+
+Constructors
+------------
+
+::
+
+ sorted_rmat_iterator();
+
+Constructs a past-the-end iterator.
+
+::
+
+
+ sorted_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true,
+ EdgePredicate ep = keep_all_edges());
+
+Constructs an R-MAT generator iterator that creates a graph with ``n``
+vertices and ``m`` edges. ``a``, ``b``, ``c``, and ``d`` represent
+the probability that a generated edge is placed of each of the 4
+quadrants of the partitioned adjacency matrix. Probabilities are
+drawn from the random number generator ``gen``. Vertex indices are
+permuted to eliminate locality when ``permute_vertices`` is true.
+``ep`` allows the user to specify which edges are retained, this is
+useful in the case where the user wishes to refrain from storing
+remote edges locally during generation to reduce memory consumption.
+
+Example
+-------
+
+::
+
+ #include <boost/graph/compressed_sparse_row_graph.hpp>
+ #include <boost/graph/rmat_graph_generator.hpp>
+ #include <boost/random/linear_congruential.hpp>
+
+ typedef boost::compressed_sparse_row_graph<> Graph;
+ typedef boost::sorted_rmat_iterator<boost::minstd_rand, Graph>
+ RMATGen;
+
+ int main()
+ {
+ boost::minstd_rand gen;
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(gen, 100, 400, 0.57, 0.19, 0.19, 0.05),
+ RMATGen(), 100);
+ return 0;
+ }
+
+Bibliography
+------------
+
+.. [CZF04] D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+ Model for Graph Mining. In Proceedings of 4th International Conference
+ on Data Mining, pages 442--446, 2004.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _compressed sparse row graph: http://www.boost.org/libs/graph/doc/compressed_sparse_row.html
\ No newline at end of file

Added: trunk/libs/graph_parallel/doc/sorted_unique_rmat_generator.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/sorted_unique_rmat_generator.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,136 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+====================================
+|Logo| Sorted unique R-MAT generator
+====================================
+
+::
+
+ template<typename RandomGenerator, typename Graph,
+ typename EdgePredicate = keep_all_edges>
+ class sorted_unique_rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair<vertices_size_type, vertices_size_type> value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ sorted_unique_rmat_iterator();
+ sorted_unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool bidirectional = true,
+ bool permute_vertices = true,
+ EdgePredicate ep = keep_all_edges());
+ // Iterator operations
+ reference operator*() const;
+ pointer operator->() const;
+ sorted_unique_rmat_iterator& operator++();
+ sorted_unique_rmat_iterator operator++(int);
+ bool operator==(const sorted_unique_rmat_iterator& other) const;
+ bool operator!=(const sorted_unique_rmat_iterator& other) const;
+ };
+
+This class template implements a generator for R-MAT graphs [CZF04]_,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning. The output of this generator is sorted
+for use with a `compressed sparse row graph`_. The edge list produced by
+this iterator is guaranteed not to contain parallel edges.
+
+Where Defined
+-------------
+<``boost/graph/rmat_graph_generator.hpp``>
+
+Constructors
+------------
+
+::
+
+ sorted_unique_rmat_iterator();
+
+Constructs a past-the-end iterator.
+
+::
+
+ sorted_unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool bidirectional = false,
+ bool permute_vertices = true,
+ EdgePredicate ep = keep_all_edges());
+
+Constructs an R-MAT generator iterator that creates a graph with ``n``
+vertices and ``m`` edges. ``a``, ``b``, ``c``, and ``d`` represent
+the probability that a generated edge is placed of each of the 4
+quadrants of the partitioned adjacency matrix. Probabilities are
+drawn from the random number generator ``gen``. Vertex indices are
+permuted to eliminate locality when ``permute_vertices`` is true.
+When ``bidirectional`` is ``true`` for every edge s-t, the
+corresponding anti-edge t-s is added as well, these anti-edges are not
+counted towards ``m``. ``ep`` allows the user to specify which edges
+are retained, this is useful in the case where the user wishes to
+refrain from storing remote edges locally during generation to reduce
+memory consumption.
+
+Example
+-------
+
+::
+
+ #include <boost/graph/distributed/mpi_process_group.hpp>
+ #include <boost/graph/compressed_sparse_row_graph.hpp>
+ #include <boost/graph/rmat_graph_generator.hpp>
+ #include <boost/random/linear_congruential.hpp>
+
+ using boost::graph::distributed::mpi_process_group;
+
+ typedef compressed_sparse_row_graph<directedS, no_property, no_property, no_property,
+ distributedS<mpi_process_group> > Graph;
+ typedef keep_local_edges<boost::parallel::variant_distribution<mpi_process_group>,
+ mpi_process_group::process_id_type> EdgeFilter;
+ typedef boost::sorted_unique_rmat_iterator<boost::minstd_rand, Graph> RMATGen;
+
+ int main()
+ {
+ boost::minstd_rand gen;
+ mpi_process_group pg;
+
+ int N = 100;
+
+ boost::parallel::variant_distribution<ProcessGroup> distrib
+ = boost::parallel::block(pg, N);
+
+ mpi_process_group::process_id_type id = process_id(pg);
+
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(gen, N, 400, 0.57, 0.19, 0.19, 0.05, true,
+ true, EdgeFilter(distrib, id)),
+ RMATGen(), N, pg, distrib);
+ return 0;
+ }
+
+
+Bibliography
+------------
+
+.. [CZF04] D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+ Model for Graph Mining. In Proceedings of 4th International Conference
+ on Data Mining, pages 442--446, 2004.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _compressed sparse row graph: http://www.boost.org/libs/graph/doc/compressed_sparse_row.html
\ No newline at end of file

Added: trunk/libs/graph_parallel/doc/ssca_generator.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/ssca_generator.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,22 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===========================
+|Logo| SSCA Generator
+===========================
+
+Generator from the Scalable Synthetic Compact Application #2 Graph Analysis benchmark.
+
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl

Added: trunk/libs/graph_parallel/doc/st_connected.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/st_connected.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,20 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===========================
+|Logo| s-t Connectivity
+===========================
+
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl

Added: trunk/libs/graph_parallel/doc/strong_components.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/strong_components.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,190 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===========================
+|Logo| Connected Components
+===========================
+
+::
+
+ template<typename Graph, typename ComponentMap>
+ inline typename property_traits<ComponentMap>::value_type
+ strong_components( const Graph& g, ComponentMap c);
+
+ namespace graph {
+ template<typename Graph, typename VertexComponentMap>
+ void
+ fleischer_hendrickson_pinar_strong_components(const Graph& g, VertexComponentMap r);
+
+ template<typename Graph, typename ReverseGraph,
+ typename ComponentMap, typename IsoMapFR, typename IsoMapRF>
+ inline typename property_traits<ComponentMap>::value_type
+ fleischer_hendrickson_pinar_strong_components(const Graph& g,
+ ComponentMap c,
+ const ReverseGraph& gr,
+ IsoMapFR fr, IsoMapRF rf);
+ }
+
+The ``strong_components()`` function computes the strongly connected
+components of a directed graph. The distributed strong components
+algorithm uses the `sequential strong components`_ algorithm to
+identify components local to a processor. The distributed portion of
+the algorithm is built on the `distributed breadth first search`_
+algorithm and is based on the work of Fleischer, Hendrickson, and
+Pinar [FHP00]_. The interface is a superset of the interface to the
+BGL `sequential strong components`_ algorithm. The number of
+strongly-connected components in the graph is returned to all
+processes.
+
+The distributed strong components algorithm works on both ``directed``
+and ``bidirectional`` graphs. In the bidirectional case, a reverse
+graph adapter is used to produce the required reverse graph. In
+the directed case, a separate graph is constructed in which all the
+edges are reversed.
+
+.. contents::
+
+Where Defined
+-------------
+<``boost/graph/distributed/strong_components.hpp``>
+
+also accessible from
+
+<``boost/graph/strong_components.hpp``>
+
+Parameters
+----------
+
+IN: ``const Graph& g``
+ The graph type must be a model of `Distributed Graph`_. The graph
+ type must also model the `Incidence Graph`_ and be directed.
+
+IN: ``ComponentMap c``
+ The algorithm computes how many strongly connected components are in the
+ graph, and assigns each component an integer label. The algorithm
+ then records to which component each vertex in the graph belongs by
+ recording the component number in the component property map. The
+ ``ComponentMap`` type must be a `Distributed Property Map`_. The
+ value type must be the ``vertices_size_type`` of the graph. The key
+ type must be the graph's vertex descriptor type.
+
+IN: ``VertexComponentMap r``
+ The algorithm computes a mapping from each vertex to the
+ representative of the strong component, stored in this property map.
+ The ``VertexComponentMap`` type must be a `Distributed Property Map`_.
+ The value and key types must be the vertex descriptor of the graph.
+
+IN: ``const ReverseGraph& gr``
+ The reverse (or transpose) graph of ``g``, such that for each
+ directed edge *(u, v)* in ``g`` there exists a directed edge
+ *(fr(v), fr(u))* in ``gr`` and for each edge *(v', u')* in *gr*
+ there exists an edge *(rf(u'), rf(v'))* in ``g``. The functions
+ *fr* and *rf* map from vertices in the graph to the reverse graph
+ and vice-verse, and are represented as property map arguments. The
+ concept requirements on this graph type are equivalent to those on
+ the ``Graph`` type, but the types need not be the same.
+
+ **Default**: Either a ``reverse_graph`` adaptor over the original
+ graph (if the graph type is bidirectional, i.e., models the
+ `Bidirectional Graph`_ concept) or a `distributed adjacency list`_
+ constructed from the input graph.
+
+IN: ``IsoMapFR fr``
+ A property map that maps from vertices in the input graph ``g`` to
+ vertices in the reversed graph ``gr``. The type ``IsoMapFR`` must
+ model the `Readable Property Map`_ concept and have the graph's
+ vertex descriptor as its key type and the reverse graph's vertex
+ descriptor as its value type.
+
+ **Default**: An identity property map (if the graph type is
+ bidirectional) or a distributed ``iterator_property_map`` (if the
+ graph type is directed).
+
+IN: ``IsoMapRF rf``
+ A property map that maps from vertices in the reversed graph ``gr``
+ to vertices in the input graph ``g``. The type ``IsoMapRF`` must
+ model the `Readable Property Map`_ concept and have the reverse
+ graph's vertex descriptor as its key type and the graph's vertex
+ descriptor as its value type.
+
+ **Default**: An identity property map (if the graph type is
+ bidirectional) or a distributed ``iterator_property_map`` (if the
+ graph type is directed).
+
+Complexity
+----------
+
+The local phase of the algorithm is *O(V + E)*. The parallel phase of
+the algorithm requires at most *O(V)* supersteps each containing two
+breadth first searches which are *O(V + E)* each.
+
+
+Algorithm Description
+---------------------
+
+Prior to executing the sequential phase of the algorithm, each process
+identifies any completely local strong components which it labels and
+removes from the vertex set considered in the parallel phase of the
+algorithm.
+
+The parallel phase of the distributed strong components algorithm
+consists of series of supersteps. Each superstep starts with one
+or more vertex sets which are guaranteed to completely contain
+any remaining strong components. A `distributed breadth first search`_
+is performed starting from the first vertex in each vertex set.
+All of these breadth first searches are performed in parallel by having
+each processor call ``breadth_first_search()`` with a different starting
+vertex, and if necessary inserting additional vertices into the
+``distributed queue`` used for breadth first search before invoking
+the algorithm. A second `distributed breadth first search`_ is
+performed on the reverse graph in the same fashion. For each initial
+vertex set, the successor set (the vertices reached in the forward
+breadth first search), and the predecessor set (the vertices reached
+in the backward breadth first search) is computed. The intersection
+of the predecessor and successor sets form a strongly connected
+component which is labeled as such. The remaining vertices in the
+initial vertex set are partitioned into three subsets each guaranteed
+to completely contain any remaining strong components. These three sets
+are the vertices in the predecessor set not contained in the identified
+strongly connected component, the vertices in the successor set not
+in the strongly connected component, and the remaing vertices in the
+initial vertex set not in the predecessor or successor sets. Once
+new vertex sets are identified, the algorithm begins a new superstep.
+The algorithm halts when no vertices remain.
+
+To boost performance in sparse graphs when identifying small components,
+when less than a given portion of the initial number of vertices
+remain in active vertex sets, a filtered graph adapter is used
+to limit the graph seen by the breadth first search algorithm to the
+active vertices.
+
+Bibliography
+------------
+
+.. [FHP00] Lisa Fleischer, Bruce Hendrickson, and Ali Pinar. On
+ Identifying Strongly Connected Components in Parallel. In Parallel and
+ Distributed Processing (IPDPS), volume 1800 of Lecture Notes in
+ Computer Science, pages 505--511, 2000. Springer.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004, 2005 The Trustees of Indiana University.
+
+Authors: Nick Edmonds, Douglas Gregor, and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Sequential strong components: http://www.boost.org/libs/graph/doc/strong_components.html
+.. _Distributed breadth first search: breadth_first_search.html
+.. _Distributed Graph: DistributedGraph.html
+.. _Distributed Property Map: distributed_property_map.html
+.. _Incidence Graph: http://www.boost.org/libs/graph/doc/IncidenceGraph.html
+.. _Bidirectional Graph: http://www.boost.org/libs/graph/doc/BidirectionalGraph.html
+.. _distributed adjacency list: distributed_adjacency_list.html
+.. _Readable Property Map: http://www.boost.org/libs/property_map/ReadablePropertyMap.html
+..

Added: trunk/libs/graph_parallel/doc/tsin_depth_first_visit.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/tsin_depth_first_visit.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,219 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+========================
+|Logo| Depth-First Visit
+========================
+
+::
+
+ template<typename DistributedGraph, typename DFSVisitor>
+ void
+ depth_first_visit(const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ DFSVisitor vis);
+
+ namespace graph {
+ template<typename DistributedGraph, typename DFSVisitor,
+ typename VertexIndexMap>
+ void
+ tsin_depth_first_visit(const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ DFSVisitor vis);
+
+ template<typename DistributedGraph, typename DFSVisitor,
+ typename VertexIndexMap>
+ void
+ tsin_depth_first_visit(const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ DFSVisitor vis, VertexIndexMap index_map);
+
+ template<typename DistributedGraph, typename ColorMap, typename ParentMap,
+ typename ExploreMap, typename NextOutEdgeMap, typename DFSVisitor>
+ void
+ tsin_depth_first_visit(const DistributedGraph& g,
+ typename graph_traits<DistributedGraph>::vertex_descriptor s,
+ DFSVisitor vis, ColorMap color, ParentMap parent, ExploreMap explore,
+ NextOutEdgeMap next_out_edge);
+ }
+
+The ``depth_first_visit()`` function performs a distributed
+depth-first traversal of an undirected graph using Tsin's corrections
+[Tsin02]_ to Cidon's algorithm [Cidon88]_. The distributed DFS is
+syntactically similar to its `sequential counterpart`_, which provides
+additional background and discussion. Differences in semantics are
+highlighted here, and we refer the reader to the documentation of the
+`sequential depth-first search`_ for the remainder of the
+details. Visitors passed to depth-first search need to account for the
+distribution of vertices across processes, because events will be
+triggered on certain processes but not others. See the section
+`Visitor Event Points`_ for details.
+
+Where Defined
+-------------
+<``boost/graph/distributed/depth_first_search.hpp``>
+
+also available in
+
+<``boost/graph/depth_first_search.hpp``>
+
+Parameters
+----------
+
+IN: ``const Graph& g``
+ The graph type must be a model of `Distributed Graph`_. The graph
+ must be undirected.
+
+IN: ``vertex_descriptor s``
+ The start vertex must be the same in every process.
+
+IN: ``DFSVisitor vis``
+ The visitor must be a distributed DFS visitor. The suble differences
+ between sequential and distributed DFS visitors are discussed in the
+ section `Visitor Event Points`_.
+
+IN: ``VertexIndexMap map``
+ A model of `Readable Property Map`_ whose key type is the vertex
+ descriptor type of the graph ``g`` and whose value type is an
+ integral type. The property map should map from vertices to their
+ (local) indices in the range *[0, num_vertices(g))*.
+
+ **Default**: ``get(vertex_index, g)``
+
+UTIL/OUT: ``ColorMap color``
+ The color map must be a `Distributed Property Map`_ with the same
+ process group as the graph ``g`` whose colors must monotonically
+ darken (white -> gray -> black).
+
+ **Default**: A distributed ``iterator_property_map`` created from a
+ ``std::vector`` of ``default_color_type``.
+
+UTIL/OUT: ``ParentMap parent``
+ The parent map must be a `Distributed Property Map`_ with the same
+ process group as the graph ``g`` whose key and values types are the
+ same as the vertex descriptor type of the graph ``g``. This
+ property map holds the parent of each vertex in the depth-first
+ search tree.
+
+ **Default**: A distributed ``iterator_property_map`` created from a
+ ``std::vector`` of the vertex descriptor type of the graph.
+
+UTIL: ``ExploreMap explore``
+ The explore map must be a `Distributed Property Map`_ with the same
+ process group as the graph ``g`` whose key and values types are the
+ same as the vertex descriptor type of the graph ``g``.
+
+ **Default**: A distributed ``iterator_property_map`` created from a
+ ``std::vector`` of the vertex descriptor type of the graph.
+
+UTIL: ``NextOutEdgeMap next_out_edge``
+ The next out-edge map must be a `Distributed Property Map`_ with the
+ same process group as the graph ``g`` whose key type is the vertex
+ descriptor of the graph ``g`` and whose value type is the
+ ``out_edge_iterator`` type of the graph. It is used internally to
+ keep track of the next edge that should be traversed from each
+ vertex.
+
+ **Default**: A distributed ``iterator_property_map`` created from a
+ ``std::vector`` of the ``out_edge_iterator`` type of the graph.
+
+Complexity
+----------
+Depth-first search is inherently sequential, so parallel speedup is
+very poor. Regardless of the number of processors, the algorithm will
+not be faster than *O(V)*; see [Tsin02]_ for more details.
+
+Visitor Event Points
+--------------------
+The `DFS Visitor`_ concept defines 8 event points that will be
+triggered by the `sequential depth-first search`_. The distributed
+DFS retains these event points, but the sequence of events
+triggered and the process in which each event occurs will change
+depending on the distribution of the graph.
+
+``initialize_vertex(s, g)``
+ This will be invoked by every process for each local vertex.
+
+
+``discover_vertex(u, g)``
+ This will be invoked each time a process discovers a new vertex
+ ``u``.
+
+
+``examine_vertex(u, g)``
+ This will be invoked by the process owning the vertex ``u``.
+
+``examine_edge(e, g)``
+ This will be invoked by the process owning the source vertex of
+ ``e``.
+
+
+``tree_edge(e, g)``
+ Similar to ``examine_edge``, this will be invoked by the process
+ owning the source vertex and may be invoked only once.
+
+
+``back_edge(e, g)``
+ Some edges that would be forward or cross edges in the sequential
+ DFS may be detected as back edges by the distributed DFS, so extra
+ ``back_edge`` events may be received.
+
+``forward_or_cross_edge(e, g)``
+ Some edges that would be forward or cross edges in the sequential
+ DFS may be detected as back edges by the distributed DFS, so fewer
+ ``forward_or_cross_edge`` events may be received in the distributed
+ algorithm than in the sequential case.
+
+``finish_vertex(e, g)``
+ See documentation for ``examine_vertex``.
+
+Making Visitors Safe for Distributed DFS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The three most important things to remember when updating an existing
+DFS visitor for distributed DFS or writing a new distributed DFS
+visitor are:
+
+1. Be sure that all state is either entirely local or in a
+ distributed data structure (most likely a property map!) using
+ the same process group as the graph.
+
+2. Be sure that the visitor doesn't require precise event sequences
+ that cannot be guaranteed by distributed DFS, e.g., requiring
+ ``back_edge`` and ``forward_or_cross_edge`` events to be completely
+ distinct.
+
+3. Be sure that the visitor can operate on incomplete
+ information. This often includes using an appropriate reduction
+ operation in a `distributed property map`_ and verifying that
+ results written are "better" that what was previously written.
+
+Bibliography
+------------
+
+.. [Cidon88] Isreal Cidon. Yet another distributed depth-first-search
+ algorithm. Information Processing Letters, 26(6):301--305, 1988.
+
+
+.. [Tsin02] Y. H. Tsin. Some remarks on distributed depth-first
+ search. Information Processing Letters, 82(4):173--178, 2002.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2005 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _sequential counterpart: http://www.boost.org/libs/graph/doc/depth_first_visit.html
+.. _sequential depth-first search: http://www.boost.org/libs/graph/doc/depth_first_visit.html
+.. _Distributed Graph: DistributedGraph.html
+.. _Immediate Process Group: concepts/ImmediateProcessGroup.html
+.. _Distributed Property Map: distributed_property_map.html
+.. _DFS Visitor: http://www.boost.org/libs/graph/doc/DFSVisitor.html
+.. _Readable Property Map: http://www.boost.org/libs/property_map/ReadablePropertyMap.html

Added: trunk/libs/graph_parallel/doc/unique_rmat_generator.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/unique_rmat_generator.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,110 @@
+.. Copyright (C) 2004-2009 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+===================================
+|Logo| Unique R-MAT generator
+===================================
+
+::
+
+ template<typename RandomGenerator, typename Graph>
+ class unique_rmat_iterator
+ {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::pair<vertices_size_type, vertices_size_type> value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ unique_rmat_iterator();
+ unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true);
+ // Iterator operations
+ reference operator*() const;
+ pointer operator->() const;
+ unique_rmat_iterator& operator++();
+ unique_rmat_iterator operator++(int);
+ bool operator==(const unique_rmat_iterator& other) const;
+ bool operator!=(const unique_rmat_iterator& other) const;
+ };
+
+This class template implements a generator for R-MAT graphs [CZF04]_,
+suitable for initializing an adjacency_list or other graph structure
+with iterator-based initialization. An R-MAT graph has a scale-free
+distribution w.r.t. vertex degree and is implemented using
+Recursive-MATrix partitioning. The edge list produced by this iterator
+is guaranteed not to contain parallel edges.
+
+Where Defined
+-------------
+<``boost/graph/rmat_graph_generator.hpp``>
+
+Constructors
+------------
+
+::
+
+ unique_rmat_iterator();
+
+Constructs a past-the-end iterator.
+
+::
+
+ unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
+ edges_size_type m, double a, double b, double c,
+ double d, bool permute_vertices = true,
+ EdgePredicate ep = keep_all_edges());
+
+Constructs an R-MAT generator iterator that creates a graph with ``n``
+vertices and ``m`` edges. ``a``, ``b``, ``c``, and ``d`` represent
+the probability that a generated edge is placed of each of the 4
+quadrants of the partitioned adjacency matrix. Probabilities are
+drawn from the random number generator ``gen``. Vertex indices are
+permuted to eliminate locality when ``permute_vertices`` is true.
+``ep`` allows the user to specify which edges are retained, this is
+useful in the case where the user wishes to refrain from storing
+remote edges locally during generation to reduce memory consumption.
+
+Example
+-------
+
+::
+
+ #include <boost/graph/adjacency_list.hpp>
+ #include <boost/graph/rmat_graph_generator.hpp>
+ #include <boost/random/linear_congruential.hpp>
+
+ typedef boost::adjacency_list<> Graph;
+ typedef boost::unique_rmat_iterator<boost::minstd_rand, Graph> RMATGen;
+
+ int main()
+ {
+ boost::minstd_rand gen;
+ // Create graph with 100 nodes and 400 edges
+ Graph g(RMATGen(gen, 100, 400, 0.57, 0.19, 0.19, 0.05,),
+ RMATGen(), 100);
+ return 0;
+ }
+
+
+Bibliography
+------------
+
+.. [CZF04] D Chakrabarti, Y Zhan, and C Faloutsos. R-MAT: A Recursive
+ Model for Graph Mining. In Proceedings of 4th International Conference
+ on Data Mining, pages 442--446, 2004.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2009 The Trustees of Indiana University.
+
+Authors: Nick Edmonds and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl

Added: trunk/libs/graph_parallel/doc/vertex_coloring.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/graph_parallel/doc/vertex_list_adaptor.rst
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/doc/vertex_list_adaptor.rst 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,121 @@
+.. Copyright (C) 2004-2008 The Trustees of Indiana University.
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+================================
+|Logo| Vertex List Graph Adaptor
+================================
+
+::
+
+ template<typename Graph, typename GlobalIndexMap>
+ class vertex_list_adaptor
+ {
+ public:
+ vertex_list_adaptor(const Graph& g,
+ const GlobalIndexMap& index_map = GlobalIndexMap());
+ };
+
+ template<typename Graph, typename GlobalIndexMap>
+ vertex_list_adaptor<Graph, GlobalIndexMap>
+ make_vertex_list_adaptor(const Graph& g, const GlobalIndexMap& index_map);
+
+ template<typename Graph>
+ vertex_list_adaptor<Graph, *unspecified*>
+ make_vertex_list_adaptor(const Graph& g);
+
+
+The vertex list graph adaptor adapts any model of `Distributed Vertex List
+Graph`_ in a `Vertex List Graph`_. In the former type of graph, the
+set of vertices is distributed across the process group, so no
+process has access to all vertices. In the latter type of graph,
+however, every process has access to every vertex in the graph. This
+is required by some distributed algorithms, such as the
+implementations of `Minimum spanning tree`_ algorithms.
+
+.. contents::
+
+Where Defined
+-------------
+<``boost/graph/distributed/vertex_list_adaptor.hpp``>
+
+
+Class template ``vertex_list_adaptor``
+--------------------------------------
+
+The ``vertex_list_adaptor`` class template takes a `Distributed
+Vertex List Graph`_ and a mapping from vertex descriptors to global
+vertex indices, which must be in the range *[0, n)*, where *n* is the
+number of vertices in the entire graph. The mapping is a `Readable
+Property Map`_ whose key type is a vertex descriptor.
+
+The vertex list adaptor stores only a reference to the underlying
+graph, forwarding all operations not related to the vertex list on to
+the underlying graph. For instance, if the underlying graph models
+`Adjacency Graph`_, then the adaptor will also model `Adjacency
+Graph`_. Note, however, that no modifications to the underlying graph
+can occur through the vertex list adaptor. Modifications made to the
+underlying graph directly will be reflected in the vertex list
+adaptor, but modifications that add or remove vertices invalidate the
+vertex list adaptor. Additionally, the vertex list adaptor provides
+access to the global index map via the ``vertex_index`` property.
+
+On construction, the vertex list adaptor performs an all-gather
+operation to create a list of all vertices in the graph within each
+process. It is this list that is accessed via *vertices* and the
+length of this list that is accessed via *num_vertices*. Due to the
+all-gather operation, the creation of this adaptor is a collective
+operation.
+
+Function templates ``make_vertex_list_adaptor``
+-----------------------------------------------
+
+These function templates construct a vertex list adaptor from a graph
+and, optionally, a property map that maps vertices to global index
+numbers.
+
+Parameters
+~~~~~~~~~~
+
+IN: ``Graph& g``
+ The graph type must be a model of `Distributed Vertex List Graph`_.
+
+IN: ``GlobalIndexMap index_map``
+ A `Distributed property map`_ whose type must model `Readable
+ property map`_ that maps from vertices to a global index. If
+ provided, this map must be initialized prior to be passed to the
+ vertex list adaptor.
+
+ **Default:** A property map of unspecified type constructed from a
+ distributed ``iterator_property_map`` that uses the
+ ``vertex_index`` property map of the underlying graph and a vector
+ of ``vertices_size_type``.
+
+Complexity
+~~~~~~~~~~
+These operations require *O(n)* time, where *n* is the number of
+vertices in the graph, and *O(n)* communication per node in the BSP model.
+
+-----------------------------------------------------------------------------
+
+Copyright (C) 2004 The Trustees of Indiana University.
+
+Authors: Douglas Gregor and Andrew Lumsdaine
+
+.. |Logo| image:: http://www.osl.iu.edu/research/pbgl/images/pbgl-logo.png
+ :align: middle
+ :alt: Parallel BGL
+ :target: http://www.osl.iu.edu/research/pbgl
+
+.. _Kruskal's algorithm: http://www.boost.org/libs/graph/doc/kruskal_min_spanning_tree.html
+.. _Vertex list graph: http://www.boost.org/libs/graph/doc/VertexListGraph.html
+.. _Adjacency graph: http://www.boost.org/libs/graph/doc/AdjacencyGraph.html
+.. _distributed adjacency list: distributed_adjacency_list.html
+.. _Minimum spanning tree: dehne_gotz_min_spanning_tree.html
+.. _Distributed Vertex List Graph: DistributedVertexListGraph.html
+.. _Distributed property map: distributed_property_map.html
+.. _Readable Property Map: http://www.boost.org/libs/property_map/ReadablePropertyMap.html
+.. _Read/Write Property Map: http://www.boost.org/libs/property_map/ReadWritePropertyMap.html
+
+

Added: trunk/libs/graph_parallel/example/CMakeLists.txt
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/example/CMakeLists.txt 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,35 @@
+add_executable(breadth_first_search breadth_first_search.cpp)
+target_link_libraries(breadth_first_search
+ boost_graph_mpi ${MPI_LIBRARIES})
+
+set_target_properties(
+ breadth_first_search
+ PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}"
+ COMPILE_FLAGS "${MPI_COMPILE_FLAGS}")
+
+if (BUILD_TESTING)
+ add_test(breadth_first_search
+ ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_MAX_NUMPROCS} ${MPIEXEC_PREFLAGS}
+ "${EXECUTABLE_OUTPUT_PATH}/\${CTEST_CONFIGURATION_TYPE}/breadth_first_search"
+ ${MPIEXEC_POSTFLAGS}
+ "${CMAKE_CURRENT_SOURCE_DIR}/weighted_graph.gr"
+ "${CMAKE_BINARY_DIR}/test/weighted_graph-bfs.gr")
+endif (BUILD_TESTING)
+
+add_executable(dijkstra_shortest_paths dijkstra_shortest_paths.cpp)
+target_link_libraries(dijkstra_shortest_paths
+ boost_graph_mpi ${MPI_LIBRARIES})
+
+set_target_properties(
+ dijkstra_shortest_paths
+ PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}"
+ COMPILE_FLAGS "${MPI_COMPILE_FLAGS}")
+
+if (BUILD_TESTING)
+ add_test(dijkstra_shortest_paths
+ ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_MAX_NUMPROCS} ${MPIEXEC_PREFLAGS}
+ "${EXECUTABLE_OUTPUT_PATH}/\${CTEST_CONFIGURATION_TYPE}/dijkstra_shortest_paths"
+ ${MPIEXEC_POSTFLAGS}
+ "${CMAKE_CURRENT_SOURCE_DIR}/weighted_graph.gr"
+ "${CMAKE_BINARY_DIR}/test/weighted_graph-dijkstra.gr")
+endif (BUILD_TESTING)
\ No newline at end of file

Added: trunk/libs/graph_parallel/example/breadth_first_search.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/example/breadth_first_search.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,102 @@
+// Copyright (C) 2004-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+// Example usage of breadth_first_search algorithm
+
+// Enable PBGL interfaces to BGL algorithms
+#include <boost/graph/use_mpi.hpp>
+
+// Communicate via MPI
+#include <boost/graph/distributed/mpi_process_group.hpp>
+
+// Breadth-first search algorithm
+#include <boost/graph/breadth_first_search.hpp>
+
+// Distributed adjacency list
+#include <boost/graph/distributed/adjacency_list.hpp>
+
+// METIS Input
+#include <boost/graph/metis.hpp>
+
+// Graphviz Output
+#include <boost/graph/distributed/graphviz.hpp>
+
+// Standard Library includes
+#include <fstream>
+#include <string>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+/* An undirected graph with distance values stored on the vertices. */
+typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>, undirectedS,
+ /*Vertex properties=*/property<vertex_distance_t, std::size_t> >
+ Graph;
+
+int main(int argc, char* argv[])
+{
+ boost::mpi::environment env(argc,argv);
+
+ // Parse command-line options
+ const char* filename = "weighted_graph.gr";
+ if (argc > 1) filename = argv[1];
+
+ // Open the METIS input file
+ std::ifstream in(filename);
+ graph::metis_reader reader(in);
+
+ // Load the graph using the default distribution
+ Graph g(reader.begin(), reader.end(),
+ reader.num_vertices());
+
+ // Get vertex 0 in the graph
+ graph_traits<Graph>::vertex_descriptor start = vertex(0, g);
+
+ // Compute BFS levels from vertex 0
+ property_map<Graph, vertex_distance_t>::type distance =
+ get(vertex_distance, g);
+
+ put(distance, start, 0);
+ breadth_first_search
+ (g, start,
+ visitor(make_bfs_visitor(record_distances(distance, on_tree_edge()))));
+
+ // Output a Graphviz DOT file
+ std::string outfile;
+
+ if (argc > 2)
+ outfile = argv[2];
+ else {
+ outfile = filename;
+ int i = outfile.rfind('.');
+ if (i != std::string::npos)
+ outfile.erase(outfile.begin() + i, outfile.end());
+ outfile += "-bfs.dot";
+ }
+
+ if (process_id(process_group(g)) == 0) {
+ std::cout << "Writing GraphViz output to " << outfile << "... ";
+ std::cout.flush();
+ }
+ write_graphviz(outfile, g,
+ make_label_writer(distance));
+ if (process_id(process_group(g)) == 0)
+ std::cout << "Done." << std::endl;
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/example/dijkstra_shortest_paths.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/example/dijkstra_shortest_paths.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,98 @@
+// Copyright (C) 2004-2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+// Example usage of dijkstra_shortest_paths algorithm
+
+// Enable PBGL interfaces to BGL algorithms
+#include <boost/graph/use_mpi.hpp>
+
+// Communication via MPI
+#include <boost/graph/distributed/mpi_process_group.hpp>
+
+// Dijkstra's single-source shortest paths algorithm
+#include <boost/graph/dijkstra_shortest_paths.hpp>
+
+// Distributed adjacency list
+#include <boost/graph/distributed/adjacency_list.hpp>
+
+// METIS Input
+#include <boost/graph/metis.hpp>
+
+// Graphviz Output
+#include <boost/graph/distributed/graphviz.hpp>
+
+// Standard Library includes
+#include <fstream>
+#include <string>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+/* An undirected, weighted graph with distance values stored on the
+ vertices. */
+typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>, undirectedS,
+ /*Vertex properties=*/property<vertex_distance_t, float>,
+ /*Edge properties=*/property<edge_weight_t, float> >
+ Graph;
+
+int main(int argc, char* argv[])
+{
+ boost::mpi::environment env(argc,argv);
+
+ // Parse command-line options
+ const char* filename = "weighted_graph.gr";
+ if (argc > 1) filename = argv[1];
+
+ // Open the METIS input file
+ std::ifstream in(filename);
+ graph::metis_reader reader(in);
+
+ // Load the graph using the default distribution
+ Graph g(reader.begin(), reader.end(), reader.weight_begin(),
+ reader.num_vertices());
+
+ // Get vertex 0 in the graph
+ graph_traits<Graph>::vertex_descriptor start = vertex(0, g);
+
+ // Compute shortest paths from vertex 0
+ dijkstra_shortest_paths(g, start,
+ distance_map(get(vertex_distance, g)));
+
+ // Output a Graphviz DOT file
+ std::string outfile = filename;
+ if (argc > 2)
+ outfile = argv[2];
+ else {
+ int i = outfile.rfind('.');
+ if (i != std::string::npos)
+ outfile.erase(outfile.begin() + i, outfile.end());
+ outfile += "-dijkstra.dot";
+ }
+
+ if (process_id(process_group(g)) == 0) {
+ std::cout << "Writing GraphViz output to " << outfile << "... ";
+ std::cout.flush();
+ }
+ write_graphviz(outfile, g,
+ make_label_writer(get(vertex_distance, g)),
+ make_label_writer(get(edge_weight, g)));
+ if (process_id(process_group(g)) == 0)
+ std::cout << "Done." << std::endl;
+
+ return 0;
+}

Copied: trunk/libs/graph_parallel/module.cmake (from r52301, /trunk/libs/graph/module.cmake)
==============================================================================
--- /trunk/libs/graph/module.cmake (original)
+++ trunk/libs/graph_parallel/module.cmake 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -1,3 +1 @@
-boost_module(graph DEPENDS property_map tuple multi_index any random)
-
-# any is there because of the dependency on boost/property_map/dynamic_property_map.hpp
+boost_module(graph_parallel DEPENDS mpi graph)

Added: trunk/libs/graph_parallel/src/CMakeLists.txt
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/src/CMakeLists.txt 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,24 @@
+add_definitions(-DBOOST_GRAPH_NO_LIB=1)
+
+if (MSVC)
+ # Without these flags, MSVC 7.1 and 8.0 crash
+ add_definitions(-GR-)
+endif (MSVC)
+
+FIND_PACKAGE(MPI)
+if (MPI_FOUND)
+ message(STATUS "MPI found")
+ # Add Boost.MPI link and add parallel source files
+ include_directories(${MPI_INCLUDE_PATH})
+
+ boost_add_library(
+ boost_graph_parallel
+ mpi_process_group.cpp tag_allocator.cpp
+ DEPENDS boost_mpi
+ SHARED_COMPILE_FLAGS "-DBOOST_GRAPH_DYN_LINK=1"
+ )
+endif (MPI_FOUND)
+
+if (NOT MPI_FOUND)
+ message(STATUS "MPI Not Found")
+endif (NOT MPI_FOUND)

Added: trunk/libs/graph_parallel/src/mpi_process_group.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/src/mpi_process_group.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,1108 @@
+// Copyright (C) 2004-2006 The Trustees of Indiana University.
+// Copyright (C) 2007 Douglas Gregor <doug.gregor_at_[hidden]>
+// Copyright (C) 2007 Matthias Troyer <troyer_at_[hidden]>
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+// Matthias Troyer
+#include <boost/graph/use_mpi.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/mpi/environment.hpp>
+#include <boost/lexical_cast.hpp>
+#include <memory>
+#include <algorithm>
+
+//#define DEBUG 1
+
+
+//#define MAX_BATCHES 1500
+#define PREALLOCATE_BATCHES 250
+// 500 is a better setting for PREALLOCATE_BATCHES if you're not using process
+// subgroups and are building 64-bit binaries. 250 allows all the CTest
+// tests to pass in both 32 and 64-bit modes. If you create multiple process
+// groups with PREALLOCATE_BATCHES at a reasonable level in 32-bit mode you
+// _will_ run out of memory and get "malloc failed" errors
+
+//#define NO_ISEND_BATCHES
+//#define NO_IMMEDIATE_PROCESSING
+//#define NO_SPLIT_BATCHES
+#define IRECV_BATCH
+
+// we cannot keep track of how many we received if we do not process them
+#ifdef NO_IMMEDIATE_PROCESSING
+#undef IRECV_BATCH
+#endif
+
+#ifdef DEBUG
+# include <iostream>
+#endif // DEBUG
+
+namespace boost { namespace graph { namespace distributed {
+
+struct mpi_process_group::deallocate_block
+{
+ explicit deallocate_block(blocks_type* blocks) : blocks(blocks) { }
+
+ void operator()(int* block_num)
+ {
+ block_type* block = (*blocks)[*block_num];
+
+ // Mark this block as inactive
+ (*blocks)[*block_num] = 0;
+
+#ifdef DEBUG
+ fprintf(stderr, "Processor %i deallocated block #%i\n",
+ boost::mpi::communicator().rank(), *block_num);
+#endif
+
+ // Delete the block and its block number
+ delete block_num;
+ delete block;
+ }
+
+private:
+ blocks_type* blocks;
+};
+
+mpi_process_group::impl::incoming_messages::incoming_messages()
+{
+ next_header.push_back(headers.begin());
+}
+
+mpi_process_group::impl::impl(std::size_t num_headers, std::size_t buffer_sz,
+ communicator_type parent_comm)
+ : comm(parent_comm, boost::mpi::comm_duplicate),
+ oob_reply_comm(parent_comm, boost::mpi::comm_duplicate),
+ allocated_tags(boost::mpi::environment::max_tag())
+{
+ max_sent=0;
+ max_received=0;
+ int n = comm.size();
+ outgoing.resize(n);
+ incoming.resize(n);
+
+ // no synchronization stage means -1
+ // to keep the convention
+ synchronizing_stage.resize(n,-1);
+ number_sent_batches.resize(n);
+ number_received_batches.resize(n);
+ trigger_context = trc_none;
+ processing_batches = 0;
+
+ // Allocator a placeholder block "0"
+ blocks.push_back(new block_type);
+
+ synchronizing = false;
+
+ set_batch_size(num_headers,buffer_sz);
+
+ for (int i = 0; i < n; ++i) {
+ incoming[i].next_header.front() = incoming[i].headers.end();
+ outgoing[i].buffer.reserve(batch_message_size);
+ }
+
+#ifdef PREALLOCATE_BATCHES
+ batch_pool.resize(PREALLOCATE_BATCHES);
+ for (std::size_t i = 0 ; i < batch_pool.size(); ++i) {
+ batch_pool[i].buffer.reserve(batch_message_size);
+ batch_pool[i].request=MPI_REQUEST_NULL;
+ free_batches.push(i);
+ }
+#endif
+}
+
+void mpi_process_group::impl::set_batch_size(std::size_t header_num, std::size_t buffer_sz)
+{
+ batch_header_number = header_num;
+ batch_buffer_size = buffer_sz;
+
+ // determine batch message size by serializing the largest possible batch
+ outgoing_messages msg;
+ msg.headers.resize(batch_header_number);
+ msg.buffer.resize(batch_buffer_size);
+ boost::mpi::packed_oarchive oa(comm);
+ oa << const_cast<const outgoing_messages&>(msg);
+ batch_message_size = oa.size();
+}
+
+
+mpi_process_group::impl::~impl()
+{
+ // Delete the placeholder "0" block
+ delete blocks.front();
+ if (!boost::mpi::environment::finalized())
+ for (std::vector<MPI_Request>::iterator it=requests.begin();
+ it != requests.end();++it)
+ MPI_Cancel(&(*it));
+}
+
+namespace detail {
+// global batch handlers
+void handle_batch (mpi_process_group const& self, int source, int,
+ mpi_process_group::outgoing_messages& batch,bool out_of_band)
+{
+#ifdef DEBUG
+ std::cerr << "Processing batch trigger\n";
+ std::cerr << "BATCH: " << process_id(self) << " <- " << source << " ("
+ << batch.headers.size() << " headers, "
+ << batch.buffer.size() << " bytes)"
+ << std::endl;
+#endif
+ // If we are not synchronizing, then this must be an early receive
+ trigger_receive_context old_context = self.impl_->trigger_context;
+ if (self.impl_->trigger_context != trc_in_synchronization)
+ self.impl_->trigger_context = trc_early_receive;
+
+ // Receive the batched messages
+ self.receive_batch(source,batch);
+
+ // Restore the previous context
+ self.impl_->trigger_context = old_context;
+}
+
+// synchronization handler
+void handle_sync (mpi_process_group const& self, int source, int tag, int val,
+ bool)
+{
+ // increment the stage for the source
+ std::size_t stage = static_cast<std::size_t>(
+ ++self.impl_->synchronizing_stage[source]);
+
+ assert(source != process_id(self));
+
+#ifdef DEBUG
+ std::ostringstream out;
+ out << process_id(self) << ": handle_sync from " << source
+ << " (stage = " << self.impl_->synchronizing_stage[source] << ")\n";
+ std::cerr << out.str();
+#endif
+
+ // record how many still have messages to be sent
+ if (self.impl_->synchronizing_unfinished.size()<=stage) {
+ assert(self.impl_->synchronizing_unfinished.size() == stage);
+ self.impl_->synchronizing_unfinished.push_back(val >= 0 ? 1 : 0);
+ }
+ else
+ self.impl_->synchronizing_unfinished[stage]+=(val >= 0 ? 1 : 0);
+
+ // record how many are in that stage
+ if (self.impl_->processors_synchronizing_stage.size()<=stage) {
+ assert(self.impl_->processors_synchronizing_stage.size() == stage);
+ self.impl_->processors_synchronizing_stage.push_back(1);
+ }
+ else
+ ++self.impl_->processors_synchronizing_stage[stage];
+
+ // subtract how many batches we were supposed to receive
+ if (val>0)
+ self.impl_->number_received_batches[source] -= val;
+}
+
+
+}
+
+mpi_process_group::mpi_process_group(communicator_type parent_comm)
+{
+ // 64K messages and 1MB buffer turned out to be a reasonable choice
+ impl_.reset(new impl(64*1024,1024*1024,parent_comm));
+#ifndef IRECV_BATCH
+ global_trigger<outgoing_messages>(msg_batch,&detail::handle_batch);
+#else // use irecv version by providing a maximum buffer size
+ global_trigger<outgoing_messages>(msg_batch,&detail::handle_batch,
+ impl_->batch_message_size);
+#endif
+ global_trigger<outgoing_messages>(msg_large_batch,&detail::handle_batch);
+ global_trigger<int>(msg_synchronizing,&detail::handle_sync);
+ rank = impl_->comm.rank();
+ size = impl_->comm.size();
+
+#ifdef SEND_OOB_BSEND
+ // let us try with a default bufferr size of 16 MB
+ if (!message_buffer_size())
+ set_message_buffer_size(16*1024*1024);
+#endif
+}
+
+mpi_process_group::mpi_process_group(std::size_t h, std::size_t sz,
+ communicator_type parent_comm)
+{
+ impl_.reset(new impl(h,sz,parent_comm));
+#ifndef IRECV_BATCH
+ global_trigger<outgoing_messages>(msg_batch,&detail::handle_batch);
+#else // use irecv version by providing a maximum buffer size
+ global_trigger<outgoing_messages>(msg_batch,&detail::handle_batch,
+ impl_->batch_message_size);
+#endif
+ global_trigger<outgoing_messages>(msg_large_batch,&detail::handle_batch);
+ global_trigger<int>(msg_synchronizing,&detail::handle_sync);
+ rank = impl_->comm.rank();
+ size = impl_->comm.size();
+#ifdef SEND_OOB_BSEND
+ // let us try with a default bufferr size of 16 MB
+ if (!message_buffer_size())
+ set_message_buffer_size(16*1024*1024);
+#endif
+}
+
+mpi_process_group::mpi_process_group(const mpi_process_group& other,
+ const receiver_type& handler, bool)
+ : impl_(other.impl_)
+{
+ rank = impl_->comm.rank();
+ size = impl_->comm.size();
+ replace_handler(handler);
+}
+
+mpi_process_group::mpi_process_group(const mpi_process_group& other,
+ attach_distributed_object, bool)
+ : impl_(other.impl_)
+{
+ rank = impl_->comm.rank();
+ size = impl_->comm.size();
+ allocate_block();
+
+ for (std::size_t i = 0; i < impl_->incoming.size(); ++i) {
+ if (my_block_number() >= (int)impl_->incoming[i].next_header.size()) {
+ impl_->incoming[i].next_header
+ .push_back(impl_->incoming[i].headers.begin());
+ } else {
+ impl_->incoming[i].next_header[my_block_number()] =
+ impl_->incoming[i].headers.begin();
+ }
+
+#ifdef DEBUG
+ if (process_id(*this) == 0) {
+ std::cerr << "Allocated tag block " << my_block_number() << std::endl;
+ }
+#endif
+ }
+}
+
+mpi_process_group::~mpi_process_group() {
+ /*
+ std::string msg = boost::lexical_cast<std::string>(process_id(*this)) + " " +
+ boost::lexical_cast<std::string>(impl_->max_received) + " " +
+ boost::lexical_cast<std::string>(impl_->max_sent) + "\n";
+ std::cerr << msg << "\n";
+ */
+}
+
+
+mpi_process_group::communicator_type communicator(const mpi_process_group& pg)
+{ return pg.impl_->comm; }
+
+void
+mpi_process_group::replace_handler(const receiver_type& handler,
+ bool out_of_band_receive)
+{
+ make_distributed_object();
+
+ // Attach the receive handler
+ impl_->blocks[my_block_number()]->on_receive = handler;
+}
+
+void
+mpi_process_group::make_distributed_object()
+{
+ if (my_block_number() == 0) {
+ allocate_block();
+
+ for (std::size_t i = 0; i < impl_->incoming.size(); ++i) {
+ if (my_block_number() >= (int)impl_->incoming[i].next_header.size()) {
+ impl_->incoming[i].next_header
+ .push_back(impl_->incoming[i].headers.begin());
+ } else {
+ impl_->incoming[i].next_header[my_block_number()] =
+ impl_->incoming[i].headers.begin();
+ }
+
+#ifdef DEBUG
+ if (process_id(*this) == 0) {
+ std::cerr << "Allocated tag block " << my_block_number() << std::endl;
+ }
+#endif
+ }
+ } else {
+ // Clear out the existing triggers
+ std::vector<shared_ptr<trigger_base> >()
+ .swap(impl_->blocks[my_block_number()]->triggers);
+ }
+
+ // Clear out the receive handler
+ impl_->blocks[my_block_number()]->on_receive = 0;
+}
+
+void
+mpi_process_group::
+replace_on_synchronize_handler(const on_synchronize_event_type& handler)
+{
+ if (my_block_number() > 0)
+ impl_->blocks[my_block_number()]->on_synchronize = handler;
+}
+
+int mpi_process_group::allocate_block(bool out_of_band_receive)
+{
+ assert(!block_num);
+ block_iterator i = impl_->blocks.begin();
+ while (i != impl_->blocks.end() && *i) ++i;
+
+ if (i == impl_->blocks.end()) {
+ impl_->blocks.push_back(new block_type());
+ i = impl_->blocks.end() - 1;
+ } else {
+ *i = new block_type();
+ }
+
+ block_num.reset(new int(i - impl_->blocks.begin()),
+ deallocate_block(&impl_->blocks));
+
+#ifdef DEBUG
+ fprintf(stderr,
+ "Processor %i allocated block #%i\n", process_id(*this), *block_num);
+#endif
+
+ return *block_num;
+}
+
+bool mpi_process_group::maybe_emit_receive(int process, int encoded_tag) const
+{
+ std::pair<int, int> decoded = decode_tag(encoded_tag);
+
+ assert (decoded.first < static_cast<int>(impl_->blocks.size()));
+
+ block_type* block = impl_->blocks[decoded.first];
+ if (!block) {
+ std::cerr << "Received message from process " << process << " with tag "
+ << decoded.second << " for non-active block "
+ << decoded.first << std::endl;
+ std::cerr << "Active blocks are: ";
+ for (std::size_t i = 0; i < impl_->blocks.size(); ++i)
+ if (impl_->blocks[i])
+ std::cerr << i << ' ';
+ std::cerr << std::endl;
+ assert(block);
+ }
+
+ if (decoded.second < static_cast<int>(block->triggers.size())
+ && block->triggers[decoded.second]) {
+ // We have a trigger for this message; use it
+ trigger_receive_context old_context = impl_->trigger_context;
+ impl_->trigger_context = trc_out_of_band;
+ block->triggers[decoded.second]->receive(*this, process, decoded.second,
+ impl_->trigger_context,
+ decoded.first);
+ impl_->trigger_context = old_context;
+ }
+ else
+ return false;
+ // We receives the message above
+ return true;
+}
+
+bool mpi_process_group::emit_receive(int process, int encoded_tag) const
+{
+ std::pair<int, int> decoded = decode_tag(encoded_tag);
+
+ if (decoded.first >= static_cast<int>(impl_->blocks.size()))
+ // This must be an out-of-band message destined for
+ // send_oob_with_reply; ignore it.
+ return false;
+
+ // Find the block that will receive this message
+ block_type* block = impl_->blocks[decoded.first];
+ assert(block);
+ if (decoded.second < static_cast<int>(block->triggers.size())
+ && block->triggers[decoded.second])
+ // We have a trigger for this message; use it
+ block->triggers[decoded.second]->receive(*this,process, decoded.second,
+ impl_->trigger_context);
+ else if (block->on_receive)
+ // Fall back to the normal message handler
+ block->on_receive(process, decoded.second);
+ else
+ // There was no handler for this message
+ return false;
+
+ // The message was handled above
+ return true;
+}
+
+void mpi_process_group::emit_on_synchronize() const
+{
+ for (block_iterator i = impl_->blocks.begin(); i != impl_->blocks.end(); ++i)
+ if (*i && (*i)->on_synchronize) (*i)->on_synchronize();
+}
+
+
+optional<std::pair<mpi_process_group::process_id_type, int> >
+mpi_process_group::probe() const
+{
+#ifdef DEBUG
+ std::cerr << "PROBE: " << process_id(*this) << ", tag block = "
+ << my_block_number() << std::endl;
+#endif
+
+ typedef std::pair<process_id_type, int> result_type;
+
+ int tag_block = my_block_number();
+
+ for (std::size_t source = 0; source < impl_->incoming.size(); ++source) {
+ impl::incoming_messages& incoming = impl_->incoming[source];
+ std::vector<impl::message_header>::iterator& i =
+ incoming.next_header[tag_block];
+ std::vector<impl::message_header>::iterator end = incoming.headers.end();
+
+ while (i != end) {
+ if (i->tag != -1 && decode_tag(i->tag).first == my_block_number()) {
+#ifdef DEBUG
+ std::cerr << "PROBE: " << process_id(*this) << " <- " << source
+ << ", block = " << my_block_number() << ", tag = "
+ << decode_tag(i->tag).second << ", bytes = " << i->bytes
+ << std::endl;
+#endif
+ return result_type(source, decode_tag(i->tag).second);
+ }
+ ++i;
+ }
+ }
+ return optional<result_type>();
+}
+
+void
+mpi_process_group::maybe_send_batch(process_id_type dest) const
+{
+#ifndef NO_SPLIT_BATCHES
+ impl::outgoing_messages& outgoing = impl_->outgoing[dest];
+ if (outgoing.buffer.size() >= impl_->batch_buffer_size ||
+ outgoing.headers.size() >= impl_->batch_header_number) {
+ // we are full and need to send
+ outgoing_messages batch;
+ batch.buffer.reserve(impl_->batch_buffer_size);
+ batch.swap(outgoing);
+ if (batch.buffer.size() >= impl_->batch_buffer_size
+ && batch.headers.size()>1 ) {
+ // we are too large, keep the last message in the outgoing buffer
+ std::copy(batch.buffer.begin()+batch.headers.back().offset,
+ batch.buffer.end(),std::back_inserter(outgoing.buffer));
+ batch.buffer.resize(batch.headers.back().offset);
+ outgoing.headers.push_back(batch.headers.back());
+ batch.headers.pop_back();
+ outgoing.headers.front().offset=0;
+ }
+ send_batch(dest,batch);
+ }
+#endif
+}
+
+void
+mpi_process_group::send_batch(process_id_type dest) const
+{
+ impl::outgoing_messages& outgoing = impl_->outgoing[dest];
+ if (outgoing.headers.size()) {
+ // need to copy to avoid race conditions
+ outgoing_messages batch;
+ batch.buffer.reserve(impl_->batch_buffer_size);
+ batch.swap(outgoing);
+ send_batch(dest,batch);
+ }
+}
+
+
+void
+mpi_process_group::send_batch(process_id_type dest,
+ outgoing_messages& outgoing) const
+{
+ impl_->free_sent_batches();
+ process_id_type id = process_id(*this);
+
+ // clear the batch
+#ifdef DEBUG
+ std::cerr << "Sending batch: " << id << " -> " << dest << std::endl;
+#endif
+ // we increment the number of batches sent
+ ++impl_->number_sent_batches[dest];
+ // and send the batch
+ assert(outgoing.headers.size() <= impl_->batch_header_number);
+ if (id != dest) {
+#ifdef NO_ISEND_BATCHES
+ impl::batch_request req;
+#else
+#ifdef PREALLOCATE_BATCHES
+ while (impl_->free_batches.empty()) {
+ impl_->free_sent_batches();
+ poll();
+ }
+ impl::batch_request& req = impl_->batch_pool[impl_->free_batches.top()];
+ impl_->free_batches.pop();
+#else
+ impl_->sent_batches.push_back(impl::batch_request());
+ impl::batch_request& req = impl_->sent_batches.back();
+#endif
+#endif
+ boost::mpi::packed_oarchive oa(impl_->comm,req.buffer);
+ oa << outgoing;
+
+ int tag = msg_batch;
+
+#ifdef IRECV_BATCH
+ if (oa.size() > impl_->batch_message_size)
+ tag = msg_large_batch;
+#endif
+
+ int result = MPI_Isend(const_cast<void*>(oa.address()), oa.size(),
+ MPI_PACKED, dest, tag, impl_->comm,
+ &req.request);
+ assert(result == MPI_SUCCESS);
+ impl_->max_sent = (std::max)(impl_->max_sent,impl_->sent_batches.size());
+#ifdef NO_ISEND_BATCHES
+ int done=0;
+ do {
+ poll();
+ MPI_Test(&req.request,&done,MPI_STATUS_IGNORE);
+ } while (!done);
+#else
+#ifdef MAX_BATCHES
+ while (impl_->sent_batches.size() >= MAX_BATCHES-1) {
+ impl_->free_sent_batches();
+ poll();
+ }
+#endif
+#endif
+ }
+ else
+ receive_batch(id,outgoing);
+}
+
+void mpi_process_group::process_batch(int source) const
+{
+ bool processing_from_queue = !impl_->new_batches.empty();
+ impl_->processing_batches++;
+ typedef std::vector<impl::message_header>::iterator iterator;
+
+ impl::incoming_messages& incoming = impl_->incoming[source];
+
+ // Set up the iterators pointing to the next header in each block
+ for (std::size_t i = 0; i < incoming.next_header.size(); ++i)
+ incoming.next_header[i] = incoming.headers.begin();
+
+ buffer_type remaining_buffer;
+ std::vector<impl::message_header> remaining_headers;
+
+ iterator end = incoming.headers.end();
+
+ for (iterator i = incoming.headers.begin(); i != end; ++i) {
+ // This this message has already been received, skip it
+ if (i->tag == -1)
+ continue;
+
+#ifdef BATCH_DEBUG
+ std::cerr << process_id(*this) << ": emit_receive(" << source << ", "
+ << decode_tag(i->tag).first << ":" << decode_tag(i->tag).second
+ << ")\n";
+#endif
+
+ if (!emit_receive(source, i->tag)) {
+#ifdef BATCH_DEBUG
+ std::cerr << process_id(*this) << ": keeping message # "
+ << remaining_headers.size() << " from " << source << " ("
+ << decode_tag(i->tag).first << ":"
+ << decode_tag(i->tag).second << ", "
+ << i->bytes << " bytes)\n";
+#endif
+ // Hold on to this message until the next stage
+ remaining_headers.push_back(*i);
+ remaining_headers.back().offset = remaining_buffer.size();
+ remaining_buffer.insert(remaining_buffer.end(),
+ &incoming.buffer[i->offset],
+ &incoming.buffer[i->offset] + i->bytes);
+ }
+ }
+
+ // Swap the remaining messages into the "incoming" set.
+ incoming.headers.swap(remaining_headers);
+ incoming.buffer.swap(remaining_buffer);
+
+ // Set up the iterators pointing to the next header in each block
+ for (std::size_t i = 0; i < incoming.next_header.size(); ++i)
+ incoming.next_header[i] = incoming.headers.begin();
+ impl_->processing_batches--;
+
+ if (!processing_from_queue)
+ while (!impl_->new_batches.empty()) {
+ receive_batch(impl_->new_batches.front().first,
+ impl_->new_batches.front().second);
+ impl_->new_batches.pop();
+ }
+}
+
+
+void mpi_process_group::receive_batch(process_id_type source,
+ outgoing_messages& new_messages) const
+{
+ impl_->free_sent_batches();
+ if(!impl_->processing_batches) {
+ // increase the number of received batches
+ ++impl_->number_received_batches[source];
+ // and receive the batch
+ impl::incoming_messages& incoming = impl_->incoming[source];
+ typedef std::vector<impl::message_header>::iterator iterator;
+ iterator end = new_messages.headers.end();
+ for (iterator i = new_messages.headers.begin(); i != end; ++i) {
+ incoming.headers.push_back(*i);
+ incoming.headers.back().offset = incoming.buffer.size();
+ incoming.buffer.insert(incoming.buffer.end(),
+ &new_messages.buffer[i->offset],
+ &new_messages.buffer[i->offset] + i->bytes);
+ }
+ // Set up the iterators pointing to the next header in each block
+ for (std::size_t i = 0; i < incoming.next_header.size(); ++i)
+ incoming.next_header[i] = incoming.headers.begin();
+#ifndef NO_IMMEDIATE_PROCESSING
+ process_batch(source);
+#endif
+ }
+ else {
+ #ifdef DEBUG
+ std::cerr << "Pushing incoming message batch onto queue since we are already processing a batch.\n";
+ #endif
+ // use swap to avoid copying
+ impl_->new_batches.push(std::make_pair(int(source),outgoing_messages()));
+ impl_->new_batches.back().second.swap(new_messages);
+ impl_->max_received = (std::max)(impl_->max_received,impl_->new_batches.size());
+ }
+}
+
+
+void mpi_process_group::pack_headers() const
+{
+ for (process_id_type other = 0; other < num_processes(*this); ++other) {
+ typedef std::vector<impl::message_header>::iterator iterator;
+
+ impl::incoming_messages& incoming = impl_->incoming[other];
+
+ buffer_type remaining_buffer;
+ std::vector<impl::message_header> remaining_headers;
+
+ iterator end = incoming.headers.end();
+ for (iterator i = incoming.headers.begin(); i != end; ++i) {
+ if (i->tag == -1)
+ continue;
+
+ // Hold on to this message until the next stage
+ remaining_headers.push_back(*i);
+ remaining_headers.back().offset = remaining_buffer.size();
+ remaining_buffer.insert(remaining_buffer.end(),
+ &incoming.buffer[i->offset],
+ &incoming.buffer[i->offset] + i->bytes);
+ }
+
+ // Swap the remaining messages into the "incoming" set.
+ incoming.headers.swap(remaining_headers);
+ incoming.buffer.swap(remaining_buffer);
+
+ // Set up the iterators pointing to the next header in each block
+ for (std::size_t i = 0; i < incoming.next_header.size(); ++i)
+ incoming.next_header[i] = incoming.headers.begin();
+ }
+}
+
+void mpi_process_group::receive_batch(boost::mpi::status& status) const
+{
+ //std::cerr << "Handling batch\n";
+ outgoing_messages batch;
+ //impl_->comm.recv(status.source(),status.tag(),batch);
+
+ //receive_oob(*this,status.source(),msg_batch,batch);
+
+ // Determine how big the receive buffer should be
+#if BOOST_VERSION >= 103600
+ int size = status.count<boost::mpi::packed>().get();
+#else
+ int size;
+ MPI_Status mpi_status(status);
+ MPI_Get_count(&mpi_status, MPI_PACKED, &size);
+#endif
+
+ // Allocate the receive buffer
+ boost::mpi::packed_iarchive in(impl_->comm,size);
+
+ // Receive the message data
+ MPI_Recv(in.address(), size, MPI_PACKED,
+ status.source(), status.tag(),
+ impl_->comm, MPI_STATUS_IGNORE);
+
+ // Unpack the message data
+ in >> batch;
+ receive_batch(status.source(),batch);
+}
+
+std::pair<boost::mpi::communicator, int>
+mpi_process_group::actual_communicator_and_tag(int tag, int block) const
+{
+ if (tag >= max_tags * static_cast<int>(impl_->blocks.size()))
+ // Use the out-of-band reply communicator
+ return std::make_pair(impl_->oob_reply_comm, tag);
+ else
+ // Use the normal communicator and translate the tag
+ return std::make_pair(impl_->comm,
+ encode_tag(block == -1? my_block_number() : block,
+ tag));
+}
+
+
+void mpi_process_group::synchronize() const
+{
+ // Don't synchronize if we've already finished
+ if (boost::mpi::environment::finalized())
+ return;
+
+#ifdef DEBUG
+ std::cerr << "SYNC: " << process_id(*this) << std::endl;
+#endif
+
+ emit_on_synchronize();
+
+ process_id_type id = process_id(*this); // Our rank
+ process_size_type p = num_processes(*this); // The number of processes
+
+ // Pack the remaining incoming messages into the beginning of the
+ // buffers, so that we can receive new messages in this
+ // synchronization step without losing those messages that have not
+ // yet been received.
+ pack_headers();
+
+ impl_->synchronizing_stage[id] = -1;
+ int stage=-1;
+ bool no_new_messages = false;
+ while (true) {
+ ++stage;
+#ifdef DEBUG
+ std::cerr << "SYNC: " << id << " starting stage " << (stage+1) << ".\n";
+#endif
+
+ // Tell everyone that we are synchronizing. Note: we use MPI_Isend since
+ // we absolutely cannot have any of these operations blocking.
+
+ // increment the stage for the source
+ ++impl_->synchronizing_stage[id];
+ if (impl_->synchronizing_stage[id] != stage)
+ std::cerr << "Expected stage " << stage << ", got " << impl_->synchronizing_stage[id] << std::endl;
+ assert(impl_->synchronizing_stage[id]==stage);
+ // record how many still have messages to be sent
+ if (static_cast<int>(impl_->synchronizing_unfinished.size())<=stage) {
+ assert(static_cast<int>(impl_->synchronizing_unfinished.size()) == stage);
+ impl_->synchronizing_unfinished.push_back(no_new_messages ? 0 : 1);
+ }
+ else
+ impl_->synchronizing_unfinished[stage]+=(no_new_messages ? 0 : 1);
+
+ // record how many are in that stage
+ if (static_cast<int>(impl_->processors_synchronizing_stage.size())<=stage) {
+ assert(static_cast<int>(impl_->processors_synchronizing_stage.size()) == stage);
+ impl_->processors_synchronizing_stage.push_back(1);
+ }
+ else
+ ++impl_->processors_synchronizing_stage[stage];
+
+ impl_->synchronizing = true;
+
+ for (int dest = 0; dest < p; ++dest) {
+ int sync_message = no_new_messages ? -1 : impl_->number_sent_batches[dest];
+ if (dest != id) {
+ impl_->number_sent_batches[dest]=0;
+ MPI_Request request;
+ MPI_Isend(&sync_message, 1, MPI_INT, dest, msg_synchronizing, impl_->comm,&request);
+ int done=0;
+ do {
+ poll();
+ MPI_Test(&request,&done,MPI_STATUS_IGNORE);
+ } while (!done);
+ }
+ else { // need to subtract how many messages I should have received
+ impl_->number_received_batches[id] -=impl_->number_sent_batches[id];
+ impl_->number_sent_batches[id]=0;
+ }
+ }
+
+ // Keep handling out-of-band messages until everyone has gotten
+ // to this point.
+ while (impl_->processors_synchronizing_stage[stage] <p) {
+ // with the trigger based solution we cannot easily pass true here
+ poll(/*wait=*/false, -1, true);
+
+ }
+
+ // check that everyone is at least here
+ for (int source=0; source<p ; ++source)
+ assert(impl_->synchronizing_stage[source] >= stage);
+
+ // receive any batches sent in the meantime
+ // all have to be available already
+ while (true) {
+ bool done=true;
+ for (int source=0; source<p ; ++source)
+ if(impl_->number_received_batches[source] < 0)
+ done = false;
+ if (done)
+ break;
+ poll(false,-1,true);
+ }
+
+#ifndef NO_IMMEDIATE_PROCESSING
+ for (int source=0; source<p ; ++source)
+ assert(impl_->number_received_batches[source] >= 0);
+#endif
+
+ impl_->synchronizing = false;
+
+ // Flush out remaining messages
+ if (impl_->synchronizing_unfinished[stage]==0)
+ break;
+#ifdef NO_IMMEDIATE_PROCESSING
+ for (process_id_type dest = 0; dest < p; ++dest)
+ process_batch(dest);
+#endif
+
+ no_new_messages = true;
+ for (process_id_type dest = 0; dest < p; ++dest) {
+ if (impl_->outgoing[dest].headers.size() ||
+ impl_->number_sent_batches[dest]>0)
+ no_new_messages = false;
+ send_batch(dest);
+ }
+ }
+
+ impl_->comm.barrier/*nomacro*/();
+#if 0
+ // set up for next synchronize call
+ for (int source=0; source<p; ++source) {
+ if (impl_->synchronizing_stage[source] != stage) {
+ std::cerr << id << ": expecting stage " << stage << " from source "
+ << source << ", got " << impl_->synchronizing_stage[source]
+ << std::endl;
+ }
+ assert(impl_->synchronizing_stage[source]==stage);
+ }
+#endif
+ std::fill(impl_->synchronizing_stage.begin(),
+ impl_->synchronizing_stage.end(), -1);
+
+ // get rid of the information regarding recorded numbers of processors
+ // for the stages we just finished
+ impl_->processors_synchronizing_stage.clear();
+ impl_->synchronizing_unfinished.clear();
+
+ for (process_id_type dest = 0; dest < p; ++dest)
+ assert (impl_->outgoing[dest].headers.empty());
+#ifndef NO_IMMEDIATE_PROCESSING
+ for (int source=0; source<p ; ++source)
+ assert (impl_->number_received_batches[source] == 0);
+#endif
+
+ impl_->free_sent_batches();
+#ifdef DEBUG
+ std::cerr << "SYNC: " << process_id(*this) << " completed." << std::endl;
+#endif
+}
+
+optional<std::pair<mpi_process_group::process_id_type, int> >
+probe(const mpi_process_group& pg)
+{ return pg.probe(); }
+
+void mpi_process_group::poll_requests(int block) const
+{
+ int size = impl_->requests.size();
+ if (size==0)
+ return;
+ std::vector<MPI_Status> statuses(size);
+ std::vector<int> indices(size);
+
+ while (true) {
+ MPI_Testsome(impl_->requests.size(),&impl_->requests[0],
+ &size,&indices[0],&statuses[0]);
+ if (size==0)
+ return; // no message waiting
+
+ // remove handled requests before we get the chance to be recursively called
+ if (size) {
+ std::vector<MPI_Request> active_requests;
+ std::size_t i=0;
+ int j=0;
+ for (;i< impl_->requests.size() && j< size; ++i) {
+ if (int(i)==indices[j])
+ // release the dealt-with request
+ ++j;
+ else // copy and keep the request
+ active_requests.push_back(impl_->requests[i]);
+ }
+ while (i < impl_->requests.size())
+ active_requests.push_back(impl_->requests[i++]);
+ impl_->requests.swap(active_requests);
+ }
+
+ optional<std::pair<int, int> > result;
+ for (int i=0;i < size; ++i) {
+ std::pair<int, int> decoded = decode_tag(statuses[i].MPI_TAG);
+ block_type* block = impl_->blocks[decoded.first];
+
+ assert (decoded.second < static_cast<int>(block->triggers.size()) && block->triggers[decoded.second]);
+ // We have a trigger for this message; use it
+ trigger_receive_context old_context = impl_->trigger_context;
+ impl_->trigger_context = trc_irecv_out_of_band;
+ block->triggers[decoded.second]->receive(*this, statuses[i].MPI_SOURCE,
+ decoded.second, impl_->trigger_context, decoded.first);
+ impl_->trigger_context = old_context;
+ }
+ }
+}
+
+
+optional<std::pair<int, int> >
+mpi_process_group::
+poll(bool wait, int block, bool synchronizing) const
+{
+ // Set the new trigger context for these receive operations
+ trigger_receive_context old_context = impl_->trigger_context;
+ if (synchronizing)
+ impl_->trigger_context = trc_in_synchronization;
+ else
+ impl_->trigger_context = trc_out_of_band;
+
+ //wait = false;
+ optional<boost::mpi::status> status;
+ bool finished=false;
+ optional<std::pair<int, int> > result;
+ do {
+ poll_requests(block);
+ // Check for any messages not yet received.
+#ifdef PBGL_PROCESS_GROUP_NO_IRECV
+ if (wait)
+ status = impl_->comm.probe();
+ else
+#endif
+ status = impl_->comm.iprobe();
+
+ if (status) { // we have a message
+ // Decode the message
+ std::pair<int, int> decoded = decode_tag(status.get().tag());
+ if (maybe_emit_receive(status.get().source(), status.get().tag()))
+ // We received the message out-of-band; poll again
+ finished = false;
+ else if (decoded.first == (block == -1 ? my_block_number() : block)) {
+ // This message is for us, but not through a trigger. Return
+ // the decoded message.
+ result = std::make_pair(status.get().source(), decoded.second);
+ // otherwise we didn't match any message we know how to deal with, so
+ // pretend no message exists.
+ finished = true;
+ }
+ }
+ else
+ // We don't have a message to process; we're done.
+ finished=!wait;
+ } while (!finished);
+
+ // Restore the prior trigger context
+ impl_->trigger_context = old_context;
+ poll_requests(block);
+ return result;
+}
+
+void synchronize(const mpi_process_group& pg) { pg.synchronize(); }
+
+mpi_process_group mpi_process_group::base() const
+{
+ mpi_process_group copy(*this);
+ copy.block_num.reset();
+ return copy;
+}
+
+
+void mpi_process_group::impl::free_sent_batches()
+{
+ typedef std::list<batch_request>::iterator iterator;
+ iterator it = sent_batches.begin();
+ int flag;
+ int result;
+ while(it != sent_batches.end()) {
+ result = MPI_Test(&it->request,&flag,MPI_STATUS_IGNORE);
+ assert(result == MPI_SUCCESS);
+ iterator next=it;
+ ++next;
+ if (flag)
+ sent_batches.erase(it);
+ it=next;
+ }
+#ifdef PREALLOCATE_BATCHES
+ for (std::size_t i=0; i< batch_pool.size();++i) {
+ if(batch_pool[i].request != MPI_REQUEST_NULL) {
+ result = MPI_Test(&batch_pool[i].request,&flag,MPI_STATUS_IGNORE);
+ assert(result == MPI_SUCCESS);
+ if (flag) {
+ free_batches.push(i);
+ batch_pool[i].request = MPI_REQUEST_NULL;
+ batch_pool[i].buffer.resize(0);
+ }
+ }
+ }
+#endif
+}
+
+void
+mpi_process_group::install_trigger(int tag, int block,
+ shared_ptr<trigger_base> const& launcher)
+{
+ block_type* my_block = impl_->blocks[block];
+ assert(my_block);
+
+ // Make sure we have enough space in the structure for this trigger.
+ if (launcher->tag() >= static_cast<int>(my_block->triggers.size()))
+ my_block->triggers.resize(launcher->tag() + 1);
+
+ // If someone already put a trigger in this spot, we have a big
+ // problem.
+ if (my_block->triggers[launcher->tag()]) {
+ std::cerr << "Block " << my_block_number()
+ << " already has a trigger for tag " << launcher->tag()
+ << std::endl;
+ }
+ assert(!my_block->triggers[launcher->tag()]);
+
+ // Attach a new trigger launcher
+ my_block->triggers[launcher->tag()] = launcher;
+}
+
+std::size_t mpi_process_group::message_buffer_size()
+{
+ return message_buffer.size();
+}
+
+
+void mpi_process_group::set_message_buffer_size(std::size_t s)
+{
+ int sz;
+ void* ptr;
+ if (!message_buffer.empty()) {
+ MPI_Buffer_detach(&ptr,&sz);
+ assert(ptr == &message_buffer.front());
+ assert(static_cast<std::size_t>(sz) == message_buffer.size());
+ }
+ else if (old_buffer != 0)
+ MPI_Buffer_detach(&old_buffer,&old_buffer_size);
+ message_buffer.resize(s);
+ if (s)
+ MPI_Buffer_attach(&message_buffer.front(), message_buffer.size());
+ else if (old_buffer_size)
+ MPI_Buffer_attach(old_buffer, old_buffer_size);
+}
+
+
+std::vector<char> mpi_process_group::message_buffer;
+int mpi_process_group::old_buffer_size=0;
+void* mpi_process_group::old_buffer=0;
+
+} } } // end namespace boost::graph::distributed

Added: trunk/libs/graph_parallel/src/tag_allocator.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/src/tag_allocator.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,45 @@
+// Copyright (C) 2007 Douglas Gregor <doug.gregor_at_[hidden]>
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#include <boost/graph/use_mpi.hpp>
+#include <boost/graph/distributed/detail/tag_allocator.hpp>
+
+namespace boost { namespace graph { namespace distributed { namespace detail {
+
+tag_allocator::token tag_allocator::get_tag()
+{
+ int tag;
+
+ if (!freed.empty()) {
+ // Grab the tag at the top of the stack.
+ tag = freed.back();
+ freed.pop_back();
+ } else
+ // Grab the bottom tag and move the bottom down
+ tag = bottom--;
+
+ return token(this, tag);
+}
+
+tag_allocator::token::token(const token& other)
+ : allocator(other.allocator), tag_(other.tag_)
+{
+ // other no longer owns this tag
+ other.tag_ = -1;
+}
+
+tag_allocator::token::~token()
+{
+ if (tag_ != -1) {
+ if (tag_ == allocator->bottom + 1)
+ // This is the bottommost tag: just bump up the bottom
+ ++allocator->bottom;
+ else
+ // This tag isn't the bottom, so push it only the freed stack
+ allocator->freed.push_back(tag_);
+ }
+}
+
+} } } } // end namespace boost::graph::distributed::detail

Added: trunk/libs/graph_parallel/test/CMakeLists.txt
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/CMakeLists.txt 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,113 @@
+FIND_PACKAGE(MPI)
+if (MPI_FOUND)
+message(STATUS "MPI Found")
+
+boost_additional_test_dependencies(graph_parallel BOOST_DEPENDS test mpi filesystem system)
+
+include_directories(${MPI_INCLUDE_PATH})
+
+# Declare a test for the Boost.MPI library, which may involve both
+# building the test and executing it with varying numbers of
+# processes. Edited to become boost_graph_parallel_test, with a different
+# default number of processors.
+#
+# boost_graph_parallel_test(testname
+# [source1 source2 ...]
+# [ARGS arg1 arg2 ...]
+# [SCHEDULE procs1 procs2 ...]
+#
+# testname is the name of the test. source1, source2, etc. are the
+# source files that will be built and linked into the test
+# executable. If no source files are provided, the file "testname.cpp"
+# will be used instead.
+macro(boost_graph_parallel_test testname)
+ PARSE_ARGUMENTS(MPI_TEST "NUMPROCS;ARGS" "" ${ARGN})
+
+ # Determine the test sources
+ if (MPI_TEST_DEFAULT_ARGS)
+ set(MPI_TEST_SOURCES ${MPI_TEST_DEFAULT_ARGS})
+ else (MPI_TEST_DEFAULT_ARGS)
+ set(MPI_TEST_SOURCES "${testname}.cpp")
+ endif (MPI_TEST_DEFAULT_ARGS)
+
+ # Build the test executable
+ boost_add_executable(${testname}
+ ${MPI_TEST_SOURCES}
+ OUTPUT_NAME tests/${PROJECT_NAME}/${testname}
+ NO_INSTALL
+ DEPENDS boost_graph_parallel boost_system
+ COMPILE_FLAGS "${MPI_COMPILE_FLAGS}"
+ LINK_FLAGS "${MPI_LINK_FLAGS}"
+ LINK_LIBS ${MPI_LIBRARIES}
+ SHARED_COMPILE_FLAGS "-DBOOST_MPI_DYN_LINK=1")
+ # if (THIS_EXE_OKAY)
+ if (NOT MPI_TEST_NUMPROCS)
+ set(MPI_TEST_NUMPROCS ${MPIEXEC_MAX_NUMPROCS})
+ endif (NOT MPI_TEST_NUMPROCS)
+
+ foreach(PROCS ${MPI_TEST_NUMPROCS})
+ add_test("${PROJECT_NAME}::${testname}-${PROCS}"
+ ${MPIEXEC}
+ -n ${PROCS}
+ ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/tests/${PROJECT_NAME}/${testname}
+ ${BOOST_TEST_ARGS}
+ )
+ endforeach(PROCS)
+ # endif (THIS_EXE_OKAY)
+endmacro(boost_graph_parallel_test)
+
+boost_graph_parallel_test(distributed_property_map_test)
+boost_graph_parallel_test(distributed_queue_test)
+boost_graph_parallel_test(process_group_serialization)
+boost_graph_parallel_test(adjlist_build_test)
+boost_graph_parallel_test(adjlist_redist_test)
+boost_graph_parallel_test(adjlist_remove_test NUMPROCS 2)
+boost_graph_parallel_test(distributed_adjacency_list_test)
+boost_graph_parallel_test(distributed_connected_components_test)
+boost_graph_parallel_test(distributed_page_rank_test)
+boost_graph_parallel_test(distributed_csr_test)
+boost_graph_parallel_test(distributed_dfs_test)
+boost_graph_parallel_test(distributed_graph_coloring_test)
+boost_graph_parallel_test(distributed_mst_test)
+boost_graph_parallel_test(distributed_strong_components_test)
+boost_graph_parallel_test(hohberg_biconnected_components_test)
+boost_graph_parallel_test(mesh_generator_test ARGS 1000 1000 1 0)
+boost_graph_parallel_test(named_vertices_seq NUMPROCS 1)
+boost_graph_parallel_test(distributed_shortest_paths_test)
+boost_graph_parallel_test(distributed_csr_algorithm_test NUMPROCS 1)
+boost_graph_parallel_test(distributed_betweenness_centrality_test)
+boost_graph_parallel_test(distributed_dimacs_reader)
+boost_graph_parallel_test(distributed_rmat_cc_ps)
+boost_graph_parallel_test(distributed_rmat_cc)
+boost_graph_parallel_test(distributed_rmat_pagerank)
+
+boost_add_executable(ssca
+ ssca.cpp
+ OUTPUT_NAME tests/${PROJECT_NAME}/ssca
+ NO_INSTALL
+ DEPENDS boost_graph_parallel boost_system
+ COMPILE_FLAGS "${MPI_COMPILE_FLAGS}"
+ LINK_FLAGS "${MPI_LINK_FLAGS}"
+ LINK_LIBS ${MPI_LIBRARIES}
+ SHARED_COMPILE_FLAGS "-DBOOST_MPI_DYN_LINK=1")
+
+boost_add_executable(algorithm_performance
+ algorithm_performance.cpp
+ OUTPUT_NAME tests/${PROJECT_NAME}/algorithm_performance
+ NO_INSTALL
+ DEPENDS boost_graph_parallel boost_system
+ COMPILE_FLAGS "${MPI_COMPILE_FLAGS}"
+ LINK_FLAGS "${MPI_LINK_FLAGS}"
+ LINK_LIBS ${MPI_LIBRARIES}
+ SHARED_COMPILE_FLAGS "-DBOOST_MPI_DYN_LINK=1")
+
+if(NOT MSVC)
+ # Due to poor handling of partial ordering of class template partial
+ # specializations, we disable these features and tests on Visual C++.
+ # Tested with Visual C++ 9 (Microsoft Visual Studio 2008); earlier
+ # versions are no better.
+ boost_graph_parallel_test(named_vertices_test)
+ boost_graph_parallel_test(named_vertices_hash_test)
+endif(NOT MSVC)
+
+endif(MPI_FOUND)

Added: trunk/libs/graph_parallel/test/adjlist_build_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/adjlist_build_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,245 @@
+// Copyright (C) 2007 Douglas Gregor
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/lexical_cast.hpp>
+#include <ctime>
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+
+ int n = 10000;
+ double p = 3e-3;
+ int seed = std::time(0);
+ int immediate_response_percent = 10;
+
+ if (argc > 1) n = lexical_cast<int>(argv[1]);
+ if (argc > 2) p = lexical_cast<double>(argv[2]);
+ if (argc > 3) seed = lexical_cast<int>(argv[3]);
+
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ bidirectionalS> Graph;
+
+ mpi_process_group pg;
+ int rank = process_id(pg);
+ int numprocs = num_processes(pg);
+ bool i_am_root = rank == 0;
+
+ // broadcast the seed
+ broadcast(pg, seed, 0);
+
+ // Random number generator
+ minstd_rand gen;
+ minstd_rand require_response_gen;
+
+ if (i_am_root) {
+ std::cout << "n = " << n << ", p = " << p << ", seed = " << seed
+ << "\nBuilding graph with the iterator constructor... ";
+ std::cout.flush();
+ }
+
+ // Build a graph using the iterator constructor, where each of the
+ // processors has exactly the same information.
+ gen.seed(seed);
+ Graph g1(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, p),
+ erdos_renyi_iterator<minstd_rand, Graph>(),
+ n, pg, Graph::graph_property_type());
+ // NGE: Grrr, the default graph property is needed to resolve an
+ // ambiguous overload in the adjaceny list constructor
+
+ // Build another, identical graph using add_edge
+ if (i_am_root) {
+ std::cout << "done.\nBuilding graph with add_edge from the root...";
+ std::cout.flush();
+ }
+
+ gen.seed(seed);
+ require_response_gen.seed(1);
+ Graph g2(n, pg);
+ if (i_am_root) {
+ // The root will add all of the edges, some percentage of which
+ // will require an immediate response from the owner of the edge.
+ for (erdos_renyi_iterator<minstd_rand, Graph> first(gen, n, p), last;
+ first != last; ++first) {
+ Graph::lazy_add_edge lazy
+ = add_edge(vertex(first->first, g2), vertex(first->second, g2), g2);
+
+ if (require_response_gen() % 100 < immediate_response_percent) {
+ // Send out-of-band to require a response
+ std::pair<graph_traits<Graph>::edge_descriptor, bool> result(lazy);
+ BOOST_CHECK(source(result.first, g2) == vertex(first->first, g2));
+ BOOST_CHECK(target(result.first, g2) == vertex(first->second, g2));
+ }
+ }
+ }
+
+ if (i_am_root) {
+ std::cout << "synchronizing...";
+ std::cout.flush();
+ }
+
+ synchronize(g2);
+
+ // Verify that the two graphs are indeed identical.
+ if (i_am_root) {
+ std::cout << "done.\nVerifying graphs...";
+ std::cout.flush();
+ }
+
+ // Check the number of vertices
+ if (num_vertices(g1) != num_vertices(g2)) {
+ std::cerr << g1.processor() << ": g1 has " << num_vertices(g1)
+ << " vertices, g2 has " << num_vertices(g2) << " vertices.\n";
+ communicator(pg).abort(-1);
+ }
+
+ // Check the number of edges
+ if (num_edges(g1) != num_edges(g2)) {
+ std::cerr << g1.processor() << ": g1 has " << num_edges(g1)
+ << " edges, g2 has " << num_edges(g2) << " edges.\n";
+ communicator(pg).abort(-1);
+ }
+
+ // Check the in-degree and out-degree of each vertex
+ graph_traits<Graph>::vertex_iterator vfirst1, vlast1, vfirst2, vlast2;
+ tie(vfirst1, vlast1) = vertices(g1);
+ tie(vfirst2, vlast2) = vertices(g2);
+ for(; vfirst1 != vlast1 && vfirst2 != vlast2; ++vfirst1, ++vfirst2) {
+ if (out_degree(*vfirst1, g1) != out_degree(*vfirst2, g2)) {
+ std::cerr << g1.processor() << ": out-degree mismatch ("
+ << out_degree(*vfirst1, g1) << " vs. "
+ << out_degree(*vfirst2, g2) << ").\n";
+ communicator(pg).abort(-1);
+ }
+
+ if (in_degree(*vfirst1, g1) != in_degree(*vfirst2, g2)) {
+ std::cerr << g1.processor() << ": in-degree mismatch ("
+ << in_degree(*vfirst1, g1) << " vs. "
+ << in_degree(*vfirst2, g2) << ").\n";
+ communicator(pg).abort(-1);
+ }
+ }
+
+ // TODO: Check the actual edge targets
+
+ // Build another, identical graph using add_edge
+ if (i_am_root) {
+ std::cout << "done.\nBuilding graph with add_edge from everywhere...";
+ std::cout.flush();
+ }
+
+ gen.seed(seed);
+ require_response_gen.seed(1);
+ Graph g3(n, pg);
+
+ {
+ // Each processor will take a chunk of incoming edges and add
+ // them. Some percentage of the edge additions will require an
+ // immediate response from the owner of the edge. This should
+ // create a lot of traffic when building the graph, but should
+ // produce a graph identical to the other graphs.
+ typedef graph_traits<Graph>::edges_size_type edges_size_type;
+
+ erdos_renyi_iterator<minstd_rand, Graph> first(gen, n, p);
+ edges_size_type chunk_size = edges_size_type(p*n*n)/numprocs;
+ edges_size_type start = chunk_size * rank;
+ edges_size_type remaining_edges =
+ (rank < numprocs - 1? chunk_size
+ : edges_size_type(p*n*n) - start);
+
+ // Spin the generator to the first edge we're responsible for
+ for (; start; ++first, --start) ;
+
+ for (; remaining_edges; --remaining_edges, ++first) {
+ Graph::lazy_add_edge lazy
+ = add_edge(vertex(first->first, g3), vertex(first->second, g3), g3);
+
+ if (require_response_gen() % 100 < immediate_response_percent) {
+ // Send out-of-band to require a response
+ std::pair<graph_traits<Graph>::edge_descriptor, bool> result(lazy);
+ BOOST_CHECK(source(result.first, g3) == vertex(first->first, g3));
+ BOOST_CHECK(target(result.first, g3) == vertex(first->second, g3));
+ }
+ }
+ }
+
+ if (i_am_root) {
+ std::cout << "synchronizing...";
+ std::cout.flush();
+ }
+
+ synchronize(g3);
+
+ // Verify that the two graphs are indeed identical.
+ if (i_am_root) {
+ std::cout << "done.\nVerifying graphs...";
+ std::cout.flush();
+ }
+
+ // Check the number of vertices
+ if (num_vertices(g1) != num_vertices(g3)) {
+ std::cerr << g1.processor() << ": g1 has " << num_vertices(g1)
+ << " vertices, g3 has " << num_vertices(g3) << " vertices.\n";
+ communicator(pg).abort(-1);
+ }
+
+ // Check the number of edges
+ if (num_edges(g1) != num_edges(g3)) {
+ std::cerr << g1.processor() << ": g1 has " << num_edges(g1)
+ << " edges, g3 has " << num_edges(g3) << " edges.\n";
+ communicator(pg).abort(-1);
+ }
+
+ // Check the in-degree and out-degree of each vertex
+ tie(vfirst1, vlast1) = vertices(g1);
+ tie(vfirst2, vlast2) = vertices(g3);
+ for(; vfirst1 != vlast1 && vfirst2 != vlast2; ++vfirst1, ++vfirst2) {
+ if (out_degree(*vfirst1, g1) != out_degree(*vfirst2, g3)) {
+ std::cerr << g1.processor() << ": out-degree mismatch ("
+ << out_degree(*vfirst1, g1) << " vs. "
+ << out_degree(*vfirst2, g3) << ").\n";
+ communicator(pg).abort(-1);
+ }
+
+ if (in_degree(*vfirst1, g1) != in_degree(*vfirst2, g3)) {
+ std::cerr << g1.processor() << ": in-degree mismatch ("
+ << in_degree(*vfirst1, g1) << " vs. "
+ << in_degree(*vfirst2, g3) << ").\n";
+ communicator(pg).abort(-1);
+ }
+ }
+
+ // TODO: Check the actual edge targets
+
+ if (i_am_root) {
+ std::cout << "done.\n";
+ std::cout.flush();
+ }
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/adjlist_redist_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/adjlist_redist_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,216 @@
+// Copyright (C) 2005, 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <iostream>
+#include <boost/property_map/property_map_iterator.hpp>
+#include <boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp>
+#include <boost/graph/distributed/vertex_list_adaptor.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/graph/distributed/graphviz.hpp>
+#include <sstream>
+#include <string>
+#include <boost/graph/iteration_macros.hpp>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+/****************************************************************************
+ * Edge weight generator iterator *
+ ****************************************************************************/
+template<typename F>
+class generator_iterator
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename F::result_type value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ explicit generator_iterator(const F& f = F()) : f(f) { value = this->f(); }
+
+ reference operator*() const { return value; }
+ pointer operator->() const { return &value; }
+
+ generator_iterator& operator++()
+ {
+ value = f();
+ return *this;
+ }
+
+ generator_iterator operator++(int)
+ {
+ generator_iterator temp(*this);
+ ++(*this);
+ return temp;
+ }
+
+ bool operator==(const generator_iterator& other) const
+ { return f == other.f; }
+
+ bool operator!=(const generator_iterator& other) const
+ { return !(*this == other); }
+
+private:
+ F f;
+ value_type value;
+};
+
+template<typename F>
+inline generator_iterator<F> make_generator_iterator(const F& f)
+{ return generator_iterator<F>(f); }
+
+typedef minstd_rand RandomGenerator;
+
+template<typename Graph>
+double get_mst_weight (const Graph& g)
+{
+ typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
+ typename property_map<Graph, edge_weight_t>::const_type weight
+ = get(edge_weight, g);
+
+ // Boruvka then merge test
+ std::vector<edge_descriptor> results;
+ graph::boruvka_then_merge(make_vertex_list_adaptor(g), weight,
+ std::back_inserter(results));
+ if (process_id(g.process_group()) == 0)
+ return accumulate(make_property_map_iterator(weight, results.begin()),
+ make_property_map_iterator(weight, results.end()),
+ 0.0);
+ else
+ return 0.0;
+}
+
+template<typename Graph>
+void test_redistribution(int n, double p, int iterations, bool debug_output)
+{
+ typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
+ RandomGenerator gen;
+ Graph g(erdos_renyi_iterator<RandomGenerator, Graph>(gen, n, p),
+ erdos_renyi_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(uniform_01<RandomGenerator>(gen)),
+ n);
+
+ int iter = 0;
+ mpi_process_group pg = g.process_group();
+
+ // Set the names of the vertices to be the global index in the
+ // initial distribution. Then when we are debugging we'll be able to
+ // see how vertices have moved.
+ {
+ typedef typename property_map<Graph, vertex_index_t>::type VertexIndexMap;
+ typedef typename property_map<Graph, vertex_global_t>::type VertexGlobalMap;
+ typename property_map<Graph, vertex_name_t>::type name_map
+ = get(vertex_name, g);
+
+ parallel::global_index_map<VertexIndexMap, VertexGlobalMap>
+ global_index(g.process_group(), num_vertices(g),
+ get(vertex_index, g), get(vertex_global, g));
+ BGL_FORALL_VERTICES_T(v, g, Graph)
+ put(name_map, v, get(global_index, v));
+ }
+
+ if (debug_output)
+ write_graphviz("redist-0.dot", g,
+ make_label_writer(get(vertex_name, g)),
+ make_label_writer(get(edge_weight, g)));
+
+ double mst_weight = get_mst_weight(g);
+ if (process_id(pg) == 0)
+ std::cout << "MST weight = " << mst_weight << std::endl;
+
+ RandomGenerator nonsync_gen(process_id(pg) + gen());
+ while (++iter <= iterations) {
+ typename property_map<Graph, vertex_rank_t>::type to_processor_map =
+ get(vertex_rank, g);
+
+ // Randomly assign a new distribution
+ typename graph_traits<Graph>::vertex_iterator vi, vi_end;
+ for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
+ put(to_processor_map, *vi, gen() % num_processes(pg));
+
+ if (process_id(pg) == 0)
+ std::cout << "Redistributing...";
+ // Perform the actual redistribution
+ g.redistribute(to_processor_map);
+
+ if (process_id(pg) == 0)
+ std::cout << " done." << std::endl;
+
+ if (debug_output) {
+ std::ostringstream out;
+ out << "redist-" << iter << ".dot";
+ write_graphviz(out.str().c_str(), g,
+ make_label_writer(get(vertex_name, g)),
+ make_label_writer(get(edge_weight, g)));
+ }
+
+ // Check that the MST weight is unchanged
+ double new_mst_weight = get_mst_weight(g);
+ if (process_id(pg) == 0) {
+ std::cout << "MST weight = " << new_mst_weight << std::endl;
+ if (std::fabs(new_mst_weight - mst_weight) > 0.0001)
+ communicator(pg).abort(-1); }
+ }
+}
+
+int test_main(int argc, char** argv)
+{
+ int n = 1000;
+ double p = 3e-3;
+ int iterations = 5;
+ bool debug_output = false;
+
+ boost::mpi::environment env(argc, argv);
+
+ if (argc > 1) n = lexical_cast<int>(argv[1]);
+ if (argc > 2) p = lexical_cast<double>(argv[2]);
+ if (argc > 3) iterations = lexical_cast<int>(argv[3]);
+ if (argc > 4) debug_output = true;
+
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS,
+ // Vertex properties
+ property<vertex_name_t, std::size_t,
+ property<vertex_rank_t, int> >,
+ // Edge properties
+ property<edge_weight_t, double> > UnstableUDGraph;
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, listS>,
+ undirectedS,
+ // Vertex properties
+ property<vertex_name_t, std::size_t,
+ property<vertex_rank_t, int,
+ property<vertex_index_t, std::size_t> > >,
+ // Edge properties
+ property<edge_weight_t, double> > StableUDGraph;
+
+ test_redistribution<UnstableUDGraph>(n, p, iterations, debug_output);
+ test_redistribution<StableUDGraph>(n, p, iterations, debug_output);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/adjlist_remove_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/adjlist_remove_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,147 @@
+// Copyright 2004 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/parallel/distribution.hpp>
+#include <iostream>
+#include <cassert>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+void test_bidirectional_graph()
+{
+ typedef adjacency_list<listS, distributedS<mpi_process_group, vecS>,
+ bidirectionalS> Graph;
+ typedef graph_traits<Graph>::vertex_descriptor Vertex;
+ typedef graph_traits<Graph>::edge_descriptor Edge;
+
+ typedef std::pair<std::size_t, std::size_t> E;
+ E edges[3] = { E(0,3), E(1,4), E(2,5) };
+
+ Graph g(&edges[0], &edges[0] + 3, 6);
+ assert(num_processes(g.process_group()) == 2);
+
+ if (process_id(g.process_group()) == 0)
+ std::cerr << "Testing bidirectional graph edge removal...";
+ synchronize(g.process_group());
+
+ graph_traits<Graph>::vertex_iterator vi = vertices(g).first;
+ Vertex u = *vi++;
+ Vertex v = *vi++;
+ Vertex w = *vi++;
+ BOOST_CHECK(vi == vertices(g).second);
+
+ BOOST_CHECK(process_id(g.process_group()) == 0 && out_degree(u, g) == 1
+ || process_id(g.process_group()) == 1 && in_degree(u, g) == 1);
+
+ BOOST_CHECK(process_id(g.process_group()) == 0 && out_degree(v, g) == 1
+ || process_id(g.process_group()) == 1 && in_degree(v, g) == 1);
+
+ BOOST_CHECK(process_id(g.process_group()) == 0 && out_degree(w, g) == 1
+ || process_id(g.process_group()) == 1 && in_degree(w, g) == 1);
+
+ // Remove edges
+ if (process_id(g.process_group()) == 0) {
+ remove_edge(*out_edges(u, g).first, g);
+ remove_edge(*out_edges(w, g).first, g);
+ } else {
+ remove_edge(*in_edges(v, g).first, g);
+ remove_edge(*in_edges(w, g).first, g);
+ }
+
+ synchronize(g);
+
+ BOOST_CHECK(num_edges(g) == 0);
+ BOOST_CHECK(out_degree(u, g) == 0);
+ BOOST_CHECK(out_degree(v, g) == 0);
+ BOOST_CHECK(out_degree(w, g) == 0);
+ BOOST_CHECK(in_degree(u, g) == 0);
+ BOOST_CHECK(in_degree(v, g) == 0);
+ BOOST_CHECK(in_degree(w, g) == 0);
+
+ if (process_id(g.process_group()) == 0) std::cerr << "OK.\n";
+}
+
+void test_undirected_graph()
+{
+ typedef adjacency_list<listS, distributedS<mpi_process_group, vecS>,
+ undirectedS> Graph;
+ typedef graph_traits<Graph>::vertex_descriptor Vertex;
+ typedef graph_traits<Graph>::edge_descriptor Edge;
+
+ typedef std::pair<std::size_t, std::size_t> E;
+ E the_edges[3] = { E(0,3), E(1,4), E(2,5) };
+
+ Graph g(&the_edges[0], &the_edges[0] + 3, 6);
+ assert(num_processes(g.process_group()) == 2);
+
+ if (process_id(g.process_group()) == 0)
+ std::cerr << "Testing undirected graph edge removal...";
+ synchronize(g.process_group());
+
+ graph_traits<Graph>::vertex_iterator vi = vertices(g).first;
+ Vertex u = *vi++;
+ Vertex v = *vi++;
+ Vertex w = *vi++;
+ BOOST_CHECK(vi == vertices(g).second);
+ BOOST_CHECK(degree(u, g) == 1);
+ BOOST_CHECK(degree(v, g) == 1);
+ BOOST_CHECK(degree(w, g) == 1);
+
+ // Remove edges
+ if (process_id(g.process_group()) == 0) {
+ BOOST_CHECK(num_edges(g) == 3);
+ remove_edge(*out_edges(u, g).first, g);
+ remove_edge(*out_edges(w, g).first, g);
+ } else {
+ BOOST_CHECK(num_edges(g) == 0);
+ remove_edge(*in_edges(v, g).first, g);
+ remove_edge(*in_edges(w, g).first, g);
+ }
+
+ synchronize(g);
+
+ if (num_edges(g) > 0) {
+ Edge e = *edges(g).first;
+ std::cerr << "#" << process_id(g.process_group()) << ": extra edge! ("
+ << local(source(e, g)) << "@" << owner(source(e, g))
+ << ", "
+ << local(target(e, g)) << "@" << owner(target(e, g))
+ << ")\n";
+ }
+
+ BOOST_CHECK(num_edges(g) == 0);
+ BOOST_CHECK(degree(u, g) == 0);
+ BOOST_CHECK(degree(v, g) == 0);
+ BOOST_CHECK(degree(w, g) == 0);
+ if (process_id(g.process_group()) == 0) std::cerr << "OK.\n";
+}
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+ test_bidirectional_graph();
+ test_undirected_graph();
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/algorithm_performance.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/algorithm_performance.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,883 @@
+// Copyright 2004 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Nick Edmonds
+// Andrew Lumsdaine
+
+// #define PBGL_ACCOUNTING
+
+#include <boost/graph/use_mpi.hpp>
+
+#include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+
+#include <boost/graph/distributed/mpi_process_group.hpp>
+
+#include <boost/test/minimal.hpp>
+#include <boost/random.hpp>
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/graph/distributed/graphviz.hpp>
+#include <boost/graph/iteration_macros.hpp>
+#include <boost/graph/properties.hpp>
+
+#include <boost/graph/rmat_graph_generator.hpp>
+#include <boost/graph/small_world_generator.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+
+#include <boost/graph/distributed/connected_components.hpp>
+#include <boost/graph/distributed/connected_components_parallel_search.hpp>
+#include <boost/graph/distributed/betweenness_centrality.hpp>
+#include <boost/graph/distributed/delta_stepping_shortest_paths.hpp>
+
+#include <time.h>
+#include <sys/time.h>
+
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <stdint.h>
+
+// Edge distribution tags select a generator
+struct rmat_edge_distribution_tag { };
+struct rmat_unique_edge_distribution_tag { };
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+/****************************************************************************
+ * Timing
+ ****************************************************************************/
+#ifndef PBGL_ACCOUNTING
+
+typedef double time_type;
+
+inline time_type get_time()
+{
+ timeval tp;
+ gettimeofday(&tp, 0);
+ return tp.tv_sec + tp.tv_usec / 1000000.0;
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+#endif // PBGL_ACCOUNTING
+
+/****************************************************************************
+ * Edge weight generator iterator *
+ ****************************************************************************/
+template<typename F, typename RandomGenerator>
+class generator_iterator
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename F::result_type value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ explicit
+ generator_iterator(RandomGenerator& gen, const F& f = F())
+ : f(f), gen(&gen)
+ {
+ value = this->f(gen);
+ }
+
+ reference operator*() const { return value; }
+ pointer operator->() const { return &value; }
+
+ generator_iterator& operator++()
+ {
+ value = f(*gen);
+ return *this;
+ }
+
+ generator_iterator operator++(int)
+ {
+ generator_iterator temp(*this);
+ ++(*this);
+ return temp;
+ }
+
+ bool operator==(const generator_iterator& other) const
+ { return f == other.f; }
+
+ bool operator!=(const generator_iterator& other) const
+ { return !(*this == other); }
+
+private:
+ F f;
+ RandomGenerator* gen;
+ value_type value;
+};
+
+template<typename F, typename RandomGenerator>
+inline generator_iterator<F, RandomGenerator>
+make_generator_iterator( RandomGenerator& gen, const F& f)
+{ return generator_iterator<F, RandomGenerator>(gen, f); }
+
+/****************************************************************************
+ * Edge Property *
+ ****************************************************************************/
+typedef int weight_type;
+
+struct WeightedEdge {
+ WeightedEdge(weight_type weight = 0) : weight(weight) { }
+
+ weight_type weight;
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & weight;
+ }
+};
+
+/****************************************************************************
+ * Algorithm Tests *
+ ****************************************************************************/
+template <typename Graph>
+void test_directed_sequential_algorithms(const Graph& g)
+{ }
+
+template <typename Graph>
+void test_undirected_sequential_algorithms(const Graph& g)
+{
+ std::vector<unsigned int> componentS(num_vertices(g));
+ typedef iterator_property_map<
+ std::vector<unsigned int>::iterator,
+ typename property_map<Graph, vertex_index_t>::type>
+ ComponentMap;
+ ComponentMap component(componentS.begin(), get(vertex_index, g));
+
+ time_type start = get_time();
+ unsigned int num_components = connected_components(g, component);
+ time_type end = get_time();
+
+ std::cerr << " Sequential connected Components time = "
+ << print_time(end - start) << " seconds.\n"
+ << " " << num_components << " components identified\n";
+}
+
+template <typename Graph, typename EdgeWeightMap>
+void test_directed_csr_only_algorithms(const Graph& g, EdgeWeightMap weight,
+ typename graph_traits<Graph>::vertices_size_type num_sources,
+ typename property_traits<EdgeWeightMap>::value_type C)
+{
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
+ typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
+ typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
+
+ typedef typename boost::graph::parallel::process_group_type<Graph>::type
+ process_group_type;
+
+ process_group_type pg = process_group(g);
+ typename process_group_type::process_id_type id = process_id(pg);
+ typename process_group_type::process_size_type p = num_processes(pg);
+
+ vertices_size_type n = num_vertices(g);
+ n = boost::parallel::all_reduce(pg, n, std::plus<vertices_size_type>());
+
+ edges_size_type m = num_edges(g);
+ m = boost::parallel::all_reduce(pg, m, std::plus<edges_size_type>());
+
+ //
+ // Betweenness Centrality (Approximate)
+ //
+ queue<vertex_descriptor> delta_stepping_vertices;
+
+ {
+ // Distributed Centrality Map
+ typedef typename property_map<Graph, vertex_index_t>::const_type IndexMap;
+ typedef iterator_property_map<std::vector<int>::iterator, IndexMap> CentralityMap;
+
+ std::vector<int> centralityS(num_vertices(g), 0);
+ CentralityMap centrality(centralityS.begin(), get(vertex_index, g));
+
+ // Calculate number of vertices of degree 0
+ vertices_size_type n0 = 0;
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ if (out_degree(v, g) == 0) n0++;
+ }
+ n0 = boost::parallel::all_reduce(pg, n0, std::plus<vertices_size_type>());
+
+ queue<vertex_descriptor> sources;
+
+ {
+ assert(num_sources >= p); // Don't feel like adding a special case for num_sources < p
+
+ minstd_rand gen;
+ uniform_int<vertices_size_type> rand_vertex(0, num_vertices(g) - 1);
+ std::vector<vertex_descriptor> all_sources, local_sources;
+ vertices_size_type local_vertices = vertices_size_type(floor((double)num_sources / p));
+ local_vertices += (id < (num_sources - (p * local_vertices)) ? 1 : 0);
+
+ while (local_vertices > 0) {
+ vertex_iterator iter = vertices(g).first;
+ std::advance(iter, rand_vertex(gen));
+
+ if (out_degree(*iter, g) != 0
+ && std::find(local_sources.begin(), local_sources.end(), *iter) == local_sources.end()) {
+ local_sources.push_back(*iter);
+ --local_vertices;
+ }
+ }
+ all_gather(pg, local_sources.begin(), local_sources.end(), all_sources);
+ std::sort(all_sources.begin(), all_sources.end());
+ for (typename std::vector<vertex_descriptor>::iterator iter = all_sources.begin();
+ iter != all_sources.end(); ++iter) {
+ sources.push(*iter);
+ delta_stepping_vertices.push(*iter);
+ }
+ }
+
+ // NOTE: The delta below assumes uniform edge weight distribution
+ time_type start = get_time();
+ brandes_betweenness_centrality(g, buffer(sources).weight_map(weight).
+ centrality_map(centrality).lookahead((m / n) * (C / 2)));
+ time_type end = get_time();
+
+ edges_size_type exactTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
+
+ if (id == 0)
+ std::cerr << " Betweenness Centrality Approximate (" << num_sources << " sources) = "
+ << print_time(end - start) << " (" << exactTEPs << " TEPs)\n";
+ }
+
+ //
+ // Delta stepping performance (to compare to SSSP inside BC
+ //
+ if (false) {
+ typedef typename property_map<Graph, vertex_index_t>::const_type IndexMap;
+ typedef iterator_property_map<std::vector<int>::iterator, IndexMap> DistanceMap;
+
+ std::vector<int> distanceS(num_vertices(g), 0);
+ DistanceMap distance(distanceS.begin(), get(vertex_index, g));
+
+ while(!delta_stepping_vertices.empty()) {
+
+ time_type start = get_time();
+ delta_stepping_shortest_paths(g, delta_stepping_vertices.top(), dummy_property_map(),
+ distance, weight);
+ time_type end = get_time();
+
+ delta_stepping_vertices.pop();
+ distance.reset();
+
+ if (id == 0)
+ std::cerr << " Delta-stepping shortest paths = " << print_time(end - start)
+ << std::endl;
+ }
+ }
+
+}
+
+template <typename Graph>
+void test_directed_algorithms(const Graph& g)
+{
+}
+
+template <typename Graph>
+void test_undirected_algorithms(const Graph& g)
+{
+ typedef typename boost::graph::parallel::process_group_type<Graph>::type
+ process_group_type;
+
+ process_group_type pg = process_group(g);
+ typename process_group_type::process_id_type id = process_id(pg);
+ typename process_group_type::process_size_type p = num_processes(pg);
+
+
+ // Connected Components
+ std::vector<unsigned int> local_components_vec(num_vertices(g));
+ typedef iterator_property_map<
+ std::vector<unsigned int>::iterator,
+ typename property_map<Graph, vertex_index_t>::type>
+ ComponentMap;
+ ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
+
+ int num_components;
+
+ time_type start = get_time();
+ num_components = connected_components(g, component);
+ time_type end = get_time();
+ if (id == 0)
+ std::cerr << " Connected Components time = " << print_time(end - start)
+ << " seconds.\n"
+ << " " << num_components << " components identified\n";
+
+ start = get_time();
+ num_components = boost::graph::distributed::connected_components_ps(g, component);
+ end = get_time();
+ if (id == 0)
+ std::cerr << " Connected Components (parallel search) time = "
+ << print_time(end - start) << " seconds.\n"
+ << " " << num_components << " components identified\n";
+}
+
+/****************************************************************************
+ * Graph Type Tests *
+ ****************************************************************************/
+
+// TODO: Re-seed PRNG before sequential tests to get the same graph as the
+// distributed case?
+
+//
+// Compressed Sparse Row
+//
+
+// R-MAT
+template <typename ProcessGroup, typename RandomGenerator, typename Distribution>
+void test_csr(const ProcessGroup& pg, RandomGenerator& gen, Distribution& distrib,
+ bool sequential_tests, size_t N, size_t M, size_t C,
+ double a, double b, double c, double d, size_t num_sources,
+ rmat_edge_distribution_tag)
+{
+ if (process_id(pg) == 0)
+ std::cerr << " R-MAT\n";
+
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge, no_property,
+ distributedS<mpi_process_group> > Graph;
+
+ Graph g(sorted_rmat_iterator<RandomGenerator, Graph>(gen, N, M, a, b, c, d),
+ sorted_rmat_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_directed_algorithms(g);
+ test_directed_csr_only_algorithms(g, get(&WeightedEdge::weight, g), num_sources, C);
+
+ if (sequential_tests && process_id(pg) == 0) {
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge>
+ seqGraph;
+
+ seqGraph sg(sorted_rmat_iterator<RandomGenerator, seqGraph>(gen, N, M, a, b, c, d),
+ sorted_rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_directed_sequential_algorithms(sg);
+ }
+}
+
+// R-MAT with unique edges
+template <typename ProcessGroup, typename RandomGenerator, typename Distribution>
+void test_csr(const ProcessGroup& pg, RandomGenerator& gen, Distribution& distrib,
+ bool sequential_tests, size_t N, size_t M, size_t C,
+ double a, double b, double c, double d, size_t num_sources,
+ rmat_unique_edge_distribution_tag)
+{
+ if (process_id(pg) == 0)
+ std::cerr << " R-MAT - unique\n";
+
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge, no_property,
+ distributedS<mpi_process_group> > Graph;
+
+ // Last boolean parameter makes R-MAT bidirectional
+ Graph g(sorted_unique_rmat_iterator<RandomGenerator, Graph>(gen, N, M, a, b, c, d),
+ sorted_unique_rmat_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_directed_algorithms(g);
+ test_directed_csr_only_algorithms(g, get(&WeightedEdge::weight, g), num_sources, C);
+
+ if (sequential_tests && process_id(pg) == 0) {
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge>
+ seqGraph;
+
+ seqGraph sg(sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(gen, N, M, a, b, c, d),
+ sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_directed_sequential_algorithms(sg);
+ }
+}
+
+// Erdos-Renyi
+template <typename ProcessGroup, typename RandomGenerator, typename Distribution>
+void test_csr(const ProcessGroup& pg, RandomGenerator& gen, Distribution& distrib,
+ bool sequential_tests, size_t N, size_t M, size_t C, size_t num_sources)
+{
+ if (process_id(pg) == 0)
+ std::cerr << " Erdos-Renyi\n";
+
+ double _p = static_cast<double>(M) / (N*N);
+
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge, no_property,
+ distributedS<mpi_process_group> > Graph;
+
+ Graph g(sorted_erdos_renyi_iterator<RandomGenerator, Graph>(gen, N, _p/2),
+ sorted_erdos_renyi_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_directed_algorithms(g);
+ test_directed_csr_only_algorithms(g, get(&WeightedEdge::weight, g), num_sources, C);
+
+ if (sequential_tests && process_id(pg) == 0) {
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge>
+ seqGraph;
+
+ seqGraph sg(sorted_erdos_renyi_iterator<RandomGenerator, seqGraph>(gen, N, _p/2),
+ sorted_erdos_renyi_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_directed_sequential_algorithms(sg);
+ }
+}
+
+// Small World
+template <typename ProcessGroup, typename RandomGenerator, typename Distribution>
+void test_csr(const ProcessGroup& pg, RandomGenerator& gen, Distribution& distrib,
+ bool sequential_tests, size_t N, size_t M, size_t C, double p,
+ size_t num_sources)
+{
+ if (process_id(pg) == 0)
+ std::cerr << " Small-World\n";
+
+ int k = M / N;
+
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge, no_property,
+ distributedS<mpi_process_group> > Graph;
+
+ Graph g(small_world_iterator<RandomGenerator, Graph>(gen, N, k, p),
+ small_world_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_directed_algorithms(g);
+ test_directed_csr_only_algorithms(g, get(&WeightedEdge::weight, g), num_sources, C);
+
+ if (sequential_tests && process_id(pg) == 0) {
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge>
+ seqGraph;
+
+ seqGraph sg(small_world_iterator<RandomGenerator, seqGraph>(gen, N, k, p),
+ small_world_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_directed_sequential_algorithms(sg);
+ }
+}
+
+//
+// Adjacency List
+//
+
+// R-MAT
+template <typename ProcessGroup, typename RandomGenerator, typename Distribution>
+void test_adjacency_list(const ProcessGroup& pg, RandomGenerator& gen, Distribution& distrib,
+ bool sequential_tests, size_t N, size_t M, size_t C,
+ double a, double b, double c, double d,
+ rmat_edge_distribution_tag)
+{
+ if (process_id(pg) == 0)
+ std::cerr << "R-MAT\n";
+
+ {
+ typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ directedS, no_property, WeightedEdge> Graph;
+
+ Graph g(rmat_iterator<RandomGenerator, Graph>(gen, N, M, a, b, c, d),
+ rmat_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_directed_algorithms(g);
+ }
+
+ {
+ typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ undirectedS, no_property, WeightedEdge> Graph;
+
+ Graph g(rmat_iterator<RandomGenerator, Graph>(gen, N, M, a, b, c, d),
+ rmat_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_undirected_algorithms(g);
+ }
+
+ if (sequential_tests && process_id(pg) == 0) {
+ {
+ typedef adjacency_list<vecS, vecS, directedS, no_property, property<edge_weight_t, int> >
+ seqGraph;
+
+ seqGraph sg(rmat_iterator<RandomGenerator, seqGraph>(gen, N, M, a, b, c, d),
+ rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_directed_sequential_algorithms(sg);
+ }
+
+ {
+ typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> >
+ seqGraph;
+
+ seqGraph sg(rmat_iterator<RandomGenerator, seqGraph>(gen, N, M, a, b, c, d),
+ rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_undirected_sequential_algorithms(sg);
+ }
+ }
+}
+
+// R-MAT with unique edges
+template <typename ProcessGroup, typename RandomGenerator, typename Distribution>
+void test_adjacency_list(const ProcessGroup& pg, RandomGenerator& gen, Distribution& distrib,
+ bool sequential_tests, size_t N, size_t M, size_t C,
+ double a, double b, double c, double d,
+ rmat_unique_edge_distribution_tag)
+{
+ if (process_id(pg) == 0)
+ std::cerr << " R-MAT - unique\n";
+
+ {
+ typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ directedS, no_property, WeightedEdge> Graph;
+
+ Graph g(sorted_unique_rmat_iterator<RandomGenerator, Graph>(gen, N, M, a, b, c, d),
+ sorted_unique_rmat_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_directed_algorithms(g);
+ }
+
+ {
+ typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ undirectedS, no_property, WeightedEdge> Graph;
+
+ Graph g(sorted_unique_rmat_iterator<RandomGenerator, Graph>(gen, N, M, a, b, c, d),
+ sorted_unique_rmat_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_undirected_algorithms(g);
+ }
+
+ if (sequential_tests && process_id(pg) == 0) {
+ {
+ typedef adjacency_list<vecS, vecS, directedS, no_property, property<edge_weight_t, int> >
+ seqGraph;
+
+ seqGraph sg(sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(gen, N, M, a, b, c, d),
+ sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_directed_sequential_algorithms(sg);
+ }
+
+ {
+ typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> >
+ seqGraph;
+
+ seqGraph sg(sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(gen, N, M, a, b, c, d),
+ sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_undirected_sequential_algorithms(sg);
+ }
+ }
+}
+
+// Erdos-Renyi
+template <typename ProcessGroup, typename RandomGenerator, typename Distribution>
+void test_adjacency_list(const ProcessGroup& pg, RandomGenerator& gen, Distribution& distrib,
+ bool sequential_tests, size_t N, size_t M, size_t C)
+{
+ if (process_id(pg) == 0)
+ std::cerr << " Erdos-Renyi\n";
+
+ double _p = static_cast<double>(M) / N*N;
+
+ {
+ typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ directedS, no_property, WeightedEdge> Graph;
+
+ Graph g(erdos_renyi_iterator<RandomGenerator, Graph>(gen, N, _p/2),
+ erdos_renyi_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_directed_algorithms(g);
+ }
+
+ {
+ typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ undirectedS, no_property, WeightedEdge> Graph;
+
+ Graph g(erdos_renyi_iterator<RandomGenerator, Graph>(gen, N, _p/2),
+ erdos_renyi_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_undirected_algorithms(g);
+ }
+
+ if (sequential_tests && process_id(pg) == 0) {
+ {
+ typedef adjacency_list<vecS, vecS, directedS, no_property, property<edge_weight_t, int> >
+ seqGraph;
+
+ seqGraph sg(erdos_renyi_iterator<RandomGenerator, seqGraph>(gen, N, _p/2),
+ erdos_renyi_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_directed_sequential_algorithms(sg);
+ }
+
+ {
+ typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> >
+ seqGraph;
+
+ seqGraph sg(erdos_renyi_iterator<RandomGenerator, seqGraph>(gen, N, _p/2),
+ erdos_renyi_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_undirected_sequential_algorithms(sg);
+ }
+ }
+}
+
+// Small World
+template <typename ProcessGroup, typename RandomGenerator, typename Distribution>
+void test_adjacency_list(const ProcessGroup& pg, RandomGenerator& gen, Distribution& distrib,
+ bool sequential_tests, size_t N, size_t M, size_t C, double p)
+{
+ if (process_id(pg) == 0)
+ std::cerr << " Small-World\n";
+
+ int k = M / N;
+
+ {
+ typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ directedS, no_property, WeightedEdge> Graph;
+
+ Graph g(small_world_iterator<RandomGenerator, Graph>(gen, N, k, p),
+ small_world_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_directed_algorithms(g);
+ }
+
+ {
+ typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ undirectedS, no_property, WeightedEdge> Graph;
+
+ Graph g(small_world_iterator<RandomGenerator, Graph>(gen, N, k, p),
+ small_world_iterator<RandomGenerator, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N, pg, distrib);
+
+ test_undirected_algorithms(g);
+ }
+
+ if (sequential_tests && process_id(pg) == 0) {
+ {
+ typedef adjacency_list<vecS, vecS, directedS, no_property, property<edge_weight_t, int> >
+ seqGraph;
+
+ seqGraph sg(small_world_iterator<RandomGenerator, seqGraph>(gen, N, k, p),
+ small_world_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_directed_sequential_algorithms(sg);
+ }
+
+ {
+ typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> >
+ seqGraph;
+
+ seqGraph sg(small_world_iterator<RandomGenerator, seqGraph>(gen, N, k, p),
+ small_world_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ N);
+
+ test_undirected_sequential_algorithms(sg);
+ }
+ }
+}
+
+void usage()
+{
+ std::cerr << "Algorithm Performance Test\n"
+ << "Usage : algorithm_performance [options]\n\n"
+ << "Options are:\n"
+ << "\t--vertices v\t\t\tNumber of vertices in the graph\n"
+ << "\t--edges v\t\t\tNumber of edges in the graph\n"
+ << "\t--seed s\t\t\tSeed for synchronized random number generator\n"
+ << "\t--max-weight miw\t\tMaximum integer edge weight\n"
+ << "\t--rewire-probability\t\tRewire-probabitility (p) for small-world graphs\n"
+ << "\t--dot\t\t\t\tEmit a dot file containing the graph\n"
+ << "\t--verify\t\t\tVerify result\n"
+ << "\t--degree-dist\t\t\tOutput degree distribution of graph\n"
+ << "\t--sequential-graph\t\tRun sequential graph tests\n"
+ << "\t--erdos-renyi\t\t\tRun tests on Erdos-Renyi graphs\n"
+ << "\t--small-world\t\t\tRun tests on Small World graphs\n"
+ << "\t--rmat\t\t\t\tRun tests on R-MAT graphs\n"
+ << "\t--rmat-unique\t\t\tRun tests on R-MAT graphs with no duplicate edges\n"
+ << "\t--csr <bool>\t\t\tRun tests using CSR graphs\n"
+ << "\t--adjacency-list <bool>\t\tRun tests using Adjacency List graphs\n";
+}
+
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ rand48 gen;
+
+ // Default args
+ size_t n = 100,
+ m = 8*n,
+ c = 100,
+ num_sources = 32,
+ num_headers = 16 * 1024,
+ batch_buffer_size = 1024 * 1024;
+ uint64_t seed = 1;
+ bool emit_dot_file = false,
+ verify = false,
+ sequential_graph = false,
+ show_degree_dist = false,
+ erdos_renyi = false,
+ small_world = false,
+ rmat = false,
+ rmat_unique = false,
+ csr = false,
+ adj_list = false;
+ double p = 0.1,
+ rmat_a = 0.5,
+ rmat_b = 0.25,
+ rmat_c = 0.1,
+ rmat_d = 0.15;
+
+ // Parse args
+ for (int i = 1; i < argc; ++i) {
+ std::string arg = argv[i];
+
+ if (arg == "--vertices")
+ n = boost::lexical_cast<size_t>( argv[i+1] );
+
+ if (arg == "--seed")
+ seed = boost::lexical_cast<uint64_t>( argv[i+1] );
+
+ if (arg == "--edges")
+ m = boost::lexical_cast<size_t>( argv[i+1] );
+
+ if (arg == "--max-weight")
+ c = boost::lexical_cast<int>( argv[i+1] );
+
+ if (arg == "--batch-buffer-size") {
+ batch_buffer_size = boost::lexical_cast<size_t>( argv[i+1] );
+ num_headers = batch_buffer_size / 16;
+ num_headers = num_headers > 0 ? num_headers : 1;
+ }
+
+ if (arg == "--rewire-probability")
+ p = boost::lexical_cast<double>( argv[i+1] );
+
+ if (arg == "--num-sources")
+ num_sources = boost::lexical_cast<size_t>( argv[i + 1] );
+
+ if (arg == "--erdos-renyi")
+ erdos_renyi = true;
+
+ if (arg == "--small-world")
+ small_world = true;
+
+ if (arg == "--rmat")
+ rmat = true;
+
+ if (arg == "--rmat-unique")
+ rmat_unique = true;
+
+ if (arg == "--dot")
+ emit_dot_file = true;
+
+ if (arg == "--verify")
+ verify = true;
+
+ if (arg == "--degree-dist")
+ show_degree_dist = true;
+
+ if (arg == "--sequential-graph")
+ sequential_graph = true;
+
+ if (arg == "--csr")
+ csr = std::string(argv[i+1]) == "true";
+
+ if (arg == "--adjacency-list")
+ adj_list = std::string(argv[i+1]) == "true";
+ }
+
+ mpi_process_group pg(num_headers, batch_buffer_size);
+
+ if (argc == 1) {
+ if (process_id(pg) == 0)
+ usage();
+ exit(-1);
+ }
+
+ gen.seed(seed);
+
+ parallel::variant_distribution<mpi_process_group> distrib
+ = parallel::block(pg, n);
+
+ if (csr) {
+ if (process_id(pg) == 0)
+ std::cerr << "CSR Graph Tests\n";
+
+ if (erdos_renyi)
+ test_csr(pg, gen, distrib, sequential_graph, n, m, c, num_sources);
+ if (small_world)
+ test_csr(pg, gen, distrib, sequential_graph, n, m, c, p, num_sources);
+ if (rmat)
+ test_csr(pg, gen, distrib, sequential_graph, n, m, c,
+ rmat_a, rmat_b, rmat_c, rmat_d, num_sources, rmat_edge_distribution_tag());
+ if (rmat_unique)
+ test_csr(pg, gen, distrib, sequential_graph, n, m, c,
+ rmat_a, rmat_b, rmat_c, rmat_d, num_sources, rmat_unique_edge_distribution_tag());
+ }
+
+ gen.seed(seed); // DEBUG
+
+ if (adj_list) {
+ if (process_id(pg) == 0)
+ std::cerr << "Adjacency List Graph Tests\n";
+
+ if (erdos_renyi)
+ test_adjacency_list(pg, gen, distrib, sequential_graph, n, m, c);
+ if (small_world)
+ test_adjacency_list(pg, gen, distrib, sequential_graph, n, m, c, p);
+ if (rmat)
+ test_adjacency_list(pg, gen, distrib, sequential_graph, n, m, c,
+ rmat_a, rmat_b, rmat_c, rmat_d, rmat_edge_distribution_tag());
+ if (rmat_unique)
+ test_adjacency_list(pg, gen, distrib, sequential_graph, n, m, c,
+ rmat_a, rmat_b, rmat_c, rmat_d, rmat_unique_edge_distribution_tag());
+ }
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_adjacency_list_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_adjacency_list_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,284 @@
+// Copyright (C) 2004-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/local_subgraph.hpp>
+#include <boost/graph/parallel/distribution.hpp>
+#include <iostream>
+#include <cassert>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+template<typename Graph>
+struct never
+{
+ typedef typename graph_traits<Graph>::edge_descriptor argument_type;
+ typedef bool result_type;
+
+ result_type operator()(argument_type) { return false; }
+};
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+
+ mpi_process_group pg;
+ parallel::block dist(pg, 20);
+
+ typedef adjacency_list<listS, distributedS<mpi_process_group, vecS>,
+ bidirectionalS> Graph1;
+ typedef adjacency_list<listS, distributedS<mpi_process_group, vecS>,
+ directedS> Graph2;
+ typedef adjacency_list<listS, distributedS<mpi_process_group, vecS>,
+ undirectedS> Graph3;
+
+ if (num_processes(pg) > 20) return -1;
+
+ if (process_id(pg) == 0) std::cout << "Graph 1------------------\n";
+
+ std::cout << "Processor #" << process_id(pg) << ": "
+ << dist.block_size(20) << " vertices." << std::endl;
+ {
+ Graph1 g1(20);
+
+ // if (process_id(pg) == num_processes(pg)() - 1)
+ // add_vertex(g1);
+
+ graph_traits<Graph1>::vertex_iterator v, v_end;
+ int counter = 0;
+ for (tie(v, v_end) = vertices(g1); v != v_end; ++v) {
+ std::cout << "Processor #" << process_id(pg) << ": vertex " << ++counter
+ << std::endl;
+
+ out_edges(*v, g1);
+ out_degree(*v, g1);
+ in_edges(*v, g1);
+ in_degree(*v, g1);
+
+ graph_traits<Graph1>::vertex_descriptor other = *v;
+ other.owner = (other.owner + 1) % num_processes(pg);
+ other.local = 0;
+ add_edge(*v, other, g1);
+
+ std::cout << "Adding edge from processor " << process_id(pg)
+ << " to processor " << other.owner << std::endl;
+ }
+
+ synchronize(g1);
+ assert((std::size_t)std::distance(edges(g1).first, edges(g1).second) == num_vertices(g1));
+
+ if (num_vertices(g1) >= 2) {
+ graph_traits<Graph1>::vertex_iterator vi = vertices(g1).first;
+ graph_traits<Graph1>::vertex_descriptor u = *vi++;
+ graph_traits<Graph1>::vertex_descriptor v = *vi++;
+ add_edge(u, v, g1);
+ assert(out_degree(u, g1) == 2);
+ assert(in_degree(v, g1) == 1);
+ }
+
+ int prior_processor = (process_id(pg) + num_processes(pg) - 1)
+ % num_processes(pg);
+ const int n = 20;
+ std::size_t vertices_in_prior = (n / num_processes(pg))
+ + (n % num_processes(pg) > prior_processor? 1 : 0);
+
+ graph_traits<Graph1>::vertex_descriptor u = *vertices(g1).first;
+ if (in_degree(u, g1) != vertices_in_prior) {
+ std::cout << "Processor #" << process_id(pg) << ": " << in_degree(u, g1)
+ << " vs. " << vertices_in_prior << std::endl;
+ }
+ assert(in_degree(u, g1) == vertices_in_prior);
+ std::cout << "Processor #" << process_id(pg) << ": " << num_edges(g1)
+ << " edges.\n";
+
+ local_subgraph<Graph1> local_g1(g1);
+ edges(local_g1);
+ vertices(local_g1);
+ if (num_vertices(local_g1) > 0) {
+ out_edges(*vertices(local_g1).first, local_g1);
+ in_edges(*vertices(local_g1).first, local_g1);
+ adjacent_vertices(*vertices(local_g1).first, local_g1);
+ if (false) {
+ remove_out_edge_if(*vertices(g1).first, never<Graph1>(), g1);
+ remove_in_edge_if(*vertices(g1).first, never<Graph1>(), g1);
+ clear_out_edges(*vertices(g1).first, g1);
+ clear_in_edges(*vertices(g1).first, g1);
+ clear_vertex(*vertices(g1).first, g1);
+ remove_vertex(*vertices(g1).first, g1);
+ }
+ }
+ remove_edge_if(never<Graph1>(), g1);
+ }
+
+
+ if (process_id(pg) == 0) std::cout << "Graph 2------------------\n";
+
+ {
+ Graph2 g2(20);
+
+ if (process_id(pg) == num_processes(pg) - 1)
+ add_vertex(g2);
+
+ graph_traits<Graph2>::vertex_iterator v, v_end;
+ int counter = 0;
+ for (tie(v, v_end) = vertices(g2); v != v_end; ++v) {
+ std::cout << "Processor #" << process_id(pg) << ": vertex " << ++counter
+ << std::endl;
+
+ out_edges(*v, g2);
+ }
+
+ synchronize(g2);
+
+ if (num_vertices(g2) >= 2) {
+ graph_traits<Graph2>::vertex_iterator vi = vertices(g2).first;
+ graph_traits<Graph2>::vertex_descriptor u = *vi++;
+ graph_traits<Graph2>::vertex_descriptor v = *vi++;
+ add_edge(u, v, g2);
+ assert(out_degree(u, g2) == 1);
+ assert(*adjacent_vertices(u, g2).first == v);
+ std::cout << "Processor #" << process_id(pg) << ": " << num_edges(g2)
+ << " edges.\n";
+ assert(std::distance(edges(g2).first, edges(g2).second) == 1);
+
+ }
+ synchronize(g2);
+
+ local_subgraph<Graph2> local_g2(g2);
+ edges(local_g2);
+ vertices(local_g2);
+ if (num_vertices(local_g2) > 0) {
+ out_edges(*vertices(local_g2).first, local_g2);
+ adjacent_vertices(*vertices(local_g2).first, local_g2);
+ remove_out_edge_if(*vertices(g2).first, never<Graph2>(), g2);
+ clear_out_edges(*vertices(g2).first, g2);
+ remove_vertex(*vertices(g2).first, g2);
+ }
+ remove_edge_if(never<Graph2>(), g2);
+ }
+
+ if (process_id(pg) == 0) std::cout << "Graph 3------------------\n";
+
+ {
+ Graph3 g3(20);
+
+ // if (process_id(pg) == num_processes(pg) - 1)
+ // add_vertex(g3);
+
+ graph_traits<Graph3>::vertex_iterator v, v_end;
+ int counter = 0;
+ for (tie(v, v_end) = vertices(g3); v != v_end; ++v) {
+ std::cout << "Processor #" << process_id(pg) << ": vertex " << ++counter
+ << std::endl;
+
+ out_edges(*v, g3);
+ out_degree(*v, g3);
+ in_edges(*v, g3);
+ in_degree(*v, g3);
+ }
+
+ int added_edges = 0;
+ if (num_vertices(g3) >= 2) {
+ graph_traits<Graph3>::vertex_iterator vi = vertices(g3).first;
+ graph_traits<Graph3>::vertex_descriptor u = *vi++;
+ graph_traits<Graph3>::vertex_descriptor v = *vi++;
+ add_edge(u, v, g3); ++added_edges;
+ assert(out_degree(u, g3) == 1);
+ assert(in_degree(u, g3) == 1);
+ graph_traits<Graph3>::edge_descriptor e = *out_edges(u, g3).first;
+ assert(source(e, g3) == u);
+ assert(target(e, g3) == v);
+ e = *in_edges(u, g3).first;
+ assert(source(e, g3) == v);
+ assert(target(e, g3) == u);
+ assert(out_degree(v, g3) == 1);
+ assert(in_degree(v, g3) == 1);
+ e = *out_edges(v, g3).first;
+ assert(source(e, g3) == v);
+ assert(target(e, g3) == u);
+ e = *in_edges(v, g3).first;
+ assert(source(e, g3) == u);
+ assert(target(e, g3) == v);
+
+ assert(*adjacent_vertices(u, g3).first == v);
+ assert(*adjacent_vertices(v, g3).first == u);
+ std::cout << "Processor #" << process_id(pg) << ": " << num_edges(g3)
+ << " edges.\n";
+ }
+
+ // Add some remote edges
+ for (tie(v, v_end) = vertices(g3); v != v_end; ++v) {
+ graph_traits<Graph1>::vertex_descriptor other = *v;
+ other.owner = (other.owner + 1) % num_processes(pg);
+ other.local = 0;
+ add_edge(*v, other, g3); ++added_edges;
+
+ std::cout << "Adding edge from processor " << process_id(pg)
+ << " to processor " << other.owner << std::endl;
+ }
+
+ synchronize(g3);
+ assert(std::distance(edges(g3).first, edges(g3).second) == added_edges);
+ assert(num_edges(g3) == added_edges);
+
+ // Verify the remote edges
+ if (num_vertices(g3) >= 2) {
+ graph_traits<Graph3>::vertex_iterator vi = vertices(g3).first;
+ graph_traits<Graph3>::vertex_descriptor u = *vi++;
+
+ int prior_processor = (process_id(pg) + num_processes(pg) - 1)
+ % num_processes(pg);
+ const int n = 20;
+ int vertices_in_prior = (n / num_processes(pg))
+ + (n % num_processes(pg) > prior_processor? 1 : 0);
+ if (in_degree(u, g3) != vertices_in_prior + 2) {
+ std::cerr << "#" << process_id(pg) << ": " << in_degree(u, g3)
+ << " != " << vertices_in_prior + 2 << std::endl;
+ }
+
+ assert(in_degree(u, g3) == vertices_in_prior + 2);
+ assert(out_degree(u, g3) == vertices_in_prior + 2);
+ }
+
+ local_subgraph<Graph3> local_g3(g3);
+ edges(local_g3);
+ vertices(local_g3);
+ if (num_vertices(local_g3) > 0) {
+ out_edges(*vertices(local_g3).first, local_g3);
+ in_edges(*vertices(local_g3).first, local_g3);
+ adjacent_vertices(*vertices(local_g3).first, local_g3);
+ remove_out_edge_if(*vertices(g3).first, never<Graph3>(), g3);
+ remove_in_edge_if(*vertices(g3).first, never<Graph3>(), g3);
+ if (false) {
+ // Removing an edge from two processes concurrently is not yet
+ // supported.
+ clear_vertex(*vertices(g3).first, g3);
+ remove_vertex(*vertices(g3).first, g3);
+ }
+ }
+ remove_edge_if(never<Graph3>(), g3);
+ }
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_betweenness_centrality_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_betweenness_centrality_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,294 @@
+// Copyright (C) 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Nick Edmonds
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+
+#define CSR
+
+#ifdef CSR
+# include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
+#else
+# include <boost/graph/distributed/adjacency_list.hpp>
+#endif
+
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/concepts.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/graph/distributed/betweenness_centrality.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/property_map/vector_property_map.hpp>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+/****************************************************************************
+ * Edge weight generator iterator *
+ ****************************************************************************/
+template<typename F, typename RandomGenerator>
+class generator_iterator
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename F::result_type value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ explicit
+ generator_iterator(RandomGenerator& gen, const F& f = F())
+ : f(f), gen(&gen)
+ {
+ value = this->f(gen);
+ }
+
+ reference operator*() const { return value; }
+ pointer operator->() const { return &value; }
+
+ generator_iterator& operator++()
+ {
+ value = f(*gen);
+ return *this;
+ }
+
+ generator_iterator operator++(int)
+ {
+ generator_iterator temp(*this);
+ ++(*this);
+ return temp;
+ }
+
+ bool operator==(const generator_iterator& other) const
+ { return f == other.f; }
+
+ bool operator!=(const generator_iterator& other) const
+ { return !(*this == other); }
+
+private:
+ F f;
+ RandomGenerator* gen;
+ value_type value;
+};
+
+template<typename F, typename RandomGenerator>
+inline generator_iterator<F, RandomGenerator>
+make_generator_iterator( RandomGenerator& gen, const F& f)
+{ return generator_iterator<F, RandomGenerator>(gen, f); }
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+typedef int weight_type;
+
+struct WeightedEdge {
+ WeightedEdge(weight_type weight = 0) : weight(weight) { }
+
+ weight_type weight;
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & weight;
+ }
+};
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+#ifdef CSR
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge,
+ no_property, distributedS<mpi_process_group> >
+ Graph;
+ typedef compressed_sparse_row_graph<directedS, no_property, WeightedEdge>
+ seqGraph;
+#else
+ typedef adjacency_list<vecS,
+ distributedS<mpi_process_group, vecS>,
+ directedS,
+ no_property,
+ property<edge_weight_t, int> > Graph;
+
+ typedef adjacency_list<vecS, vecS, directedS, no_property,
+ property<edge_weight_t, int> > seqGraph;
+#endif
+
+
+ typedef sorted_erdos_renyi_iterator<minstd_rand, Graph> ERIter;
+
+ typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ typedef graph_traits<Graph>::edge_descriptor edge_descriptor;
+
+ int n = 100;
+ double prob = 0.1;
+ int C = 3;
+
+ minstd_rand gen;
+
+ gen.seed(1);
+
+ // NOTE: Weighted betweenness centrality only works with non-zero edge weights
+
+ // Build graphs
+ Graph g(ERIter(gen, n, prob), ERIter(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ n);
+
+ gen.seed(1); // Re-seed PRNG so we get the same graph
+
+ seqGraph sg(ERIter(gen, n, prob), ERIter(),
+ make_generator_iterator(gen, uniform_int<int>(1, C)),
+ n);
+
+ // Test Betweenness Centrality
+ typedef property_map<Graph, vertex_index_t>::const_type IndexMap;
+ typedef iterator_property_map<std::vector<int>::iterator, IndexMap>
+ CentralityMap;
+
+ std::vector<int> centralityS(num_vertices(g), 0);
+ CentralityMap centrality(centralityS.begin(), get(vertex_index, g));
+
+ brandes_betweenness_centrality(g, centrality);
+
+ std::vector<int> weightedCentralityS(num_vertices(g), 0);
+ CentralityMap weightedCentrality(weightedCentralityS.begin(), get(vertex_index, g));
+
+ brandes_betweenness_centrality(g, centrality_map(weightedCentrality).
+#ifdef CSR
+ weight_map(get(&WeightedEdge::weight, g)));
+#else
+ weight_map(get(edge_weight, g)));
+#endif
+
+ int g_cpd = central_point_dominance(g, centrality);
+
+ //
+ // Non-distributed (embarassingly parallel) Betweenness Centrality
+ //
+ typedef boost::graph::parallel::process_group_type<Graph>::type
+ process_group_type;
+
+ process_group_type pg = process_group(g);
+
+ process_group_type::process_id_type id = process_id(pg);
+ process_group_type::process_size_type p = num_processes(pg);
+
+ typedef property_map<seqGraph, vertex_index_t>::const_type seqIndexMap;
+ typedef iterator_property_map<std::vector<int>::iterator, seqIndexMap> seqCentralityMap;
+
+ std::vector<int> nonDistributedCentralityS(num_vertices(sg), 0);
+ seqCentralityMap nonDistributedCentrality(nonDistributedCentralityS.begin(), get(vertex_index, sg));
+
+ std::vector<int> nonDistributedWeightedCentralityS(num_vertices(sg), 0);
+ seqCentralityMap nonDistributedWeightedCentrality(nonDistributedWeightedCentralityS.begin(),
+ get(vertex_index, sg));
+
+ non_distributed_brandes_betweenness_centrality(pg, sg, nonDistributedCentrality);
+
+ non_distributed_brandes_betweenness_centrality(pg, sg,
+ centrality_map(nonDistributedWeightedCentrality).
+#ifdef CSR
+ weight_map(get(&WeightedEdge::weight, sg)));
+#else
+ weight_map(get(edge_weight, sg)));
+#endif
+
+ //
+ // Verify
+ //
+ std::vector<int> seqCentralityS(num_vertices(sg), 0);
+ seqCentralityMap seqCentrality(seqCentralityS.begin(), get(vertex_index, sg));
+
+ std::vector<int> seqWeightedCentralityS(num_vertices(sg), 0);
+ seqCentralityMap seqWeightedCentrality(seqWeightedCentralityS.begin(), get(vertex_index, sg));
+
+ brandes_betweenness_centrality(sg, seqCentrality);
+
+ brandes_betweenness_centrality(sg, centrality_map(seqWeightedCentrality).
+#ifdef CSR
+ weight_map(get(&WeightedEdge::weight, sg)));
+#else
+ weight_map(get(edge_weight, sg)));
+#endif
+
+ int sg_cpd = central_point_dominance(sg, seqCentrality);
+
+ // Verify exact betweenness centrality
+ //
+ // We're cheating when we map vertices in g to vertices in sg
+ // since we know that g is using the block distribution here
+ typedef property_map<Graph, vertex_owner_t>::const_type OwnerMap;
+ typedef property_map<Graph, vertex_local_t>::const_type LocalMap;
+
+ OwnerMap owner = get(vertex_owner, g);
+ LocalMap local = get(vertex_local, g);
+
+ bool passed = true;
+
+ {
+ typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
+ vertex_iterator v, v_end;
+
+ for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
+ if (get(centrality, *v) != seqCentralityS[(n/p) * get(owner, *v) + get(local, *v)]) {
+ std::cerr << " " << id << ": Error - centrality of " << get(local, *v) << "@" << get(owner, *v)
+ << " does not match the sequential result (" << get(centrality, *v) << " vs. "
+ << seqCentralityS[(n/p) * get(owner, *v) + get(local, *v)] << ")\n";
+ passed = false;
+ }
+
+ if (get(weightedCentrality, *v) != seqWeightedCentralityS[(n/p) * get(owner, *v) + get(local, *v)]) {
+ std::cerr << " " << id << ": Error - weighted centrality of " << get(local, *v) << "@" << get(owner, *v)
+ << " does not match the sequential result (" << get(weightedCentrality, *v) << " vs. "
+ << seqWeightedCentralityS[(n/p) * get(owner, *v) + get(local, *v)] << ")\n";
+ passed = false;
+ }
+ }
+ }
+
+ if (id == 0) {
+ typedef graph_traits<seqGraph>::vertex_iterator vertex_iterator;
+ vertex_iterator v, v_end;
+
+ for (tie(v, v_end) = vertices(sg); v != v_end; ++v) {
+ if (get(seqCentrality, *v) != get(nonDistributedCentrality, *v)) {
+ std::cerr << " " << id << ": Error - non-distributed centrality of " << *v
+ << " does not match the sequential result (" << get(nonDistributedCentrality, *v)
+ << " vs. " << get(seqCentrality, *v) << ")\n";
+ passed = false;
+ }
+
+ if (get(seqWeightedCentrality, *v) != get(nonDistributedWeightedCentrality, *v)) {
+ std::cerr << " " << id << ": Error - non-distributed weighted centrality of " << *v
+ << " does not match the sequential result (" << get(nonDistributedWeightedCentrality, *v)
+ << " vs. " << get(seqCentrality, *v) << ")\n";
+ passed = false;
+ }
+ }
+ }
+
+ if (g_cpd != sg_cpd) {
+ passed = false;
+ std::cerr << "Central point dominance did not match the sequential result\n";
+ }
+
+ if (!passed)
+ MPI_Abort(MPI_COMM_WORLD, -1);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_connected_components_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_connected_components_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,208 @@
+// Copyright (C) 2004-2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/connected_components.hpp>
+#include <boost/graph/distributed/connected_components_parallel_search.hpp>
+#include <boost/graph/random.hpp>
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/parallel/distribution.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/graph/distributed/graphviz.hpp>
+#include <iostream>
+#include <cstdlib>
+#include <iomanip>
+#include <boost/random.hpp>
+#include <boost/test/minimal.hpp>
+
+#include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
+#include <boost/graph/rmat_graph_generator.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+typedef double time_type;
+
+inline time_type get_time()
+{
+ return MPI_Wtime();
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+template<typename T>
+class map_lt
+{
+public:
+ bool operator()() const { return false; }
+ bool operator()(T x, T y) const { return (owner(x) < owner(y) || (owner(x) == owner(y) && local(x) < local(y))); }
+};
+
+void
+test_distributed_connected_components(int n, double _p, bool verify, bool emit_dot_file, int seed, bool parallel_search)
+{
+// typedef adjacency_list<listS,
+// distributedS<mpi_process_group, vecS>,
+// undirectedS> Graph;
+
+ typedef compressed_sparse_row_graph<directedS, no_property, no_property, no_property,
+ distributedS<mpi_process_group> > Graph;
+
+ typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
+ typedef iterator_property_map<std::vector<vertex_descriptor>::iterator, property_map<Graph, vertex_index_t>::type> ParentMap;
+ typedef std::pair<int, int> Edge;
+
+ minstd_rand gen;
+
+ gen.seed(seed);
+
+ mpi_process_group pg;
+ parallel::variant_distribution<mpi_process_group> distrib
+ = parallel::block(pg, n);
+
+ minstd_rand dist_gen;
+#if 0
+ if (false) {
+ distrib = parallel::random_distribution(pg, dist_gen, n);
+ } else if (true) {
+ distrib = parallel::oned_block_cyclic(pg, 13);
+ }
+#endif
+
+// Graph g(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, _p/2),
+// erdos_renyi_iterator<minstd_rand, Graph>(),
+// n, pg, distrib);
+
+ int m = n * n * _p/2;
+ double a = 0.57, b = 0.19, c = 0.19, d = 0.05;
+
+ // Last boolean parameter makes R-MAT bidirectional
+ Graph g(sorted_unique_rmat_iterator<minstd_rand, Graph>(gen, n, m, a, b, c, d, true),
+ sorted_unique_rmat_iterator<minstd_rand, Graph>(),
+ n, pg, distrib);
+
+ synchronize(g);
+
+ std::vector<int> local_components_vec(num_vertices(g));
+ typedef iterator_property_map<std::vector<int>::iterator, property_map<Graph, vertex_index_t>::type> ComponentMap;
+ ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
+
+ int num_components = 0;
+
+ time_type start = get_time();
+ if (parallel_search) {
+ num_components = connected_components_ps(g, component);
+ } else {
+ num_components = connected_components(g, component);
+ }
+ time_type end = get_time();
+ if (process_id(g.process_group()) == 0)
+ std::cerr << "Connected Components time = " << print_time(end - start) << " seconds.\n"
+ << num_components << " components identified\n";
+
+ if ( verify )
+ {
+ if ( process_id(g.process_group()) == 0 )
+ {
+ component.set_max_ghost_cells(0);
+ for (int i = 0; i < n; ++i)
+ get(component, vertex(i, g));
+ synchronize(component);
+
+ // Check against the sequential version
+ typedef adjacency_list<listS,
+ vecS,
+ undirectedS,
+ // Vertex properties
+ no_property,
+ // Edge properties
+ no_property > Graph2;
+
+ gen.seed(seed);
+
+// Graph2 g2(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, _p/2),
+// erdos_renyi_iterator<minstd_rand, Graph>(),
+// n);
+
+ Graph2 g2( sorted_unique_rmat_iterator<minstd_rand, Graph>(gen, n, m, a, b, c, d, true),
+ sorted_unique_rmat_iterator<minstd_rand, Graph>(),
+ n);
+
+ std::vector<int> component2 (n);
+ int tmp;
+ tmp = connected_components(g2, make_iterator_property_map(component2.begin(), get(vertex_index, g2)));
+ std::cerr << "Verifier found " << tmp << " components" << std::endl;
+
+ // Make sure components and component2 match
+ std::map<int, int> c2c;
+ int i;
+ // This fails if there are more components in 'component' than
+ // 'component2' because multiple components in 'component' may
+ // legitimately map to the same component number in 'component2'.
+ // We can either test the mapping in the opposite direction or
+ // just assert that the numbers of components found by both
+ // algorithms is the same
+ for ( i = 0; i < n; i++ )
+ if ( c2c.find( get(component, vertex(i, g)) ) == c2c.end() )
+ c2c[get(component, vertex(i, g))] = component2[i];
+ else
+ if ( c2c[get(component, vertex(i, g))] != component2[i] )
+ break;
+
+ if ( i < n || num_components != tmp) {
+ printf("Unable to verify CC result...\n");
+ } else
+ printf("Passed verification... %i connected components\n",
+ (int)c2c.size());
+ }
+ else
+ {
+ synchronize(component);
+ }
+ if ( emit_dot_file )
+ write_graphviz("cc.dot", g, paint_by_number(component));
+ }
+}
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ if ( argc < 6 ) {
+ test_distributed_connected_components(10000, 0.001, true, false, 1, false);
+ test_distributed_connected_components(10000, 0.001, true, false, 1, true);
+ }
+ else
+ test_distributed_connected_components
+ (atoi(argv[1]), atof(argv[2]),
+ argv[3]==std::string("true"), argv[4]==std::string("true"),
+ argc == 6? 1 : atoi(argv[6]),
+ argv[5]==std::string("true"));
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_csr_algorithm_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_csr_algorithm_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,366 @@
+// Copyright (C) 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Nick Edmonds
+// Andrew Lumsdaine
+
+// A test of the distributed compressed sparse row graph type
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/concepts.hpp>
+
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/graph/small_world_generator.hpp>
+#include <boost/graph/rmat_graph_generator.hpp>
+
+#include <boost/graph/breadth_first_search.hpp>
+#include <boost/graph/depth_first_search.hpp>
+#include <boost/graph/distributed/delta_stepping_shortest_paths.hpp>
+#include <boost/graph/dijkstra_shortest_paths.hpp>
+#include <boost/graph/distributed/page_rank.hpp>
+#include <boost/graph/distributed/boman_et_al_graph_coloring.hpp>
+#include <boost/graph/connected_components.hpp>
+#include <boost/graph/strong_components.hpp>
+#include <boost/graph/distributed/betweenness_centrality.hpp>
+#include <boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp>
+
+#if 0 // Contains internal AdjList types not present in CSR graph
+# include <boost/graph/distributed/connected_components_parallel_search.hpp>
+#endif
+
+#include <boost/graph/distributed/vertex_list_adaptor.hpp> // Needed for MST
+
+#include <boost/random/linear_congruential.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/property_map/vector_property_map.hpp>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+
+/****************************************************************************
+ * Edge weight generator iterator *
+ ****************************************************************************/
+template<typename F, typename RandomGenerator>
+class generator_iterator
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename F::result_type value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ explicit
+ generator_iterator(RandomGenerator& gen, const F& f = F())
+ : f(f), gen(&gen)
+ {
+ value = this->f(gen);
+ }
+
+ reference operator*() const { return value; }
+ pointer operator->() const { return &value; }
+
+ generator_iterator& operator++()
+ {
+ value = f(*gen);
+ return *this;
+ }
+
+ generator_iterator operator++(int)
+ {
+ generator_iterator temp(*this);
+ ++(*this);
+ return temp;
+ }
+
+ bool operator==(const generator_iterator& other) const
+ { return f == other.f; }
+
+ bool operator!=(const generator_iterator& other) const
+ { return !(*this == other); }
+
+private:
+ F f;
+ RandomGenerator* gen;
+ value_type value;
+};
+
+template<typename F, typename RandomGenerator>
+inline generator_iterator<F, RandomGenerator>
+make_generator_iterator( RandomGenerator& gen, const F& f)
+{ return generator_iterator<F, RandomGenerator>(gen, f); }
+
+
+/****************************************************************************
+ * Printing DFS Visitor *
+ ****************************************************************************/
+
+struct printing_dfs_visitor
+{
+ template<typename Vertex, typename Graph>
+ void initialize_vertex(Vertex v, const Graph& g)
+ {
+ vertex_event("initialize_vertex", v, g);
+ }
+
+ template<typename Vertex, typename Graph>
+ void start_vertex(Vertex v, const Graph& g)
+ {
+ vertex_event("start_vertex", v, g);
+ }
+
+ template<typename Vertex, typename Graph>
+ void discover_vertex(Vertex v, const Graph& g)
+ {
+ vertex_event("discover_vertex", v, g);
+ }
+
+ template<typename Edge, typename Graph>
+ void examine_edge(Edge e, const Graph& g)
+ {
+ edge_event("examine_edge", e, g);
+ }
+
+ template<typename Edge, typename Graph>
+ void tree_edge(Edge e, const Graph& g)
+ {
+ edge_event("tree_edge", e, g);
+ }
+
+ template<typename Edge, typename Graph>
+ void back_edge(Edge e, const Graph& g)
+ {
+ edge_event("back_edge", e, g);
+ }
+
+ template<typename Edge, typename Graph>
+ void forward_or_cross_edge(Edge e, const Graph& g)
+ {
+ edge_event("forward_or_cross_edge", e, g);
+ }
+
+ template<typename Vertex, typename Graph>
+ void finish_vertex(Vertex v, const Graph& g)
+ {
+ vertex_event("finish_vertex", v, g);
+ }
+
+private:
+ template<typename Vertex, typename Graph>
+ void vertex_event(const char* name, Vertex v, const Graph& g)
+ {
+ std::cerr << "#" << process_id(g.process_group()) << ": " << name << "("
+ << get_vertex_name(v, g) << ": " << local(v) << "@" << owner(v)
+ << ")\n";
+ }
+
+ template<typename Edge, typename Graph>
+ void edge_event(const char* name, Edge e, const Graph& g)
+ {
+ std::cerr << "#" << process_id(g.process_group()) << ": " << name << "("
+ << get_vertex_name(source(e, g), g) << ": "
+ << local(source(e, g)) << "@" << owner(source(e, g)) << ", "
+ << get_vertex_name(target(e, g), g) << ": "
+ << local(target(e, g)) << "@" << owner(target(e, g)) << ")\n";
+ }
+
+};
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+typedef int weight_type;
+
+struct WeightedEdge {
+ WeightedEdge(weight_type weight = 0) : weight(weight) { }
+
+ weight_type weight;
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & weight;
+ }
+};
+
+struct VertexProperties {
+ VertexProperties(int d = 0)
+ : distance(d) { }
+
+ int distance;
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & distance;
+ }
+};
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ typedef compressed_sparse_row_graph<directedS, VertexProperties, WeightedEdge,
+ no_property, distributedS<mpi_process_group> >
+ Digraph;
+
+ // Make sure we can build graphs using common graph generators
+ typedef sorted_erdos_renyi_iterator<minstd_rand, Digraph> ERIter;
+ typedef small_world_iterator<minstd_rand, Digraph> SWIter;
+ typedef sorted_rmat_iterator<minstd_rand, Digraph> RMATIter;
+
+ typedef graph_traits<Digraph>::vertex_descriptor vertex_descriptor;
+ typedef graph_traits<Digraph>::edge_descriptor edge_descriptor;
+
+ int n = 40;
+ int k = 3;
+ double prob = 0.1;
+ int C = 10;
+ double a = 0.5, b = 0.1, c = 0.25, d = 0.15;
+ int iterations = 50;
+ int num_colors = n / 10;
+ int lookahead = C / 10;
+
+ minstd_rand gen;
+
+ // Directed Graphs
+ Digraph g(ERIter(gen, n, prob), ERIter(),
+ make_generator_iterator(gen, uniform_int<int>(0, C)),
+ n);
+ Digraph g2(SWIter(gen, n, k, prob), SWIter(), n);
+ Digraph g3(RMATIter(gen, n, (n*n*prob), a, b, c, d), RMATIter(), n);
+
+ // Test BFS
+ breadth_first_search(g, vertex(0, g), visitor(bfs_visitor<>()));
+
+ // Test SSSP Algorithms
+ graph::distributed::delta_stepping_shortest_paths(g,
+ vertex(0, g),
+ dummy_property_map(),
+ get(&VertexProperties::distance, g),
+ get(&WeightedEdge::weight, g));
+
+ dijkstra_shortest_paths(g, vertex(0, g),
+ distance_map(get(&VertexProperties::distance, g)).
+ weight_map(get(&WeightedEdge::weight, g)));
+
+ dijkstra_shortest_paths(g, vertex(0, g),
+ distance_map(get(&VertexProperties::distance, g)).
+ weight_map(get(&WeightedEdge::weight, g)).
+ lookahead(lookahead));
+
+ // Test PageRank
+ using boost::graph::n_iterations;
+
+ std::vector<double> ranks(num_vertices(g));
+
+ page_rank(g,
+ make_iterator_property_map(ranks.begin(),
+ get(boost::vertex_index, g)),
+ n_iterations(iterations), 0.85, vertex(0, g));
+
+ // Test Graph Coloring
+ typedef property_map<Digraph, vertex_index_t>::type vertex_index_map;
+
+ std::vector<int> colors_vec(num_vertices(g));
+ iterator_property_map<int*, vertex_index_map> color(&colors_vec[0],
+ get(vertex_index, g));
+
+ graph::boman_et_al_graph_coloring(g, color, num_colors);
+
+ // Test DFS
+ //
+ // DFS requires an undirected graph, currently CSR graphs must be directed
+#if 0
+ std::vector<vertex_descriptor> parent(num_vertices(g));
+ std::vector<vertex_descriptor> explore(num_vertices(g));
+
+ boost::graph::tsin_depth_first_visit
+ (g,
+ vertex(0, g),
+ printing_dfs_visitor(),
+ color,
+ make_iterator_property_map(parent.begin(), get(vertex_index, g)),
+ make_iterator_property_map(explore.begin(), get(vertex_index, g)),
+ get(vertex_index, g));
+#endif
+
+ // Test Connected Components
+ //
+ // CC requires an undirected graph, currently CSR graphs must be directed
+#if 0
+ std::vector<int> local_components_vec(num_vertices(g));
+ typedef iterator_property_map<std::vector<int>::iterator,
+ vertex_index_map> ComponentMap;
+ ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
+
+ assert(connected_components(g, component) ==
+ connected_components_ps(g, component));
+#endif
+
+ // Test Betweenness Centrality
+ //
+ // Betweenness Centrality is broken at the moment
+ typedef iterator_property_map<std::vector<int>::iterator, vertex_index_map>
+ CentralityMap;
+
+ std::vector<int> centralityS(num_vertices(g), 0);
+ CentralityMap centrality(centralityS.begin(), get(vertex_index, g));
+
+ brandes_betweenness_centrality(g, centrality);
+
+ //
+ // Test MST
+ //
+ std::vector<edge_descriptor> mst_edges;
+
+ dense_boruvka_minimum_spanning_tree(make_vertex_list_adaptor(g),
+ get(&WeightedEdge::weight, g),
+ std::back_inserter(mst_edges));
+
+ mst_edges.clear();
+ merge_local_minimum_spanning_trees(make_vertex_list_adaptor(g),
+ get(&WeightedEdge::weight, g),
+ std::back_inserter(mst_edges));
+
+ mst_edges.clear();
+ boruvka_then_merge(make_vertex_list_adaptor(g),
+ get(&WeightedEdge::weight, g),
+ std::back_inserter(mst_edges));
+
+ mst_edges.clear();
+ boruvka_mixed_merge(make_vertex_list_adaptor(g),
+ get(&WeightedEdge::weight, g),
+ std::back_inserter(mst_edges));
+
+ // Test Strong Components
+ //
+ // Can't build reverse graph of a CSR graph
+#if 0
+ std::vector<int> local_components_vec(num_vertices(g));
+ typedef iterator_property_map<std::vector<int>::iterator,
+ vertex_index_map> ComponentMap;
+ ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
+
+ int num_components = strong_components(g, component);
+#endif
+
+ std::ofstream out("dcsr.dot");
+ write_graphviz(out, g);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_csr_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_csr_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,102 @@
+// Copyright (C) 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+// A test of the distributed compressed sparse row graph type
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/concepts.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <boost/graph/breadth_first_search.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/property_map/vector_property_map.hpp>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+void concept_checks()
+{
+ typedef compressed_sparse_row_graph<directedS, void, void, no_property,
+ distributedS<mpi_process_group> >
+ Digraph;
+ typedef graph_traits<Digraph>::vertex_descriptor vertex_descriptor;
+ typedef graph_traits<Digraph>::edge_descriptor edge_descriptor;
+
+ function_requires< GraphConcept<Digraph> >();
+ function_requires< IncidenceGraphConcept<Digraph> >();
+ function_requires< AdjacencyGraphConcept<Digraph> >();
+
+ function_requires< DistributedVertexListGraphConcept<Digraph> >();
+ function_requires< DistributedEdgeListGraphConcept<Digraph> >();
+
+ function_requires<
+ ReadablePropertyGraphConcept<Digraph, vertex_descriptor, vertex_global_t>
+ >();
+ function_requires<
+ ReadablePropertyGraphConcept<Digraph, vertex_descriptor, vertex_owner_t>
+ >();
+ function_requires<
+ ReadablePropertyGraphConcept<Digraph, vertex_descriptor, vertex_local_t>
+ >();
+ function_requires<
+ ReadablePropertyGraphConcept<Digraph, vertex_descriptor, vertex_index_t>
+ >();
+
+ function_requires<
+ ReadablePropertyGraphConcept<Digraph, edge_descriptor, edge_global_t>
+ >();
+
+ // DPG TBD: edge_owner, edge_local property maps
+
+ function_requires<
+ ReadablePropertyGraphConcept<Digraph, edge_descriptor, edge_index_t>
+ >();
+
+ // Check default construction
+ Digraph g;
+}
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ concept_checks();
+
+ typedef compressed_sparse_row_graph<directedS, void, void, no_property,
+ distributedS<mpi_process_group> >
+ Digraph;
+
+ // Build an Erdos-Renyi graph to test with
+ typedef sorted_erdos_renyi_iterator<minstd_rand, Digraph> ERIter;
+
+ int n = 40;
+ double prob = 0.1;
+
+ minstd_rand gen;
+ Digraph g(ERIter(gen, n, prob), ERIter(), n);
+
+ breadth_first_search(g, vertex(0, g), visitor(bfs_visitor<>()));
+
+ std::ofstream out("dcsr.dot");
+ write_graphviz(out, g);
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_dfs_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_dfs_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,165 @@
+//=======================================================================
+// Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee,
+// Copyright 2004 Douglas Gregor
+// Copyright (C) 2006-2008
+
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/depth_first_search.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/test/minimal.hpp>
+#include <iostream>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+// Set up the vertex names
+enum vertex_id_t { u, v, w, x, y, z, N };
+char vertex_names[] = { 'u', 'v', 'w', 'x', 'y', 'z' };
+
+template<typename Vertex, typename Graph>
+char get_vertex_name(Vertex v, const Graph& g)
+{
+ return vertex_names[g.distribution().global(owner(v), local(v))];
+}
+
+struct printing_dfs_visitor
+{
+ template<typename Vertex, typename Graph>
+ void initialize_vertex(Vertex v, const Graph& g)
+ {
+ vertex_event("initialize_vertex", v, g);
+ }
+
+ template<typename Vertex, typename Graph>
+ void start_vertex(Vertex v, const Graph& g)
+ {
+ vertex_event("start_vertex", v, g);
+ }
+
+ template<typename Vertex, typename Graph>
+ void discover_vertex(Vertex v, const Graph& g)
+ {
+ vertex_event("discover_vertex", v, g);
+ }
+
+ template<typename Edge, typename Graph>
+ void examine_edge(Edge e, const Graph& g)
+ {
+ edge_event("examine_edge", e, g);
+ }
+
+ template<typename Edge, typename Graph>
+ void tree_edge(Edge e, const Graph& g)
+ {
+ edge_event("tree_edge", e, g);
+ }
+
+ template<typename Edge, typename Graph>
+ void back_edge(Edge e, const Graph& g)
+ {
+ edge_event("back_edge", e, g);
+ }
+
+ template<typename Edge, typename Graph>
+ void forward_or_cross_edge(Edge e, const Graph& g)
+ {
+ edge_event("forward_or_cross_edge", e, g);
+ }
+
+ template<typename Vertex, typename Graph>
+ void finish_vertex(Vertex v, const Graph& g)
+ {
+ vertex_event("finish_vertex", v, g);
+ }
+
+private:
+ template<typename Vertex, typename Graph>
+ void vertex_event(const char* name, Vertex v, const Graph& g)
+ {
+ std::cerr << "#" << process_id(g.process_group()) << ": " << name << "("
+ << get_vertex_name(v, g) << ": " << local(v) << "@" << owner(v)
+ << ")\n";
+ }
+
+ template<typename Edge, typename Graph>
+ void edge_event(const char* name, Edge e, const Graph& g)
+ {
+ std::cerr << "#" << process_id(g.process_group()) << ": " << name << "("
+ << get_vertex_name(source(e, g), g) << ": "
+ << local(source(e, g)) << "@" << owner(source(e, g)) << ", "
+ << get_vertex_name(target(e, g), g) << ": "
+ << local(target(e, g)) << "@" << owner(target(e, g)) << ")\n";
+ }
+
+};
+
+void
+test_distributed_dfs()
+{
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS,
+ // Vertex properties
+ property<vertex_color_t, default_color_type> >
+ Graph;
+ typedef graph_traits<Graph>::vertices_size_type size_type;
+ typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+
+ // Specify the edges in the graph
+ typedef std::pair<int, int> E;
+ E edge_array[] = { E(u, v), E(u, w), E(u, x), E(x, v), E(y, x),
+ E(v, y), E(w, y), E(w, z), E(z, z) };
+ Graph g(edge_array, edge_array + sizeof(edge_array) / sizeof(E), N);
+
+ std::vector<vertex_descriptor> parent(num_vertices(g));
+ std::vector<vertex_descriptor> explore(num_vertices(g));
+
+ boost::graph::tsin_depth_first_visit
+ (g,
+ vertex(u, g),
+ printing_dfs_visitor(),
+ get(vertex_color, g),
+ make_iterator_property_map(parent.begin(), get(vertex_index, g)),
+ make_iterator_property_map(explore.begin(), get(vertex_index, g)),
+ get(vertex_index, g));
+
+ std::size_t correct_parents1[N] = {u, u, y, y, v, w};
+ std::size_t correct_parents2[N] = {u, u, y, v, x, w};
+
+ for (std::size_t i = 0; i < N; ++i) {
+ vertex_descriptor v = vertex(i, g);
+ if (owner(v) == process_id(g.process_group())) {
+ std::cout << "parent(" << get_vertex_name(v, g) << ") = "
+ << get_vertex_name(parent[v.local], g) << std::endl;
+
+ }
+ }
+
+ if (false) {
+ depth_first_visit(g, vertex(u, g), printing_dfs_visitor());
+ }
+}
+
+int
+test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+ test_distributed_dfs();
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_dimacs_reader.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_dimacs_reader.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,86 @@
+// Copyright (C) 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Brian Barrett
+// Nick Edmonds
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/dimacs.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/test/minimal.hpp>
+
+#include <iostream>
+#include <cstdlib>
+#include <iomanip>
+#include <fstream>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using namespace boost::graph;
+using boost::graph::distributed::mpi_process_group;
+
+typedef double time_type;
+
+inline time_type get_time()
+{
+ return MPI_Wtime();
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+void
+test_dimacs_reader(const char *filename)
+{
+ mpi_process_group pg;
+ mpi_process_group::process_id_type id = process_id(pg);
+
+ typedef adjacency_list<vecS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS> Graph;
+
+ std::ifstream file(filename);
+ dimacs_basic_reader reader = dimacs_basic_reader(file, false);
+ dimacs_basic_reader end;
+ boost::parallel::variant_distribution<mpi_process_group> distrib =
+ boost::parallel::block(pg, reader.n_vertices());
+
+ Graph g(dimacs_edge_iterator<dimacs_basic_reader>(reader),
+ dimacs_edge_iterator<dimacs_basic_reader>(end),
+ reader.n_vertices(), pg, distrib);;
+
+ // write_graphviz("reader.dot", g);
+}
+
+int
+test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ if (argc == 2) {
+ test_dimacs_reader(argv[1]);
+ }
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_graph_coloring_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_graph_coloring_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,102 @@
+// Copyright (C) 2005, 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+#define PBGL_ACCOUNTING
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/boman_et_al_graph_coloring.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/graph/parallel/distribution.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <iostream>
+#include <boost/random.hpp>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+void
+test_distributed_graph_coloring(int n, double p, int s,
+ int seed, bool emit_dot_file)
+{
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS> Graph;
+
+ typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
+ typedef property_map<Graph, vertex_index_t>::type vertex_index_map;
+
+ // Build a random number generator
+ minstd_rand gen;
+ gen.seed(seed);
+
+ // Build a random graph
+ Graph g(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, p),
+ erdos_renyi_iterator<minstd_rand, Graph>(),
+ n);
+
+ // Set up color map
+ std::vector<int> colors_vec(num_vertices(g));
+ iterator_property_map<int*, vertex_index_map> color(&colors_vec[0],
+ get(vertex_index, g));
+
+ // Run the graph coloring algorithm
+ graph::boman_et_al_graph_coloring(g, color, s);
+
+ if (process_id(g.process_group()) == 0) {
+ graph::distributed::boman_et_al_graph_coloring_stats.print(std::cout);
+ }
+
+ if ( emit_dot_file ) {
+ if ( process_id(g.process_group()) == 0 ) {
+ for (int i = 0; i < n; ++i)
+ get(color, vertex(i, g));
+ synchronize(color);
+ } else {
+ synchronize(color);
+ }
+
+ write_graphviz("coloring.dot", g, paint_by_number(color));
+ }
+}
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ int n = 1000;
+ double p = 0.01;
+ int s = 100;
+ int seed = 1;
+ bool emit_dot_file = false;
+
+ if (argc > 1) n = lexical_cast<int>(argv[1]);
+ if (argc > 2) p = lexical_cast<double>(argv[2]);
+ if (argc > 3) s = lexical_cast<int>(argv[3]);
+ if (argc > 4) seed = lexical_cast<int>(argv[4]);
+ if (argc > 5) emit_dot_file = lexical_cast<bool>(argv[5]);
+
+ test_distributed_graph_coloring(n, p, s, seed, emit_dot_file);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_mst_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_mst_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,152 @@
+// Copyright 2004 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/vertex_list_adaptor.hpp>
+#include <boost/graph/parallel/distribution.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <iostream>
+#include <cstdlib>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+template<typename Graph, typename WeightMap, typename InputIterator>
+int
+total_weight(const Graph& g, WeightMap weight_map,
+ InputIterator first, InputIterator last)
+{
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+
+ int total_weight = 0;
+ while (first != last) {
+ total_weight += get(weight_map, *first);
+ if (process_id(g.process_group()) == 0) {
+ vertex_descriptor u = source(*first, g);
+ vertex_descriptor v = target(*first, g);
+ std::cout << "(" << g.distribution().global(owner(u), local(u))
+ << ", " << g.distribution().global(owner(v), local(v))
+ << ")\n";
+ }
+ ++first;
+ }
+
+ return total_weight;
+}
+
+void
+test_distributed_dense_boruvka()
+{
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS,
+ // Vertex properties
+ no_property,
+ // Edge properties
+ property<edge_weight_t, int> > Graph;
+
+ typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
+ typedef graph_traits<Graph>::edge_descriptor edge_descriptor;
+
+ typedef std::pair<int, int> E;
+
+ const int num_nodes = 5;
+ E edge_array[] = { E(0, 2), E(1, 3), E(1, 4), E(2, 1), E(2, 3),
+ E(3, 4), E(4, 0), E(4, 1)
+ };
+ int weights[] = { 1, 1, 2, 7, 3, 1, 1, 1 };
+ std::size_t num_edges = sizeof(edge_array) / sizeof(E);
+
+ Graph g(edge_array, edge_array + num_edges, weights, num_nodes);
+
+ {
+ if (process_id(g.process_group()) == 0)
+ std::cerr << "--Dense Boruvka--\n";
+ typedef property_map<Graph, edge_weight_t>::type WeightMap;
+ WeightMap weight_map = get(edge_weight, g);
+
+ std::vector<edge_descriptor> mst_edges;
+ dense_boruvka_minimum_spanning_tree(make_vertex_list_adaptor(g),
+ weight_map,
+ std::back_inserter(mst_edges));
+ int w = total_weight(g, weight_map, mst_edges.begin(), mst_edges.end());
+ BOOST_CHECK(w == 4);
+ BOOST_CHECK(mst_edges.size() == 4);
+ }
+
+ {
+ if (process_id(g.process_group()) == 0)
+ std::cerr << "--Merge local MSTs--\n";
+ typedef property_map<Graph, edge_weight_t>::type WeightMap;
+ WeightMap weight_map = get(edge_weight, g);
+
+ std::vector<edge_descriptor> mst_edges;
+ merge_local_minimum_spanning_trees(make_vertex_list_adaptor(g), weight_map,
+ std::back_inserter(mst_edges));
+ if (process_id(g.process_group()) == 0) {
+ int w = total_weight(g, weight_map, mst_edges.begin(), mst_edges.end());
+ BOOST_CHECK(w == 4);
+ BOOST_CHECK(mst_edges.size() == 4);
+ }
+ }
+
+ {
+ if (process_id(g.process_group()) == 0)
+ std::cerr << "--Boruvka then Merge--\n";
+ typedef property_map<Graph, edge_weight_t>::type WeightMap;
+ WeightMap weight_map = get(edge_weight, g);
+
+ std::vector<edge_descriptor> mst_edges;
+ boruvka_then_merge(make_vertex_list_adaptor(g), weight_map,
+ std::back_inserter(mst_edges));
+ if (process_id(g.process_group()) == 0) {
+ int w = total_weight(g, weight_map, mst_edges.begin(), mst_edges.end());
+ BOOST_CHECK(w == 4);
+ BOOST_CHECK(mst_edges.size() == 4);
+ }
+ }
+
+ {
+ if (process_id(g.process_group()) == 0)
+ std::cerr << "--Boruvka mixed Merge--\n";
+ typedef property_map<Graph, edge_weight_t>::type WeightMap;
+ WeightMap weight_map = get(edge_weight, g);
+
+ std::vector<edge_descriptor> mst_edges;
+ boruvka_mixed_merge(make_vertex_list_adaptor(g), weight_map,
+ std::back_inserter(mst_edges));
+ if (process_id(g.process_group()) == 0) {
+ int w = total_weight(g, weight_map, mst_edges.begin(), mst_edges.end());
+ BOOST_CHECK(w == 4);
+ BOOST_CHECK(mst_edges.size() == 4);
+ }
+ }
+}
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+ test_distributed_dense_boruvka();
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_page_rank_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_page_rank_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,109 @@
+// Copyright 2004 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/page_rank.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/test/minimal.hpp>
+#include <vector>
+#include <iostream>
+#include <stdlib.h>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+bool close_to(double x, double y)
+{
+ double diff = x - y;
+ if (diff < 0) diff = -diff;
+ double base = (y == 0? x : y);
+ if (base != 0) return diff / base < 0.01;
+ else return true;
+}
+
+// Make convenient labels for the vertices
+enum vertex_id_t { A, B, C, D, N };
+
+void test_distributed_page_rank(int iterations)
+{
+ using namespace boost::graph;
+
+ // create a typedef for the Graph type
+ typedef adjacency_list<vecS,
+ distributedS<mpi_process_group, vecS>,
+ bidirectionalS
+ > Graph;
+ typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+
+ // writing out the edges in the graph
+ typedef std::pair<int, int> Edge;
+ Edge edge_array[] =
+ { Edge(A,B), Edge(A,C), Edge(B,C), Edge(C,A), Edge(D,C) };
+ const int num_edges = sizeof(edge_array)/sizeof(edge_array[0]);
+
+ // declare a graph object
+ Graph g(edge_array, edge_array + num_edges, N);
+
+ std::vector<double> ranks(num_vertices(g));
+
+ page_rank(g,
+ make_iterator_property_map(ranks.begin(),
+ get(boost::vertex_index, g)),
+ n_iterations(iterations), 0.85, N);
+
+ double local_sum = 0.0;
+ for(unsigned int i = 0; i < num_vertices(g); ++i) {
+ std::cout << (char)('A' + g.distribution().global(i)) << " = "
+ << ranks[i] << std::endl;
+ local_sum += ranks[i];
+ }
+ double sum=0.;
+ boost::mpi::reduce(communicator(g.process_group()),
+ local_sum, sum, std::plus<double>(), 0);
+ if (process_id(g.process_group()) == 0) {
+ std::cout << "Sum = " << sum << "\n\n";
+ BOOST_CHECK(close_to(sum, 4)); // 1 when alpha=0
+ }
+
+ // double expected_ranks0[N] = {0.400009, 0.199993, 0.399998, 0.0};
+ double expected_ranks[N] = {1.49011, 0.783296, 1.5766, 0.15};
+ for (int i = 0; i < N; ++i) {
+ vertex_descriptor v = vertex(i, g);
+ if (v != Graph::null_vertex()
+ && owner(v) == process_id(g.process_group())) {
+ BOOST_CHECK(close_to(ranks[local(v)], expected_ranks[i]));
+ }
+ }
+}
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ int iterations = 50;
+ if (argc > 1) {
+ iterations = atoi(argv[1]);
+ }
+
+ test_distributed_page_rank(iterations);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_property_map_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_property_map_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,355 @@
+// Copyright (C) 2004-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/property_map/property_map.hpp>
+#include <boost/test/minimal.hpp>
+#include <vector>
+#include <string>
+#include <boost/serialization/string.hpp>
+#include <boost/serialization/utility.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/graph/parallel/basic_reduce.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+enum color_t { red, blue };
+
+struct remote_key
+{
+ remote_key(int p = -1, std::size_t l = 0) : processor(p), local_key(l) {}
+
+ int processor;
+ std::size_t local_key;
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & processor & local_key;
+ }
+};
+
+namespace boost { namespace mpi {
+ template<> struct is_mpi_datatype<remote_key> : mpl::true_ { };
+} }
+BOOST_IS_BITWISE_SERIALIZABLE(remote_key)
+BOOST_CLASS_IMPLEMENTATION(remote_key,object_serializable)
+BOOST_CLASS_TRACKING(remote_key,track_never)
+
+namespace boost {
+
+template<>
+struct hash<remote_key>
+{
+ std::size_t operator()(const remote_key& key) const
+ {
+ std::size_t hash = hash_value(key.processor);
+ hash_combine(hash, key.local_key);
+ return hash;
+ }
+};
+}
+
+inline bool operator==(const remote_key& x, const remote_key& y)
+{ return x.processor == y.processor && x.local_key == y.local_key; }
+
+struct remote_key_to_global
+{
+ typedef readable_property_map_tag category;
+ typedef remote_key key_type;
+ typedef std::pair<int, std::size_t> value_type;
+ typedef value_type reference;
+};
+
+inline std::pair<int, std::size_t>
+get(remote_key_to_global, const remote_key& key)
+{
+ return std::make_pair(key.processor, key.local_key);
+}
+
+template<typename T>
+struct my_reduce : boost::parallel::basic_reduce<T> {
+ BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
+};
+
+void colored_test()
+{
+ mpi_process_group pg;
+ const int n = 500;
+
+ color_t my_start_color = process_id(pg) % 2 == 0? ::red : ::blue;
+ int next_processor = (process_id(pg) + 1) % num_processes(pg);
+ color_t next_start_color = next_processor % 2 == 0? ::red : ::blue;
+
+ // Initial color map: even-numbered processes are all red,
+ // odd-numbered processes are all blue.
+ std::vector<color_t> color_vec(n, my_start_color);
+
+ typedef iterator_property_map<std::vector<color_t>::iterator,
+ identity_property_map> LocalPropertyMap;
+ LocalPropertyMap local_colors(color_vec.begin(), identity_property_map());
+
+ synchronize(pg);
+
+ // Create the distributed property map
+ typedef boost::parallel::distributed_property_map<mpi_process_group,
+ remote_key_to_global,
+ LocalPropertyMap> ColorMap;
+ ColorMap colors(pg, remote_key_to_global(), local_colors);
+ colors.set_reduce(my_reduce<color_t>());
+
+ if (process_id(pg) == 0) std::cerr << "Checking local colors...";
+ // check local processor colors
+ for (int i = 0; i < n; ++i) {
+ remote_key k(process_id(pg), i);
+ BOOST_CHECK(get(colors, k) == my_start_color);
+ }
+
+ colors.set_consistency_model(boost::parallel::cm_bidirectional);
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's default colors...";
+ // check next processor's colors
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(colors, k) == color_t());
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's colors...";
+ // check next processor's colors
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(colors, k) == next_start_color);
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChanging next processor's colors...";
+ // change the next processor's colors
+ color_t next_finish_color = next_processor % 2 == 0? ::blue : ::red;
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ put(colors, k, next_finish_color);
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed colors...";
+ // check our own colors
+ color_t my_finish_color = process_id(pg) % 2 == 0? ::blue : ::red;
+ for (int i = 0; i < n; ++i) {
+ remote_key k(process_id(pg), i);
+ BOOST_CHECK(get(colors, k) == my_finish_color);
+ }
+
+ // check our neighbor's colors
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed colors on neighbor...";
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(colors, k) == next_finish_color);
+ }
+
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\n";
+}
+
+void bool_test()
+{
+ mpi_process_group pg;
+ const int n = 500;
+
+ bool my_start_value = process_id(pg) % 2;
+ int next_processor = (process_id(pg) + 1) % num_processes(pg);
+ bool next_start_value = !my_start_value;
+
+ // Initial color map: even-numbered processes are false,
+ // odd-numbered processes are true
+ std::vector<bool> bool_vec(n, my_start_value);
+
+ typedef iterator_property_map<std::vector<bool>::iterator,
+ identity_property_map> LocalPropertyMap;
+ LocalPropertyMap local_values(bool_vec.begin(), identity_property_map());
+
+ synchronize(pg);
+
+ // Create the distributed property map
+ typedef boost::parallel::distributed_property_map<mpi_process_group,
+ remote_key_to_global,
+ LocalPropertyMap> ValueMap;
+ ValueMap values(pg, remote_key_to_global(), local_values);
+ values.set_reduce(my_reduce<bool>());
+
+ if (process_id(pg) == 0) std::cerr << "Checking local values...";
+ // check local processor values
+ for (int i = 0; i < n; ++i) {
+ remote_key k(process_id(pg), i);
+ BOOST_CHECK(get(values, k) == my_start_value);
+ }
+
+ values.set_consistency_model(boost::parallel::cm_bidirectional);
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's default values...";
+ // check next processor's values
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(values, k) == false);
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's values...";
+ // check next processor's values
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(values, k) == next_start_value);
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChanging next processor's values...";
+ // change the next processor's values
+ bool next_finish_value = next_processor % 2 == 0;
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ put(values, k, next_finish_value);
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed values...";
+ // check our own values
+ bool my_finish_value = process_id(pg) % 2 == 0;
+ for (int i = 0; i < n; ++i) {
+ remote_key k(process_id(pg), i);
+ BOOST_CHECK(get(values, k) == my_finish_value);
+ }
+
+ // check our neighbor's values
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed values on neighbor...";
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(values, k) == next_finish_value);
+ }
+
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\n";
+}
+
+void string_test()
+{
+ mpi_process_group pg;
+ const int n = 500;
+
+ std::string my_start_string = lexical_cast<std::string>(process_id(pg));
+ int next_processor = (process_id(pg) + 1) % num_processes(pg);
+ std::string next_start_string = lexical_cast<std::string>(next_processor);
+
+ // Initial color map: even-numbered processes are false,
+ // odd-numbered processes are true
+ std::vector<std::string> string_vec(n, my_start_string);
+
+ typedef iterator_property_map<std::vector<std::string>::iterator,
+ identity_property_map> LocalPropertyMap;
+ LocalPropertyMap local_strings(string_vec.begin(), identity_property_map());
+
+ synchronize(pg);
+
+ // Create the distributed property map
+ typedef boost::parallel::distributed_property_map<mpi_process_group,
+ remote_key_to_global,
+ LocalPropertyMap> StringMap;
+ StringMap strings(pg, remote_key_to_global(), local_strings);
+ strings.set_reduce(my_reduce<std::string>());
+
+ if (process_id(pg) == 0) std::cerr << "Checking local strings...";
+ // check local processor strings
+ for (int i = 0; i < n; ++i) {
+ remote_key k(process_id(pg), i);
+ BOOST_CHECK(get(strings, k) == my_start_string);
+ }
+
+ strings.set_consistency_model(boost::parallel::cm_bidirectional);
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's default strings...";
+ // check next processor's strings
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(strings, k) == std::string());
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking next processor's strings...";
+ // check next processor's strings
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(strings, k) == next_start_string);
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChanging next processor's strings...";
+ // change the next processor's strings
+ std::string next_finish_string = next_start_string + next_start_string;
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ put(strings, k, next_finish_string);
+ }
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nSynchronizing...";
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed strings...";
+ // check our own strings
+ std::string my_finish_string = my_start_string + my_start_string;
+ for (int i = 0; i < n; ++i) {
+ remote_key k(process_id(pg), i);
+ BOOST_CHECK(get(strings, k) == my_finish_string);
+ }
+
+ // check our neighbor's strings
+ if (process_id(pg) == 0) std::cerr << "OK.\nChecking changed strings on neighbor...";
+ for (int i = 0; i < n; ++i) {
+ remote_key k(next_processor, i);
+ BOOST_CHECK(get(strings, k) == next_finish_string);
+ }
+
+ synchronize(pg);
+
+ if (process_id(pg) == 0) std::cerr << "OK.\n";
+}
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+ colored_test();
+ bool_test();
+ string_test();
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_queue_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_queue_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,115 @@
+// Copyright (C) 2004-2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/queue.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/pending/queue.hpp>
+#include <boost/property_map/property_map.hpp>
+#include <utility>
+#include <iostream>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using boost::graph::distributed::mpi_process_group;
+
+struct global_value
+{
+ global_value(int p = -1, std::size_t l = 0) : processor(p), value(l) {}
+
+ int processor;
+ std::size_t value;
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & processor & value;
+ }
+};
+
+namespace boost { namespace mpi {
+ template<> struct is_mpi_datatype<global_value> : mpl::true_ { };
+} } // end namespace boost::mpi
+
+BOOST_IS_BITWISE_SERIALIZABLE(global_value)
+BOOST_CLASS_IMPLEMENTATION(global_value,object_serializable)
+BOOST_CLASS_TRACKING(global_value,track_never)
+
+inline bool operator==(const global_value& x, const global_value& y)
+{ return x.processor == y.processor && x.value == y.value; }
+
+struct global_value_owner_map
+{
+ typedef int value_type;
+ typedef value_type reference;
+ typedef global_value key_type;
+ typedef boost::readable_property_map_tag category;
+};
+
+int get(global_value_owner_map, global_value k)
+{
+ return k.processor;
+}
+
+void test_distributed_queue()
+{
+ mpi_process_group process_group;
+
+ typedef boost::queue<global_value> local_queue_type;
+
+ typedef boost::graph::distributed::distributed_queue<mpi_process_group,
+ global_value_owner_map,
+ local_queue_type> dist_queue_type;
+
+ dist_queue_type Q(process_group, global_value_owner_map());
+
+ mpi_process_group::process_id_type id = process_id(process_group),
+ n = num_processes(process_group);
+ global_value v(0, 0);
+
+ if (id == 0) {
+ std::cerr << "Should print level of each processor in a binary tree:\n";
+ }
+ synchronize(process_group);
+
+ if (id == n-1) Q.push(v);
+ while (!Q.empty()) {
+ v = Q.top(); Q.pop();
+
+ std::cerr << "#" << id << ": level = " << v.value << std::endl;
+
+ int level_begin = 1;
+ for (std::size_t i = 0; i < v.value; ++i) level_begin *= 2;
+ int level_end = level_begin * 2;
+ BOOST_CHECK(level_begin <= (id + 1));
+ BOOST_CHECK((id + 1) <= level_end);
+
+ ++v.value;
+ v.processor = v.processor * 2 + 1;
+ if (v.processor < n) Q.push(v);
+ ++v.processor;
+ if (v.processor < n) Q.push(v);
+ }
+}
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+ test_distributed_queue();
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_rmat_cc.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_rmat_cc.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,118 @@
+// Copyright (C) 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Brian Barrett
+// Nick Edmonds
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/concepts.hpp>
+#include <boost/graph/distributed/connected_components_parallel_search.hpp>
+#include <boost/graph/distributed/connected_components.hpp>
+#include <boost/graph/rmat_graph_generator.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/property_map/vector_property_map.hpp>
+
+#include <iostream>
+#include <cstdlib>
+#include <iomanip>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+typedef double time_type;
+
+inline time_type get_time()
+{
+ return MPI_Wtime();
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+void
+test_filtered_rmat_cc(int n, int m, double a, double b, double c, double d)
+{
+ mpi_process_group pg;
+ mpi_process_group::process_id_type id = process_id(pg);
+
+ if (id == 0) printf("INFO: Params: n=%d, m=%d, a=%f, b=%f, c=%f, d=%f.\n",
+ n, m, a, b, c, d);
+
+ parallel::variant_distribution<mpi_process_group> distrib
+ = parallel::block(pg, n);
+
+ typedef adjacency_list<vecS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS> Graph;
+
+ typedef keep_local_edges<parallel::variant_distribution<mpi_process_group>,
+ mpi_process_group::process_id_type>
+ EdgeFilter;
+
+ typedef unique_rmat_iterator<rand48, Graph, EdgeFilter>
+ RMATIter;
+
+ if (id == 0) printf("INFO: Generating graph.\n");
+
+ rand48 gen;
+ Graph g(RMATIter(gen, n, m, a, b, c, d, true, EdgeFilter(distrib, id)),
+ RMATIter(), n, pg, distrib);
+
+ synchronize(g);
+
+ if (id == 0) printf("INFO: Starting connected components.\n");
+
+ std::vector<int> local_components_vec(num_vertices(g));
+ typedef iterator_property_map<std::vector<int>::iterator, property_map<Graph, vertex_index_t>::type> ComponentMap;
+ ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
+
+ time_type start = get_time();
+ int num_components = connected_components(g, component);
+ time_type end = get_time();
+
+ if (process_id(g.process_group()) == 0) {
+ std::cout << "INFO: Test Complete. components found = " << num_components
+ << ", time = " << print_time(end - start) << "s." << std::endl;
+ printf("RESULT: %d %d %d %f %f %f %f %f\n",
+ num_processes(pg), n, m, a, b, c, d, end - start);
+ }
+
+}
+
+int
+main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ if (argc < 7)
+ test_filtered_rmat_cc(40, 200, 0.58, 0.19, 0.19, 0.04);
+ else
+ test_filtered_rmat_cc(atoi(argv[1]), atoi(argv[2]),
+ atof(argv[3]), atof(argv[4]),
+ atof(argv[5]), atof(argv[6]));
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_rmat_cc_ps.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_rmat_cc_ps.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,117 @@
+// Copyright (C) 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Brian Barrett
+// Nick Edmonds
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/concepts.hpp>
+#include <boost/graph/distributed/connected_components_parallel_search.hpp>
+#include <boost/graph/distributed/connected_components.hpp>
+#include <boost/graph/rmat_graph_generator.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/property_map/vector_property_map.hpp>
+
+#include <iostream>
+#include <cstdlib>
+#include <iomanip>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+typedef double time_type;
+
+inline time_type get_time()
+{
+ return MPI_Wtime();
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+void
+test_filtered_rmat_cc(int n, int m, double a, double b, double c, double d)
+{
+ mpi_process_group pg;
+ std::size_t id = process_id(pg);
+
+ if (id == 0) printf("INFO: Params: n=%d, m=%d, a=%f, b=%f, c=%f, d=%f.\n",
+ n, m, a, b, c, d);
+
+ typedef parallel::variant_distribution<mpi_process_group> Distribution;
+ Distribution distrib = parallel::block(pg, n);
+
+ typedef adjacency_list<vecS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS> Graph;
+
+ typedef scalable_rmat_iterator<mpi_process_group, Distribution, rand48, Graph>
+ RMATIter;
+
+ if (id == 0) printf("INFO: Generating graph.\n");
+
+ rand48 gen;
+ time_type gen_start = get_time();
+ Graph g(RMATIter(pg, distrib, gen, n, m, a, b, c, d, true),
+ RMATIter(), n, pg, distrib);
+ time_type gen_end = get_time();
+ std::cout << "INFO: Graph Gen time: " << print_time(gen_end - gen_start) << std::endl;
+
+ synchronize(g);
+
+ if (id == 0) printf("INFO: Starting connected components.\n");
+
+ std::vector<int> local_components_vec(num_vertices(g));
+ typedef iterator_property_map<std::vector<int>::iterator, property_map<Graph, vertex_index_t>::type> ComponentMap;
+ ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
+
+ time_type start = get_time();
+ int num_components = connected_components_ps(g, component);
+ time_type end = get_time();
+
+ if (process_id(g.process_group()) == 0) {
+ std::cout << "INFO: Test Complete. components found = " << num_components
+ << ", time = " << print_time(end - start) << "s." << std::endl;
+ printf("RESULT: %d %d %d %f %f %f %f %f\n",
+ num_processes(pg), n, m, a, b, c, d, end - start);
+ }
+
+}
+
+int
+main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ if (argc < 7)
+ test_filtered_rmat_cc(40, 200, 0.58, 0.19, 0.19, 0.04);
+ else
+ test_filtered_rmat_cc(atoi(argv[1]), atoi(argv[2]),
+ atof(argv[3]), atof(argv[4]),
+ atof(argv[5]), atof(argv[6]));
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_rmat_pagerank.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_rmat_pagerank.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,113 @@
+// Copyright (C) 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Brian Barrett
+// Nick Edmonds
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/concepts.hpp>
+#include <boost/graph/distributed/page_rank.hpp>
+#include <boost/graph/rmat_graph_generator.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/property_map/vector_property_map.hpp>
+
+#include <iostream>
+#include <cstdlib>
+#include <iomanip>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+typedef double time_type;
+
+inline time_type get_time()
+{
+ return MPI_Wtime();
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+void
+test_filtered_rmat_pagerank(int n, int m, double a, double b, double c, double d, int iters)
+{
+ mpi_process_group pg;
+ std::size_t id = process_id(pg);
+
+ if (id == 0) printf("INFO: Params: n=%d, m=%d, a=%f, b=%f, c=%f, d=%f, iters=%d.\n",
+ n, m, a, b, c, d, iters);
+
+ typedef parallel::variant_distribution<mpi_process_group> Distribution;
+ Distribution distrib = parallel::block(pg, n);
+
+ typedef adjacency_list<vecS,
+ distributedS<mpi_process_group, vecS>,
+ bidirectionalS> Graph;
+
+ typedef scalable_rmat_iterator<mpi_process_group, Distribution, rand48, Graph>
+ RMATIter;
+
+ if (id == 0) printf("INFO: Generating graph.\n");
+
+ rand48 gen;
+ Graph g(RMATIter(pg, distrib, gen, n, m, a, b, c, d, true),
+ RMATIter(), n, pg, distrib);
+
+ synchronize(g);
+
+ if (id == 0) printf("INFO: Starting PageRank.\n");
+
+ std::vector<double> ranks(num_vertices(g));
+
+ time_type start = get_time();
+ page_rank(g, make_iterator_property_map(ranks.begin(), get(boost::vertex_index, g)),
+ graph::n_iterations(iters), 0.85, n);
+ time_type end = get_time();
+
+ if (process_id(g.process_group()) == 0) {
+ std::cout << "INFO: Test Complete. time = " <<
+ print_time(end - start) << "s." << std::endl;
+ printf("RESULT: %d %d %d %f %f %f %f %f\n",
+ num_processes(pg), n, m, a, b, c, d, end - start);
+ }
+
+}
+
+int
+main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ if (argc < 8)
+ test_filtered_rmat_pagerank(40, 200, 0.58, 0.19, 0.19, 0.04, 10);
+ else
+ test_filtered_rmat_pagerank(atoi(argv[1]), atoi(argv[2]), atof(argv[3]),
+ atof(argv[4]), atof(argv[5]), atof(argv[6]),
+ atoi(argv[7]));
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_shortest_paths_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_shortest_paths_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,221 @@
+// Copyright (C) 2005, 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+#define PBGL_ACCOUNTING
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/delta_stepping_shortest_paths.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/graph/parallel/distribution.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/random.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/graph/iteration_macros.hpp>
+
+#include <sys/time.h>
+#include <time.h>
+#include <iostream>
+#include <iomanip>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+/****************************************************************************
+ * Timing *
+ ****************************************************************************/
+typedef double time_type;
+
+inline time_type get_time()
+{
+ timeval tp;
+ gettimeofday(&tp, 0);
+ return tp.tv_sec + tp.tv_usec / 1000000.0;
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+/****************************************************************************
+ * Edge weight generator iterator *
+ ****************************************************************************/
+template<typename F, typename RandomGenerator>
+class generator_iterator
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename F::result_type value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ explicit
+ generator_iterator(RandomGenerator& gen, const F& f = F())
+ : f(f), gen(&gen)
+ {
+ value = this->f(gen);
+ }
+
+ reference operator*() const { return value; }
+ pointer operator->() const { return &value; }
+
+ generator_iterator& operator++()
+ {
+ value = f(*gen);
+ return *this;
+ }
+
+ generator_iterator operator++(int)
+ {
+ generator_iterator temp(*this);
+ ++(*this);
+ return temp;
+ }
+
+ bool operator==(const generator_iterator& other) const
+ { return f == other.f; }
+
+ bool operator!=(const generator_iterator& other) const
+ { return !(*this == other); }
+
+private:
+ F f;
+ RandomGenerator* gen;
+ value_type value;
+};
+
+template<typename F, typename RandomGenerator>
+inline generator_iterator<F, RandomGenerator>
+make_generator_iterator( RandomGenerator& gen, const F& f)
+{ return generator_iterator<F, RandomGenerator>(gen, f); }
+
+/****************************************************************************
+ * Verification *
+ ****************************************************************************/
+template <typename Graph, typename DistanceMap, typename WeightMap>
+void
+verify_shortest_paths(const Graph& g, DistanceMap distance,
+ const WeightMap& weight) {
+
+ distance.set_max_ghost_cells(0);
+
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ BGL_FORALL_OUTEDGES_T(v, e, g, Graph) {
+ get(distance, target(e, g));
+ }
+ }
+
+ synchronize(process_group(g));
+
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ BGL_FORALL_OUTEDGES_T(v, e, g, Graph) {
+ assert(get(distance, target(e, g)) <=
+ get(distance, source(e, g)) + get(weight, e));
+ }
+ }
+}
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+typedef int weight_type;
+
+struct WeightedEdge {
+ WeightedEdge(weight_type weight = 0) : weight(weight) { }
+
+ weight_type weight;
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & weight;
+ }
+};
+
+struct VertexProperties {
+ VertexProperties(int d = 0)
+ : distance(d) { }
+
+ int distance;
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & distance;
+ }
+};
+
+void
+test_distributed_shortest_paths(int n, double p, int c, int seed)
+{
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS,
+ VertexProperties,
+ WeightedEdge> Graph;
+
+ typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
+ typedef graph_traits<Graph>::vertices_size_type vertices_size_type;
+ typedef property_map<Graph, vertex_index_t>::type vertex_index_map;
+
+ // Build a random number generator
+ minstd_rand gen;
+ gen.seed(seed);
+
+ // Build a random graph
+ Graph g(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, p),
+ erdos_renyi_iterator<minstd_rand, Graph>(),
+ make_generator_iterator(gen, uniform_int<int>(0, c)),
+ n);
+
+ uniform_int<vertices_size_type> rand_vertex(0, n);
+
+ graph::distributed::delta_stepping_shortest_paths(g,
+ vertex(rand_vertex(gen), g),
+ dummy_property_map(),
+ get(&VertexProperties::distance, g),
+ get(&WeightedEdge::weight, g));
+
+ verify_shortest_paths(g,
+ get(&VertexProperties::distance, g),
+ get(&WeightedEdge::weight, g));
+}
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ int n = 1000;
+ double p = 0.01;
+ int c = 100;
+ int seed = 1;
+
+ if (argc > 1) n = lexical_cast<int>(argv[1]);
+ if (argc > 2) p = lexical_cast<double>(argv[2]);
+ if (argc > 3) c = lexical_cast<int>(argv[3]);
+ if (argc > 4) seed = lexical_cast<int>(argv[4]);
+
+ test_distributed_shortest_paths(n, p, c, seed);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/distributed_strong_components_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/distributed_strong_components_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,180 @@
+// Copyright (C) 2004-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Nick Edmonds
+// Douglas Gregor
+// Andrew Lumsdaine
+
+// SCC won't work with CSR currently due to the way the reverse graph
+// is constructed in the SCC algorithm
+
+#include <boost/graph/use_mpi.hpp>
+
+// #define CSR
+
+#ifdef CSR
+# include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
+#else
+# include <boost/graph/distributed/adjacency_list.hpp>
+#endif
+
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/strong_components.hpp>
+#include <boost/graph/random.hpp>
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/parallel/distribution.hpp>
+#include <boost/graph/erdos_renyi_generator.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/graph/distributed/graphviz.hpp>
+#include <iostream>
+#include <cstdlib>
+#include <iomanip>
+#include <boost/random.hpp>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+typedef double time_type;
+
+inline time_type get_time()
+{
+ return MPI_Wtime();
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+void
+test_distributed_strong_components(int n, double _p, bool verify, bool emit_dot_file, int seed)
+{
+#ifdef CSR
+ typedef compressed_sparse_row_graph<directedS, no_property, no_property, no_property,
+ distributedS<mpi_process_group> > Graph;
+#else
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ bidirectionalS > Graph;
+#endif
+
+ typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
+ typedef iterator_property_map<std::vector<vertex_descriptor>::iterator, property_map<Graph, vertex_index_t>::type> ParentMap;
+ typedef std::pair<int, int> Edge;
+
+ minstd_rand gen;
+
+ gen.seed(seed);
+
+ mpi_process_group pg;
+ parallel::variant_distribution<mpi_process_group> distrib
+ = parallel::block(pg, n);
+
+#ifdef CSR
+ Graph g(sorted_erdos_renyi_iterator<minstd_rand, Graph>(gen, n, _p/2),
+ sorted_erdos_renyi_iterator<minstd_rand, Graph>(),
+ n, pg, distrib);
+#else
+ Graph g(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, _p/2),
+ erdos_renyi_iterator<minstd_rand, Graph>(),
+ n, pg, distrib);
+#endif
+
+ synchronize(g);
+
+ std::vector<int> local_components_vec(num_vertices(g));
+ typedef iterator_property_map<std::vector<int>::iterator, property_map<Graph, vertex_index_t>::type> ComponentMap;
+ ComponentMap component(local_components_vec.begin(), get(vertex_index, g));
+
+ int num_components = 0;
+
+ time_type start = get_time();
+ num_components = strong_components(g, component);
+ time_type end = get_time();
+ if (process_id(g.process_group()) == 0)
+ std::cerr << "Erdos-Reyni graph:\n" << n << " Vertices " << _p << " Edge probability "
+ << num_processes(pg) << " Processors\n"
+ << "Strong Components time = " << print_time(end - start) << " seconds.\n"
+ << num_components << " components identified\n";
+
+
+ if ( verify )
+ {
+ if ( process_id(g.process_group()) == 0 )
+ {
+ for (int i = 0; i < n; ++i)
+ get(component, vertex(i, g));
+ synchronize(component);
+
+ // Check against the sequential version
+ typedef adjacency_list<listS, vecS, directedS> Graph2;
+
+ gen.seed(seed);
+
+ Graph2 g2(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, _p/2),
+ erdos_renyi_iterator<minstd_rand, Graph>(),
+ n);
+
+ std::vector<int> component2(n);
+ int seq_num_components = strong_components(g2, make_iterator_property_map(component2.begin(), get(vertex_index, g2)));
+
+ assert(num_components == seq_num_components);
+
+ // Make sure components and component2 match
+ std::map<int, int> c2c;
+ int i;
+ for ( i = 0; i < n; i++ )
+ if ( c2c.find( get(component, vertex(i, g)) ) == c2c.end() )
+ c2c[get(component, vertex(i, g))] = component2[i];
+ else
+ if ( c2c[get(component, vertex(i, g))] != component2[i] )
+ break;
+
+ if ( i < n )
+ std::cerr << "Unable to verify SCC result...\n";
+ else
+ std::cerr << "Passed verification... " << seq_num_components << " strong components\n";
+ }
+ else
+ {
+ synchronize(component);
+ }
+ if ( emit_dot_file )
+ write_graphviz("scc.dot", g, paint_by_number(component));
+ }
+}
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ if (argc == 1)
+ test_distributed_strong_components(10000, 0.0005, true, false, 1);
+ else if ( argc < 5 )
+ std::cerr << "usage: test_distributed_strong_components <int num_vertices> <double p> <bool verify?> <bool emit_dotfile?> [seed]\n";
+ else
+ test_distributed_strong_components
+ (atoi(argv[1]), atof(argv[2]),
+ argv[3]==std::string("true"), argv[4]==std::string("true"),
+ argc == 5? 1 : atoi(argv[5]));
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/hohberg_biconnected_components_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/hohberg_biconnected_components_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,175 @@
+// Copyright (C) 2005-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+//
+// Test of Hohberg's distributed biconnected components algorithm.
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/hohberg_biconnected_components.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using boost::graph::distributed::mpi_process_group;
+
+using namespace boost;
+
+template<typename Graph>
+void check_components(const Graph& g, std::size_t num_comps)
+{
+ std::size_t not_mapped = (std::numeric_limits<std::size_t>::max)();
+ std::vector<std::size_t> color_to_name(num_comps, not_mapped);
+ BGL_FORALL_EDGES_T(e, g, Graph) {
+ BOOST_CHECK(get(edge_color, g, e) < num_comps);
+ if (color_to_name[get(edge_color, g, e)] == not_mapped)
+ color_to_name[get(edge_color, g, e)] = get(edge_name, g, e);
+ BOOST_CHECK(color_to_name[get(edge_color,g,e)] == get(edge_name,g,e));
+
+ if (color_to_name[get(edge_color,g,e)] != get(edge_name,g,e)) {
+ for (std::size_t i = 0; i < color_to_name.size(); ++i)
+ std::cerr << color_to_name[i] << ' ';
+
+ std::cerr << std::endl;
+
+ std::cerr << color_to_name[get(edge_color,g,e)] << " != "
+ << get(edge_name,g,e) << " on edge "
+ << local(source(e, g)) << " -> " << local(target(e, g))
+ << std::endl;
+ }
+ }
+}
+
+template<typename Graph>
+void
+test_small_hohberg_biconnected_components(Graph& g, int n, int comps_expected,
+ bool single_component = true)
+{
+ using boost::graph::distributed::hohberg_biconnected_components;
+
+ bool is_root = (process_id(process_group(g)) == 0);
+
+ if (single_component) {
+ for (int i = 0; i < n; ++i) {
+ if (is_root) std::cerr << "Testing with leader = " << i << std::endl;
+
+ // Scramble edge_color_map
+ BGL_FORALL_EDGES_T(e, g, Graph)
+ put(edge_color, g, e, 17);
+
+ typename graph_traits<Graph>::vertex_descriptor leader = vertex(i, g);
+ int num_comps =
+ hohberg_biconnected_components(g, get(edge_color, g), &leader,
+ &leader + 1);
+
+ BOOST_CHECK(num_comps == comps_expected);
+ check_components(g, num_comps);
+ }
+ }
+
+ if (is_root) std::cerr << "Testing simple interface." << std::endl;
+ synchronize(g);
+
+ // Scramble edge_color_map
+ int i = 0;
+ BGL_FORALL_EDGES_T(e, g, Graph) {
+ ++i;
+ put(edge_color, g, e, 17);
+ }
+ std::cerr << process_id(process_group(g)) << " has "
+ << i << " edges.\n";
+
+ int num_comps = hohberg_biconnected_components(g, get(edge_color, g));
+
+ BOOST_CHECK(num_comps == comps_expected);
+ check_components(g, num_comps);
+}
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS,
+ // Vertex properties
+ no_property,
+ // Edge properties
+ property<edge_name_t, std::size_t,
+ property<edge_color_t, std::size_t> > > Graph;
+
+ typedef std::pair<int, int> E;
+
+ {
+ // Example 1: A single component with 2 bicomponents
+ E edges_init[] = { E(0, 1), E(0, 2), E(1, 3), E(2, 4), E(3, 4), E(4, 5),
+ E(4, 6), E(5, 6) };
+ const int m = sizeof(edges_init) / sizeof(E);
+ std::size_t expected_components[m] = { 0, 0, 0, 0, 0, 1, 1, 1 };
+ const int n = 7;
+ Graph g(&edges_init[0], &edges_init[0] + m, &expected_components[0], n);
+
+ int num_comps_expected =
+ *std::max_element(&expected_components[0], &expected_components[0] + m)
+ + 1;
+
+ test_small_hohberg_biconnected_components(g, n, num_comps_expected);
+ }
+
+ {
+ // Example 2: A single component with 4 bicomponents
+ E edges_init[] = { E(0, 1), E(1, 2), E(2, 0), E(2, 3), E(3, 4), E(4, 5),
+ E(5, 2), E(3, 6), E(6, 7), E(7, 8), E(8, 6) };
+ const int m = sizeof(edges_init) / sizeof(E);
+ std::size_t expected_components[m] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 3, 3 };
+ const int n = 9;
+ Graph g(&edges_init[0], &edges_init[0] + m, &expected_components[0], n);
+
+ int num_comps_expected =
+ *std::max_element(&expected_components[0], &expected_components[0] + m)
+ + 1;
+
+ test_small_hohberg_biconnected_components(g, n, num_comps_expected);
+ }
+
+ {
+ // Example 3: Two components, 6 bicomponents
+ // This is just the concatenation of the two previous graphs.
+ E edges_init[] = { /* Example 1 graph */
+ E(0, 1), E(0, 2), E(1, 3), E(2, 4), E(3, 4), E(4, 5),
+ E(4, 6), E(5, 6),
+ /* Example 2 graph */
+ E(7, 8), E(8, 9), E(9, 7), E(9, 10), E(10, 11),
+ E(11, 12), E(12, 9), E(10, 13), E(13, 14), E(14, 15),
+ E(15, 13) };
+ const int m = sizeof(edges_init) / sizeof(E);
+ std::size_t expected_components[m] =
+ { /* Example 1 */0, 0, 0, 0, 0, 1, 1, 1,
+ /* Example 2 */2, 2, 2, 3, 3, 3, 3, 4, 5, 5, 5 };
+ const int n = 16;
+ Graph g(&edges_init[0], &edges_init[0] + m, &expected_components[0], n);
+
+ int num_comps_expected =
+ *std::max_element(&expected_components[0], &expected_components[0] + m)
+ + 1;
+
+ test_small_hohberg_biconnected_components(g, n, num_comps_expected,
+ false);
+ }
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/mesh_generator_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/mesh_generator_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,133 @@
+// Copyright (C) 2004-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/mesh_graph_generator.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/graphviz.hpp>
+#include <boost/graph/iteration_macros.hpp>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <string>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+/****************************************************************************
+ * Timing
+ ****************************************************************************/
+typedef double time_type;
+
+inline time_type get_time()
+{
+ return MPI_Wtime();
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+/****************************************************************************
+ * Edge weight generator iterator *
+ ****************************************************************************/
+template<typename F>
+class generator_iterator
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename F::result_type value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ explicit generator_iterator(const F& f = F()) : f(f) { value = this->f(); }
+
+ reference operator*() const { return value; }
+ pointer operator->() const { return &value; }
+
+ generator_iterator& operator++()
+ {
+ value = f();
+ return *this;
+ }
+
+ generator_iterator operator++(int)
+ {
+ generator_iterator temp(*this);
+ ++(*this);
+ return temp;
+ }
+
+ bool operator==(const generator_iterator& other) const
+ { return f == other.f; }
+
+ bool operator!=(const generator_iterator& other) const
+ { return !(*this == other); }
+
+private:
+ F f;
+ value_type value;
+};
+
+template<typename F>
+inline generator_iterator<F> make_generator_iterator(const F& f)
+{ return generator_iterator<F>(f); }
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ if (argc < 5) {
+ std::cerr << "Usage: mesh_generator_test <x> <y> <toroidal> <emit dot file>\n";
+ exit(-1);
+ }
+
+ int x(atoi(argv[1])), y(atoi(argv[2]));
+ bool toroidal(argv[3] == std::string("true"));
+ bool emit_dot_file(argv[4] == std::string("true"));
+
+ typedef adjacency_list<listS,
+ distributedS<mpi_process_group, vecS>,
+ undirectedS> Graph;
+
+ Graph g(mesh_iterator<Graph>(x, y, toroidal),
+ mesh_iterator<Graph>(),
+ x*y);
+
+ synchronize(g);
+
+ BGL_FORALL_VERTICES(v, g, Graph)
+ if (toroidal)
+ assert(out_degree(v, g) == 4);
+ else
+ assert(out_degree(v, g) >= 2 && out_degree(v, g) <= 4);
+
+ if ( emit_dot_file )
+ write_graphviz("mesh.dot", g);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/named_vertices_hash_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/named_vertices_hash_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,158 @@
+// Copyright (C) 2007-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/mpl/print.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/iteration_macros.hpp>
+#include <boost/test/minimal.hpp>
+#include <string>
+#include <iostream>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+/// City structure to be attached to each vertex
+struct City {
+ City() {}
+
+ City(const std::string& name, int population = -1)
+ : name(name), population(population) { }
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & name & population;
+ }
+
+ std::string name;
+ int population;
+};
+
+/// Our distribution function
+template<typename T>
+struct named_vertices_hashed_distribution
+{
+ template<typename ProcessGroup>
+ named_vertices_hashed_distribution(const ProcessGroup& pg,
+ std::size_t /*num_vertices*/ = 0)
+ : n(num_processes(pg)) { }
+
+ int operator()(const T& value) const
+ {
+ return hasher(value) % n;
+ }
+
+ std::size_t n;
+ boost::hash<T> hasher;
+};
+
+typedef named_vertices_hashed_distribution<std::string> hasher_type;
+
+namespace boost { namespace graph {
+
+/// Use the City name as a key for indexing cities in a graph
+template<>
+struct internal_vertex_name<City>
+{
+ typedef multi_index::member<City, std::string, &City::name> type;
+};
+
+/// Allow the graph to build cities given only their names (filling in
+/// the defaults for fields).
+template<>
+struct internal_vertex_constructor<City>
+{
+ typedef vertex_from_name<City> type;
+};
+
+// namespace distributed
+// {
+// /// Use the City name as the source for the distribution hasher
+// ///
+// /// This is currently needed in addition to the specification of this
+// /// hasher functor as the 3rd template parameter to the distributedS
+// /// template.
+// template<>
+// struct internal_vertex_name_distribution<City>
+// {
+// typedef named_vertices_hashed_distribution<std::string> type;
+// };
+// }
+
+} } // end namespace boost::graph
+
+/// Our road map, where each of the vertices are cities
+typedef boost::adjacency_list<vecS,
+ distributedS<mpi_process_group, vecS, hasher_type>,
+ bidirectionalS, City> RoadMap;
+typedef graph_traits<RoadMap>::vertex_descriptor Vertex;
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+
+ mpi_process_group pg;
+ RoadMap map; // (pg, hasher_type(pg));
+
+ int rank = process_id(pg);
+ bool i_am_root = rank == 0;
+
+ /// Create vertices for Bloomington, Indianapolis, Chicago. Everyone will
+ /// try to do this, but only one of each vertex will be added.
+ Vertex bloomington = add_vertex(City("Bloomington", 69291), map);
+ Vertex chicago = add_vertex(City("Chicago", 9500000), map);
+ Vertex indianapolis = add_vertex(City("Indianapolis", 791926), map);
+
+ BGL_FORALL_VERTICES(city, map, RoadMap)
+ std::cout << rank << ": " << map[city].name << ", population "
+ << map[city].population << std::endl;
+
+ BOOST_CHECK(*find_vertex("Bloomington", map) == bloomington);
+ BOOST_CHECK(*find_vertex("Indianapolis", map) == indianapolis);
+ BOOST_CHECK(*find_vertex("Chicago", map) == chicago);
+
+ if (i_am_root) {
+ add_edge(bloomington, "Indianapolis", map);
+ add_edge("Indianapolis", chicago, map);
+ add_edge("Indianapolis", "Cincinnati", map);
+ }
+
+ synchronize(map);
+
+ {
+ property_map<RoadMap, std::string City::*>::type
+ city_name = get(&City::name, map);
+
+ BGL_FORALL_EDGES(road, map, RoadMap)
+ std::cout << rank << ": " << get(city_name, source(road, map)) << " -> "
+ << get(city_name, target(road, map)) << std::endl;
+
+ synchronize(map);
+ }
+
+ // Make sure the vertex for "Cincinnati" was created implicitly
+ Vertex cincinnati = *find_vertex("Cincinnati", map);
+ if (get(get(vertex_owner, map), cincinnati)
+ == process_id(map.process_group()))
+ BOOST_CHECK(map[cincinnati].population == -1);
+
+ synchronize(map);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/named_vertices_seq.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/named_vertices_seq.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,91 @@
+// Copyright (C) 2007-2008 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/iteration_macros.hpp>
+#include <string>
+#include <iostream>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+
+/// City structure to be attached to each vertex
+struct City {
+ City() {}
+
+ City(const std::string& name, int population = -1)
+ : name(name), population(population) { }
+
+ std::string name;
+ int population;
+};
+
+namespace boost { namespace graph {
+
+/// Use the City name as a key for indexing cities in a graph
+template<>
+struct internal_vertex_name<City>
+{
+ typedef multi_index::member<City, std::string, &City::name> type;
+};
+
+/// Allow the graph to build cities given only their names (filling in
+/// the defaults for fields).
+template<>
+struct internal_vertex_constructor<City>
+{
+ typedef vertex_from_name<City> type;
+};
+
+} } // end namespace boost::graph
+
+/// Our road map, where each of the vertices are cities
+typedef adjacency_list<vecS, vecS, directedS, City> RoadMap;
+typedef graph_traits<RoadMap>::vertex_descriptor Vertex;
+
+int test_main(int argc, char* argv[])
+{
+ RoadMap map;
+
+ /// Create vertices for Bloomington, Indianapolis, Chicago
+ Vertex bloomington = add_vertex(City("Bloomington", 69291), map);
+ Vertex indianapolis = add_vertex(City("Indianapolis", 791926), map);
+ Vertex chicago = add_vertex(City("Chicago", 9500000), map);
+
+ BOOST_CHECK(add_vertex(City("Bloomington", 69291), map) == bloomington);
+
+ BGL_FORALL_VERTICES(city, map, RoadMap)
+ std::cout << map[city].name << ", population " << map[city].population
+ << std::endl;
+
+ BOOST_CHECK(*find_vertex("Bloomington", map) == bloomington);
+ BOOST_CHECK(*find_vertex("Indianapolis", map) == indianapolis);
+ BOOST_CHECK(*find_vertex("Chicago", map) == chicago);
+
+ add_edge(bloomington, "Indianapolis", map);
+ add_edge("Indianapolis", chicago, map);
+ add_edge("Indianapolis", "Cincinnati", map);
+
+ BGL_FORALL_EDGES(road, map, RoadMap)
+ std::cout << map[source(road, map)].name << " -> "
+ << map[target(road, map)].name << std::endl;
+
+ BOOST_CHECK(map[*find_vertex("Cincinnati", map)].population == -1);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/named_vertices_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/named_vertices_test.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,121 @@
+// Copyright (C) 2007 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/graph/distributed/adjacency_list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/iteration_macros.hpp>
+#include <boost/test/minimal.hpp>
+#include <string>
+#include <iostream>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using namespace boost;
+using boost::graph::distributed::mpi_process_group;
+
+/// City structure to be attached to each vertex
+struct City {
+ City() {}
+
+ City(const std::string& name, int population = -1)
+ : name(name), population(population) { }
+
+ template<typename Archiver>
+ void serialize(Archiver& ar, const unsigned int /*version*/)
+ {
+ ar & name & population;
+ }
+
+ std::string name;
+ int population;
+};
+
+namespace boost { namespace graph {
+
+/// Use the City name as a key for indexing cities in a graph
+template<>
+struct internal_vertex_name<City>
+{
+ typedef multi_index::member<City, std::string, &City::name> type;
+};
+
+/// Allow the graph to build cities given only their names (filling in
+/// the defaults for fields).
+template<>
+struct internal_vertex_constructor<City>
+{
+ typedef vertex_from_name<City> type;
+};
+
+} } // end namespace boost::graph
+
+/// Our road map, where each of the vertices are cities
+typedef boost::adjacency_list<vecS, distributedS<mpi_process_group, vecS>,
+ bidirectionalS, City> RoadMap;
+typedef graph_traits<RoadMap>::vertex_descriptor Vertex;
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+
+ RoadMap map;
+
+ int rank = process_id(mpi_process_group());
+ bool i_am_root = rank == 0;
+
+ /// Create vertices for Bloomington, Indianapolis, Chicago. Everyone will
+ /// try to do this, but only one of each vertex will be added.
+ Vertex bloomington = add_vertex(City("Bloomington", 69291), map);
+ Vertex chicago = add_vertex(City("Chicago", 9500000), map);
+ Vertex indianapolis = add_vertex(City("Indianapolis", 791926), map);
+
+ BGL_FORALL_VERTICES(city, map, RoadMap)
+ std::cout << rank << ": " << map[city].name << ", population "
+ << map[city].population << std::endl;
+
+ BOOST_CHECK(*find_vertex("Bloomington", map) == bloomington);
+ BOOST_CHECK(*find_vertex("Indianapolis", map) == indianapolis);
+ BOOST_CHECK(*find_vertex("Chicago", map) == chicago);
+
+ if (i_am_root) {
+ add_edge(bloomington, "Indianapolis", map);
+ add_edge("Indianapolis", chicago, map);
+ add_edge("Indianapolis", "Cincinnati", map);
+ }
+
+ synchronize(map);
+
+ {
+ property_map<RoadMap, std::string City::*>::type
+ city_name = get(&City::name, map);
+
+ BGL_FORALL_EDGES(road, map, RoadMap)
+ std::cout << rank << ": " << get(city_name, source(road, map)) << " -> "
+ << get(city_name, target(road, map)) << std::endl;
+
+ synchronize(map);
+ }
+
+ // Make sure the vertex for "Cincinnati" was created implicitly
+ Vertex cincinnati = *find_vertex("Cincinnati", map);
+ if (get(vertex_owner, map, cincinnati)
+ == process_id(map.process_group()))
+ BOOST_CHECK(map[cincinnati].population == -1);
+
+ synchronize(map);
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/process_group_serialization.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/process_group_serialization.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,54 @@
+// Copyright (C) 2006 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/serialization/list.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/test/minimal.hpp>
+
+#ifdef BOOST_NO_EXCEPTIONS
+void
+boost::throw_exception(std::exception const& ex)
+{
+ std::cout << ex.what() << std::endl;
+ abort();
+}
+#endif
+
+using boost::graph::distributed::mpi_process_group;
+
+int test_main(int argc, char** argv)
+{
+ boost::mpi::environment env(argc, argv);
+
+ mpi_process_group pg;
+
+ int seventeen = 17;
+ std::list<int> seventeens(17, 17);
+
+ if (process_id(pg) == 0) {
+ send(pg, 1, 0, seventeen);
+ send(pg, 1, 1, seventeens);
+ }
+ synchronize(pg);
+
+ if (process_id(pg) == 1) {
+ int value;
+ receive(pg, 0, 0, value);
+ BOOST_CHECK(seventeen == value);
+
+ std::list<int> values;
+ receive(pg, 0, 1, values);
+ BOOST_CHECK(seventeens == values);
+ }
+
+ return 0;
+}

Added: trunk/libs/graph_parallel/test/ssca.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph_parallel/test/ssca.cpp 2009-04-10 21:33:02 EDT (Fri, 10 Apr 2009)
@@ -0,0 +1,1262 @@
+// Copyright 2004 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Nick Edmonds
+// Andrew Lumsdaine
+
+#include <boost/graph/use_mpi.hpp>
+
+#define CSR
+
+#ifdef CSR
+# include <boost/graph/distributed/compressed_sparse_row_graph.hpp>
+#else
+# include <boost/graph/distributed/adjacency_list.hpp>
+#endif
+
+#include <boost/test/minimal.hpp>
+#include <boost/graph/distributed/mpi_process_group.hpp>
+#include <boost/graph/distributed/queue.hpp>
+
+#include <boost/graph/parallel/distribution.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/bind.hpp>
+#include <sys/time.h>
+#include <time.h>
+
+#include <boost/random.hpp>
+#include <boost/property_map/parallel/distributed_property_map.hpp>
+
+#include <boost/random/linear_congruential.hpp>
+
+#include <boost/graph/distributed/graphviz.hpp>
+#include <boost/graph/graph_traits.hpp>
+#include <boost/graph/iteration_macros.hpp>
+
+#include <boost/graph/parallel/algorithm.hpp>
+#include <boost/graph/breadth_first_search.hpp>
+#include <boost/pending/queue.hpp>
+
+#include <boost/graph/rmat_graph_generator.hpp>
+#include <boost/graph/distributed/betweenness_centrality.hpp>
+#include <boost/graph/distributed/filtered_graph.hpp>
+#include <boost/graph/parallel/container_traits.hpp>
+
+#include <boost/graph/properties.hpp>
+
+#include <algorithm>
+#include <vector>
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <sstream>
+#include <stdint.h>
+
+using namespace boost;
+
+// #define DEBUG
+
+typedef rand48 RandomGenerator;
+
+/****************************************************************************
+ * Timing
+ ****************************************************************************/
+#ifndef PBGL_ACCOUNTING
+
+typedef double time_type;
+
+inline time_type get_time()
+{
+ timeval tp;
+ gettimeofday(&tp, 0);
+ return tp.tv_sec + tp.tv_usec / 1000000.0;
+}
+
+std::string print_time(time_type t)
+{
+ std::ostringstream out;
+ out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
+ return out.str();
+}
+
+#endif // PBGL_ACCOUNTING
+
+/****************************************************************************
+ * Edge weight generator iterator *
+ ****************************************************************************/
+template<typename F, typename RandomGenerator>
+class generator_iterator
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename F::result_type value_type;
+ typedef const value_type& reference;
+ typedef const value_type* pointer;
+ typedef void difference_type;
+
+ explicit
+ generator_iterator(RandomGenerator& gen, const F& f = F())
+ : f(f), gen(&gen)
+ {
+ value = this->f(gen);
+ }
+
+ reference operator*() const { return value; }
+ pointer operator->() const { return &value; }
+
+ generator_iterator& operator++()
+ {
+ value = f(*gen);
+ return *this;
+ }
+
+ generator_iterator operator++(int)
+ {
+ generator_iterator temp(*this);
+ ++(*this);
+ return temp;
+ }
+
+ bool operator==(const generator_iterator& other) const
+ { return f == other.f; }
+
+ bool operator!=(const generator_iterator& other) const
+ { return !(*this == other); }
+
+private:
+ F f;
+ RandomGenerator* gen;
+ value_type value;
+};
+
+template<typename F, typename RandomGenerator>
+inline generator_iterator<F, RandomGenerator>
+make_generator_iterator( RandomGenerator& gen, const F& f)
+{ return generator_iterator<F, RandomGenerator>(gen, f); }
+
+template<typename Graph, typename DistanceMap, typename WeightMap, typename ColorMap>
+struct ssca_visitor : bfs_visitor<>
+{
+ typedef typename property_traits<WeightMap>::value_type Weight;
+ typedef typename property_traits<ColorMap>::value_type ColorValue;
+ typedef color_traits<ColorValue> Color;
+
+ ssca_visitor(DistanceMap& distance, const WeightMap& weight, ColorMap& color,
+ Weight max_)
+ : distance(distance), weight(weight), color(color), max_(max_) {}
+
+ template<typename Edge>
+ void tree_edge(Edge e, const Graph& g)
+ {
+ int new_distance = get(weight, e) == (std::numeric_limits<Weight>::max)() ?
+ (std::numeric_limits<Weight>::max)() : get(distance, source(e, g)) + get(weight, e);
+
+ put(distance, target(e, g), new_distance);
+ if (new_distance > max_)
+ put(color, target(e, g), Color::black());
+ }
+
+ private:
+ DistanceMap& distance;
+ const WeightMap& weight;
+ ColorMap& color;
+ Weight max_;
+};
+
+// Generate source vertices for approximate BC
+template <typename Graph, typename Buffer>
+void
+generate_sources(const Graph& g, Buffer sources,
+ typename graph_traits<Graph>::vertices_size_type num_sources)
+{
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
+ typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
+
+ typedef typename boost::graph::parallel::process_group_type<Graph>::type
+ process_group_type;
+ process_group_type pg = g.process_group();
+
+ typename process_group_type::process_id_type id = process_id(pg);
+ typename process_group_type::process_size_type p = num_processes(pg);
+
+ // Don't feel like adding a special case for num_sources < p
+ assert(num_sources >= p);
+
+ minstd_rand gen;
+ uniform_int<vertices_size_type> rand_vertex(0, num_vertices(g) - 1);
+ std::vector<vertex_descriptor> all_sources, local_sources;
+ vertices_size_type local_vertices = vertices_size_type(floor((double)num_sources / p));
+ local_vertices += (id < (num_sources - (p * local_vertices)) ? 1 : 0);
+
+ while (local_vertices > 0) {
+ vertex_iterator iter = vertices(g).first;
+ std::advance(iter, rand_vertex(gen));
+
+ if (out_degree(*iter, g) != 0
+ && std::find(local_sources.begin(), local_sources.end(), *iter) == local_sources.end()) {
+ local_sources.push_back(*iter);
+ --local_vertices;
+ }
+ }
+ all_gather(pg, local_sources.begin(), local_sources.end(), all_sources);
+ std::sort(all_sources.begin(), all_sources.end());
+ for (typename std::vector<vertex_descriptor>::iterator iter = all_sources.begin();
+ iter != all_sources.end(); ++iter)
+ sources.push(*iter);
+}
+
+// Kernel 2 - Classify large sets
+template <typename Graph, typename WeightMap>
+void classify_sets(const Graph& g, const WeightMap& weight_map,
+ std::vector<std::pair<typename graph_traits<Graph>::vertex_descriptor,
+ typename graph_traits<Graph>::vertex_descriptor> > & global_S)
+{
+ typedef typename boost::graph::parallel::process_group_type<Graph>::type
+ process_group_type;
+ process_group_type pg = g.process_group();
+
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ std::vector<std::pair<vertex_descriptor, vertex_descriptor> > S;
+
+ time_type start = get_time();
+
+#ifdef CSR
+ typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
+ typedef typename property_map<Graph, vertex_local_t>::const_type LocalMap;
+ OwnerMap owner = get(vertex_owner, g);
+ LocalMap local = get(vertex_local, g);
+#endif
+
+ int max_ = 0;
+ BGL_FORALL_EDGES_T(e, g, Graph) {
+#ifdef CSR
+ if (get(owner, source(e, g)) == process_id(pg)) {
+#endif
+ int w = get(weight_map, e);
+ if (w > max_) {
+ max_ = w;
+ S.clear();
+ }
+
+ if (w >= max_)
+ S.push_back(std::make_pair(source(e, g), target(e, g)));
+#ifdef CSR
+ }
+#endif
+ }
+
+ int global_max = all_reduce(pg, max_, boost::parallel::maximum<int>());
+ if (max_ < global_max)
+ S.clear();
+
+ global_S.clear();
+
+ all_gather(pg, S.begin(), S.end(), global_S);
+
+ // This is probably unnecessary as long as the sets of edges owned by procs is disjoint
+ std::sort(global_S.begin(), global_S.end());
+ std::unique(global_S.begin(), global_S.end());
+
+ synchronize(pg);
+
+ time_type end = get_time();
+
+ if (process_id(pg) == 0) {
+ std::cerr << " Distributed Graph: " << print_time(end - start) << std::endl
+ << " Max int weight = " << global_max << std::endl;
+ }
+}
+
+template <typename ProcessGroup, typename Graph, typename WeightMap,
+ typename EdgeVector>
+void seq_classify_sets(const ProcessGroup& pg, const Graph& g,
+ const WeightMap& weight_map, EdgeVector& S)
+{
+ typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
+ typedef typename property_traits<WeightMap>::value_type edge_weight_type;
+
+ time_type start = get_time();
+
+ edge_weight_type max_ = 0;
+ BGL_FORALL_EDGES_T(e, g, Graph) {
+ edge_weight_type w = get(weight_map, e);
+ if (w > max_) {
+ max_ = w;
+ S.clear();
+ }
+
+ if (w >= max_)
+ S.push_back(e);
+ }
+
+ synchronize(pg);
+
+ time_type end = get_time();
+
+ if (process_id(pg) == 0)
+ std::cerr << " Non-Distributed Graph: " << print_time(end - start) << std::endl
+ << " Max int weight = " << max_ << std::endl;
+}
+
+// Kernel 3 - Graph Extraction
+template <typename Graph, typename OwnerMap, typename LocalMap,
+ typename WeightMap, typename DistanceMap, typename ColorMap,
+ typename EdgeVector>
+void subgraph_extraction(Graph& g, const OwnerMap& owner, const LocalMap& local,
+ const WeightMap& weight_map, DistanceMap distances,
+ ColorMap color_map, const EdgeVector& S,
+ int subGraphEdgeLength)
+{
+ // Nick: I think turning the vertex black when the maximum distance is
+ // exceeded will prevent BFS from exploring beyond the subgraph.
+ // Unfortunately we can't run subgraph extraction in parallel
+ // because the subgraphs may overlap
+
+ typedef typename property_traits<ColorMap>::value_type ColorValue;
+ typedef color_traits<ColorValue> Color;
+
+ typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+
+ typedef typename boost::graph::parallel::process_group_type<Graph>::type
+ process_group_type;
+
+ typedef boost::graph::distributed::distributed_queue<process_group_type,
+ OwnerMap, queue<vertex_descriptor> > queue_t;
+
+ process_group_type pg = g.process_group();
+ typename process_group_type::process_id_type id = process_id(pg);
+
+ queue_t Q(pg, owner);
+
+ EdgeVector sources(S.begin(), S.end());
+
+#ifdef DEBUG
+ std::vector<std::vector<vertex_descriptor> > subgraphs;
+#endif
+
+ synchronize(pg);
+
+ typedef typename std::vector<std::pair<vertex_descriptor, vertex_descriptor> >::iterator
+ source_iterator;
+
+ time_type start = get_time();
+ for (source_iterator iter = sources.begin(); iter != sources.end(); ++iter) {
+ // Reinitialize distance and color maps every BFS
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ if (get(owner, v) == id) {
+ local_put(color_map, v, Color::white());
+ local_put(distances, v, (std::numeric_limits<int>::max)());
+ }
+ }
+
+ vertex_descriptor u = iter->first, v = iter->second;
+
+ local_put(distances, u, 0);
+ local_put(distances, v, 0);
+
+ while (!Q.empty()) Q.pop();
+ if (get(owner, u) == id)
+ Q.push(u);
+
+ local_put(color_map, u, Color::gray());
+
+ breadth_first_search(g, v, Q,
+ ssca_visitor<Graph, DistanceMap, WeightMap, ColorMap>
+ (distances, weight_map, color_map, subGraphEdgeLength),
+ color_map);
+
+ // At this point all vertices with distance > 0 in addition to the
+ // starting vertices compose the subgraph.
+#ifdef DEBUG
+ subgraphs.push_back(std::vector<vertex_descriptor>());
+ std::vector<vertex_descriptor>& subgraph = subgraphs.back();
+
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ if (get(distances, v) < (std::numeric_limits<int>::max)())
+ subgraph.push_back(v);
+ }
+#endif
+ }
+
+ synchronize(pg);
+
+ time_type end = get_time();
+
+#ifdef DEBUG
+ for (unsigned int i = 0; i < subgraphs.size(); i++) {
+ all_gather(pg, subgraphs[i].begin(), subgraphs[i].end(), subgraphs[i]);
+ std::sort(subgraphs[i].begin(), subgraphs[i].end());
+ subgraphs[i].erase(std::unique(subgraphs[i].begin(), subgraphs[i].end()),
+ subgraphs[i].end());
+ }
+
+ if (process_id(pg) == 0)
+ for (int i = 0; abs(i) < subgraphs.size(); i++) {
+ std::cerr << "Subgraph " << i << " :\n";
+ for (int j = 0; abs(j) < subgraphs[i].size(); j++)
+ std::cerr << " " << get(local, subgraphs[i][j]) << "@"
+ << get(owner, subgraphs[i][j]) << std::endl;
+ }
+#endif
+
+ if (process_id(pg) == 0)
+ std::cerr << " Distributed Graph: " << print_time(end - start) << std::endl;
+}
+
+template <typename ProcessGroup, typename Graph, typename WeightMap,
+ typename DistanceMap, typename ColorMap, typename EdgeVector>
+void seq_subgraph_extraction(const ProcessGroup& pg, const Graph& g,
+ const WeightMap& weight_map, DistanceMap distances,
+ ColorMap color_map, const EdgeVector& S,
+ int subGraphEdgeLength)
+{
+ // Nick: I think turning the vertex black when the maximum distance is
+ // exceeded will prevent BFS from exploring beyond the subgraph.
+
+ using boost::graph::distributed::mpi_process_group;
+
+ typedef typename property_traits<ColorMap>::value_type ColorValue;
+ typedef color_traits<ColorValue> Color;
+
+ typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+
+ boost::queue<vertex_descriptor> Q;
+
+ std::vector<edge_descriptor> sources(S.begin(), S.end());
+
+#ifdef DEBUG
+ std::vector<std::vector<vertex_descriptor> > subgraphs;
+#endif
+
+ synchronize(pg);
+
+ typedef ProcessGroup process_group_type;
+
+ typename process_group_type::process_id_type id = process_id(pg);
+ typename process_group_type::process_size_type p = num_processes(pg);
+
+ time_type start = get_time();
+
+ for (int i = id; i < sources.size(); i += p) {
+
+ // Reinitialize distance and color maps every BFS
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ put(color_map, v, Color::white());
+ put(distances, v, (std::numeric_limits<int>::max)());
+ }
+
+ vertex_descriptor u = source(sources[i], g),
+ v = target(sources[i], g);
+
+ put(distances, u, 0);
+ put(distances, v, 0);
+
+ while (!Q.empty()) Q.pop();
+ Q.push(u);
+
+ put(color_map, u, Color::gray());
+
+ breadth_first_search(g, v, Q,
+ ssca_visitor<Graph, DistanceMap, WeightMap, ColorMap>
+ (distances, weight_map, color_map, subGraphEdgeLength),
+ color_map);
+
+#ifdef DEBUG
+ subgraphs.push_back(std::vector<vertex_descriptor>());
+ std::vector<vertex_descriptor>& subgraph = subgraphs.back();
+
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ if (get(distances, v) < (std::numeric_limits<int>::max)())
+ subgraph.push_back(v);
+ }
+#endif
+ }
+
+ synchronize(pg);
+
+ time_type end = get_time();
+
+#ifdef DEBUG
+ std::vector<vertex_descriptor> ser_subgraphs;
+
+ for (int i = 0; i < subgraphs.size(); ++i) {
+ for (int j = 0; j < subgraphs[i].size(); ++j)
+ ser_subgraphs.push_back(subgraphs[i][j]);
+ ser_subgraphs.push_back(graph_traits<Graph>::null_vertex());
+ }
+
+ all_gather(pg, ser_subgraphs.begin(), ser_subgraphs.end(), ser_subgraphs);
+
+ int i = 0;
+ typename std::vector<vertex_descriptor>::iterator iter(ser_subgraphs.begin());
+
+ while (iter != ser_subgraphs.end()) {
+ std::cerr << "Subgraph " << i << " :\n";
+ while (*iter != graph_traits<Graph>::null_vertex()) {
+ std::cerr << " " << *iter << std::endl;
+ ++iter;
+ }
+ ++i;
+ ++iter;
+ }
+#endif
+
+ if (process_id(pg) == 0)
+ std::cerr << " Non-Distributed Graph: " << print_time(end - start) << std::endl;
+}
+
+template <typename ProcessGroup, typename Graph, typename CentralityMap>
+void
+extract_max_bc_vertices(const ProcessGroup& pg, const Graph& g, const CentralityMap& centrality,
+ std::vector<typename graph_traits<Graph>::vertex_descriptor>& max_bc_vec)
+{
+ using boost::graph::parallel::process_group;
+ using boost::parallel::all_gather;
+ using boost::parallel::all_reduce;
+
+ // Find set of vertices with highest BC score
+ typedef typename property_traits<CentralityMap>::value_type centrality_type;
+ std::vector<centrality_type> max_bc_vertices;
+ centrality_type max_ = 0;
+
+ max_bc_vec.clear();
+
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ if (get(centrality, v) == max_)
+ max_bc_vec.push_back(v);
+ else if (get(centrality, v) > max_) {
+ max_ = get(centrality, v);
+ max_bc_vec.clear();
+ max_bc_vec.push_back(v);
+ }
+ }
+
+ centrality_type global_max = all_reduce(pg, max_, boost::parallel::minimum<int>());
+
+ if (global_max > max_)
+ max_bc_vec.clear();
+
+ all_gather(pg, max_bc_vec.begin(), max_bc_vec.end(), max_bc_vec);
+}
+
+
+// Function object to filter edges divisible by 8
+// EdgeWeightMap::value_type must be integral!
+template <typename EdgeWeightMap>
+struct edge_weight_not_divisible_by_eight {
+ typedef typename property_traits<EdgeWeightMap>::value_type weight_type;
+
+ edge_weight_not_divisible_by_eight() { }
+ edge_weight_not_divisible_by_eight(EdgeWeightMap weight) : m_weight(weight) { }
+ template <typename Edge>
+ bool operator()(const Edge& e) const {
+ return (get(m_weight, e) & ((std::numeric_limits<weight_type>::max)() - 7)) != get(m_weight, e);
+ }
+
+ EdgeWeightMap m_weight;
+};
+
+//
+// Vertex and Edge properties
+//
+#ifdef CSR
+typedef int weight_type;
+
+struct WeightedEdge {
+ WeightedEdge(weight_type weight = 0) : weight(weight) { }
+
+ weight_type weight;
+};
+
+struct VertexProperties {
+ VertexProperties(int distance = 0, default_color_type color = white_color)
+ : distance(distance), color(color) { }
+
+ int distance;
+ default_color_type color;
+};
+#endif
+
+template <typename RandomGenerator, typename ProcessGroup, typename vertices_size_type,
+ typename edges_size_type>
+void
+run_non_distributed_graph_tests(RandomGenerator& gen, const ProcessGroup& pg,
+ vertices_size_type n, edges_size_type m,
+ std::size_t maxEdgeWeight, uint64_t seed,
+ int K4Alpha, double a, double b, double c, double d,
+ int subGraphEdgeLength, bool show_degree_dist,
+ bool full_bc, bool verify)
+{
+#ifdef CSR
+ typedef compressed_sparse_row_graph<directedS, VertexProperties, WeightedEdge>
+ seqGraph;
+#else
+ typedef adjacency_list<vecS, vecS, directedS,
+ // Vertex properties
+ property<vertex_distance_t, int,
+ property<vertex_color_t, default_color_type> >,
+ // Edge properties
+ property<edge_weight_t, int> > seqGraph;
+#endif
+
+ // Generate sequential graph for non_distributed betweenness centrality
+ // Reseed the PRNG to get the same graph
+ gen.seed(seed);
+
+ synchronize(pg);
+
+ time_type start = get_time();
+
+#ifdef CSR
+ seqGraph sg(sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(gen, n, m, a, b, c, d),
+ sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
+ n);
+#else
+ seqGraph sg(unique_rmat_iterator<RandomGenerator, seqGraph>(gen, n, m, a, b, c, d),
+ unique_rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
+ n);
+#endif
+
+ // Not strictly necessary to synchronize here, but it make sure that the
+ // time we measure is the time needed for all copies of the graph to be
+ // constructed
+ synchronize(pg);
+
+ time_type end = get_time();
+
+ if (process_id(pg) == 0)
+ std::cerr<< "Kernel 1:\n"
+ << " Non-Distributed Graph: " << print_time(end - start) << std::endl;
+
+ std::map<int, int> degree_dist;
+ if ( show_degree_dist ) {
+ BGL_FORALL_VERTICES_T(v, sg, seqGraph) {
+ degree_dist[out_degree(v, sg)]++;
+ }
+
+ std::cerr << "Degree - Fraction of vertices of that degree\n";
+ for (std::map<int, int>::iterator iter = degree_dist.begin();
+ iter != degree_dist.end(); ++iter)
+ std::cerr << " " << iter->first << " - " << double(iter->second) / num_vertices(sg) << std::endl << std::endl;
+ }
+
+ //
+ // Kernel 2 - Classify large sets
+ //
+ std::vector<graph_traits<seqGraph>::edge_descriptor> seqS;
+
+ if (process_id(pg) == 0)
+ std::cerr << "Kernel 2:\n";
+
+ seq_classify_sets(pg, sg,
+#ifdef CSR
+ get(&WeightedEdge::weight, sg),
+#else
+ get(edge_weight, sg),
+#endif
+ seqS);
+
+ //
+ // Kernel 3 - Graph Extraction
+ //
+#ifdef CSR
+ typedef weight_type weight_t;
+ weight_t unit_weight(1);
+#else
+ int unit_weight(1);;
+#endif
+
+ if (process_id(pg) == 0)
+ std::cerr << "Kernel 3:\n";
+
+ seq_subgraph_extraction(pg, sg,
+#ifdef CSR
+// get(&WeightedEdge::weight, sg),
+ ref_property_map<graph_traits<seqGraph>::edge_descriptor, weight_t>(unit_weight),
+ get(&VertexProperties::distance, sg),
+ get(&VertexProperties::color, sg),
+#else
+// get(edge_weight, sg),
+ ref_property_map<graph_traits<seqGraph>::edge_descriptor, int>(unit_weight),
+ get(vertex_distance, sg),
+ get(vertex_color, sg),
+#endif
+ seqS, subGraphEdgeLength);
+
+#ifdef CSR
+ typedef property_map<seqGraph, weight_type WeightedEdge::*>::type seqEdgeWeightMap;
+ edge_weight_not_divisible_by_eight<seqEdgeWeightMap> sg_filter(get(&WeightedEdge::weight, sg));
+#else
+ typedef property_map<seqGraph, edge_weight_t>::type seqEdgeWeightMap;
+ edge_weight_not_divisible_by_eight<seqEdgeWeightMap> sg_filter(get(edge_weight, sg));
+#endif
+
+ typedef filtered_graph<const seqGraph, edge_weight_not_divisible_by_eight<seqEdgeWeightMap> >
+ filteredSeqGraph;
+
+ filteredSeqGraph fsg(sg, sg_filter);
+
+ std::vector<graph_traits<seqGraph>::vertex_descriptor> max_seq_bc_vec;
+
+ // Non-Distributed Centrality Map
+ typedef property_map<seqGraph, vertex_index_t>::const_type seqIndexMap;
+ typedef iterator_property_map<std::vector<int>::iterator, seqIndexMap> seqCentralityMap;
+
+ std::vector<int> non_distributed_centralityS(num_vertices(sg), 0);
+ seqCentralityMap non_distributed_centrality(non_distributed_centralityS.begin(),
+ get(vertex_index, sg));
+
+ vertices_size_type n0 = 0;
+ BGL_FORALL_VERTICES_T(v, fsg, filteredSeqGraph) {
+ if (out_degree(v, fsg) == 0) ++n0;
+ }
+
+ if (process_id(pg) == 0)
+ std::cerr << "Kernel 4:\n";
+
+ // Run Betweenness Centrality
+ if (full_bc) {
+
+ // Non-Distributed Graph BC
+ start = get_time();
+ non_distributed_brandes_betweenness_centrality(pg, fsg, non_distributed_centrality);
+ extract_max_bc_vertices(pg, fsg, non_distributed_centrality, max_seq_bc_vec);
+ end = get_time();
+
+ edges_size_type nonDistributedExactTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
+
+ if (process_id(pg) == 0)
+ std::cerr << " non-Distributed Graph Exact = " << print_time(end - start) << " ("
+ << nonDistributedExactTEPs << " TEPs)\n";
+ }
+
+ // Non-Distributed Graph Approximate BC
+ std::vector<int> nonDistributedApproxCentralityS(num_vertices(sg), 0);
+ seqCentralityMap nonDistributedApproxCentrality(nonDistributedApproxCentralityS.begin(),
+ get(vertex_index, sg));
+
+ queue<typename graph_traits<filteredSeqGraph>::vertex_descriptor> sources;
+ {
+ minstd_rand gen;
+ uniform_int<vertices_size_type> rand_vertex(0, num_vertices(fsg) - 1);
+ int remaining_sources = floor(pow(2, K4Alpha));
+ std::vector<typename graph_traits<filteredSeqGraph>::vertex_descriptor> temp_sources;
+
+ while (remaining_sources > 0) {
+ typename graph_traits<filteredSeqGraph>::vertex_descriptor v =
+ vertex(rand_vertex(gen), fsg);
+
+ if (out_degree(v, fsg) != 0
+ && std::find(temp_sources.begin(), temp_sources.end(), v) == temp_sources.end()) {
+ temp_sources.push_back(v);
+ --remaining_sources;
+ }
+ }
+
+ for (int i = 0; i < temp_sources.size(); ++i)
+ sources.push(temp_sources[i]);
+ }
+
+ start = get_time();
+ non_distributed_brandes_betweenness_centrality(pg, fsg, buffer(sources).
+ centrality_map(nonDistributedApproxCentrality));
+ extract_max_bc_vertices(pg, fsg, nonDistributedApproxCentrality, max_seq_bc_vec);
+ end = get_time();
+
+ edges_size_type nonDistributedApproxTEPs = edges_size_type(floor(7 * n * pow(2, K4Alpha) / (end - start)));
+
+ if (process_id(pg) == 0)
+ std::cerr << " Non-Distributed Graph Approximate (" << floor(pow(2, K4Alpha)) << " sources) = "
+ << print_time(end - start) << " (" << nonDistributedApproxTEPs << " TEPs)\n";
+
+ // Verify Correctness of Kernel 4
+ if (full_bc && verify && process_id(pg) == 0) {
+
+ std::vector<int> seq_centralityS(num_vertices(fsg), 0);
+ seqCentralityMap seq_centrality(seq_centralityS.begin(), get(vertex_index, fsg));
+
+ max_seq_bc_vec.clear();
+ property_traits<seqCentralityMap>::value_type max_ = 0;
+
+ start = get_time();
+ brandes_betweenness_centrality(fsg, seq_centrality);
+
+ typedef filtered_graph<const seqGraph, edge_weight_not_divisible_by_eight<seqEdgeWeightMap> >
+ filteredSeqGraph;
+
+ BGL_FORALL_VERTICES_T(v, fsg, filteredSeqGraph ) {
+ if (get(seq_centrality, v) == max_)
+ max_seq_bc_vec.push_back(v);
+ else if (get(seq_centrality, v) > max_) {
+ max_ = get(seq_centrality, v);
+ max_seq_bc_vec.clear();
+ max_seq_bc_vec.push_back(v);
+ }
+ }
+
+ end = get_time();
+
+ edges_size_type sequentialTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
+
+ std::cerr << " Sequential = " << print_time(end - start) << " (" << sequentialTEPs << " TEPs)\n";
+
+ typename ProcessGroup::process_id_type id = process_id(pg);
+ typename ProcessGroup::process_size_type p = num_processes(pg);
+
+ assert((double)n/p == floor((double)n/p));
+
+ std::cerr << "\nVerifying non-scalable betweenness centrality...\n";
+
+ {
+ bool passed = true;
+
+ // Verify non-scalable betweenness centrality
+ BGL_FORALL_VERTICES_T(v, sg, seqGraph) {
+ if (get(non_distributed_centrality, v) != get(seq_centrality, v)) {
+ std::cerr << " " << id << ": Error - centrality of " << v
+ << " does not match the sequential result ("
+ << get(non_distributed_centrality, v) << " vs. "
+ << get(seq_centrality, v) << ")\n";
+ passed = false;
+ }
+ }
+
+ if (passed)
+ std::cerr << " PASSED\n";
+ }
+
+ }
+
+}
+
+template <typename RandomGenerator, typename ProcessGroup, typename vertices_size_type,
+ typename edges_size_type>
+void
+run_distributed_graph_tests(RandomGenerator& gen, const ProcessGroup& pg,
+ vertices_size_type n, edges_size_type m,
+ std::size_t maxEdgeWeight, uint64_t seed,
+ int K4Alpha, double a, double b, double c, double d,
+ int subGraphEdgeLength, bool show_degree_dist,
+ bool emit_dot_file, bool full_bc, bool verify)
+{
+#ifdef CSR
+ typedef compressed_sparse_row_graph<directedS, VertexProperties, WeightedEdge, no_property,
+ distributedS<ProcessGroup> > Graph;
+#else
+ typedef adjacency_list<vecS,
+ distributedS<ProcessGroup, vecS>,
+ directedS,
+ // Vertex properties
+ property<vertex_distance_t, int,
+ property<vertex_color_t, default_color_type> >,
+ // Edge properties
+ property<edge_weight_t, int> > Graph;
+#endif
+
+ gen.seed(seed);
+
+ parallel::variant_distribution<ProcessGroup> distrib
+ = parallel::block(pg, n);
+
+ typedef typename ProcessGroup::process_id_type process_id_type;
+ process_id_type id = process_id(pg);
+
+ typedef typename property_map<Graph, vertex_owner_t>::const_type OwnerMap;
+ typedef typename property_map<Graph, vertex_local_t>::const_type LocalMap;
+
+ typedef keep_local_edges<parallel::variant_distribution<ProcessGroup>,
+ process_id_type>
+ EdgeFilter;
+
+ //
+ // Kernel 1 - Graph construction
+ // Nick: The benchmark specifies that we only have to time graph generation from
+ // edge tuples, the generator generates the edge tuples at graph construction
+ // time so we're timing some overhead in the random number generator, etc.
+ synchronize(pg);
+
+ time_type start = get_time();
+
+#ifdef CSR
+// typedef sorted_unique_rmat_iterator<RandomGenerator, Graph, EdgeFilter> RMATIter;
+ typedef sorted_rmat_iterator<RandomGenerator, Graph, keep_all_edges> RMATIter;
+
+ Graph g(//RMATIter(gen, n, m, a, b, c, d, false, true, EdgeFilter(distrib, id)),
+ RMATIter(gen, n, m, a, b, c, d, true, keep_all_edges()),
+ RMATIter(),
+ make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
+ n, pg, distrib);
+#else
+ typedef unique_rmat_iterator<RandomGenerator, Graph, EdgeFilter> RMATIter;
+ Graph g(RMATIter(gen, n, m, a, b, c, d, true EdgeFilter(distrib, id)),
+ RMATIter(),
+ make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
+ n, pg, distrib);
+#endif
+
+ synchronize(pg);
+
+ time_type end = get_time();
+
+ if (id == 0)
+ std::cerr<< "Kernel 1:\n"
+ << " Distributed Graph: " << print_time(end - start) << std::endl;
+
+ if ( emit_dot_file )
+ write_graphviz("ssca.dot", g);
+
+ //
+ // Kernel 2 - Classify large sets
+ //
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
+ std::vector<std::pair<vertex_descriptor, vertex_descriptor> > S;
+
+ if (id == 0)
+ std::cerr << "Kernel 2:\n";
+
+ classify_sets(g,
+#ifdef CSR
+ get(&WeightedEdge::weight, g),
+#else
+ get(edge_weight, g),
+#endif
+ S);
+
+ //
+ // Kernel 3 - Graph Extraction
+ //
+ OwnerMap owner = get(vertex_owner, g);
+ LocalMap local = get(vertex_local, g);
+
+ if (id == 0)
+ std::cerr << "Kernel 3:\n";
+
+#ifdef CSR
+ typedef weight_type weight_t;
+ weight_t unit_weight(1);
+#else
+ int unit_weight(1);;
+#endif
+
+ subgraph_extraction(g, owner, local,
+#ifdef CSR
+// get(&WeightedEdge::weight, g),
+ ref_property_map<typename graph_traits<Graph>::edge_descriptor, weight_t>(unit_weight),
+ get(&VertexProperties::distance, g),
+ get(&VertexProperties::color, g),
+#else
+// get(edge_weight, g),
+ ref_property_map<graph_traits<Graph>::edge_descriptor, int>(unit_weight),
+ get(vertex_distance, g),
+ get(vertex_color, g),
+#endif
+ S, subGraphEdgeLength);
+
+ //
+ // Kernel 4 - Betweenness Centrality
+ //
+
+ // Filter edges with weights divisible by 8
+#ifdef CSR
+ typedef typename property_map<Graph, weight_type WeightedEdge::*>::type EdgeWeightMap;
+ edge_weight_not_divisible_by_eight<EdgeWeightMap> filter(get(&WeightedEdge::weight, g));
+#else
+ typedef typename property_map<Graph, edge_weight_t>::type EdgeWeightMap;
+ edge_weight_not_divisible_by_eight<EdgeWeightMap> filter(get(edge_weight, g));
+#endif
+
+ typedef filtered_graph<const Graph, edge_weight_not_divisible_by_eight<EdgeWeightMap> >
+ filteredGraph;
+ filteredGraph fg(g, filter);
+
+ // Vectors of max BC scores for all tests
+ std::vector<typename graph_traits<Graph>::vertex_descriptor> max_bc_vec;
+
+ // Distributed Centrality Map
+ typedef typename property_map<Graph, vertex_index_t>::const_type IndexMap;
+ typedef iterator_property_map<std::vector<int>::iterator, IndexMap> CentralityMap;
+
+ std::vector<int> centralityS(num_vertices(g), 0);
+ CentralityMap centrality(centralityS.begin(), get(vertex_index, g));
+
+ // Calculate number of vertices of degree 0
+ vertices_size_type local_n0 = 0, n0;
+ BGL_FORALL_VERTICES_T(v, fg, filteredGraph) {
+ if (out_degree(v, g) == 0) local_n0++;
+ }
+ n0 = boost::parallel::all_reduce(pg, local_n0, std::plus<vertices_size_type>());
+
+ if (id == 0)
+ std::cerr << "Kernel 4:\n";
+
+ // Run Betweenness Centrality
+ if (full_bc) {
+
+ // Distributed Graph Full BC
+ start = get_time();
+ brandes_betweenness_centrality(fg, centrality);
+ extract_max_bc_vertices(pg, g, centrality, max_bc_vec);
+ end = get_time();
+
+ edges_size_type exactTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
+
+ if (id == 0)
+ std::cerr << " Exact = " << print_time(end - start) << " ("
+ << exactTEPs << " TEPs)\n";
+ }
+
+ // Distributed Graph Approximate BC
+ std::vector<int> approxCentralityS(num_vertices(g), 0);
+ CentralityMap approxCentrality(approxCentralityS.begin(), get(vertex_index, g));
+
+ queue<vertex_descriptor> sources;
+ generate_sources(g, sources, vertices_size_type(floor(pow(2, K4Alpha))));
+
+ start = get_time();
+ brandes_betweenness_centrality(fg, buffer(sources).centrality_map(approxCentrality));
+ extract_max_bc_vertices(pg, fg, approxCentrality, max_bc_vec);
+ end = get_time();
+
+ edges_size_type approxTEPs = edges_size_type(floor(7 * n * pow(2, K4Alpha) / (end - start)));
+
+ if (id == 0)
+ std::cerr << " Approximate (" << floor(pow(2, K4Alpha)) << " sources) = "
+ << print_time(end - start) << " (" << approxTEPs << " TEPs)\n";
+
+
+ // Verify Correctness of Kernel 4
+ if (full_bc && verify && id == 0) {
+
+ // Build non-distributed graph to verify against
+ typedef adjacency_list<vecS, vecS, directedS,
+ // Vertex properties
+ property<vertex_distance_t, int,
+ property<vertex_color_t, default_color_type> >,
+ // Edge properties
+ property<edge_weight_t, int> > seqGraph;
+
+ gen.seed(seed);
+
+#ifdef CSR
+ seqGraph sg(sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(gen, n, m, a, b, c, d),
+ sorted_unique_rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
+ n);
+#else
+ seqGraph sg(unique_rmat_iterator<RandomGenerator, seqGraph>(gen, n, m, a, b, c, d),
+ unique_rmat_iterator<RandomGenerator, seqGraph>(),
+ make_generator_iterator(gen, uniform_int<int>(0, maxEdgeWeight)),
+ n);
+#endif
+
+ typedef property_map<seqGraph, edge_weight_t>::type seqEdgeWeightMap;
+ edge_weight_not_divisible_by_eight<seqEdgeWeightMap> sg_filter(get(edge_weight, sg));
+
+ filtered_graph<const seqGraph, edge_weight_not_divisible_by_eight<seqEdgeWeightMap> >
+ fsg(sg, sg_filter);
+
+ // Build sequential centrality map
+ typedef property_map<seqGraph, vertex_index_t>::const_type seqIndexMap;
+ typedef iterator_property_map<std::vector<int>::iterator, seqIndexMap> seqCentralityMap;
+
+ std::vector<int> seq_centralityS(num_vertices(sg), 0);
+ seqCentralityMap seq_centrality(seq_centralityS.begin(), get(vertex_index, sg));
+
+ std::vector<graph_traits<seqGraph>::vertex_descriptor> max_seq_bc_vec;
+
+ max_seq_bc_vec.clear();
+ property_traits<seqCentralityMap>::value_type max_ = 0;
+
+ start = get_time();
+ brandes_betweenness_centrality(fsg, seq_centrality);
+
+ typedef filtered_graph<const seqGraph, edge_weight_not_divisible_by_eight<seqEdgeWeightMap> >
+ filteredSeqGraph;
+
+ BGL_FORALL_VERTICES_T(v, fsg, filteredSeqGraph ) {
+ if (get(seq_centrality, v) == max_)
+ max_seq_bc_vec.push_back(v);
+ else if (get(seq_centrality, v) > max_) {
+ max_ = get(seq_centrality, v);
+ max_seq_bc_vec.clear();
+ max_seq_bc_vec.push_back(v);
+ }
+ }
+
+ end = get_time();
+
+ edges_size_type sequentialTEPs = edges_size_type(floor(7 * n* (n - n0) / (end - start)));
+
+ std::cerr << " Sequential = " << print_time(end - start) << " (" << sequentialTEPs << " TEPs)\n";
+
+ typename ProcessGroup::process_size_type p = num_processes(pg);
+
+ assert((double)n/p == floor((double)n/p));
+
+ std::cerr << "\nVerifying betweenness centrality...\n";
+
+ {
+ bool passed = true;
+
+ // Verify exact betweenness centrality
+ BGL_FORALL_VERTICES_T(v, g, Graph) {
+ if (get(centrality, v) != seq_centralityS[(n/p) * get(owner, v) + get(local, v)]) {
+ std::cerr << " " << id << ": Error - centrality of " << get(local, v) << "@" << get(owner, v)
+ << " does not match the sequential result (" << get(centrality, v) << " vs. "
+ << seq_centralityS[(n/p) * get(owner, v) + get(local, v)] << ")\n";
+ passed = false;
+ }
+ }
+
+ if (passed)
+ std::cerr << " PASSED\n";
+ }
+ }
+}
+
+void usage()
+{
+ std::cerr << "SSCA benchmark.\n\n"
+ << "Usage : ssca [options]\n\n"
+ << "Options are:\n"
+ << "\t--vertices v\t\t\tNumber of vertices in the graph\n"
+ << "\t--edges v\t\t\tNumber of edges in the graph\n"
+ << "\t--seed s\t\t\tSeed for synchronized random number generator\n"
+ << "\t--full-bc\t\t\tRun full (exact) Betweenness Centrality\n"
+ << "\t--max-weight miw\t\tMaximum integer edge weight\n"
+ << "\t--subgraph-edge-length sel\tEdge length of subgraphs to extract in Kernel 3\n"
+ << "\t--k4alpha k\t\t\tValue of K4Alpha in Kernel 4\n"
+ << "\t--scale s\t\t\tSCALE parameter for the SSCA benchmark (sets n, m, and C)\n"
+ << "\t--dot\t\t\t\tEmit a dot file containing the graph\n"
+ << "\t--verify\t\t\tVerify result\n"
+ << "\t--degree-dist\t\t\t Output degree distribution of graph\n"
+ << "\t--no-distributed-graph\t\tOmit distributed graph tests\n";
+}
+
+int test_main(int argc, char* argv[])
+{
+ mpi::environment env(argc, argv);
+
+ using boost::graph::distributed::mpi_process_group;
+
+#ifdef CSR
+ typedef compressed_sparse_row_graph<directedS, VertexProperties, WeightedEdge, no_property,
+ distributedS<mpi_process_group> > Graph;
+#else
+ typedef adjacency_list<vecS,
+ distributedS<mpi_process_group, vecS>,
+ directedS,
+ // Vertex properties
+ property<vertex_distance_t, int,
+ property<vertex_color_t, default_color_type> >,
+ // Edge properties
+ property<edge_weight_t, int> > Graph;
+#endif
+
+ typedef graph_traits<Graph>::vertices_size_type vertices_size_type;
+ typedef graph_traits<Graph>::edges_size_type edges_size_type;
+
+ RandomGenerator gen;
+
+ // Default args
+ vertices_size_type n = 100;
+ edges_size_type m = 8*n;
+ uint64_t seed = 1;
+ int maxEdgeWeight = 100,
+ subGraphEdgeLength = 8,
+ K4Alpha = 0.5;
+ double a = 0.57, b = 0.19, c = 0.19, d = 0.05;
+ bool emit_dot_file = false, verify = false, full_bc = true,
+ distributed_graph = true, show_degree_dist = false,
+ non_distributed_graph = true;
+
+ mpi_process_group pg;
+
+ if (argc == 1) {
+ if (process_id(pg) == 0)
+ usage();
+ exit(-1);
+ }
+
+ // Parse args
+ for (int i = 1; i < argc; ++i) {
+ std::string arg = argv[i];
+
+ if (arg == "--vertices")
+ n = boost::lexical_cast<vertices_size_type>( argv[i+1] );
+
+ if (arg == "--seed")
+ seed = boost::lexical_cast<uint64_t>( argv[i+1] );
+
+ if (arg == "--full-bc")
+ full_bc = (argv[i+1]== "true");
+
+ if (arg == "--max-weight")
+ maxEdgeWeight = boost::lexical_cast<int>( argv[i+1] );
+
+ if (arg == "--subgraph-edge-length")
+ subGraphEdgeLength = boost::lexical_cast<int>( argv[i+1] );
+
+ if (arg == "--edges")
+ m = boost::lexical_cast<edges_size_type>( argv[i+1] );
+
+ if (arg == "--k4alpha")
+ K4Alpha = boost::lexical_cast<int>( argv[i+1] );
+
+ if (arg == "--dot")
+ emit_dot_file = true;
+
+ if (arg == "--verify")
+ verify = true;
+
+ if (arg == "--degree-dist")
+ show_degree_dist = true;
+
+ if (arg == "--no-distributed-graph")
+ distributed_graph = false;
+
+ if (arg == "--no-non-distributed-graph")
+ non_distributed_graph = false;
+
+ if (arg == "--scale") {
+ vertices_size_type scale = boost::lexical_cast<vertices_size_type>( argv[i+1] );
+ maxEdgeWeight = n = vertices_size_type(floor(pow(2, scale)));
+ m = 8 * n;
+ }
+
+ if (arg == "--help") {
+ if (process_id(pg) == 0)
+ usage();
+ exit(-1);
+ }
+ }
+
+ if (non_distributed_graph) {
+ if (process_id(pg) == 0)
+ std::cerr << "Non-Distributed Graph Tests\n";
+
+ run_non_distributed_graph_tests(gen, pg, n, m, maxEdgeWeight, seed, K4Alpha, a, b, c, d,
+ subGraphEdgeLength, show_degree_dist, full_bc, verify);
+ }
+
+ if (distributed_graph) {
+ if (process_id(pg) == 0)
+ std::cerr << "Distributed Graph Tests\n";
+
+ run_distributed_graph_tests(gen, pg, n, m, maxEdgeWeight, seed, K4Alpha, a, b, c, d,
+ subGraphEdgeLength, show_degree_dist, emit_dot_file,
+ full_bc, verify);
+ }
+
+ return 0;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk