Squashed 'boost/' content from commit b4feb19f2

git-subtree-dir: boost
git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
Bill Somerville
2018-06-09 21:48:32 +01:00
commit 4ebe6417a5
12444 changed files with 2327021 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
//=======================================================================
// Copyright 2002 Indiana University.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
#ifndef BOOST_ADJACENCY_ITERATOR_HPP
#define BOOST_ADJACENCY_ITERATOR_HPP
#include <boost/detail/iterator.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/graph/graph_traits.hpp>
namespace boost
{
template <class Graph, class Vertex, class OutEdgeIter, class Difference>
struct adjacency_iterator
: iterator_adaptor<
adjacency_iterator<Graph,Vertex,OutEdgeIter,Difference>
, OutEdgeIter
, Vertex
, use_default
, Vertex
, Difference
>
{
typedef iterator_adaptor<
adjacency_iterator<Graph,Vertex,OutEdgeIter,Difference>
, OutEdgeIter
, Vertex
, use_default
, Vertex
, Difference
> super_t;
inline adjacency_iterator() {}
inline adjacency_iterator(OutEdgeIter const& i, const Graph* g) : super_t(i), m_g(g) { }
inline Vertex
dereference() const
{ return target(*this->base(), *m_g); }
const Graph* m_g;
};
template <class Graph,
class Vertex = typename graph_traits<Graph>::vertex_descriptor,
class OutEdgeIter=typename graph_traits<Graph>::out_edge_iterator>
class adjacency_iterator_generator
{
typedef typename boost::detail::iterator_traits<OutEdgeIter>
::difference_type difference_type;
public:
typedef adjacency_iterator<Graph,Vertex,OutEdgeIter,difference_type> type;
};
template <class Graph, class Vertex, class InEdgeIter, class Difference>
struct inv_adjacency_iterator
: iterator_adaptor<
inv_adjacency_iterator<Graph,Vertex,InEdgeIter,Difference>
, InEdgeIter
, Vertex
, use_default
, Vertex
, Difference
>
{
typedef iterator_adaptor<
inv_adjacency_iterator<Graph,Vertex,InEdgeIter,Difference>
, InEdgeIter
, Vertex
, use_default
, Vertex
, Difference
> super_t;
inline inv_adjacency_iterator() { }
inline inv_adjacency_iterator(InEdgeIter const& i, const Graph* g) : super_t(i), m_g(g) { }
inline Vertex
dereference() const
{ return source(*this->base(), *m_g); }
const Graph* m_g;
};
template <class Graph,
class Vertex = typename graph_traits<Graph>::vertex_descriptor,
class InEdgeIter = typename graph_traits<Graph>::in_edge_iterator>
class inv_adjacency_iterator_generator {
typedef typename boost::detail::iterator_traits<InEdgeIter>
::difference_type difference_type;
public:
typedef inv_adjacency_iterator<Graph, Vertex, InEdgeIter, difference_type> type;
};
} // namespace boost
#endif // BOOST_DETAIL_ADJACENCY_ITERATOR_HPP
+433
View File
@@ -0,0 +1,433 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Copyright 2010 Thomas Claveirole
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Thomas Claveirole
//
// 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)
//=======================================================================
#ifndef BOOST_GRAPH_ADJACENCY_LIST_HPP
#define BOOST_GRAPH_ADJACENCY_LIST_HPP
#include <boost/config.hpp>
#include <vector>
#include <list>
#include <set>
#include <boost/unordered_set.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_mutability_traits.hpp>
#include <boost/graph/graph_selectors.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/graph/detail/edge.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/named_graph.hpp>
namespace boost {
//===========================================================================
// Selectors for the VertexList and EdgeList template parameters of
// adjacency_list, and the container_gen traits class which is used
// to map the selectors to the container type used to implement the
// graph.
struct vecS { };
struct listS { };
struct setS { };
struct mapS { };
struct multisetS { };
struct multimapS { };
struct hash_setS { };
struct hash_mapS { };
struct hash_multisetS { };
struct hash_multimapS { };
template <class Selector, class ValueType>
struct container_gen { };
template <class ValueType>
struct container_gen<listS, ValueType> {
typedef std::list<ValueType> type;
};
template <class ValueType>
struct container_gen<vecS, ValueType> {
typedef std::vector<ValueType> type;
};
template <class ValueType>
struct container_gen<mapS, ValueType> {
typedef std::set<ValueType> type;
};
template <class ValueType>
struct container_gen<setS, ValueType> {
typedef std::set<ValueType> type;
};
template <class ValueType>
struct container_gen<multisetS, ValueType> {
typedef std::multiset<ValueType> type;
};
template <class ValueType>
struct container_gen<multimapS, ValueType> {
typedef std::multiset<ValueType> type;
};
template <class ValueType>
struct container_gen<hash_setS, ValueType> {
typedef boost::unordered_set<ValueType> type;
};
template <class ValueType>
struct container_gen<hash_mapS, ValueType> {
typedef boost::unordered_set<ValueType> type;
};
template <class ValueType>
struct container_gen<hash_multisetS, ValueType> {
typedef boost::unordered_multiset<ValueType> type;
};
template <class ValueType>
struct container_gen<hash_multimapS, ValueType> {
typedef boost::unordered_multiset<ValueType> type;
};
template <class StorageSelector>
struct parallel_edge_traits { };
template <>
struct parallel_edge_traits<vecS> {
typedef allow_parallel_edge_tag type; };
template <>
struct parallel_edge_traits<listS> {
typedef allow_parallel_edge_tag type; };
template <>
struct parallel_edge_traits<setS> {
typedef disallow_parallel_edge_tag type; };
template <>
struct parallel_edge_traits<multisetS> {
typedef allow_parallel_edge_tag type; };
template <>
struct parallel_edge_traits<hash_setS> {
typedef disallow_parallel_edge_tag type;
};
// mapS is obsolete, replaced with setS
template <>
struct parallel_edge_traits<mapS> {
typedef disallow_parallel_edge_tag type; };
template <>
struct parallel_edge_traits<hash_mapS> {
typedef disallow_parallel_edge_tag type;
};
template <>
struct parallel_edge_traits<hash_multisetS> {
typedef allow_parallel_edge_tag type;
};
template <>
struct parallel_edge_traits<hash_multimapS> {
typedef allow_parallel_edge_tag type;
};
namespace detail {
template <class Directed> struct is_random_access {
enum { value = false};
typedef mpl::false_ type;
};
template <>
struct is_random_access<vecS> {
enum { value = true };
typedef mpl::true_ type;
};
} // namespace detail
template <typename Selector> struct is_distributed_selector: mpl::false_ {};
//===========================================================================
// The adjacency_list_traits class, which provides a way to access
// some of the associated types of an adjacency_list type without
// having to first create the adjacency_list type. This is useful
// when trying to create interior vertex or edge properties who's
// value type is a vertex or edge descriptor.
template <class OutEdgeListS = vecS,
class VertexListS = vecS,
class DirectedS = directedS,
class EdgeListS = listS>
struct adjacency_list_traits
{
typedef typename detail::is_random_access<VertexListS>::type
is_rand_access;
typedef typename DirectedS::is_bidir_t is_bidir;
typedef typename DirectedS::is_directed_t is_directed;
typedef typename mpl::if_<is_bidir,
bidirectional_tag,
typename mpl::if_<is_directed,
directed_tag, undirected_tag
>::type
>::type directed_category;
typedef typename parallel_edge_traits<OutEdgeListS>::type
edge_parallel_category;
typedef std::size_t vertices_size_type;
typedef void* vertex_ptr;
typedef typename mpl::if_<is_rand_access,
vertices_size_type, vertex_ptr>::type vertex_descriptor;
typedef detail::edge_desc_impl<directed_category, vertex_descriptor>
edge_descriptor;
private:
// Logic to figure out the edges_size_type
struct dummy {};
typedef typename container_gen<EdgeListS, dummy>::type EdgeContainer;
typedef typename DirectedS::is_bidir_t BidirectionalT;
typedef typename DirectedS::is_directed_t DirectedT;
typedef typename mpl::and_<DirectedT,
typename mpl::not_<BidirectionalT>::type >::type on_edge_storage;
public:
typedef typename mpl::if_<on_edge_storage,
std::size_t, typename EdgeContainer::size_type
>::type edges_size_type;
};
} // namespace boost
#include <boost/graph/detail/adjacency_list.hpp>
namespace boost {
//===========================================================================
// The adjacency_list class.
//
template <class OutEdgeListS = vecS, // a Sequence or an AssociativeContainer
class VertexListS = vecS, // a Sequence or a RandomAccessContainer
class DirectedS = directedS,
class VertexProperty = no_property,
class EdgeProperty = no_property,
class GraphProperty = no_property,
class EdgeListS = listS>
class adjacency_list
: public detail::adj_list_gen<
adjacency_list<OutEdgeListS,VertexListS,DirectedS,
VertexProperty,EdgeProperty,GraphProperty,EdgeListS>,
VertexListS, OutEdgeListS, DirectedS,
VertexProperty, EdgeProperty,
GraphProperty, EdgeListS>::type,
// Support for named vertices
public graph::maybe_named_graph<
adjacency_list<OutEdgeListS,VertexListS,DirectedS,
VertexProperty,EdgeProperty,GraphProperty,EdgeListS>,
typename adjacency_list_traits<OutEdgeListS, VertexListS, DirectedS,
EdgeListS>::vertex_descriptor,
VertexProperty>
{
public:
typedef GraphProperty graph_property_type;
typedef typename lookup_one_property<GraphProperty, graph_bundle_t>::type graph_bundled;
typedef VertexProperty vertex_property_type;
typedef typename lookup_one_property<VertexProperty, vertex_bundle_t>::type vertex_bundled;
typedef EdgeProperty edge_property_type;
typedef typename lookup_one_property<EdgeProperty, edge_bundle_t>::type edge_bundled;
private:
typedef adjacency_list self;
typedef typename detail::adj_list_gen<
self, VertexListS, OutEdgeListS, DirectedS,
vertex_property_type, edge_property_type, GraphProperty, EdgeListS
>::type Base;
public:
typedef typename Base::stored_vertex stored_vertex;
typedef typename Base::vertices_size_type vertices_size_type;
typedef typename Base::edges_size_type edges_size_type;
typedef typename Base::degree_size_type degree_size_type;
typedef typename Base::vertex_descriptor vertex_descriptor;
typedef typename Base::edge_descriptor edge_descriptor;
typedef OutEdgeListS out_edge_list_selector;
typedef VertexListS vertex_list_selector;
typedef DirectedS directed_selector;
typedef EdgeListS edge_list_selector;
adjacency_list(const GraphProperty& p = GraphProperty())
: m_property(new graph_property_type(p))
{ }
adjacency_list(const adjacency_list& x)
: Base(x), m_property(new graph_property_type(*x.m_property))
{ }
adjacency_list& operator=(const adjacency_list& x) {
// TBD: probably should give the strong guarantee
if (&x != this) {
Base::operator=(x);
// Copy/swap the ptr since we can't just assign it...
property_ptr p(new graph_property_type(*x.m_property));
m_property.swap(p);
}
return *this;
}
// Required by Mutable Graph
adjacency_list(vertices_size_type num_vertices,
const GraphProperty& p = GraphProperty())
: Base(num_vertices), m_property(new graph_property_type(p))
{ }
// Required by Iterator Constructible Graph
template <class EdgeIterator>
adjacency_list(EdgeIterator first, EdgeIterator last,
vertices_size_type n,
edges_size_type = 0,
const GraphProperty& p = GraphProperty())
: Base(n, first, last), m_property(new graph_property_type(p))
{ }
template <class EdgeIterator, class EdgePropertyIterator>
adjacency_list(EdgeIterator first, EdgeIterator last,
EdgePropertyIterator ep_iter,
vertices_size_type n,
edges_size_type = 0,
const GraphProperty& p = GraphProperty())
: Base(n, first, last, ep_iter), m_property(new graph_property_type(p))
{ }
void swap(adjacency_list& x) {
// Is there a more efficient way to do this?
adjacency_list tmp(x);
x = *this;
*this = tmp;
}
void clear()
{
this->clearing_graph();
Base::clear();
}
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
// Directly access a vertex or edge bundle
vertex_bundled& operator[](vertex_descriptor v)
{ return get(vertex_bundle, *this)[v]; }
const vertex_bundled& operator[](vertex_descriptor v) const
{ return get(vertex_bundle, *this)[v]; }
edge_bundled& operator[](edge_descriptor e)
{ return get(edge_bundle, *this)[e]; }
const edge_bundled& operator[](edge_descriptor e) const
{ return get(edge_bundle, *this)[e]; }
graph_bundled& operator[](graph_bundle_t)
{ return get_property(*this); }
graph_bundled const& operator[](graph_bundle_t) const
{ return get_property(*this); }
#endif
// protected: (would be protected if friends were more portable)
typedef scoped_ptr<graph_property_type> property_ptr;
property_ptr m_property;
};
#define ADJLIST_PARAMS \
typename OEL, typename VL, typename D, typename VP, typename EP, \
typename GP, typename EL
#define ADJLIST adjacency_list<OEL,VL,D,VP,EP,GP,EL>
template<ADJLIST_PARAMS, typename Tag, typename Value>
inline void set_property(ADJLIST& g, Tag tag, Value const& value) {
get_property_value(*g.m_property, tag) = value;
}
template<ADJLIST_PARAMS, typename Tag>
inline typename graph_property<ADJLIST, Tag>::type&
get_property(ADJLIST& g, Tag tag) {
return get_property_value(*g.m_property, tag);
}
template<ADJLIST_PARAMS, typename Tag>
inline typename graph_property<ADJLIST, Tag>::type const&
get_property(ADJLIST const& g, Tag tag) {
return get_property_value(*g.m_property, tag);
}
// dwa 09/25/00 - needed to be more explicit so reverse_graph would work.
template <class Directed, class Vertex,
class OutEdgeListS,
class VertexListS,
class DirectedS,
class VertexProperty,
class EdgeProperty,
class GraphProperty, class EdgeListS>
inline Vertex
source(const detail::edge_base<Directed,Vertex>& e,
const adjacency_list<OutEdgeListS, VertexListS, DirectedS,
VertexProperty, EdgeProperty, GraphProperty, EdgeListS>&)
{
return e.m_source;
}
template <class Directed, class Vertex, class OutEdgeListS,
class VertexListS, class DirectedS, class VertexProperty,
class EdgeProperty, class GraphProperty, class EdgeListS>
inline Vertex
target(const detail::edge_base<Directed,Vertex>& e,
const adjacency_list<OutEdgeListS, VertexListS, DirectedS,
VertexProperty, EdgeProperty, GraphProperty, EdgeListS>&)
{
return e.m_target;
}
// Mutability Traits
template <ADJLIST_PARAMS>
struct graph_mutability_traits<ADJLIST> {
typedef mutable_property_graph_tag category;
};
// Can't remove vertices from adjacency lists with VL==vecS
template <typename OEL, typename D, typename VP, typename EP, typename GP, typename EL>
struct graph_mutability_traits< adjacency_list<OEL,vecS,D,VP,EP,GP,EL> > {
typedef add_only_property_graph_tag category;
};
#undef ADJLIST_PARAMS
#undef ADJLIST
} // namespace boost
#endif // BOOST_GRAPH_ADJACENCY_LIST_HPP
+413
View File
@@ -0,0 +1,413 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
//
#ifndef BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP
#define BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP
/*
Breadth First Search Algorithm (Cormen, Leiserson, and Rivest p. 470)
*/
#include <boost/config.hpp>
#include <vector>
#include <boost/pending/queue.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/visitors.hpp>
#include <boost/graph/named_function_params.hpp>
#include <boost/graph/overloading.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/two_bit_color_map.hpp>
#include <boost/concept/assert.hpp>
#ifdef BOOST_GRAPH_USE_MPI
#include <boost/graph/distributed/concepts.hpp>
#endif // BOOST_GRAPH_USE_MPI
namespace boost {
template <class Visitor, class Graph>
struct BFSVisitorConcept {
void constraints() {
BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept<Visitor> ));
vis.initialize_vertex(u, g);
vis.discover_vertex(u, g);
vis.examine_vertex(u, g);
vis.examine_edge(e, g);
vis.tree_edge(e, g);
vis.non_tree_edge(e, g);
vis.gray_target(e, g);
vis.black_target(e, g);
vis.finish_vertex(u, g);
}
Visitor vis;
Graph g;
typename graph_traits<Graph>::vertex_descriptor u;
typename graph_traits<Graph>::edge_descriptor e;
};
// Multiple-source version
template <class IncidenceGraph, class Buffer, class BFSVisitor,
class ColorMap, class SourceIterator>
void breadth_first_visit
(const IncidenceGraph& g,
SourceIterator sources_begin, SourceIterator sources_end,
Buffer& Q, BFSVisitor vis, ColorMap color)
{
BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<IncidenceGraph> ));
typedef graph_traits<IncidenceGraph> GTraits;
typedef typename GTraits::vertex_descriptor Vertex;
BOOST_CONCEPT_ASSERT(( BFSVisitorConcept<BFSVisitor, IncidenceGraph> ));
BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ColorMap, Vertex> ));
typedef typename property_traits<ColorMap>::value_type ColorValue;
typedef color_traits<ColorValue> Color;
typename GTraits::out_edge_iterator ei, ei_end;
for (; sources_begin != sources_end; ++sources_begin) {
Vertex s = *sources_begin;
put(color, s, Color::gray()); vis.discover_vertex(s, g);
Q.push(s);
}
while (! Q.empty()) {
Vertex u = Q.top(); Q.pop(); vis.examine_vertex(u, g);
for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
Vertex v = target(*ei, g); vis.examine_edge(*ei, g);
ColorValue v_color = get(color, v);
if (v_color == Color::white()) { vis.tree_edge(*ei, g);
put(color, v, Color::gray()); vis.discover_vertex(v, g);
Q.push(v);
} else { vis.non_tree_edge(*ei, g);
if (v_color == Color::gray()) vis.gray_target(*ei, g);
else vis.black_target(*ei, g);
}
} // end for
put(color, u, Color::black()); vis.finish_vertex(u, g);
} // end while
} // breadth_first_visit
// Single-source version
template <class IncidenceGraph, class Buffer, class BFSVisitor,
class ColorMap>
void breadth_first_visit
(const IncidenceGraph& g,
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
Buffer& Q, BFSVisitor vis, ColorMap color)
{
typename graph_traits<IncidenceGraph>::vertex_descriptor sources[1] = {s};
breadth_first_visit(g, sources, sources + 1, Q, vis, color);
}
template <class VertexListGraph, class SourceIterator,
class Buffer, class BFSVisitor,
class ColorMap>
void breadth_first_search
(const VertexListGraph& g,
SourceIterator sources_begin, SourceIterator sources_end,
Buffer& Q, BFSVisitor vis, ColorMap color)
{
// Initialization
typedef typename property_traits<ColorMap>::value_type ColorValue;
typedef color_traits<ColorValue> Color;
typename boost::graph_traits<VertexListGraph>::vertex_iterator i, i_end;
for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i) {
vis.initialize_vertex(*i, g);
put(color, *i, Color::white());
}
breadth_first_visit(g, sources_begin, sources_end, Q, vis, color);
}
template <class VertexListGraph, class Buffer, class BFSVisitor,
class ColorMap>
void breadth_first_search
(const VertexListGraph& g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
Buffer& Q, BFSVisitor vis, ColorMap color)
{
typename graph_traits<VertexListGraph>::vertex_descriptor sources[1] = {s};
breadth_first_search(g, sources, sources + 1, Q, vis, color);
}
namespace graph { struct bfs_visitor_event_not_overridden {}; }
template <class Visitors = null_visitor>
class bfs_visitor {
public:
bfs_visitor() { }
bfs_visitor(Visitors vis) : m_vis(vis) { }
template <class Vertex, class Graph>
graph::bfs_visitor_event_not_overridden
initialize_vertex(Vertex u, Graph& g)
{
invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex());
return graph::bfs_visitor_event_not_overridden();
}
template <class Vertex, class Graph>
graph::bfs_visitor_event_not_overridden
discover_vertex(Vertex u, Graph& g)
{
invoke_visitors(m_vis, u, g, ::boost::on_discover_vertex());
return graph::bfs_visitor_event_not_overridden();
}
template <class Vertex, class Graph>
graph::bfs_visitor_event_not_overridden
examine_vertex(Vertex u, Graph& g)
{
invoke_visitors(m_vis, u, g, ::boost::on_examine_vertex());
return graph::bfs_visitor_event_not_overridden();
}
template <class Edge, class Graph>
graph::bfs_visitor_event_not_overridden
examine_edge(Edge e, Graph& g)
{
invoke_visitors(m_vis, e, g, ::boost::on_examine_edge());
return graph::bfs_visitor_event_not_overridden();
}
template <class Edge, class Graph>
graph::bfs_visitor_event_not_overridden
tree_edge(Edge e, Graph& g)
{
invoke_visitors(m_vis, e, g, ::boost::on_tree_edge());
return graph::bfs_visitor_event_not_overridden();
}
template <class Edge, class Graph>
graph::bfs_visitor_event_not_overridden
non_tree_edge(Edge e, Graph& g)
{
invoke_visitors(m_vis, e, g, ::boost::on_non_tree_edge());
return graph::bfs_visitor_event_not_overridden();
}
template <class Edge, class Graph>
graph::bfs_visitor_event_not_overridden
gray_target(Edge e, Graph& g)
{
invoke_visitors(m_vis, e, g, ::boost::on_gray_target());
return graph::bfs_visitor_event_not_overridden();
}
template <class Edge, class Graph>
graph::bfs_visitor_event_not_overridden
black_target(Edge e, Graph& g)
{
invoke_visitors(m_vis, e, g, ::boost::on_black_target());
return graph::bfs_visitor_event_not_overridden();
}
template <class Vertex, class Graph>
graph::bfs_visitor_event_not_overridden
finish_vertex(Vertex u, Graph& g)
{
invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex());
return graph::bfs_visitor_event_not_overridden();
}
BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,bfs)
BOOST_GRAPH_EVENT_STUB(on_discover_vertex,bfs)
BOOST_GRAPH_EVENT_STUB(on_examine_vertex,bfs)
BOOST_GRAPH_EVENT_STUB(on_examine_edge,bfs)
BOOST_GRAPH_EVENT_STUB(on_tree_edge,bfs)
BOOST_GRAPH_EVENT_STUB(on_non_tree_edge,bfs)
BOOST_GRAPH_EVENT_STUB(on_gray_target,bfs)
BOOST_GRAPH_EVENT_STUB(on_black_target,bfs)
BOOST_GRAPH_EVENT_STUB(on_finish_vertex,bfs)
protected:
Visitors m_vis;
};
template <class Visitors>
bfs_visitor<Visitors>
make_bfs_visitor(Visitors vis) {
return bfs_visitor<Visitors>(vis);
}
typedef bfs_visitor<> default_bfs_visitor;
namespace detail {
template <class VertexListGraph, class ColorMap, class BFSVisitor,
class P, class T, class R>
void bfs_helper
(VertexListGraph& g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
ColorMap color,
BFSVisitor vis,
const bgl_named_params<P, T, R>& params,
boost::mpl::false_)
{
typedef graph_traits<VertexListGraph> Traits;
// Buffer default
typedef typename Traits::vertex_descriptor Vertex;
typedef boost::queue<Vertex> queue_t;
queue_t Q;
breadth_first_search
(g, s,
choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(),
vis, color);
}
#ifdef BOOST_GRAPH_USE_MPI
template <class DistributedGraph, class ColorMap, class BFSVisitor,
class P, class T, class R>
void bfs_helper
(DistributedGraph& g,
typename graph_traits<DistributedGraph>::vertex_descriptor s,
ColorMap color,
BFSVisitor vis,
const bgl_named_params<P, T, R>& params,
boost::mpl::true_);
#endif // BOOST_GRAPH_USE_MPI
//-------------------------------------------------------------------------
// Choose between default color and color parameters. Using
// function dispatching so that we don't require vertex index if
// the color default is not being used.
template <class ColorMap>
struct bfs_dispatch {
template <class VertexListGraph, class P, class T, class R>
static void apply
(VertexListGraph& g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
const bgl_named_params<P, T, R>& params,
ColorMap color)
{
bfs_helper
(g, s, color,
choose_param(get_param(params, graph_visitor),
make_bfs_visitor(null_visitor())),
params,
boost::mpl::bool_<
boost::is_base_and_derived<
distributed_graph_tag,
typename graph_traits<VertexListGraph>::traversal_category>::value>());
}
};
template <>
struct bfs_dispatch<param_not_found> {
template <class VertexListGraph, class P, class T, class R>
static void apply
(VertexListGraph& g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
const bgl_named_params<P, T, R>& params,
param_not_found)
{
null_visitor null_vis;
bfs_helper
(g, s,
make_two_bit_color_map
(num_vertices(g),
choose_const_pmap(get_param(params, vertex_index),
g, vertex_index)),
choose_param(get_param(params, graph_visitor),
make_bfs_visitor(null_vis)),
params,
boost::mpl::bool_<
boost::is_base_and_derived<
distributed_graph_tag,
typename graph_traits<VertexListGraph>::traversal_category>::value>());
}
};
} // namespace detail
#if 1
// Named Parameter Variant
template <class VertexListGraph, class P, class T, class R>
void breadth_first_search
(const VertexListGraph& g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
const bgl_named_params<P, T, R>& params)
{
// The graph is passed by *const* reference so that graph adaptors
// (temporaries) can be passed into this function. However, the
// graph is not really const since we may write to property maps
// of the graph.
VertexListGraph& ng = const_cast<VertexListGraph&>(g);
typedef typename get_param_type< vertex_color_t, bgl_named_params<P,T,R> >::type C;
detail::bfs_dispatch<C>::apply(ng, s, params,
get_param(params, vertex_color));
}
#endif
// This version does not initialize colors, user has to.
template <class IncidenceGraph, class P, class T, class R>
void breadth_first_visit
(const IncidenceGraph& g,
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
const bgl_named_params<P, T, R>& params)
{
// The graph is passed by *const* reference so that graph adaptors
// (temporaries) can be passed into this function. However, the
// graph is not really const since we may write to property maps
// of the graph.
IncidenceGraph& ng = const_cast<IncidenceGraph&>(g);
typedef graph_traits<IncidenceGraph> Traits;
// Buffer default
typedef typename Traits::vertex_descriptor vertex_descriptor;
typedef boost::queue<vertex_descriptor> queue_t;
queue_t Q;
breadth_first_visit
(ng, s,
choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(),
choose_param(get_param(params, graph_visitor),
make_bfs_visitor(null_visitor())),
choose_pmap(get_param(params, vertex_color), ng, vertex_color)
);
}
namespace graph {
namespace detail {
template <typename Graph, typename Source>
struct breadth_first_search_impl {
typedef void result_type;
template <typename ArgPack>
void operator()(const Graph& g, const Source& source, const ArgPack& arg_pack) {
using namespace boost::graph::keywords;
typename boost::graph_traits<Graph>::vertex_descriptor sources[1] = {source};
boost::queue<typename boost::graph_traits<Graph>::vertex_descriptor> Q;
boost::breadth_first_search(g,
&sources[0],
&sources[1],
boost::unwrap_ref(arg_pack[_buffer | boost::ref(Q)]),
arg_pack[_visitor | make_bfs_visitor(null_visitor())],
boost::detail::make_color_map_from_arg_pack(g, arg_pack));
}
};
}
BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(breadth_first_search, 2, 4)
}
#if 0
// Named Parameter Variant
BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(breadth_first_search, 2)
#endif
} // namespace boost
#ifdef BOOST_GRAPH_USE_MPI
# include <boost/graph/distributed/breadth_first_search.hpp>
#endif
#endif // BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP
+92
View File
@@ -0,0 +1,92 @@
// Copyright Daniel Trebbien 2010.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or the copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GRAPH_BUFFER_CONCEPTS_HPP
#define BOOST_GRAPH_BUFFER_CONCEPTS_HPP 1
#include <boost/concept_check.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/concept/detail/concept_def.hpp>
namespace boost {
BOOST_concept(Buffer, (B))
{
typedef typename B::value_type value_type;
typedef typename B::size_type size_type;
BOOST_CONCEPT_USAGE(Buffer) {
typedef typename boost::add_reference<value_type>::type reference;
BOOST_CONCEPT_ASSERT((Assignable<value_type>));
buf.push(g_ct);
buf.pop();
reference t = buf.top();
boost::ignore_unused_variable_warning(t);
}
void const_constraints(const B& cbuf) {
typedef typename boost::add_const<typename boost::remove_reference<value_type>::type>::type& const_reference;
const_reference ct = cbuf.top();
s = cbuf.size();
if (cbuf.empty())
dummy = __LINE__;
}
int dummy;
static const value_type g_ct;
size_type s;
B buf;
};
BOOST_concept(UpdatableQueue, (Q))
: Buffer<Q>
{
BOOST_CONCEPT_USAGE(UpdatableQueue) {
q.update(g_ct);
}
void const_constraints(const Q& cq) {
if (cq.contains(g_ct))
dummy = __LINE__;
}
int dummy;
static const typename Buffer<Q>::value_type g_ct;
Q q;
};
BOOST_concept(KeyedUpdatableQueue, (Q))
: UpdatableQueue<Q>
{
typedef typename Q::key_type key_type;
typedef typename Q::key_map key_map;
BOOST_CONCEPT_USAGE(KeyedUpdatableQueue) {
BOOST_CONCEPT_ASSERT((boost::ReadWritePropertyMapConcept<key_map, typename Buffer<Q>::value_type>));
}
void const_constraints(const Q& cq) {
km = cq.keys();
k = get(km, g_ct);
}
static const typename Buffer<Q>::value_type g_ct;
key_type k;
key_map km;
Q q;
};
} // end `namespace boost`
#include <boost/concept/detail/concept_undef.hpp>
#endif // !BOOST_GRAPH_BUFFER_CONCEPTS_HPP
@@ -0,0 +1,117 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
//
#ifndef BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP
#define BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP
#include <iterator>
#include <utility>
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
# define BOOST_GRAPH_NO_OPTIONAL
#endif
#ifdef BOOST_GRAPH_NO_OPTIONAL
# define BOOST_GRAPH_MEMBER .
#else
# define BOOST_GRAPH_MEMBER ->
# include <boost/optional.hpp>
#endif // ndef BOOST_GRAPH_NO_OPTIONAL
namespace boost {
namespace detail {
template <class VertexIterator, class OutEdgeIterator, class Graph>
class adj_list_edge_iterator {
typedef adj_list_edge_iterator self;
public:
typedef std::forward_iterator_tag iterator_category;
typedef typename OutEdgeIterator::value_type value_type;
typedef typename OutEdgeIterator::reference reference;
typedef typename OutEdgeIterator::pointer pointer;
typedef typename OutEdgeIterator::difference_type difference_type;
typedef difference_type distance_type;
inline adj_list_edge_iterator() {}
inline adj_list_edge_iterator(const self& x)
: vBegin(x.vBegin), vCurr(x.vCurr), vEnd(x.vEnd),
edges(x.edges), m_g(x.m_g) { }
template <class G>
inline adj_list_edge_iterator(VertexIterator b,
VertexIterator c,
VertexIterator e,
const G& g)
: vBegin(b), vCurr(c), vEnd(e), m_g(&g) {
if ( vCurr != vEnd ) {
while ( vCurr != vEnd && out_degree(*vCurr, *m_g) == 0 )
++vCurr;
if ( vCurr != vEnd )
edges = out_edges(*vCurr, *m_g);
}
}
/*Note:
In the directed graph cases, it is fine.
For undirected graphs, one edge go through twice.
*/
inline self& operator++() {
++edges BOOST_GRAPH_MEMBER first;
if (edges BOOST_GRAPH_MEMBER first == edges BOOST_GRAPH_MEMBER second)
{
++vCurr;
while ( vCurr != vEnd && out_degree(*vCurr, *m_g) == 0 )
++vCurr;
if ( vCurr != vEnd )
edges = out_edges(*vCurr, *m_g);
}
return *this;
}
inline self operator++(int) {
self tmp = *this;
++(*this);
return tmp;
}
inline value_type operator*() const
{ return *edges BOOST_GRAPH_MEMBER first; }
inline bool operator==(const self& x) const {
return vCurr == x.vCurr
&& (vCurr == vEnd
|| edges BOOST_GRAPH_MEMBER first == x.edges BOOST_GRAPH_MEMBER first);
}
inline bool operator!=(const self& x) const {
return vCurr != x.vCurr
|| (vCurr != vEnd
&& edges BOOST_GRAPH_MEMBER first != x.edges BOOST_GRAPH_MEMBER first);
}
protected:
VertexIterator vBegin;
VertexIterator vCurr;
VertexIterator vEnd;
#ifdef BOOST_GRAPH_NO_OPTIONAL
std::pair<OutEdgeIterator, OutEdgeIterator> edges;
#else
boost::optional<std::pair<OutEdgeIterator, OutEdgeIterator> >
edges;
#endif // ndef BOOST_GRAPH_NO_OPTIONAL
const Graph* m_g;
};
} // namespace detail
}
#undef BOOST_GRAPH_MEMBER
#endif // BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP
File diff suppressed because it is too large Load Diff
+319
View File
@@ -0,0 +1,319 @@
//
//=======================================================================
// Copyright 2009 Trustees of Indiana University
// Authors: Jeremiah J. Willcock, Andrew Lumsdaine
//
// 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)
//=======================================================================
//
#ifndef BOOST_D_ARY_HEAP_HPP
#define BOOST_D_ARY_HEAP_HPP
#include <vector>
#include <cstddef>
#include <algorithm>
#include <utility>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/shared_array.hpp>
#include <boost/property_map/property_map.hpp>
// WARNING: it is not safe to copy a d_ary_heap_indirect and then modify one of
// the copies. The class is required to be copyable so it can be passed around
// (without move support from C++11), but it deep-copies the heap contents yet
// shallow-copies the index_in_heap_map.
namespace boost {
// Swap two elements in a property map without assuming they model
// LvaluePropertyMap -- currently not used
template <typename PropMap>
inline void property_map_swap(
PropMap prop_map,
const typename boost::property_traits<PropMap>::key_type& ka,
const typename boost::property_traits<PropMap>::key_type& kb) {
typename boost::property_traits<PropMap>::value_type va = get(prop_map, ka);
put(prop_map, ka, get(prop_map, kb));
put(prop_map, kb, va);
}
namespace detail {
template <typename Value>
class fixed_max_size_vector {
boost::shared_array<Value> m_data;
std::size_t m_size;
public:
typedef std::size_t size_type;
fixed_max_size_vector(std::size_t max_size)
: m_data(new Value[max_size]), m_size(0) {}
std::size_t size() const {return m_size;}
bool empty() const {return m_size == 0;}
Value& operator[](std::size_t i) {return m_data[i];}
const Value& operator[](std::size_t i) const {return m_data[i];}
void push_back(Value v) {m_data[m_size++] = v;}
void pop_back() {--m_size;}
Value& back() {return m_data[m_size - 1];}
const Value& back() const {return m_data[m_size - 1];}
};
}
// D-ary heap using an indirect compare operator (use identity_property_map
// as DistanceMap to get a direct compare operator). This heap appears to be
// commonly used for Dijkstra's algorithm for its good practical performance
// on some platforms; asymptotically, it has an O(lg N) decrease-key
// operation while that can be done in constant time on a relaxed heap. The
// implementation is mostly based on the binary heap page on Wikipedia and
// online sources that state that the operations are the same for d-ary
// heaps. This code is not based on the old Boost d-ary heap code.
//
// - d_ary_heap_indirect is a model of UpdatableQueue as is needed for
// dijkstra_shortest_paths.
//
// - Value must model Assignable.
// - Arity must be at least 2 (optimal value appears to be 4, both in my and
// third-party experiments).
// - IndexInHeapMap must be a ReadWritePropertyMap from Value to
// Container::size_type (to store the index of each stored value within the
// heap for decrease-key aka update).
// - DistanceMap must be a ReadablePropertyMap from Value to something
// (typedef'ed as distance_type).
// - Compare must be a BinaryPredicate used as a less-than operator on
// distance_type.
// - Container must be a random-access, contiguous container (in practice,
// the operations used probably require that it is std::vector<Value>).
//
template <typename Value,
std::size_t Arity,
typename IndexInHeapPropertyMap,
typename DistanceMap,
typename Compare = std::less<Value>,
typename Container = std::vector<Value> >
class d_ary_heap_indirect {
BOOST_STATIC_ASSERT (Arity >= 2);
public:
typedef typename Container::size_type size_type;
typedef Value value_type;
typedef typename boost::property_traits<DistanceMap>::value_type key_type;
typedef DistanceMap key_map;
d_ary_heap_indirect(DistanceMap distance,
IndexInHeapPropertyMap index_in_heap,
const Compare& compare = Compare(),
const Container& data = Container())
: compare(compare), data(data), distance(distance),
index_in_heap(index_in_heap) {}
/* Implicit copy constructor */
/* Implicit assignment operator */
size_type size() const {
return data.size();
}
bool empty() const {
return data.empty();
}
void push(const Value& v) {
size_type index = data.size();
data.push_back(v);
put(index_in_heap, v, index);
preserve_heap_property_up(index);
verify_heap();
}
Value& top() {
BOOST_ASSERT (!this->empty());
return data[0];
}
const Value& top() const {
BOOST_ASSERT (!this->empty());
return data[0];
}
void pop() {
BOOST_ASSERT (!this->empty());
put(index_in_heap, data[0], (size_type)(-1));
if (data.size() != 1) {
data[0] = data.back();
put(index_in_heap, data[0], (size_type)(0));
data.pop_back();
preserve_heap_property_down();
verify_heap();
} else {
data.pop_back();
}
}
// This function assumes the key has been updated (using an external write
// to the distance map or such)
// See http://coding.derkeiler.com/Archive/General/comp.theory/2007-05/msg00043.html
void update(const Value& v) { /* decrease-key */
size_type index = get(index_in_heap, v);
preserve_heap_property_up(index);
verify_heap();
}
bool contains(const Value& v) const {
size_type index = get(index_in_heap, v);
return (index != (size_type)(-1));
}
void push_or_update(const Value& v) { /* insert if not present, else update */
size_type index = get(index_in_heap, v);
if (index == (size_type)(-1)) {
index = data.size();
data.push_back(v);
put(index_in_heap, v, index);
}
preserve_heap_property_up(index);
verify_heap();
}
DistanceMap keys() const {
return distance;
}
private:
Compare compare;
Container data;
DistanceMap distance;
IndexInHeapPropertyMap index_in_heap;
// The distances being compared using compare and that are stored in the
// distance map
typedef typename boost::property_traits<DistanceMap>::value_type distance_type;
// Get the parent of a given node in the heap
static size_type parent(size_type index) {
return (index - 1) / Arity;
}
// Get the child_idx'th child of a given node; 0 <= child_idx < Arity
static size_type child(size_type index, std::size_t child_idx) {
return index * Arity + child_idx + 1;
}
// Swap two elements in the heap by index, updating index_in_heap
void swap_heap_elements(size_type index_a, size_type index_b) {
using std::swap;
Value value_a = data[index_a];
Value value_b = data[index_b];
data[index_a] = value_b;
data[index_b] = value_a;
put(index_in_heap, value_a, index_b);
put(index_in_heap, value_b, index_a);
}
// Emulate the indirect_cmp that is now folded into this heap class
bool compare_indirect(const Value& a, const Value& b) const {
return compare(get(distance, a), get(distance, b));
}
// Verify that the array forms a heap; commented out by default
void verify_heap() const {
// This is a very expensive test so it should be disabled even when
// NDEBUG is not defined
#if 0
for (size_t i = 1; i < data.size(); ++i) {
if (compare_indirect(data[i], data[parent(i)])) {
BOOST_ASSERT (!"Element is smaller than its parent");
}
}
#endif
}
// Starting at a node, move up the tree swapping elements to preserve the
// heap property
void preserve_heap_property_up(size_type index) {
size_type orig_index = index;
size_type num_levels_moved = 0;
// The first loop just saves swaps that need to be done in order to avoid
// aliasing issues in its search; there is a second loop that does the
// necessary swap operations
if (index == 0) return; // Do nothing on root
Value currently_being_moved = data[index];
distance_type currently_being_moved_dist =
get(distance, currently_being_moved);
for (;;) {
if (index == 0) break; // Stop at root
size_type parent_index = parent(index);
Value parent_value = data[parent_index];
if (compare(currently_being_moved_dist, get(distance, parent_value))) {
++num_levels_moved;
index = parent_index;
continue;
} else {
break; // Heap property satisfied
}
}
// Actually do the moves -- move num_levels_moved elements down in the
// tree, then put currently_being_moved at the top
index = orig_index;
for (size_type i = 0; i < num_levels_moved; ++i) {
size_type parent_index = parent(index);
Value parent_value = data[parent_index];
put(index_in_heap, parent_value, index);
data[index] = parent_value;
index = parent_index;
}
data[index] = currently_being_moved;
put(index_in_heap, currently_being_moved, index);
verify_heap();
}
// From the root, swap elements (each one with its smallest child) if there
// are any parent-child pairs that violate the heap property
void preserve_heap_property_down() {
if (data.empty()) return;
size_type index = 0;
Value currently_being_moved = data[0];
distance_type currently_being_moved_dist =
get(distance, currently_being_moved);
size_type heap_size = data.size();
Value* data_ptr = &data[0];
for (;;) {
size_type first_child_index = child(index, 0);
if (first_child_index >= heap_size) break; /* No children */
Value* child_base_ptr = data_ptr + first_child_index;
size_type smallest_child_index = 0;
distance_type smallest_child_dist = get(distance, child_base_ptr[smallest_child_index]);
if (first_child_index + Arity <= heap_size) {
// Special case for a statically known loop count (common case)
for (size_t i = 1; i < Arity; ++i) {
Value i_value = child_base_ptr[i];
distance_type i_dist = get(distance, i_value);
if (compare(i_dist, smallest_child_dist)) {
smallest_child_index = i;
smallest_child_dist = i_dist;
}
}
} else {
for (size_t i = 1; i < heap_size - first_child_index; ++i) {
distance_type i_dist = get(distance, child_base_ptr[i]);
if (compare(i_dist, smallest_child_dist)) {
smallest_child_index = i;
smallest_child_dist = i_dist;
}
}
}
if (compare(smallest_child_dist, currently_being_moved_dist)) {
swap_heap_elements(smallest_child_index + first_child_index, index);
index = smallest_child_index + first_child_index;
continue;
} else {
break; // Heap property satisfied
}
}
verify_heap();
}
};
} // namespace boost
#endif // BOOST_D_ARY_HEAP_HPP
+121
View File
@@ -0,0 +1,121 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
#ifndef BOOST_GRAPH_DETAIL_EDGE_HPP
#define BOOST_GRAPH_DETAIL_EDGE_HPP
#include <iosfwd>
#include <boost/functional/hash.hpp>
namespace boost {
namespace detail {
template <typename Directed, typename Vertex>
struct edge_base
{
inline edge_base() {}
inline edge_base(Vertex s, Vertex d)
: m_source(s), m_target(d) { }
Vertex m_source;
Vertex m_target;
};
template <typename Directed, typename Vertex>
class edge_desc_impl : public edge_base<Directed,Vertex> {
typedef edge_desc_impl self;
typedef edge_base<Directed,Vertex> Base;
public:
typedef void property_type;
inline edge_desc_impl() : m_eproperty(0) {}
inline edge_desc_impl(Vertex s, Vertex d, const property_type* eplug)
: Base(s,d), m_eproperty(const_cast<property_type*>(eplug)) { }
property_type* get_property() { return m_eproperty; }
const property_type* get_property() const { return m_eproperty; }
// protected:
property_type* m_eproperty;
};
template <class D, class V>
inline bool
operator==(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() == b.get_property();
}
template <class D, class V>
inline bool
operator!=(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return ! (a.get_property() == b.get_property());
}
// Order edges according to the address of their property object
template <class D, class V>
inline bool
operator<(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() < b.get_property();
}
template <class D, class V>
inline bool
operator<=(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() <= b.get_property();
}
template <class D, class V>
inline bool
operator>(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() > b.get_property();
}
template <class D, class V>
inline bool
operator>=(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() >= b.get_property();
}
} //namespace detail
} // namespace boost
namespace std {
template <class Char, class Traits, class D, class V>
std::basic_ostream<Char, Traits>&
operator<<(std::basic_ostream<Char, Traits>& os,
const boost::detail::edge_desc_impl<D,V>& e)
{
return os << "(" << e.m_source << "," << e.m_target << ")";
}
}
// 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()); }
};
}
#endif // BOOST_GRAPH_DETAIL_DETAIL_EDGE_HPP
@@ -0,0 +1,163 @@
// 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_GRAPH_PARALLEL_BFS_HPP
#define BOOST_GRAPH_PARALLEL_BFS_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/graph/breadth_first_search.hpp>
#include <boost/graph/overloading.hpp>
#include <boost/graph/distributed/concepts.hpp>
#include <boost/graph/distributed/detail/filtered_queue.hpp>
#include <boost/graph/distributed/queue.hpp>
#include <boost/dynamic_bitset.hpp>
#include <boost/pending/queue.hpp>
#include <boost/graph/parallel/properties.hpp>
#include <boost/graph/parallel/container_traits.hpp>
namespace boost {
namespace detail {
/** @brief A unary predicate that decides when to push into a
* breadth-first search queue.
*
* This predicate stores a color map that is used to determine
* when to push. If it is provided with a key for which the color
* is white, it darkens the color to gray and returns true (so
* that the value will be pushed appropriately); if the color is
* not white, it returns false so that the vertex will be
* ignored.
*/
template<typename ColorMap>
struct darken_and_push
{
typedef typename property_traits<ColorMap>::key_type argument_type;
typedef bool result_type;
explicit darken_and_push(const ColorMap& color) : color(color) { }
bool operator()(const argument_type& value) const
{
typedef color_traits<typename property_traits<ColorMap>::value_type>
Color;
if (get(color, value) == Color::white()) {
put(color, value, Color::gray());
return true;
} else {
return false;
}
}
ColorMap color;
};
template<typename IndexMap>
struct has_not_been_seen
{
typedef bool result_type;
has_not_been_seen() { }
has_not_been_seen(std::size_t n, IndexMap index_map)
: seen(n), index_map(index_map) {}
template<typename Key>
result_type operator()(Key key)
{
bool result = seen[get(index_map, key)];
seen[get(index_map, key)] = true;
return !result;
}
void swap(has_not_been_seen& other)
{
using std::swap;
swap(seen, other.seen);
swap(index_map, other.index_map);
}
private:
dynamic_bitset<> seen;
IndexMap index_map;
};
template<typename IndexMap>
inline void
swap(has_not_been_seen<IndexMap>& x, has_not_been_seen<IndexMap>& y)
{
x.swap(y);
}
template <class DistributedGraph, class ColorMap, class BFSVisitor,
class BufferRef, class VertexIndexMap>
inline void
parallel_bfs_helper
(DistributedGraph& g,
typename graph_traits<DistributedGraph>::vertex_descriptor s,
ColorMap color,
BFSVisitor vis,
BufferRef Q,
VertexIndexMap)
{
set_property_map_role(vertex_color, color);
color.set_consistency_model(0);
breadth_first_search(g, s, Q.ref, vis, color);
}
template <class DistributedGraph, class ColorMap, class BFSVisitor,
class VertexIndexMap>
void parallel_bfs_helper
(DistributedGraph& g,
typename graph_traits<DistributedGraph>::vertex_descriptor s,
ColorMap color,
BFSVisitor vis,
boost::param_not_found,
VertexIndexMap vertex_index)
{
using boost::graph::parallel::process_group;
typedef graph_traits<DistributedGraph> Traits;
typedef typename Traits::vertex_descriptor Vertex;
typedef typename boost::graph::parallel::process_group_type<DistributedGraph>::type
process_group_type;
set_property_map_role(vertex_color, color);
color.set_consistency_model(0);
// Buffer default
typedef typename property_map<DistributedGraph, vertex_owner_t>
::const_type vertex_owner_map;
typedef boost::graph::distributed::distributed_queue<
process_group_type, vertex_owner_map, queue<Vertex>,
detail::darken_and_push<ColorMap> > queue_t;
queue_t Q(process_group(g),
get(vertex_owner, g),
detail::darken_and_push<ColorMap>(color));
breadth_first_search(g, s, Q, vis, color);
}
template <class DistributedGraph, class ColorMap, class BFSVisitor,
class P, class T, class R>
void bfs_helper
(DistributedGraph& g,
typename graph_traits<DistributedGraph>::vertex_descriptor s,
ColorMap color,
BFSVisitor vis,
const bgl_named_params<P, T, R>& params,
boost::mpl::true_)
{
parallel_bfs_helper
(g, s, color, vis, get_param(params, buffer_param_t()),
choose_const_pmap(get_param(params, vertex_index), g, vertex_index));
}
}
}
#endif // BOOST_GRAPH_PARALLEL_BFS_HPP
+213
View File
@@ -0,0 +1,213 @@
// 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
//
// Distributed graph concepts and helpers
//
#ifndef BOOST_GRAPH_DISTRIBUTED_CONCEPTS_HPP
#define BOOST_GRAPH_DISTRIBUTED_CONCEPTS_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/version.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/concept/assert.hpp>
#if BOOST_VERSION >= 103500
# include <boost/concept/detail/concept_def.hpp>
#endif
namespace boost {
#if BOOST_VERSION >= 103500
namespace concepts {
#endif
#if BOOST_VERSION < 103500
template <class G>
struct DistributedVertexListGraphConcept
{
typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
typedef typename graph_traits<G>::vertices_size_type vertices_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
BOOST_CONCEPT_ASSERT(( GraphConcept<G> ));
BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<vertex_iterator> ));
BOOST_CONCEPT_ASSERT(( ConvertibleConcept<traversal_category,
distributed_vertex_list_graph_tag> ));
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(g);
v = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(cg);
v = *p.first;
V = num_vertices(cg);
}
std::pair<vertex_iterator,vertex_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
G g;
vertices_size_type V;
};
template <class G>
struct DistributedEdgeListGraphConcept
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::edge_iterator edge_iterator;
typedef typename graph_traits<G>::edges_size_type edges_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
BOOST_CONCEPT_ASSERT(( GraphConcept<G> ));
BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<edge_iterator> ));
BOOST_CONCEPT_ASSERT(( DefaultConstructibleConcept<edge_descriptor> ));
BOOST_CONCEPT_ASSERT(( EqualityComparableConcept<edge_descriptor> ));
BOOST_CONCEPT_ASSERT(( AssignableConcept<edge_descriptor> ));
BOOST_CONCEPT_ASSERT(( ConvertibleConcept<traversal_category,
distributed_edge_list_graph_tag> ));
p = edges(g);
e = *p.first;
u = source(e, g);
v = target(e, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = edges(cg);
E = num_edges(cg);
e = *p.first;
u = source(e, cg);
v = target(e, cg);
}
std::pair<edge_iterator,edge_iterator> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename graph_traits<G>::edge_descriptor e;
edges_size_type E;
G g;
};
#else
BOOST_concept(DistributedVertexListGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
typedef typename graph_traits<G>::vertices_size_type vertices_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
~DistributedVertexListGraph() {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<vertex_iterator>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
distributed_vertex_list_graph_tag>));
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(g);
v = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(cg);
v = *p.first;
V = num_vertices(cg);
}
std::pair<vertex_iterator,vertex_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
G g;
vertices_size_type V;
};
BOOST_concept(DistributedEdgeListGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::edge_iterator edge_iterator;
typedef typename graph_traits<G>::edges_size_type edges_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
~DistributedEdgeListGraph() {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<edge_iterator>));
BOOST_CONCEPT_ASSERT((DefaultConstructible<edge_descriptor>));
BOOST_CONCEPT_ASSERT((EqualityComparable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Assignable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
distributed_edge_list_graph_tag>));
p = edges(g);
e = *p.first;
u = source(e, g);
v = target(e, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = edges(cg);
E = num_edges(cg);
e = *p.first;
u = source(e, cg);
v = target(e, cg);
}
std::pair<edge_iterator,edge_iterator> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename graph_traits<G>::edge_descriptor e;
edges_size_type E;
G g;
};
#endif
#if BOOST_VERSION >= 103500
} // end namespace concepts
using concepts::DistributedVertexListGraphConcept;
using concepts::DistributedEdgeListGraphConcept;
#endif
} // end namespace boost
#if BOOST_VERSION >= 103500
# include <boost/concept/detail/concept_undef.hpp>
#endif
#endif // BOOST_GRAPH_DISTRIBUTED_CONCEPTS_HPP
@@ -0,0 +1,108 @@
// 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
#ifndef BOOST_FILTERED_QUEUE_HPP
#define BOOST_FILTERED_QUEUE_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 <algorithm>
namespace boost {
/** Queue adaptor that filters elements pushed into the queue
* according to some predicate.
*/
template<typename Buffer, typename Predicate>
class filtered_queue
{
public:
typedef Buffer buffer_type;
typedef Predicate predicate_type;
typedef typename Buffer::value_type value_type;
typedef typename Buffer::size_type size_type;
/**
* Constructs a new filtered queue with an initial buffer and a
* predicate.
*
* @param buffer the initial buffer
* @param pred the predicate
*/
explicit
filtered_queue(const buffer_type& buffer = buffer_type(),
const predicate_type& pred = predicate_type())
: buffer(buffer), pred(pred) {}
/** Push a value into the queue.
*
* If the predicate returns @c true for @p x, pushes @p x into the
* buffer.
*/
void push(const value_type& x) { if (pred(x)) buffer.push(x); }
/** Pop the front element off the buffer.
*
* @pre @c !empty()
*/
void pop() { buffer.pop(); }
/** Retrieve the front (top) element in the buffer.
*
* @pre @c !empty()
*/
value_type& top() { return buffer.top(); }
/**
* \overload
*/
const value_type& top() const { return buffer.top(); }
/** Determine the number of elements in the buffer. */
size_type size() const { return buffer.size(); }
/** Determine if the buffer is empty. */
bool empty() const { return buffer.empty(); }
/** Get a reference to the underlying buffer. */
buffer_type& base() { return buffer; }
const buffer_type& base() const { return buffer; }
/** Swap the contents of this with @p other. */
void swap(filtered_queue& other)
{
using std::swap;
swap(buffer, other.buffer);
swap(pred, other.pred);
}
private:
buffer_type buffer;
predicate_type pred;
};
/** Create a filtered queue. */
template<typename Buffer, typename Predicate>
inline filtered_queue<Buffer, Predicate>
make_filtered_queue(const Buffer& buffer, const Predicate& pred)
{ return filtered_queue<Buffer, Predicate>(buffer, pred); }
/** Swap a filtered_queue. */
template<typename Buffer, typename Predicate>
inline void
swap(filtered_queue<Buffer, Predicate>& x,
filtered_queue<Buffer, Predicate>& y)
{
x.swap(y);
}
} // end namespace boost
#endif // BOOST_FILTERED_QUEUE_HPP
+177
View File
@@ -0,0 +1,177 @@
// 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/optional.hpp>
#include <cassert>
#include <boost/graph/parallel/algorithm.hpp>
#include <boost/graph/parallel/process_group.hpp>
#include <functional>
#include <algorithm>
#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 graph { namespace distributed {
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
BOOST_DISTRIBUTED_QUEUE_TYPE::
distributed_queue(const ProcessGroup& process_group, const OwnerMap& owner,
const Buffer& buffer, bool polling)
: process_group(process_group, attach_distributed_object()),
owner(owner),
buffer(buffer),
polling(polling)
{
if (!polling)
outgoing_buffers.reset(
new outgoing_buffers_t(num_processes(process_group)));
setup_triggers();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
BOOST_DISTRIBUTED_QUEUE_TYPE::
distributed_queue(const ProcessGroup& process_group, const OwnerMap& owner,
const Buffer& buffer, const UnaryPredicate& pred,
bool polling)
: process_group(process_group, attach_distributed_object()),
owner(owner),
buffer(buffer),
pred(pred),
polling(polling)
{
if (!polling)
outgoing_buffers.reset(
new outgoing_buffers_t(num_processes(process_group)));
setup_triggers();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
BOOST_DISTRIBUTED_QUEUE_TYPE::
distributed_queue(const ProcessGroup& process_group, const OwnerMap& owner,
const UnaryPredicate& pred, bool polling)
: process_group(process_group, attach_distributed_object()),
owner(owner),
pred(pred),
polling(polling)
{
if (!polling)
outgoing_buffers.reset(
new outgoing_buffers_t(num_processes(process_group)));
setup_triggers();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
void
BOOST_DISTRIBUTED_QUEUE_TYPE::push(const value_type& x)
{
typename ProcessGroup::process_id_type dest = get(owner, x);
if (outgoing_buffers)
outgoing_buffers->at(dest).push_back(x);
else if (dest == process_id(process_group))
buffer.push(x);
else
send(process_group, get(owner, x), msg_push, x);
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
bool
BOOST_DISTRIBUTED_QUEUE_TYPE::empty() const
{
/* Processes will stay here until the buffer is nonempty or
synchronization with the other processes indicates that all local
buffers are empty (and no messages are in transit).
*/
while (buffer.empty() && !do_synchronize()) ;
return buffer.empty();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
typename BOOST_DISTRIBUTED_QUEUE_TYPE::size_type
BOOST_DISTRIBUTED_QUEUE_TYPE::size() const
{
empty();
return buffer.size();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
void BOOST_DISTRIBUTED_QUEUE_TYPE::setup_triggers()
{
using boost::graph::parallel::simple_trigger;
simple_trigger(process_group, msg_push, this,
&distributed_queue::handle_push);
simple_trigger(process_group, msg_multipush, this,
&distributed_queue::handle_multipush);
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
void
BOOST_DISTRIBUTED_QUEUE_TYPE::
handle_push(int /*source*/, int /*tag*/, const value_type& value,
trigger_receive_context)
{
if (pred(value)) buffer.push(value);
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
void
BOOST_DISTRIBUTED_QUEUE_TYPE::
handle_multipush(int /*source*/, int /*tag*/,
const std::vector<value_type>& values,
trigger_receive_context)
{
for (std::size_t i = 0; i < values.size(); ++i)
if (pred(values[i])) buffer.push(values[i]);
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
bool
BOOST_DISTRIBUTED_QUEUE_TYPE::do_synchronize() const
{
#ifdef PBGL_ACCOUNTING
++num_synchronizations;
#endif
using boost::parallel::all_reduce;
using std::swap;
typedef typename ProcessGroup::process_id_type process_id_type;
if (outgoing_buffers) {
// Transfer all of the push requests
process_id_type id = process_id(process_group);
process_id_type np = num_processes(process_group);
for (process_id_type dest = 0; dest < np; ++dest) {
outgoing_buffer_t& outgoing = outgoing_buffers->at(dest);
std::size_t size = outgoing.size();
if (size != 0) {
if (dest != id) {
send(process_group, dest, msg_multipush, outgoing);
} else {
for (std::size_t i = 0; i < size; ++i)
buffer.push(outgoing[i]);
}
outgoing.clear();
}
}
}
synchronize(process_group);
unsigned local_size = buffer.size();
unsigned global_size =
all_reduce(process_group, local_size, std::plus<unsigned>());
return global_size == 0;
}
} } } // end namespace boost::graph::distributed
+278
View File
@@ -0,0 +1,278 @@
// 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
#ifndef BOOST_GRAPH_DISTRIBUTED_QUEUE_HPP
#define BOOST_GRAPH_DISTRIBUTED_QUEUE_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/graph/parallel/process_group.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
namespace boost { namespace graph { namespace distributed {
/// A unary predicate that always returns "true".
struct always_push
{
template<typename T> bool operator()(const T&) const { return true; }
};
/** A distributed queue adaptor.
*
* Class template @c 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 @ref Buffer
* concept. Each process stores a distinct copy of the local queue,
* from which it draws or removes elements via the @ref pop and @ref
* top members.
*
* The value type of the local queue must be a model of the @ref
* GlobalDescriptor concept. The @ref 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 @ref empty and
* @ref 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 @ref
* 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 @ref push operation will place
* the value @c x onto its owner's queue. All processes will
* synchronize at the call to empty, and only the process owning @c x
* will be allowed to execute the loop (@ref 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 @ref empty, more processes
* may have nonempty local queues to execute. Once all local queues
* are empty, @ref Q.empty() returns @c false for all processes.
*
* The distributed queue can receive messages at two different times:
* during synchronization and when polling @ref empty. Messages are
* always received during synchronization, to ensure that accurate
* local queue sizes can be determines. However, whether @ref 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 @ref Buffer
* concept. However, the @ref push routine does not necessarily
* increase the result of @c size() by one (although the size of the
* global queue does increase by one).
*/
template<typename ProcessGroup, typename OwnerMap, typename Buffer,
typename UnaryPredicate = always_push>
class distributed_queue
{
typedef distributed_queue self_type;
enum {
/** Message indicating a remote push. The message contains a
* single value x of type value_type that is to be pushed on the
* receiver's queue.
*/
msg_push,
/** Push many elements at once. */
msg_multipush
};
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;
/** Construct a new distributed queue.
*
* Build a new distributed queue that communicates over the given @p
* process_group, whose local queue is initialized via @p buffer and
* which may or may not poll for messages.
*/
explicit
distributed_queue(const ProcessGroup& process_group,
const OwnerMap& owner,
const Buffer& buffer,
bool polling = false);
/** Construct a new distributed queue.
*
* Build a new distributed queue that communicates over the given @p
* process_group, whose local queue is initialized via @p buffer and
* which may or may not poll for messages.
*/
explicit
distributed_queue(const ProcessGroup& process_group = ProcessGroup(),
const OwnerMap& owner = OwnerMap(),
const Buffer& buffer = Buffer(),
const UnaryPredicate& pred = UnaryPredicate(),
bool polling = false);
/** Construct a new distributed queue.
*
* Build a new distributed queue that communicates over the given @p
* process_group, whose local queue is default-initalized and which
* may or may not poll for messages.
*/
distributed_queue(const ProcessGroup& process_group, const OwnerMap& owner,
const UnaryPredicate& pred, bool polling = false);
/** Virtual destructor required with virtual functions.
*
*/
virtual ~distributed_queue() {}
/** 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 push(const value_type& x);
/** Pop an element off the local queue.
*
* @p @c !empty()
*/
void pop() { buffer.pop(); }
/**
* Return the element at the top of the local queue.
*
* @p @c !empty()
*/
value_type& top() { return buffer.top(); }
/**
* \overload
*/
const value_type& top() const { return buffer.top(); }
/** Determine if the queue is empty.
*
* When the local queue is nonempty, returns @c 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 @c true) (2) the entire distributed queue is empty
* (returns @c false).
*/
bool empty() const;
/** Determine the size of the local queue.
*
* The behavior of this routine is equivalent to the behavior of
* @ref empty, except that when @ref empty returns true this
* function returns the size of the local queue and when @ref empty
* returns false this function returns zero.
*/
size_type size() const;
// private:
/** Synchronize the distributed queue and determine if all queues
* are empty.
*
* \returns \c true when all local queues are empty, or false if at least
* one of the local queues is nonempty.
* Defined as virtual for derived classes like depth_limited_distributed_queue.
*/
virtual bool do_synchronize() const;
private:
// Setup triggers
void setup_triggers();
// Message handlers
void
handle_push(int source, int tag, const value_type& value,
trigger_receive_context);
void
handle_multipush(int source, int tag, const std::vector<value_type>& values,
trigger_receive_context);
mutable ProcessGroup process_group;
OwnerMap owner;
mutable Buffer buffer;
UnaryPredicate pred;
bool polling;
typedef std::vector<value_type> outgoing_buffer_t;
typedef std::vector<outgoing_buffer_t> outgoing_buffers_t;
shared_ptr<outgoing_buffers_t> outgoing_buffers;
};
/// Helper macro containing the normal names for the template
/// parameters to distributed_queue.
#define BOOST_DISTRIBUTED_QUEUE_PARMS \
typename ProcessGroup, typename OwnerMap, typename Buffer, \
typename UnaryPredicate
/// Helper macro containing the normal template-id for
/// distributed_queue.
#define BOOST_DISTRIBUTED_QUEUE_TYPE \
distributed_queue<ProcessGroup, OwnerMap, Buffer, UnaryPredicate>
/** Synchronize all processes involved with the given distributed queue.
*
* This function will synchronize all of the local queues for a given
* distributed queue, by ensuring that no additional messages are in
* transit. It is rarely required by the user, because most
* synchronization of distributed queues occurs via the @c empty or @c
* size methods.
*/
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
inline void
synchronize(const BOOST_DISTRIBUTED_QUEUE_TYPE& Q)
{ Q.do_synchronize(); }
/// Construct a new distributed queue.
template<typename ProcessGroup, typename OwnerMap, typename Buffer>
inline distributed_queue<ProcessGroup, OwnerMap, Buffer>
make_distributed_queue(const ProcessGroup& process_group,
const OwnerMap& owner,
const Buffer& buffer,
bool polling = false)
{
typedef distributed_queue<ProcessGroup, OwnerMap, Buffer> result_type;
return result_type(process_group, owner, buffer, polling);
}
} } } // end namespace boost::graph::distributed
#include <boost/graph/distributed/detail/queue.ipp>
#undef BOOST_DISTRIBUTED_QUEUE_TYPE
#undef BOOST_DISTRIBUTED_QUEUE_PARMS
#endif // BOOST_GRAPH_DISTRIBUTED_QUEUE_HPP
@@ -0,0 +1,116 @@
// 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
// Jeremiah Willcock
// Andrew Lumsdaine
// Distributed version of the two-bit color map
#ifndef BOOST_DISTRIBUTED_TWO_BIT_COLOR_MAP_HPP
#define BOOST_DISTRIBUTED_TWO_BIT_COLOR_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/graph/two_bit_color_map.hpp>
#include <boost/property_map/parallel/distributed_property_map.hpp>
#include <boost/property_map/parallel/local_property_map.hpp>
namespace boost {
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
class two_bit_color_map<local_property_map<ProcessGroup,GlobalMap,StorageMap> >
: public parallel::distributed_property_map<ProcessGroup, GlobalMap,
two_bit_color_map<StorageMap> >
{
typedef two_bit_color_map<StorageMap> local_map;
typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
local_map >
inherited;
typedef local_property_map<ProcessGroup, GlobalMap, StorageMap>
index_map_type;
public:
two_bit_color_map(std::size_t inital_size,
const index_map_type& index = index_map_type())
: inherited(index.process_group(), index.global(),
local_map(inital_size, index.base())) { }
inherited& base() { return *this; }
const inherited& base() const { return *this; }
};
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline two_bit_color_type
get(two_bit_color_map<local_property_map<ProcessGroup,GlobalMap,StorageMap> >
const& pm,
typename property_traits<GlobalMap>::key_type key)
{
return get(pm.base(), key);
}
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline void
put(two_bit_color_map<local_property_map<ProcessGroup,GlobalMap,StorageMap> >
const& pm,
typename property_traits<GlobalMap>::key_type key,
two_bit_color_type value)
{
put(pm.base(), key, value);
}
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
class two_bit_color_map<parallel::distributed_property_map<
ProcessGroup, GlobalMap, StorageMap> >
: public parallel::distributed_property_map<
ProcessGroup, GlobalMap, two_bit_color_map<StorageMap> >
{
typedef two_bit_color_map<StorageMap> local_map;
typedef parallel::distributed_property_map<ProcessGroup,GlobalMap,local_map>
inherited;
typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
StorageMap>
index_map_type;
public:
two_bit_color_map(std::size_t inital_size,
const index_map_type& index = index_map_type())
: inherited(index.process_group(), index.global(),
local_map(inital_size, index.base())) { }
inherited& base() { return *this; }
const inherited& base() const { return *this; }
};
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline two_bit_color_type
get(two_bit_color_map<
parallel::distributed_property_map<
ProcessGroup, GlobalMap, two_bit_color_map<StorageMap> > > const& pm,
typename property_traits<GlobalMap>::key_type key)
{
return get(pm.base(), key);
}
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline void
put(two_bit_color_map<
parallel::distributed_property_map<
ProcessGroup, GlobalMap, two_bit_color_map<StorageMap> > > const& pm,
typename property_traits<GlobalMap>::key_type key,
two_bit_color_type value)
{
put(pm.base(), key, value);
}
} // end namespace boost
#endif // BOOST_DISTRIBUTED_TWO_BIT_COLOR_MAP_HPP
+620
View File
@@ -0,0 +1,620 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// Copyright 2009, Andrew Sutton
//
// 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)
//=======================================================================
//
#ifndef BOOST_GRAPH_CONCEPTS_HPP
#define BOOST_GRAPH_CONCEPTS_HPP
#include <boost/config.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/numeric_values.hpp>
#include <boost/graph/buffer_concepts.hpp>
#include <boost/concept_check.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/not.hpp>
#include <boost/static_assert.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/concept/assert.hpp>
#include <boost/concept/detail/concept_def.hpp>
namespace boost
{
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
//
// It is needed in order to allow us to write using boost::vertices as
// needed for ADL when using vector_as_graph below.
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) \
&& !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# define BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
#endif
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
template <class T>
typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
#endif
namespace concepts {
BOOST_concept(MultiPassInputIterator,(T)) {
BOOST_CONCEPT_USAGE(MultiPassInputIterator) {
BOOST_CONCEPT_ASSERT((InputIterator<T>));
}
};
BOOST_concept(Graph,(G))
{
typedef typename graph_traits<G>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::directed_category directed_category;
typedef typename graph_traits<G>::edge_parallel_category edge_parallel_category;
typedef typename graph_traits<G>::traversal_category traversal_category;
BOOST_CONCEPT_USAGE(Graph)
{
BOOST_CONCEPT_ASSERT((DefaultConstructible<vertex_descriptor>));
BOOST_CONCEPT_ASSERT((EqualityComparable<vertex_descriptor>));
BOOST_CONCEPT_ASSERT((Assignable<vertex_descriptor>));
}
G g;
};
BOOST_concept(IncidenceGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::out_edge_iterator out_edge_iterator;
typedef typename graph_traits<G>::degree_size_type degree_size_type;
typedef typename graph_traits<G>::traversal_category traversal_category;
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<out_edge_iterator, void> >::value));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<degree_size_type, void> >::value));
BOOST_CONCEPT_USAGE(IncidenceGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<out_edge_iterator>));
BOOST_CONCEPT_ASSERT((DefaultConstructible<edge_descriptor>));
BOOST_CONCEPT_ASSERT((EqualityComparable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Assignable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
incidence_graph_tag>));
p = out_edges(u, g);
n = out_degree(u, g);
e = *p.first;
u = source(e, g);
v = target(e, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = out_edges(u, cg);
n = out_degree(u, cg);
e = *p.first;
u = source(e, cg);
v = target(e, cg);
}
std::pair<out_edge_iterator, out_edge_iterator> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename graph_traits<G>::edge_descriptor e;
typename graph_traits<G>::degree_size_type n;
G g;
};
BOOST_concept(BidirectionalGraph,(G))
: IncidenceGraph<G>
{
typedef typename graph_traits<G>::in_edge_iterator
in_edge_iterator;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_CONCEPT_USAGE(BidirectionalGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<in_edge_iterator>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
bidirectional_graph_tag>));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<in_edge_iterator, void> >::value));
p = in_edges(v, g);
n = in_degree(v, g);
n = degree(v, g);
e = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
p = in_edges(v, cg);
n = in_degree(v, cg);
n = degree(v, cg);
e = *p.first;
}
std::pair<in_edge_iterator, in_edge_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
typename graph_traits<G>::edge_descriptor e;
typename graph_traits<G>::degree_size_type n;
G g;
};
BOOST_concept(AdjacencyGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::adjacency_iterator
adjacency_iterator;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_CONCEPT_USAGE(AdjacencyGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<adjacency_iterator>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
adjacency_graph_tag>));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<adjacency_iterator, void> >::value));
p = adjacent_vertices(v, g);
v = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
p = adjacent_vertices(v, cg);
}
std::pair<adjacency_iterator,adjacency_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
G g;
};
BOOST_concept(VertexListGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
typedef typename graph_traits<G>::vertices_size_type vertices_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_CONCEPT_USAGE(VertexListGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<vertex_iterator>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
vertex_list_graph_tag>));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<vertex_iterator, void> >::value));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<vertices_size_type, void> >::value));
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(g);
v = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(cg);
v = *p.first;
V = num_vertices(cg);
}
std::pair<vertex_iterator,vertex_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
G g;
vertices_size_type V;
};
BOOST_concept(EdgeListGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::edge_iterator edge_iterator;
typedef typename graph_traits<G>::edges_size_type edges_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_CONCEPT_USAGE(EdgeListGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<edge_iterator>));
BOOST_CONCEPT_ASSERT((DefaultConstructible<edge_descriptor>));
BOOST_CONCEPT_ASSERT((EqualityComparable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Assignable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
edge_list_graph_tag>));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<edge_iterator, void> >::value));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<edges_size_type, void> >::value));
p = edges(g);
e = *p.first;
u = source(e, g);
v = target(e, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = edges(cg);
E = num_edges(cg);
e = *p.first;
u = source(e, cg);
v = target(e, cg);
}
std::pair<edge_iterator,edge_iterator> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename graph_traits<G>::edge_descriptor e;
edges_size_type E;
G g;
};
BOOST_concept(VertexAndEdgeListGraph,(G))
: VertexListGraph<G>
, EdgeListGraph<G>
{
};
// Where to put the requirement for this constructor?
// G g(n_vertices);
// Not in mutable graph, then LEDA graph's can't be models of
// MutableGraph.
BOOST_concept(EdgeMutableGraph,(G))
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
BOOST_CONCEPT_USAGE(EdgeMutableGraph) {
p = add_edge(u, v, g);
remove_edge(u, v, g);
remove_edge(e, g);
clear_vertex(v, g);
}
G g;
edge_descriptor e;
std::pair<edge_descriptor, bool> p;
typename graph_traits<G>::vertex_descriptor u, v;
};
BOOST_concept(VertexMutableGraph,(G))
{
BOOST_CONCEPT_USAGE(VertexMutableGraph) {
v = add_vertex(g);
remove_vertex(v, g);
}
G g;
typename graph_traits<G>::vertex_descriptor u, v;
};
BOOST_concept(MutableGraph,(G))
: EdgeMutableGraph<G>
, VertexMutableGraph<G>
{
};
template <class edge_descriptor>
struct dummy_edge_predicate {
bool operator()(const edge_descriptor&) const {
return false;
}
};
BOOST_concept(MutableIncidenceGraph,(G))
: MutableGraph<G>
{
BOOST_CONCEPT_USAGE(MutableIncidenceGraph) {
remove_edge(iter, g);
remove_out_edge_if(u, p, g);
}
G g;
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
dummy_edge_predicate<edge_descriptor> p;
typename boost::graph_traits<G>::vertex_descriptor u;
typename boost::graph_traits<G>::out_edge_iterator iter;
};
BOOST_concept(MutableBidirectionalGraph,(G))
: MutableIncidenceGraph<G>
{
BOOST_CONCEPT_USAGE(MutableBidirectionalGraph)
{
remove_in_edge_if(u, p, g);
}
G g;
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
dummy_edge_predicate<edge_descriptor> p;
typename boost::graph_traits<G>::vertex_descriptor u;
};
BOOST_concept(MutableEdgeListGraph,(G))
: EdgeMutableGraph<G>
{
BOOST_CONCEPT_USAGE(MutableEdgeListGraph) {
remove_edge_if(p, g);
}
G g;
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
dummy_edge_predicate<edge_descriptor> p;
};
BOOST_concept(VertexMutablePropertyGraph,(G))
: VertexMutableGraph<G>
{
BOOST_CONCEPT_USAGE(VertexMutablePropertyGraph) {
v = add_vertex(vp, g);
}
G g;
typename graph_traits<G>::vertex_descriptor v;
typename vertex_property_type<G>::type vp;
};
BOOST_concept(EdgeMutablePropertyGraph,(G))
: EdgeMutableGraph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
BOOST_CONCEPT_USAGE(EdgeMutablePropertyGraph) {
p = add_edge(u, v, ep, g);
}
G g;
std::pair<edge_descriptor, bool> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename edge_property_type<G>::type ep;
};
BOOST_concept(AdjacencyMatrix,(G))
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
BOOST_CONCEPT_USAGE(AdjacencyMatrix) {
p = edge(u, v, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = edge(u, v, cg);
}
typename graph_traits<G>::vertex_descriptor u, v;
std::pair<edge_descriptor, bool> p;
G g;
};
BOOST_concept(ReadablePropertyGraph,(G)(X)(Property))
: Graph<G>
{
typedef typename property_map<G, Property>::const_type const_Map;
BOOST_CONCEPT_USAGE(ReadablePropertyGraph)
{
BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept<const_Map, X>));
const_constraints(g);
}
void const_constraints(const G& cg) {
const_Map pmap = get(Property(), cg);
pval = get(Property(), cg, x);
ignore_unused_variable_warning(pmap);
}
G g;
X x;
typename property_traits<const_Map>::value_type pval;
};
BOOST_concept(PropertyGraph,(G)(X)(Property))
: ReadablePropertyGraph<G, X, Property>
{
typedef typename property_map<G, Property>::type Map;
BOOST_CONCEPT_USAGE(PropertyGraph) {
BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept<Map, X>));
Map pmap = get(Property(), g);
pval = get(Property(), g, x);
put(Property(), g, x, pval);
ignore_unused_variable_warning(pmap);
}
G g;
X x;
typename property_traits<Map>::value_type pval;
};
BOOST_concept(LvaluePropertyGraph,(G)(X)(Property))
: ReadablePropertyGraph<G, X, Property>
{
typedef typename property_map<G, Property>::type Map;
typedef typename property_map<G, Property>::const_type const_Map;
BOOST_CONCEPT_USAGE(LvaluePropertyGraph) {
BOOST_CONCEPT_ASSERT((LvaluePropertyMapConcept<const_Map, X>));
pval = get(Property(), g, x);
put(Property(), g, x, pval);
}
G g;
X x;
typename property_traits<Map>::value_type pval;
};
// The *IndexGraph concepts are "semantic" graph concpepts. These can be
// applied to describe any graph that has an index map that can be accessed
// using the get(*_index, g) method. For example, adjacency lists with
// VertexSet == vecS are implicitly models of this concept.
//
// NOTE: We could require an associated type vertex_index_type, but that
// would mean propagating that type name into graph_traits and all of the
// other graph implementations. Much easier to simply call it unsigned.
BOOST_concept(VertexIndexGraph,(Graph))
{
BOOST_CONCEPT_USAGE(VertexIndexGraph)
{
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
typedef typename property_map<Graph, vertex_index_t>::type Map;
typedef unsigned Index; // This could be Graph::vertex_index_type
Map m = get(vertex_index, g);
Index x = get(vertex_index, g, Vertex());
ignore_unused_variable_warning(m);
ignore_unused_variable_warning(x);
// This is relaxed
renumber_vertex_indices(g);
const_constraints(g);
}
void const_constraints(const Graph& g_)
{
typedef typename property_map<Graph, vertex_index_t>::const_type Map;
Map m = get(vertex_index, g_);
ignore_unused_variable_warning(m);
}
private:
Graph g;
};
BOOST_concept(EdgeIndexGraph,(Graph))
{
BOOST_CONCEPT_USAGE(EdgeIndexGraph)
{
typedef typename graph_traits<Graph>::edge_descriptor Edge;
typedef typename property_map<Graph, edge_index_t>::type Map;
typedef unsigned Index; // This could be Graph::vertex_index_type
Map m = get(edge_index, g);
Index x = get(edge_index, g, Edge());
ignore_unused_variable_warning(m);
ignore_unused_variable_warning(x);
// This is relaxed
renumber_edge_indices(g);
const_constraints(g);
}
void const_constraints(const Graph& g_)
{
typedef typename property_map<Graph, edge_index_t>::const_type Map;
Map m = get(edge_index, g_);
ignore_unused_variable_warning(m);
}
private:
Graph g;
};
BOOST_concept(ColorValue,(C))
: EqualityComparable<C>
, DefaultConstructible<C>
{
BOOST_CONCEPT_USAGE(ColorValue) {
c = color_traits<C>::white();
c = color_traits<C>::gray();
c = color_traits<C>::black();
}
C c;
};
BOOST_concept(BasicMatrix,(M)(I)(V))
{
BOOST_CONCEPT_USAGE(BasicMatrix) {
V& elt = A[i][j];
const_constraints(A);
ignore_unused_variable_warning(elt);
}
void const_constraints(const M& cA) {
const V& elt = cA[i][j];
ignore_unused_variable_warning(elt);
}
M A;
I i, j;
};
// The following concepts describe aspects of numberic values and measure
// functions. We're extending the notion of numeric values to include
// emulation for zero and infinity.
BOOST_concept(NumericValue,(Numeric))
{
BOOST_CONCEPT_USAGE(NumericValue)
{
BOOST_CONCEPT_ASSERT(( DefaultConstructible<Numeric> ));
BOOST_CONCEPT_ASSERT(( CopyConstructible<Numeric> ));
numeric_values<Numeric>::zero();
numeric_values<Numeric>::infinity();
}
};
BOOST_concept(DegreeMeasure,(Measure)(Graph))
{
BOOST_CONCEPT_USAGE(DegreeMeasure)
{
typedef typename Measure::degree_type Degree;
typedef typename Measure::vertex_type Vertex;
Degree d = m(Vertex(), g);
ignore_unused_variable_warning(d);
}
private:
Measure m;
Graph g;
};
BOOST_concept(DistanceMeasure,(Measure)(Graph))
{
BOOST_CONCEPT_USAGE(DistanceMeasure)
{
typedef typename Measure::distance_type Distance;
typedef typename Measure::result_type Result;
Result r = m(Distance(), g);
ignore_unused_variable_warning(r);
}
private:
Measure m;
Graph g;
};
} /* namespace concepts */
using boost::concepts::MultiPassInputIteratorConcept;
// Graph concepts
using boost::concepts::GraphConcept;
using boost::concepts::IncidenceGraphConcept;
using boost::concepts::BidirectionalGraphConcept;
using boost::concepts::AdjacencyGraphConcept;
using boost::concepts::VertexListGraphConcept;
using boost::concepts::EdgeListGraphConcept;
using boost::concepts::VertexAndEdgeListGraphConcept;
using boost::concepts::EdgeMutableGraphConcept;
using boost::concepts::VertexMutableGraphConcept;
using boost::concepts::MutableGraphConcept;
using boost::concepts::MutableIncidenceGraphConcept;
using boost::concepts::MutableBidirectionalGraphConcept;
using boost::concepts::MutableEdgeListGraphConcept;
using boost::concepts::VertexMutablePropertyGraphConcept;
using boost::concepts::EdgeMutablePropertyGraphConcept;
using boost::concepts::AdjacencyMatrixConcept;
using boost::concepts::ReadablePropertyGraphConcept;
using boost::concepts::PropertyGraphConcept;
using boost::concepts::LvaluePropertyGraphConcept;
using boost::concepts::VertexIndexGraphConcept;
using boost::concepts::EdgeIndexGraphConcept;
// Utility concepts
using boost::concepts::ColorValueConcept;
using boost::concepts::BasicMatrixConcept;
using boost::concepts::NumericValueConcept;
using boost::concepts::DistanceMeasureConcept;
using boost::concepts::DegreeMeasureConcept;
} /* namespace boost */
#include <boost/concept/detail/concept_undef.hpp>
#endif /* BOOST_GRAPH_CONCEPTS_H */
+204
View File
@@ -0,0 +1,204 @@
// Copyright (C) 2009 Andrew Sutton
//
// 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)
#ifndef BOOST_GRAPH_MUTABILITY_TRAITS_HPP
#define BOOST_GRAPH_MUTABILITY_TRAITS_HPP
#include <boost/config.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost {
// The mutabiltiy categories classify graphs by their mutating operations
// on the edge and vertex sets. This is a substantially more refined
// categorization than the MutableGraph and MutablePropertyGraph denote.
// Currently, this framework is only used in the graph tests to help
// dispatch test to the correct places. However, there are probably some
// constructive or destructive algorithms (i.e., graph generators) that
// may use these to describe requirements on graph inputs.
struct add_vertex_tag { };
struct add_vertex_property_tag : virtual add_vertex_tag { };
struct add_edge_tag { };
struct add_edge_property_tag : virtual add_edge_tag { };
struct remove_vertex_tag { };
struct remove_edge_tag { };
struct mutable_vertex_graph_tag
: virtual add_vertex_tag, virtual remove_vertex_tag
{ };
struct mutable_vertex_property_graph_tag
: virtual add_vertex_property_tag, virtual remove_vertex_tag
{ };
struct mutable_edge_graph_tag
: virtual add_edge_tag, virtual remove_edge_tag
{ };
struct mutable_edge_property_graph_tag
: virtual add_edge_property_tag, virtual remove_edge_tag
{ };
struct mutable_graph_tag
: virtual mutable_vertex_graph_tag
, virtual mutable_edge_graph_tag
{ };
struct mutable_property_graph_tag
: virtual mutable_vertex_property_graph_tag
, virtual mutable_edge_property_graph_tag
{ };
// Some graphs just don't like to be torn down. Note this only restricts
// teardown to the set of vertices, not the vertex set.
// TODO: Find a better name for this tag.
struct add_only_property_graph_tag
: virtual add_vertex_property_tag
, virtual mutable_edge_property_graph_tag
{ };
/**
* The graph_mutability_traits provide methods for determining the
* interfaces supported by graph classes for adding and removing vertices
* and edges.
*/
template <typename Graph>
struct graph_mutability_traits {
typedef typename Graph::mutability_category category;
};
template <typename Graph>
struct graph_has_add_vertex
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
add_vertex_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_add_vertex_with_property
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
add_vertex_property_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_remove_vertex
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
remove_vertex_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_add_edge
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
add_edge_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_add_edge_with_property
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
add_edge_property_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_remove_edge
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
remove_edge_tag
>::value
>
{ };
template <typename Graph>
struct is_mutable_vertex_graph
: mpl::and_<
graph_has_add_vertex<Graph>,
graph_has_remove_vertex<Graph>
>
{ };
template <typename Graph>
struct is_mutable_vertex_property_graph
: mpl::and_<
graph_has_add_vertex_with_property<Graph>,
graph_has_remove_vertex<Graph>
>
{ };
template <typename Graph>
struct is_mutable_edge_graph
: mpl::and_<
graph_has_add_edge<Graph>,
graph_has_remove_edge<Graph>
>
{ };
template <typename Graph>
struct is_mutable_edge_property_graph
: mpl::and_<
graph_has_add_edge_with_property<Graph>,
graph_has_remove_edge<Graph>
>
{ };
template <typename Graph>
struct is_mutable_graph
: mpl::and_<
is_mutable_vertex_graph<Graph>,
is_mutable_edge_graph<Graph>
>
{ };
template <typename Graph>
struct is_mutable_property_graph
: mpl::and_<
is_mutable_vertex_property_graph<Graph>,
is_mutable_edge_property_graph<Graph>
>
{ };
template <typename Graph>
struct is_add_only_property_graph
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
add_only_property_graph_tag
>::value
>
{ };
/** @name Mutability Traits Specializations */
//@{
//@}
} // namespace boost
#endif
+38
View File
@@ -0,0 +1,38 @@
//=======================================================================
// Copyright 2002 Indiana University.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
#ifndef BOOST_GRAPH_SELECTORS_HPP
#define BOOST_GRAPH_SELECTORS_HPP
#include <boost/mpl/bool.hpp>
namespace boost {
//===========================================================================
// Selectors for the Directed template parameter of adjacency_list
// and adjacency_matrix.
struct directedS { enum { is_directed = true, is_bidir = false };
typedef mpl::true_ is_directed_t;
typedef mpl::false_ is_bidir_t;
};
struct undirectedS {
enum { is_directed = false, is_bidir = false };
typedef mpl::false_ is_directed_t;
typedef mpl::false_ is_bidir_t;
};
struct bidirectionalS {
enum { is_directed = true, is_bidir = true };
typedef mpl::true_ is_directed_t;
typedef mpl::true_ is_bidir_t;
};
} // namespace boost
#endif // BOOST_GRAPH_SELECTORS_HPP
+404
View File
@@ -0,0 +1,404 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
#ifndef BOOST_GRAPH_TRAITS_HPP
#define BOOST_GRAPH_TRAITS_HPP
#include <boost/config.hpp>
#include <iterator>
#include <utility> /* Primarily for std::pair */
#include <boost/tuple/tuple.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/pending/property.hpp>
#include <boost/detail/workaround.hpp>
namespace boost {
namespace detail {
#define BOOST_GRAPH_MEMBER_OR_VOID(name) \
BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \
template <typename T> struct BOOST_JOIN(get_member_, name) {typedef typename T::name type;}; \
template <typename T> struct BOOST_JOIN(get_opt_member_, name): \
boost::mpl::eval_if_c< \
BOOST_JOIN(has_, name)<T>::value, \
BOOST_JOIN(get_member_, name)<T>, \
boost::mpl::identity<void> > \
{};
BOOST_GRAPH_MEMBER_OR_VOID(adjacency_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(out_edge_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(in_edge_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(vertex_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(edge_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(vertices_size_type)
BOOST_GRAPH_MEMBER_OR_VOID(edges_size_type)
BOOST_GRAPH_MEMBER_OR_VOID(degree_size_type)
}
template <typename G>
struct graph_traits {
#define BOOST_GRAPH_PULL_OPT_MEMBER(name) \
typedef typename detail::BOOST_JOIN(get_opt_member_, name)<G>::type name;
typedef typename G::vertex_descriptor vertex_descriptor;
typedef typename G::edge_descriptor edge_descriptor;
BOOST_GRAPH_PULL_OPT_MEMBER(adjacency_iterator)
BOOST_GRAPH_PULL_OPT_MEMBER(out_edge_iterator)
BOOST_GRAPH_PULL_OPT_MEMBER(in_edge_iterator)
BOOST_GRAPH_PULL_OPT_MEMBER(vertex_iterator)
BOOST_GRAPH_PULL_OPT_MEMBER(edge_iterator)
typedef typename G::directed_category directed_category;
typedef typename G::edge_parallel_category edge_parallel_category;
typedef typename G::traversal_category traversal_category;
BOOST_GRAPH_PULL_OPT_MEMBER(vertices_size_type)
BOOST_GRAPH_PULL_OPT_MEMBER(edges_size_type)
BOOST_GRAPH_PULL_OPT_MEMBER(degree_size_type)
#undef BOOST_GRAPH_PULL_OPT_MEMBER
static inline vertex_descriptor null_vertex();
};
template <typename G>
inline typename graph_traits<G>::vertex_descriptor
graph_traits<G>::null_vertex()
{ return G::null_vertex(); }
// directed_category tags
struct directed_tag { };
struct undirected_tag { };
struct bidirectional_tag : public directed_tag { };
namespace detail {
inline bool is_directed(directed_tag) { return true; }
inline bool is_directed(undirected_tag) { return false; }
}
/** Return true if the given graph is directed. */
template <typename Graph>
bool is_directed(const Graph&) {
typedef typename graph_traits<Graph>::directed_category Cat;
return detail::is_directed(Cat());
}
/** Return true if the given graph is undirected. */
template <typename Graph>
bool is_undirected(const Graph& g) {
return !is_directed(g);
}
/** @name Directed/Undirected Graph Traits */
//@{
namespace graph_detail {
template <typename Tag>
struct is_directed_tag
: mpl::bool_<is_convertible<Tag, directed_tag>::value>
{ };
} // namespace graph_detail
template <typename Graph>
struct is_directed_graph
: graph_detail::is_directed_tag<
typename graph_traits<Graph>::directed_category
>
{ };
template <typename Graph>
struct is_undirected_graph
: mpl::not_< is_directed_graph<Graph> >
{ };
//@}
// edge_parallel_category tags
struct allow_parallel_edge_tag { };
struct disallow_parallel_edge_tag { };
namespace detail {
inline bool allows_parallel(allow_parallel_edge_tag) { return true; }
inline bool allows_parallel(disallow_parallel_edge_tag) { return false; }
}
template <typename Graph>
bool allows_parallel_edges(const Graph&) {
typedef typename graph_traits<Graph>::edge_parallel_category Cat;
return detail::allows_parallel(Cat());
}
/** @name Parallel Edges Traits */
//@{
/**
* The is_multigraph metafunction returns true if the graph allows
* parallel edges. Technically, a multigraph is a simple graph that
* allows parallel edges, but since there are no traits for the allowance
* or disallowance of loops, this is a moot point.
*/
template <typename Graph>
struct is_multigraph
: mpl::bool_<
is_same<
typename graph_traits<Graph>::edge_parallel_category,
allow_parallel_edge_tag
>::value
>
{ };
//@}
// traversal_category tags
struct incidence_graph_tag { };
struct adjacency_graph_tag { };
struct bidirectional_graph_tag : virtual incidence_graph_tag { };
struct vertex_list_graph_tag { };
struct edge_list_graph_tag { };
struct adjacency_matrix_tag { };
// Parallel traversal_category tags
struct distributed_graph_tag { };
struct distributed_vertex_list_graph_tag { };
struct distributed_edge_list_graph_tag { };
#define BOOST_GRAPH_SEQUENTIAL_TRAITS_DEFINES_DISTRIBUTED_TAGS // Disable these from external versions of PBGL
/** @name Traversal Category Traits
* These traits classify graph types by their supported methods of
* vertex and edge traversal.
*/
//@{
template <typename Graph>
struct is_incidence_graph
: mpl::bool_<
is_convertible<
typename graph_traits<Graph>::traversal_category,
incidence_graph_tag
>::value
>
{ };
template <typename Graph>
struct is_bidirectional_graph
: mpl::bool_<
is_convertible<
typename graph_traits<Graph>::traversal_category,
bidirectional_graph_tag
>::value
>
{ };
template <typename Graph>
struct is_vertex_list_graph
: mpl::bool_<
is_convertible<
typename graph_traits<Graph>::traversal_category,
vertex_list_graph_tag
>::value
>
{ };
template <typename Graph>
struct is_edge_list_graph
: mpl::bool_<
is_convertible<
typename graph_traits<Graph>::traversal_category,
edge_list_graph_tag
>::value
>
{ };
template <typename Graph>
struct is_adjacency_matrix
: mpl::bool_<
is_convertible<
typename graph_traits<Graph>::traversal_category,
adjacency_matrix_tag
>::value
>
{ };
//@}
/** @name Directed Graph Traits
* These metafunctions are used to fully classify directed vs. undirected
* graphs. Recall that an undirected graph is also bidirectional, but it
* cannot be both undirected and directed at the same time.
*/
//@{
template <typename Graph>
struct is_directed_unidirectional_graph
: mpl::and_<
is_directed_graph<Graph>, mpl::not_< is_bidirectional_graph<Graph> >
>
{ };
template <typename Graph>
struct is_directed_bidirectional_graph
: mpl::and_<
is_directed_graph<Graph>, is_bidirectional_graph<Graph>
>
{ };
//@}
//?? not the right place ?? Lee
typedef boost::forward_traversal_tag multi_pass_input_iterator_tag;
namespace detail {
BOOST_MPL_HAS_XXX_TRAIT_DEF(graph_property_type)
BOOST_MPL_HAS_XXX_TRAIT_DEF(edge_property_type)
BOOST_MPL_HAS_XXX_TRAIT_DEF(vertex_property_type)
template <typename G> struct get_graph_property_type {typedef typename G::graph_property_type type;};
template <typename G> struct get_edge_property_type {typedef typename G::edge_property_type type;};
template <typename G> struct get_vertex_property_type {typedef typename G::vertex_property_type type;};
}
template <typename G>
struct graph_property_type
: boost::mpl::eval_if<detail::has_graph_property_type<G>,
detail::get_graph_property_type<G>,
no_property> {};
template <typename G>
struct edge_property_type
: boost::mpl::eval_if<detail::has_edge_property_type<G>,
detail::get_edge_property_type<G>,
no_property> {};
template <typename G>
struct vertex_property_type
: boost::mpl::eval_if<detail::has_vertex_property_type<G>,
detail::get_vertex_property_type<G>,
no_property> {};
template<typename G>
struct graph_bundle_type {
typedef typename G::graph_bundled type;
};
template<typename G>
struct vertex_bundle_type {
typedef typename G::vertex_bundled type;
};
template<typename G>
struct edge_bundle_type {
typedef typename G::edge_bundled type;
};
namespace graph { namespace detail {
template<typename Graph, typename Descriptor>
class bundled_result {
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
typedef typename mpl::if_c<(is_same<Descriptor, Vertex>::value),
vertex_bundle_type<Graph>,
edge_bundle_type<Graph> >::type bundler;
public:
typedef typename bundler::type type;
};
template<typename Graph>
class bundled_result<Graph, graph_bundle_t> {
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_bundle_type<Graph> bundler;
public:
typedef typename bundler::type type;
};
} } // namespace graph::detail
namespace graph_detail {
// A helper metafunction for determining whether or not a type is
// bundled.
template <typename T>
struct is_no_bundle : mpl::bool_<is_same<T, no_property>::value>
{ };
} // namespace graph_detail
/** @name Graph Property Traits
* These metafunctions (along with those above), can be used to access the
* vertex and edge properties (bundled or otherwise) of vertices and
* edges.
*/
//@{
template<typename Graph>
struct has_graph_property
: mpl::not_<
typename detail::is_no_property<
typename graph_property_type<Graph>::type
>::type
>::type
{ };
template<typename Graph>
struct has_bundled_graph_property
: mpl::not_<
graph_detail::is_no_bundle<typename graph_bundle_type<Graph>::type>
>
{ };
template <typename Graph>
struct has_vertex_property
: mpl::not_<
typename detail::is_no_property<typename vertex_property_type<Graph>::type>
>::type
{ };
template <typename Graph>
struct has_bundled_vertex_property
: mpl::not_<
graph_detail::is_no_bundle<typename vertex_bundle_type<Graph>::type>
>
{ };
template <typename Graph>
struct has_edge_property
: mpl::not_<
typename detail::is_no_property<typename edge_property_type<Graph>::type>
>::type
{ };
template <typename Graph>
struct has_bundled_edge_property
: mpl::not_<
graph_detail::is_no_bundle<typename edge_bundle_type<Graph>::type>
>
{ };
//@}
} // namespace boost
// Since pair is in namespace std, Koenig lookup will find source and
// target if they are also defined in namespace std. This is illegal,
// but the alternative is to put source and target in the global
// namespace which causes name conflicts with other libraries (like
// SUIF).
namespace std {
/* Some helper functions for dealing with pairs as edges */
template <class T, class G>
T source(pair<T,T> p, const G&) { return p.first; }
template <class T, class G>
T target(pair<T,T> p, const G&) { return p.second; }
}
#if defined(__GNUC__) && defined(__SGI_STL_PORT)
// For some reason g++ with STLport does not see the above definition
// of source() and target() unless we bring them into the boost
// namespace.
namespace boost {
using std::source;
using std::target;
}
#endif
#endif // BOOST_GRAPH_TRAITS_HPP
+140
View File
@@ -0,0 +1,140 @@
//=======================================================================
// Copyright 2001 Indiana University
// Author: Jeremy G. Siek
//
// 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)
//=======================================================================
#ifndef BOOST_GRAPH_ITERATION_MACROS_HPP
#define BOOST_GRAPH_ITERATION_MACROS_HPP
#include <utility>
#define BGL_CAT(x,y) x ## y
#define BGL_RANGE(linenum) BGL_CAT(bgl_range_,linenum)
#define BGL_FIRST(linenum) (BGL_RANGE(linenum).first)
#define BGL_LAST(linenum) (BGL_RANGE(linenum).second)
/*
BGL_FORALL_VERTICES_T(v, g, graph_t) // This is on line 9
expands to the following, but all on the same line
for (typename boost::graph_traits<graph_t>::vertex_iterator
bgl_first_9 = vertices(g).first, bgl_last_9 = vertices(g).second;
bgl_first_9 != bgl_last_9; bgl_first_9 = bgl_last_9)
for (typename boost::graph_traits<graph_t>::vertex_descriptor v;
bgl_first_9 != bgl_last_9 ? (v = *bgl_first_9, true) : false;
++bgl_first_9)
The purpose of having two for-loops is just to provide a place to
declare both the iterator and value variables. There is really only
one loop. The stopping condition gets executed two more times than it
usually would be, oh well. The reason for the bgl_first_9 = bgl_last_9
in the outer for-loop is in case the user puts a break statement
in the inner for-loop.
The other macros work in a similar fashion.
Use the _T versions when the graph type is a template parameter or
dependent on a template parameter. Otherwise use the non _T versions.
-----------------------
6/9/09 THK
The above contains two calls to the vertices function. I modified these
macros to expand to
for (std::pair<typename boost::graph_traits<graph_t>::vertex_iterator,
typename boost::graph_traits<graph_t>::vertex_iterator> bgl_range_9 = vertices(g);
bgl_range_9.first != bgl_range_9.second;
bgl_range_9.first = bgl_range_9.second)
for (typename boost::graph_traits<graph_t>::vertex_descriptor v;
bgl_range_9.first != bgl_range_9.second ? (v = *bgl_range_9.first, true) : false;
++bgl_range_9.first)
*/
#define BGL_FORALL_VERTICES_T(VNAME, GNAME, GraphType) \
for (std::pair<typename boost::graph_traits<GraphType>::vertex_iterator, \
typename boost::graph_traits<GraphType>::vertex_iterator> BGL_RANGE(__LINE__) = vertices(GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (typename boost::graph_traits<GraphType>::vertex_descriptor VNAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (VNAME = *BGL_FIRST(__LINE__), true):false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_VERTICES(VNAME, GNAME, GraphType) \
for (std::pair<boost::graph_traits<GraphType>::vertex_iterator, \
boost::graph_traits<GraphType>::vertex_iterator> BGL_RANGE(__LINE__) = vertices(GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (boost::graph_traits<GraphType>::vertex_descriptor VNAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (VNAME = *BGL_FIRST(__LINE__), true):false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_EDGES_T(ENAME, GNAME, GraphType) \
for (std::pair<typename boost::graph_traits<GraphType>::edge_iterator, \
typename boost::graph_traits<GraphType>::edge_iterator> BGL_RANGE(__LINE__) = edges(GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (typename boost::graph_traits<GraphType>::edge_descriptor ENAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true):false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_EDGES(ENAME, GNAME, GraphType) \
for (std::pair<boost::graph_traits<GraphType>::edge_iterator, \
boost::graph_traits<GraphType>::edge_iterator> BGL_RANGE(__LINE__) = edges(GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (boost::graph_traits<GraphType>::edge_descriptor ENAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true):false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_ADJ_T(UNAME, VNAME, GNAME, GraphType) \
for (std::pair<typename boost::graph_traits<GraphType>::adjacency_iterator, \
typename boost::graph_traits<GraphType>::adjacency_iterator> BGL_RANGE(__LINE__) = adjacent_vertices(UNAME, GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (typename boost::graph_traits<GraphType>::vertex_descriptor VNAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (VNAME = *BGL_FIRST(__LINE__), true) : false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_ADJ(UNAME, VNAME, GNAME, GraphType) \
for (std::pair<boost::graph_traits<GraphType>::adjacency_iterator, \
boost::graph_traits<GraphType>::adjacency_iterator> BGL_RANGE(__LINE__) = adjacent_vertices(UNAME, GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (boost::graph_traits<GraphType>::vertex_descriptor VNAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (VNAME = *BGL_FIRST(__LINE__), true) : false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_OUTEDGES_T(UNAME, ENAME, GNAME, GraphType) \
for (std::pair<typename boost::graph_traits<GraphType>::out_edge_iterator, \
typename boost::graph_traits<GraphType>::out_edge_iterator> BGL_RANGE(__LINE__) = out_edges(UNAME, GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (typename boost::graph_traits<GraphType>::edge_descriptor ENAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true) : false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_OUTEDGES(UNAME, ENAME, GNAME, GraphType) \
for (std::pair<boost::graph_traits<GraphType>::out_edge_iterator, \
boost::graph_traits<GraphType>::out_edge_iterator> BGL_RANGE(__LINE__) = out_edges(UNAME, GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (boost::graph_traits<GraphType>::edge_descriptor ENAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true) : false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_INEDGES_T(UNAME, ENAME, GNAME, GraphType) \
for (std::pair<typename boost::graph_traits<GraphType>::in_edge_iterator, \
typename boost::graph_traits<GraphType>::in_edge_iterator> BGL_RANGE(__LINE__) = in_edges(UNAME, GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (typename boost::graph_traits<GraphType>::edge_descriptor ENAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true) : false; \
++BGL_FIRST(__LINE__))
#define BGL_FORALL_INEDGES(UNAME, ENAME, GNAME, GraphType) \
for (std::pair<boost::graph_traits<GraphType>::in_edge_iterator, \
boost::graph_traits<GraphType>::in_edge_iterator> BGL_RANGE(__LINE__) = in_edges(UNAME, GNAME); \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \
for (boost::graph_traits<GraphType>::edge_descriptor ENAME; \
BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true) : false; \
++BGL_FIRST(__LINE__))
#endif // BOOST_GRAPH_ITERATION_MACROS_HPP
+746
View File
@@ -0,0 +1,746 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
#ifndef BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP
#define BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP
#include <functional>
#include <vector>
#include <boost/limits.hpp>
#include <boost/ref.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/preprocessor.hpp>
#include <boost/parameter/name.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/not.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/detail/d_ary_heap.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/property_map/shared_array_property_map.hpp>
namespace boost {
struct parity_map_t { };
struct vertex_assignment_map_t { };
struct distance_compare_t { };
struct distance_combine_t { };
struct distance_inf_t { };
struct distance_zero_t { };
struct buffer_param_t { };
struct edge_copy_t { };
struct vertex_copy_t { };
struct vertex_isomorphism_t { };
struct vertex_invariant_t { };
struct vertex_invariant1_t { };
struct vertex_invariant2_t { };
struct edge_compare_t { };
struct vertex_max_invariant_t { };
struct orig_to_copy_t { };
struct root_vertex_t { };
struct polling_t { };
struct lookahead_t { };
struct in_parallel_t { };
struct attractive_force_t { };
struct repulsive_force_t { };
struct force_pairs_t { };
struct cooling_t { };
struct vertex_displacement_t { };
struct iterations_t { };
struct diameter_range_t { };
struct learning_constant_range_t { };
struct vertices_equivalent_t { };
struct edges_equivalent_t { };
struct index_in_heap_map_t { };
struct max_priority_queue_t { };
#define BOOST_BGL_DECLARE_NAMED_PARAMS \
BOOST_BGL_ONE_PARAM_CREF(weight_map, edge_weight) \
BOOST_BGL_ONE_PARAM_CREF(weight_map2, edge_weight2) \
BOOST_BGL_ONE_PARAM_CREF(distance_map, vertex_distance) \
BOOST_BGL_ONE_PARAM_CREF(distance_map2, vertex_distance2) \
BOOST_BGL_ONE_PARAM_CREF(predecessor_map, vertex_predecessor) \
BOOST_BGL_ONE_PARAM_CREF(rank_map, vertex_rank) \
BOOST_BGL_ONE_PARAM_CREF(root_map, vertex_root) \
BOOST_BGL_ONE_PARAM_CREF(root_vertex, root_vertex) \
BOOST_BGL_ONE_PARAM_CREF(edge_centrality_map, edge_centrality) \
BOOST_BGL_ONE_PARAM_CREF(centrality_map, vertex_centrality) \
BOOST_BGL_ONE_PARAM_CREF(parity_map, parity_map) \
BOOST_BGL_ONE_PARAM_CREF(color_map, vertex_color) \
BOOST_BGL_ONE_PARAM_CREF(edge_color_map, edge_color) \
BOOST_BGL_ONE_PARAM_CREF(capacity_map, edge_capacity) \
BOOST_BGL_ONE_PARAM_CREF(residual_capacity_map, edge_residual_capacity) \
BOOST_BGL_ONE_PARAM_CREF(reverse_edge_map, edge_reverse) \
BOOST_BGL_ONE_PARAM_CREF(discover_time_map, vertex_discover_time) \
BOOST_BGL_ONE_PARAM_CREF(lowpoint_map, vertex_lowpoint) \
BOOST_BGL_ONE_PARAM_CREF(vertex_index_map, vertex_index) \
BOOST_BGL_ONE_PARAM_CREF(vertex_index1_map, vertex_index1) \
BOOST_BGL_ONE_PARAM_CREF(vertex_index2_map, vertex_index2) \
BOOST_BGL_ONE_PARAM_CREF(vertex_assignment_map, vertex_assignment_map) \
BOOST_BGL_ONE_PARAM_CREF(visitor, graph_visitor) \
BOOST_BGL_ONE_PARAM_CREF(distance_compare, distance_compare) \
BOOST_BGL_ONE_PARAM_CREF(distance_combine, distance_combine) \
BOOST_BGL_ONE_PARAM_CREF(distance_inf, distance_inf) \
BOOST_BGL_ONE_PARAM_CREF(distance_zero, distance_zero) \
BOOST_BGL_ONE_PARAM_CREF(edge_copy, edge_copy) \
BOOST_BGL_ONE_PARAM_CREF(vertex_copy, vertex_copy) \
BOOST_BGL_ONE_PARAM_REF(buffer, buffer_param) \
BOOST_BGL_ONE_PARAM_CREF(orig_to_copy, orig_to_copy) \
BOOST_BGL_ONE_PARAM_CREF(isomorphism_map, vertex_isomorphism) \
BOOST_BGL_ONE_PARAM_CREF(vertex_invariant, vertex_invariant) \
BOOST_BGL_ONE_PARAM_CREF(vertex_invariant1, vertex_invariant1) \
BOOST_BGL_ONE_PARAM_CREF(vertex_invariant2, vertex_invariant2) \
BOOST_BGL_ONE_PARAM_CREF(vertex_max_invariant, vertex_max_invariant) \
BOOST_BGL_ONE_PARAM_CREF(polling, polling) \
BOOST_BGL_ONE_PARAM_CREF(lookahead, lookahead) \
BOOST_BGL_ONE_PARAM_CREF(in_parallel, in_parallel) \
BOOST_BGL_ONE_PARAM_CREF(displacement_map, vertex_displacement) \
BOOST_BGL_ONE_PARAM_CREF(attractive_force, attractive_force) \
BOOST_BGL_ONE_PARAM_CREF(repulsive_force, repulsive_force) \
BOOST_BGL_ONE_PARAM_CREF(force_pairs, force_pairs) \
BOOST_BGL_ONE_PARAM_CREF(cooling, cooling) \
BOOST_BGL_ONE_PARAM_CREF(iterations, iterations) \
BOOST_BGL_ONE_PARAM_CREF(diameter_range, diameter_range) \
BOOST_BGL_ONE_PARAM_CREF(learning_constant_range, learning_constant_range) \
BOOST_BGL_ONE_PARAM_CREF(vertices_equivalent, vertices_equivalent) \
BOOST_BGL_ONE_PARAM_CREF(edges_equivalent, edges_equivalent) \
BOOST_BGL_ONE_PARAM_CREF(index_in_heap_map, index_in_heap_map) \
BOOST_BGL_ONE_PARAM_REF(max_priority_queue, max_priority_queue)
template <typename T, typename Tag, typename Base = no_property>
struct bgl_named_params
{
typedef bgl_named_params self;
typedef Base next_type;
typedef Tag tag_type;
typedef T value_type;
bgl_named_params(T v = T()) : m_value(v) { }
bgl_named_params(T v, const Base& b) : m_value(v), m_base(b) { }
T m_value;
Base m_base;
#define BOOST_BGL_ONE_PARAM_REF(name, key) \
template <typename PType> \
bgl_named_params<boost::reference_wrapper<PType>, BOOST_PP_CAT(key, _t), self> \
name(PType& p) const { \
typedef bgl_named_params<boost::reference_wrapper<PType>, BOOST_PP_CAT(key, _t), self> Params; \
return Params(boost::ref(p), *this); \
} \
#define BOOST_BGL_ONE_PARAM_CREF(name, key) \
template <typename PType> \
bgl_named_params<PType, BOOST_PP_CAT(key, _t), self> \
name(const PType& p) const { \
typedef bgl_named_params<PType, BOOST_PP_CAT(key, _t), self> Params; \
return Params(p, *this); \
} \
BOOST_BGL_DECLARE_NAMED_PARAMS
#undef BOOST_BGL_ONE_PARAM_REF
#undef BOOST_BGL_ONE_PARAM_CREF
// Duplicate
template <typename PType>
bgl_named_params<PType, vertex_color_t, self>
vertex_color_map(const PType& p) const {return this->color_map(p);}
};
#define BOOST_BGL_ONE_PARAM_REF(name, key) \
template <typename PType> \
bgl_named_params<boost::reference_wrapper<PType>, BOOST_PP_CAT(key, _t)> \
name(PType& p) { \
typedef bgl_named_params<boost::reference_wrapper<PType>, BOOST_PP_CAT(key, _t)> Params; \
return Params(boost::ref(p)); \
} \
#define BOOST_BGL_ONE_PARAM_CREF(name, key) \
template <typename PType> \
bgl_named_params<PType, BOOST_PP_CAT(key, _t)> \
name(const PType& p) { \
typedef bgl_named_params<PType, BOOST_PP_CAT(key, _t)> Params; \
return Params(p); \
} \
BOOST_BGL_DECLARE_NAMED_PARAMS
#undef BOOST_BGL_ONE_PARAM_REF
#undef BOOST_BGL_ONE_PARAM_CREF
// Duplicate
template <typename PType>
bgl_named_params<PType, vertex_color_t>
vertex_color_map(const PType& p) {return color_map(p);}
namespace detail {
struct unused_tag_type {};
}
typedef bgl_named_params<char, detail::unused_tag_type> no_named_parameters;
//===========================================================================
// Functions for extracting parameters from bgl_named_params
template <typename Tag, typename Args>
struct lookup_named_param {};
template <typename T, typename Tag, typename Base>
struct lookup_named_param<Tag, bgl_named_params<T, Tag, Base> > {
typedef T type;
static const T& get(const bgl_named_params<T, Tag, Base>& p) {
return p.m_value;
}
};
template <typename Tag1, typename T, typename Tag, typename Base>
struct lookup_named_param<Tag1, bgl_named_params<T, Tag, Base> > {
typedef typename lookup_named_param<Tag1, Base>::type type;
static const type& get(const bgl_named_params<T, Tag, Base>& p) {
return lookup_named_param<Tag1, Base>::get(p.m_base);
}
};
template <typename Tag, typename Args, typename Def>
struct lookup_named_param_def {
typedef Def type;
static const Def& get(const Args&, const Def& def) {return def;}
};
template <typename T, typename Tag, typename Base, typename Def>
struct lookup_named_param_def<Tag, bgl_named_params<T, Tag, Base>, Def> {
typedef T type;
static const type& get(const bgl_named_params<T, Tag, Base>& p, const Def&) {
return p.m_value;
}
};
template <typename Tag1, typename T, typename Tag, typename Base, typename Def>
struct lookup_named_param_def<Tag1, bgl_named_params<T, Tag, Base>, Def> {
typedef typename lookup_named_param_def<Tag1, Base, Def>::type type;
static const type& get(const bgl_named_params<T, Tag, Base>& p, const Def& def) {
return lookup_named_param_def<Tag1, Base, Def>::get(p.m_base, def);
}
};
struct param_not_found {};
template <typename Tag, typename Args>
struct get_param_type:
lookup_named_param_def<Tag, Args, param_not_found> {};
template <class Tag, typename Args>
inline
const typename lookup_named_param_def<Tag, Args, param_not_found>::type&
get_param(const Args& p, Tag) {
return lookup_named_param_def<Tag, Args, param_not_found>::get(p, param_not_found());
}
template <class P, class Default>
const P& choose_param(const P& param, const Default&) {
return param;
}
template <class Default>
Default choose_param(const param_not_found&, const Default& d) {
return d;
}
template <typename T>
inline bool is_default_param(const T&) { return false; }
inline bool is_default_param(const param_not_found&)
{ return true; }
namespace detail {
template <typename T>
struct const_type_as_type {typedef typename T::const_type type;};
} // namespace detail
// Use this function instead of choose_param() when you want
// to avoid requiring get(tag, g) when it is not used.
namespace detail {
template <typename GraphIsConst, typename Graph, typename Param, typename Tag>
struct choose_impl_result:
boost::mpl::eval_if<
boost::is_same<Param, param_not_found>,
boost::mpl::eval_if<
GraphIsConst,
detail::const_type_as_type<property_map<Graph, Tag> >,
property_map<Graph, Tag> >,
boost::mpl::identity<Param> > {};
// Parameters of f are (GraphIsConst, Graph, Param, Tag)
template <bool Found> struct choose_impl_helper;
template <> struct choose_impl_helper<false> {
template <typename Param, typename Graph, typename PropertyTag>
static typename property_map<typename boost::remove_const<Graph>::type, PropertyTag>::const_type
f(boost::mpl::true_, const Graph& g, const Param&, PropertyTag tag) {
return get(tag, g);
}
template <typename Param, typename Graph, typename PropertyTag>
static typename property_map<typename boost::remove_const<Graph>::type, PropertyTag>::type
f(boost::mpl::false_, Graph& g, const Param&, PropertyTag tag) {
return get(tag, g);
}
};
template <> struct choose_impl_helper<true> {
template <typename GraphIsConst, typename Param, typename Graph, typename PropertyTag>
static Param f(GraphIsConst, const Graph&, const Param& p, PropertyTag) {
return p;
}
};
}
template <typename Param, typename Graph, typename PropertyTag>
typename detail::choose_impl_result<boost::mpl::true_, Graph, Param, PropertyTag>::type
choose_const_pmap(const Param& p, const Graph& g, PropertyTag tag)
{
return detail::choose_impl_helper<!boost::is_same<Param, param_not_found>::value>
::f(boost::mpl::true_(), g, p, tag);
}
template <typename Param, typename Graph, typename PropertyTag>
typename detail::choose_impl_result<boost::mpl::false_, Graph, Param, PropertyTag>::type
choose_pmap(const Param& p, Graph& g, PropertyTag tag)
{
return detail::choose_impl_helper<!boost::is_same<Param, param_not_found>::value>
::f(boost::mpl::false_(), g, p, tag);
}
namespace detail {
// used in the max-flow algorithms
template <class Graph, class P, class T, class R>
struct edge_capacity_value
{
typedef bgl_named_params<P, T, R> Params;
typedef typename detail::choose_impl_result<boost::mpl::true_, Graph, typename get_param_type<edge_capacity_t, Params>::type, edge_capacity_t>::type CapacityEdgeMap;
typedef typename property_traits<CapacityEdgeMap>::value_type type;
};
// used in the max-flow algorithms
template <class Graph, class P, class T, class R>
struct edge_weight_value
{
typedef bgl_named_params<P, T, R> Params;
typedef typename detail::choose_impl_result<boost::mpl::true_, Graph, typename get_param_type<edge_weight_t, Params>::type, edge_weight_t>::type WeightMap;
typedef typename property_traits<WeightMap>::value_type type;
};
}
// Declare all new tags
namespace graph {
namespace keywords {
#define BOOST_BGL_ONE_PARAM_REF(name, key) BOOST_PARAMETER_NAME(name)
#define BOOST_BGL_ONE_PARAM_CREF(name, key) BOOST_PARAMETER_NAME(name)
BOOST_BGL_DECLARE_NAMED_PARAMS
#undef BOOST_BGL_ONE_PARAM_REF
#undef BOOST_BGL_ONE_PARAM_CREF
}
}
namespace detail {
template <typename Tag> struct convert_one_keyword {};
#define BOOST_BGL_ONE_PARAM_REF(name, key) \
template <> \
struct convert_one_keyword<BOOST_PP_CAT(key, _t)> { \
typedef boost::graph::keywords::tag::name type; \
};
#define BOOST_BGL_ONE_PARAM_CREF(name, key) BOOST_BGL_ONE_PARAM_REF(name, key)
BOOST_BGL_DECLARE_NAMED_PARAMS
#undef BOOST_BGL_ONE_PARAM_REF
#undef BOOST_BGL_ONE_PARAM_CREF
template <typename T>
struct convert_bgl_params_to_boost_parameter {
typedef typename convert_one_keyword<typename T::tag_type>::type new_kw;
typedef boost::parameter::aux::tagged_argument<new_kw, const typename T::value_type> tagged_arg_type;
typedef convert_bgl_params_to_boost_parameter<typename T::next_type> rest_conv;
typedef boost::parameter::aux::arg_list<tagged_arg_type, typename rest_conv::type> type;
static type conv(const T& x) {
return type(tagged_arg_type(x.m_value), rest_conv::conv(x.m_base));
}
};
template <typename P, typename R>
struct convert_bgl_params_to_boost_parameter<bgl_named_params<P, int, R> > {
typedef convert_bgl_params_to_boost_parameter<R> rest_conv;
typedef typename rest_conv::type type;
static type conv(const bgl_named_params<P, int, R>& x) {
return rest_conv::conv(x.m_base);
}
};
template <>
struct convert_bgl_params_to_boost_parameter<boost::no_property> {
typedef boost::parameter::aux::empty_arg_list type;
static type conv(const boost::no_property&) {return type();}
};
template <>
struct convert_bgl_params_to_boost_parameter<boost::no_named_parameters> {
typedef boost::parameter::aux::empty_arg_list type;
static type conv(const boost::no_named_parameters&) {return type();}
};
struct bgl_parameter_not_found_type {};
template <typename ArgPack, typename KeywordType>
struct parameter_exists : boost::mpl::not_<boost::is_same<typename boost::parameter::binding<ArgPack, KeywordType, bgl_parameter_not_found_type>::type, bgl_parameter_not_found_type> > {};
}
#define BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(old_type, old_var) \
typedef typename boost::detail::convert_bgl_params_to_boost_parameter<old_type>::type arg_pack_type; \
arg_pack_type arg_pack = boost::detail::convert_bgl_params_to_boost_parameter<old_type>::conv(old_var);
namespace detail {
template <typename ArgType, typename Prop, typename Graph, bool Exists>
struct override_const_property_t {
typedef typename boost::remove_const<ArgType>::type result_type;
result_type operator()(const Graph&, const ArgType& a) const {return a;}
};
template <typename ArgType, typename Prop, typename Graph>
struct override_const_property_t<ArgType, Prop, Graph, false> {
typedef typename boost::property_map<Graph, Prop>::const_type result_type;
result_type operator()(const Graph& g, const ArgType&) const {return get(Prop(), g);}
};
template <typename ArgPack, typename Tag, typename Prop, typename Graph>
struct override_const_property_result {
typedef
typename override_const_property_t<
typename boost::parameter::value_type<ArgPack, Tag, int>::type,
Prop,
Graph,
boost::detail::parameter_exists<ArgPack, Tag>::value
>::result_type
type;
};
template <typename ArgPack, typename Tag, typename Prop, typename Graph>
typename override_const_property_result<ArgPack, Tag, Prop, Graph>::type
override_const_property(const ArgPack& ap, const boost::parameter::keyword<Tag>& t, const Graph& g, Prop) {
return override_const_property_t<
typename boost::parameter::value_type<ArgPack, Tag, int>::type,
Prop,
Graph,
boost::detail::parameter_exists<ArgPack, Tag>::value
>()(g, ap[t | 0]);
}
template <typename ArgType, typename Prop, typename Graph, bool Exists>
struct override_property_t {
typedef ArgType result_type;
result_type operator()(const Graph&, const typename boost::add_reference<ArgType>::type a) const {return a;}
};
template <typename ArgType, typename Prop, typename Graph>
struct override_property_t<ArgType, Prop, Graph, false> {
typedef typename boost::property_map<Graph, Prop>::type result_type;
result_type operator()(const Graph& g, const ArgType&) const {return get(Prop(), g);}
};
template <typename ArgPack, typename Tag, typename Prop, typename Graph>
struct override_property_result {
typedef
typename override_property_t<
typename boost::parameter::value_type<ArgPack, Tag, int>::type,
Prop,
Graph,
boost::detail::parameter_exists<ArgPack, Tag>::value
>::result_type
type;
};
template <typename ArgPack, typename Tag, typename Prop, typename Graph>
typename override_property_result<ArgPack, Tag, Prop, Graph>::type
override_property(const ArgPack& ap, const boost::parameter::keyword<Tag>& t, const Graph& g, Prop) {
return override_property_t<
typename boost::parameter::value_type<ArgPack, Tag, int>::type,
Prop,
Graph,
boost::detail::parameter_exists<ArgPack, Tag>::value
>()(g, ap[t | 0]);
}
template <typename F> struct make_arg_pack_type;
template <> struct make_arg_pack_type<void()> {typedef boost::parameter::aux::empty_arg_list type;};
template <typename K, typename A>
struct make_arg_pack_type<void(K, A)> {
typedef boost::parameter::aux::tagged_argument<K, A> type;
};
#define BOOST_GRAPH_OPENING_PART_OF_PAIR(z, i, n) boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<BOOST_PP_CAT(Keyword, BOOST_PP_SUB(n, i)), BOOST_PP_CAT(Arg, BOOST_PP_SUB(n, i))>,
#define BOOST_GRAPH_MAKE_PAIR_PARAM(z, i, _) const boost::parameter::aux::tagged_argument<BOOST_PP_CAT(Keyword, i), BOOST_PP_CAT(Arg, i)>& BOOST_PP_CAT(kw, i)
#define BOOST_GRAPH_MAKE_AP_TYPE_SPECIALIZATION(z, i, _) \
template <BOOST_PP_ENUM_PARAMS(i, typename Keyword), BOOST_PP_ENUM_PARAMS(i, typename Arg)> \
struct make_arg_pack_type<void(BOOST_PP_ENUM_PARAMS(i, Keyword), BOOST_PP_ENUM_PARAMS(i, Arg))> { \
typedef \
BOOST_PP_REPEAT(i, BOOST_GRAPH_OPENING_PART_OF_PAIR, BOOST_PP_DEC(i)) boost::parameter::aux::empty_arg_list BOOST_PP_REPEAT(i, > BOOST_PP_TUPLE_EAT(3), ~) \
type; \
};
BOOST_PP_REPEAT_FROM_TO(2, 11, BOOST_GRAPH_MAKE_AP_TYPE_SPECIALIZATION, ~)
#undef BOOST_GRAPH_MAKE_AP_TYPE_SPECIALIZATION
#define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(name, nfixed, nnamed_max) \
/* Entry point for conversion from BGL-style named parameters */ \
template <BOOST_PP_ENUM_PARAMS(nfixed, typename Param) BOOST_PP_COMMA_IF(nfixed) typename ArgPack> \
typename boost::result_of< \
detail::BOOST_PP_CAT(name, _impl)<BOOST_PP_ENUM_PARAMS(nfixed, Param)>(BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) const ArgPack&) \
>::type \
BOOST_PP_CAT(name, _with_named_params)(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) BOOST_PP_COMMA_IF(nfixed) const ArgPack& arg_pack) { \
return detail::BOOST_PP_CAT(name, _impl)<BOOST_PP_ENUM_PARAMS(nfixed, Param)>()(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \
} \
/* Individual functions taking Boost.Parameter-style keyword arguments */ \
BOOST_PP_REPEAT(BOOST_PP_INC(nnamed_max), BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONE, (name)(nfixed))
#define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONE(z, nnamed, seq) \
BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONEX(z, nnamed, BOOST_PP_SEQ_ELEM(0, seq), BOOST_PP_SEQ_ELEM(1, seq))
#define BOOST_GRAPH_MAKE_FORWARDING_FUNCTION_ONEX(z, nnamed, name, nfixed) \
template <BOOST_PP_ENUM_PARAMS(nfixed, typename Param) BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, typename Keyword) BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, typename Arg)> \
typename boost::result_of< \
detail::BOOST_PP_CAT(name, _impl)<BOOST_PP_ENUM_PARAMS(nfixed, Param)> \
(BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) \
const typename boost::detail::make_arg_pack_type<void(BOOST_PP_ENUM_PARAMS(nnamed, Keyword) BOOST_PP_COMMA_IF(nnamed) BOOST_PP_ENUM_PARAMS(nnamed, Arg))>::type&) \
>::type \
name(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) \
BOOST_PP_ENUM_TRAILING(nnamed, BOOST_GRAPH_MAKE_PAIR_PARAM, ~)) { \
return detail::BOOST_PP_CAT(name, _impl)<BOOST_PP_ENUM_PARAMS(nfixed, Param)>() \
(BOOST_PP_ENUM_PARAMS(nfixed, param), \
(boost::parameter::aux::empty_arg_list() BOOST_PP_ENUM_TRAILING_PARAMS(nnamed, kw))); \
}
#define BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(name, nfixed) \
template <BOOST_PP_ENUM_PARAMS(nfixed, typename Param) BOOST_PP_COMMA_IF(nfixed) class P, class T, class R> \
typename boost::result_of< \
::boost::graph::detail::BOOST_PP_CAT(name, _impl) BOOST_PP_EXPR_IF(nfixed, <) BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_EXPR_IF(nfixed, >) \
(BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) \
const typename boost::detail::convert_bgl_params_to_boost_parameter<boost::bgl_named_params<P, T, R> >::type &) \
>::type \
name(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param) BOOST_PP_COMMA_IF(nfixed) const boost::bgl_named_params<P, T, R>& old_style_params) { \
typedef boost::bgl_named_params<P, T, R> old_style_params_type; \
BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(old_style_params_type, old_style_params) \
return ::boost::graph::BOOST_PP_CAT(name, _with_named_params)(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \
} \
\
BOOST_PP_EXPR_IF(nfixed, template <) BOOST_PP_ENUM_PARAMS(nfixed, typename Param) BOOST_PP_EXPR_IF(nfixed, >) \
BOOST_PP_EXPR_IF(nfixed, typename) boost::result_of< \
::boost::graph::detail::BOOST_PP_CAT(name, _impl) BOOST_PP_EXPR_IF(nfixed, <) BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_EXPR_IF(nfixed, >) \
(BOOST_PP_ENUM_PARAMS(nfixed, Param) BOOST_PP_COMMA_IF(nfixed) const boost::parameter::aux::empty_arg_list &) \
>::type \
name(BOOST_PP_ENUM_BINARY_PARAMS(nfixed, const Param, & param)) { \
BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(boost::no_named_parameters, boost::no_named_parameters()) \
return ::boost::graph::BOOST_PP_CAT(name, _with_named_params)(BOOST_PP_ENUM_PARAMS(nfixed, param) BOOST_PP_COMMA_IF(nfixed) arg_pack); \
}
}
namespace detail {
template <bool Exists, typename Graph, typename ArgPack, typename Value, typename PM>
struct map_maker_helper {
typedef PM map_type;
static PM make_map(const Graph&, Value, const PM& pm, const ArgPack&) {
return pm;
}
};
template <typename Graph, typename ArgPack, typename Value, typename PM>
struct map_maker_helper<false, Graph, ArgPack, Value, PM> {
typedef typename boost::remove_const<
typename override_const_property_t<
typename boost::parameter::value_type<
ArgPack, boost::graph::keywords::tag::vertex_index_map, int>::type,
boost::vertex_index_t,
Graph,
boost::detail::parameter_exists<
ArgPack, boost::graph::keywords::tag::vertex_index_map>::value
>::result_type>::type vi_map_type;
typedef
boost::shared_array_property_map<Value, vi_map_type>
map_type;
static map_type make_map(const Graph& g,
Value v,
const PM&,
const ArgPack& ap) {
return make_shared_array_property_map(
num_vertices(g),
v,
override_const_property(
ap,
boost::graph::keywords::_vertex_index_map,
g, vertex_index));
}
};
template <typename Graph, typename ArgPack, typename MapTag, typename ValueType>
struct map_maker {
BOOST_STATIC_CONSTANT(
bool,
has_map =
(parameter_exists<ArgPack, MapTag>
::value));
typedef map_maker_helper<has_map, Graph, ArgPack, ValueType,
typename boost::remove_const<
typename boost::parameter::value_type<
ArgPack,
MapTag,
int
>::type
>::type> helper;
typedef typename helper::map_type map_type;
static map_type make_map(const Graph& g, const ArgPack& ap, ValueType default_value) {
return helper::make_map(g, default_value, ap[::boost::parameter::keyword<MapTag>::instance | 0], ap);
}
};
template <typename MapTag, typename ValueType = void>
class make_property_map_from_arg_pack_gen {
ValueType default_value;
public:
make_property_map_from_arg_pack_gen(ValueType default_value)
: default_value(default_value) {}
template <typename Graph, typename ArgPack>
typename map_maker<Graph, ArgPack, MapTag, ValueType>::map_type
operator()(const Graph& g, const ArgPack& ap) const {
return map_maker<Graph, ArgPack, MapTag, ValueType>::make_map(g, ap, default_value);
}
};
template <typename MapTag>
class make_property_map_from_arg_pack_gen<MapTag, void> {
public:
template <typename ValueType, typename Graph, typename ArgPack>
typename map_maker<Graph, ArgPack, MapTag, ValueType>::map_type
operator()(const Graph& g, const ArgPack& ap, ValueType default_value) const {
return map_maker<Graph, ArgPack, MapTag, ValueType>::make_map(g, ap, default_value);
}
};
static const
make_property_map_from_arg_pack_gen<
boost::graph::keywords::tag::color_map,
default_color_type>
make_color_map_from_arg_pack(white_color);
template <bool Exists, class Graph, class ArgPack, class KeyT, class ValueT, class KeyMapTag, class IndexInHeapMapTag, class Compare, class Q>
struct priority_queue_maker_helper {
typedef Q priority_queue_type;
static priority_queue_type
make_queue(const Graph&, const ArgPack&, KeyT, const Q& q) {
return q;
}
};
template <class Graph, class ArgPack, class KeyT, class ValueT, class KeyMapTag, class IndexInHeapMapTag, class Compare, class Q>
struct priority_queue_maker_helper<false, Graph, ArgPack, KeyT, ValueT, KeyMapTag, IndexInHeapMapTag, Compare, Q> {
typedef typename std::vector<ValueT>::size_type default_index_in_heap_type;
typedef typename map_maker<Graph, ArgPack, IndexInHeapMapTag, default_index_in_heap_type>::helper::map_type index_in_heap_map;
typedef boost::d_ary_heap_indirect<ValueT, 4, index_in_heap_map, typename map_maker<Graph, ArgPack, KeyMapTag, KeyT>::helper::map_type, Compare> priority_queue_type;
static priority_queue_type
make_queue(const Graph& g, const ArgPack& ap, KeyT defaultKey, const Q&) {
return priority_queue_type(
map_maker<Graph, ArgPack, KeyMapTag, KeyT>::make_map(g, ap, defaultKey),
map_maker<Graph, ArgPack, IndexInHeapMapTag, default_index_in_heap_type>::make_map(g, ap, typename boost::property_traits<index_in_heap_map>::value_type(-1))
);
}
};
template <class Graph, class ArgPack, class KeyT, class ValueT, class PriorityQueueTag, class KeyMapTag, class IndexInHeapMapTag, class Compare>
struct priority_queue_maker {
BOOST_STATIC_CONSTANT(
bool,
g_hasQ =
(parameter_exists<ArgPack, PriorityQueueTag>
::value));
typedef boost::reference_wrapper<int> int_refw;
typedef typename boost::parameter::value_type<
ArgPack,
PriorityQueueTag,
int_refw
>::type
param_value_type_wrapper;
typedef typename param_value_type_wrapper::type
param_value_type;
typedef typename boost::remove_const<param_value_type>::type param_value_type_no_const;
typedef priority_queue_maker_helper<g_hasQ, Graph, ArgPack, KeyT, ValueT, KeyMapTag, IndexInHeapMapTag, Compare,
param_value_type_no_const> helper;
typedef typename helper::priority_queue_type priority_queue_type;
static priority_queue_type make_queue(const Graph& g, const ArgPack& ap, KeyT defaultKey) {
return helper::make_queue(g, ap, defaultKey, ap[::boost::parameter::keyword<PriorityQueueTag>::instance | 0]);
}
};
template <class PriorityQueueTag, class KeyT, class ValueT, class Compare = std::less<KeyT>, class KeyMapTag = boost::graph::keywords::tag::distance_map, class IndexInHeapMapTag = boost::graph::keywords::tag::index_in_heap_map>
struct make_priority_queue_from_arg_pack_gen {
KeyT defaultKey;
make_priority_queue_from_arg_pack_gen(KeyT defaultKey_) : defaultKey(defaultKey_) { }
template <class F>
struct result {
typedef typename remove_const<typename remove_reference<typename function_traits<F>::arg1_type>::type>::type graph_type;
typedef typename remove_const<typename remove_reference<typename function_traits<F>::arg2_type>::type>::type arg_pack_type;
typedef typename priority_queue_maker<graph_type, arg_pack_type, KeyT, ValueT, PriorityQueueTag, KeyMapTag, IndexInHeapMapTag, Compare>::priority_queue_type type;
};
template <class Graph, class ArgPack>
typename priority_queue_maker<Graph, ArgPack, KeyT, ValueT, PriorityQueueTag, KeyMapTag, IndexInHeapMapTag, Compare>::priority_queue_type
operator()(const Graph& g, const ArgPack& ap) const {
return priority_queue_maker<Graph, ArgPack, KeyT, ValueT, PriorityQueueTag, KeyMapTag, IndexInHeapMapTag, Compare>::make_queue(g, ap, defaultKey);
}
};
template <typename G>
typename boost::graph_traits<G>::vertex_descriptor
get_null_vertex(const G&) {return boost::graph_traits<G>::null_vertex();}
template <typename G>
typename boost::graph_traits<G>::vertex_descriptor
get_default_starting_vertex(const G& g) {
std::pair<typename boost::graph_traits<G>::vertex_iterator, typename boost::graph_traits<G>::vertex_iterator> iters = vertices(g);
return (iters.first == iters.second) ? boost::graph_traits<G>::null_vertex() : *iters.first;
}
template <typename G>
struct get_default_starting_vertex_t {
typedef typename boost::graph_traits<G>::vertex_descriptor result_type;
const G& g;
get_default_starting_vertex_t(const G& g): g(g) {}
result_type operator()() const {return get_default_starting_vertex(g);}
};
// Wrapper to avoid instantiating numeric_limits when users provide distance_inf value manually
template <typename T>
struct get_max {
T operator()() const {
return (std::numeric_limits<T>::max)();
}
typedef T result_type;
};
} // namespace detail
} // namespace boost
#undef BOOST_BGL_DECLARE_NAMED_PARAMS
#endif // BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP
+508
View File
@@ -0,0 +1,508 @@
// 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)
// Provides support for named vertices in graphs, allowing one to more
// easily associate unique external names (URLs, city names, employee
// ID numbers, etc.) with the vertices of a graph.
#ifndef BOOST_GRAPH_NAMED_GRAPH_HPP
#define BOOST_GRAPH_NAMED_GRAPH_HPP
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/functional/hash.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/optional.hpp>
#include <boost/pending/property.hpp> // for boost::lookup_one_property
#include <boost/pending/container_traits.hpp>
#include <boost/throw_exception.hpp>
#include <boost/tuple/tuple.hpp> // for boost::make_tuple
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
#include <functional> // for std::equal_to
#include <stdexcept> // for std::runtime_error
#include <utility> // for std::pair
namespace boost { namespace graph {
/*******************************************************************
* User-customized traits *
*******************************************************************/
/**
* @brief Trait used to extract the internal vertex name from a vertex
* property.
*
* To enable the use of internal vertex names in a graph type,
* specialize the @c internal_vertex_name trait for your graph
* property (e.g., @c a City class, which stores information about the
* vertices in a road map).
*/
template<typename VertexProperty>
struct internal_vertex_name
{
/**
* The @c type field provides a function object that extracts a key
* from the @c VertexProperty. The function object type must have a
* nested @c result_type that provides the type of the key. For
* more information, see the @c KeyExtractor concept in the
* Boost.MultiIndex documentation: @c type must either be @c void
* (if @c VertexProperty does not have an internal vertex name) or
* a model of @c KeyExtractor.
*/
typedef void type;
};
/**
* Extract the internal vertex name from a @c property structure by
* looking at its base.
*/
template<typename Tag, typename T, typename Base>
struct internal_vertex_name<property<Tag, T, Base> >
: internal_vertex_name<Base> { };
/**
* Construct an instance of @c VertexProperty directly from its
* name. This function object should be used within the @c
* internal_vertex_constructor trait.
*/
template<typename VertexProperty>
struct vertex_from_name
{
private:
typedef typename internal_vertex_name<VertexProperty>::type extract_name_type;
typedef typename remove_cv<
typename remove_reference<
typename extract_name_type::result_type>::type>::type
vertex_name_type;
public:
typedef vertex_name_type argument_type;
typedef VertexProperty result_type;
VertexProperty operator()(const vertex_name_type& name)
{
return VertexProperty(name);
}
};
/**
* Throw an exception whenever one tries to construct a @c
* VertexProperty instance from its name.
*/
template<typename VertexProperty>
struct cannot_add_vertex
{
private:
typedef typename internal_vertex_name<VertexProperty>::type extract_name_type;
typedef typename remove_cv<
typename remove_reference<
typename extract_name_type::result_type>::type>::type
vertex_name_type;
public:
typedef vertex_name_type argument_type;
typedef VertexProperty result_type;
VertexProperty operator()(const vertex_name_type&)
{
boost::throw_exception(std::runtime_error("add_vertex: "
"unable to create a vertex from its name"));
}
};
/**
* @brief Trait used to construct an instance of a @c VertexProperty,
* which is a class type that stores the properties associated with a
* vertex in a graph, from just the name of that vertex property. This
* operation is used when an operation is required to map from a
* vertex name to a vertex descriptor (e.g., to add an edge outgoing
* from that vertex), but no vertex by the name exists. The function
* object provided by this trait will be used to add new vertices
* based only on their names. Since this cannot be done for arbitrary
* types, the default behavior is to throw an exception when this
* routine is called, which requires that all named vertices be added
* before adding any edges by name.
*/
template<typename VertexProperty>
struct internal_vertex_constructor
{
/**
* The @c type field provides a function object that constructs a
* new instance of @c VertexProperty from the name of the vertex (as
* determined by @c internal_vertex_name). The function object shall
* accept a vertex name and return a @c VertexProperty. Predefined
* options include:
*
* @c vertex_from_name<VertexProperty>: construct an instance of
* @c VertexProperty directly from the name.
*
* @c cannot_add_vertex<VertexProperty>: the default value, which
* throws an @c std::runtime_error if one attempts to add a vertex
* given just the name.
*/
typedef cannot_add_vertex<VertexProperty> type;
};
/**
* Extract the internal vertex constructor from a @c property structure by
* looking at its base.
*/
template<typename Tag, typename T, typename Base>
struct internal_vertex_constructor<property<Tag, T, Base> >
: internal_vertex_constructor<Base> { };
/*******************************************************************
* Named graph mixin *
*******************************************************************/
/**
* named_graph is a mixin that provides names for the vertices of a
* graph, including a mapping from names to vertices. Graph types that
* may or may not be have vertex names (depending on the properties
* supplied by the user) should use maybe_named_graph.
*
* Template parameters:
*
* Graph: the graph type that derives from named_graph
*
* Vertex: the type of a vertex descriptor in Graph. Note: we cannot
* use graph_traits here, because the Graph is not yet defined.
*
* VertexProperty: the type stored with each vertex in the Graph.
*/
template<typename Graph, typename Vertex, typename VertexProperty>
class named_graph
{
public:
/// The type of the function object that extracts names from vertex
/// properties.
typedef typename internal_vertex_name<VertexProperty>::type extract_name_type;
/// The type of the "bundled" property, from which the name can be
/// extracted.
typedef typename lookup_one_property<VertexProperty, vertex_bundle_t>::type
bundled_vertex_property_type;
/// The type of the function object that generates vertex properties
/// from names, for the implicit addition of vertices.
typedef typename internal_vertex_constructor<VertexProperty>::type
vertex_constructor_type;
/// The type used to name vertices in the graph
typedef typename remove_cv<
typename remove_reference<
typename extract_name_type::result_type>::type>::type
vertex_name_type;
/// The type of vertex descriptors in the graph
typedef Vertex vertex_descriptor;
private:
/// Key extractor for use with the multi_index_container
struct extract_name_from_vertex
{
typedef vertex_name_type result_type;
extract_name_from_vertex(Graph& graph, const extract_name_type& extract)
: graph(graph), extract(extract) { }
const result_type& operator()(Vertex vertex) const
{
return extract(graph[vertex]);
}
Graph& graph;
extract_name_type extract;
};
public:
/// The type that maps names to vertices
typedef multi_index::multi_index_container<
Vertex,
multi_index::indexed_by<
multi_index::hashed_unique<multi_index::tag<vertex_name_t>,
extract_name_from_vertex> >
> named_vertices_type;
/// The set of vertices, indexed by name
typedef typename named_vertices_type::template index<vertex_name_t>::type
vertices_by_name_type;
/// Construct an instance of the named graph mixin, using the given
/// function object to extract a name from the bundled property
/// associated with a vertex.
named_graph(const extract_name_type& extract = extract_name_type(),
const vertex_constructor_type& vertex_constructor
= vertex_constructor_type());
/// Notify the named_graph that we have added the given vertex. The
/// name of the vertex will be added to the mapping.
void added_vertex(Vertex vertex);
/// Notify the named_graph that we are removing the given
/// vertex. The name of the vertex will be removed from the mapping.
template <typename VertexIterStability>
void removing_vertex(Vertex vertex, VertexIterStability);
/// Notify the named_graph that we are clearing the graph.
/// This will clear out all of the name->vertex mappings
void clearing_graph();
/// Retrieve the derived instance
Graph& derived() { return static_cast<Graph&>(*this); }
const Graph& derived() const { return static_cast<const Graph&>(*this); }
/// Extract the name from a vertex property instance
typename extract_name_type::result_type
extract_name(const bundled_vertex_property_type& property);
/// Search for a vertex that has the given property (based on its
/// name)
optional<vertex_descriptor>
vertex_by_property(const bundled_vertex_property_type& property);
/// Mapping from names to vertices
named_vertices_type named_vertices;
/// Constructs a vertex from the name of that vertex
vertex_constructor_type vertex_constructor;
};
/// Helper macro containing the template parameters of named_graph
#define BGL_NAMED_GRAPH_PARAMS \
typename Graph, typename Vertex, typename VertexProperty
/// Helper macro containing the named_graph<...> instantiation
#define BGL_NAMED_GRAPH \
named_graph<Graph, Vertex, VertexProperty>
template<BGL_NAMED_GRAPH_PARAMS>
BGL_NAMED_GRAPH::named_graph(const extract_name_type& extract,
const vertex_constructor_type& vertex_constructor)
: named_vertices(
typename named_vertices_type::ctor_args_list(
boost::make_tuple(
boost::make_tuple(
0, // initial number of buckets
extract_name_from_vertex(derived(), extract),
boost::hash<vertex_name_type>(),
std::equal_to<vertex_name_type>())))),
vertex_constructor(vertex_constructor)
{
}
template<BGL_NAMED_GRAPH_PARAMS>
inline void BGL_NAMED_GRAPH::added_vertex(Vertex vertex)
{
named_vertices.insert(vertex);
}
template<BGL_NAMED_GRAPH_PARAMS>
template<typename VertexIterStability>
inline void BGL_NAMED_GRAPH::removing_vertex(Vertex vertex, VertexIterStability)
{
BOOST_STATIC_ASSERT_MSG ((boost::is_base_of<boost::graph_detail::stable_tag, VertexIterStability>::value), "Named graphs cannot use vecS as vertex container and remove vertices; the lack of vertex descriptor stability (which iterator stability is a proxy for) means that the name -> vertex mapping would need to be completely rebuilt after each deletion. See https://svn.boost.org/trac/boost/ticket/7863 for more information and a test case.");
typedef typename BGL_NAMED_GRAPH::vertex_name_type vertex_name_type;
const vertex_name_type& vertex_name = extract_name(derived()[vertex]);
named_vertices.erase(vertex_name);
}
template<BGL_NAMED_GRAPH_PARAMS>
inline void BGL_NAMED_GRAPH::clearing_graph()
{
named_vertices.clear();
}
template<BGL_NAMED_GRAPH_PARAMS>
typename BGL_NAMED_GRAPH::extract_name_type::result_type
BGL_NAMED_GRAPH::extract_name(const bundled_vertex_property_type& property)
{
return named_vertices.key_extractor().extract(property);
}
template<BGL_NAMED_GRAPH_PARAMS>
optional<typename BGL_NAMED_GRAPH::vertex_descriptor>
BGL_NAMED_GRAPH::
vertex_by_property(const bundled_vertex_property_type& property)
{
return find_vertex(extract_name(property), *this);
}
/// Retrieve the vertex associated with the given name
template<BGL_NAMED_GRAPH_PARAMS>
optional<Vertex>
find_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name,
const BGL_NAMED_GRAPH& g)
{
typedef typename BGL_NAMED_GRAPH::vertices_by_name_type
vertices_by_name_type;
// Retrieve the set of vertices indexed by name
vertices_by_name_type const& vertices_by_name
= g.named_vertices.template get<vertex_name_t>();
/// Look for a vertex with the given name
typename vertices_by_name_type::const_iterator iter
= vertices_by_name.find(name);
if (iter == vertices_by_name.end())
return optional<Vertex>(); // vertex not found
else
return *iter;
}
/// Retrieve the vertex associated with the given name, or add a new
/// vertex with that name if no such vertex is available.
/// Note: This is enabled only when the vertex property type is different
/// from the vertex name to avoid ambiguous overload problems with
/// the add_vertex() function that takes a vertex property.
template<BGL_NAMED_GRAPH_PARAMS>
typename disable_if<is_same<
typename BGL_NAMED_GRAPH::vertex_name_type,
VertexProperty
>,
Vertex>::type
add_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name,
BGL_NAMED_GRAPH& g)
{
if (optional<Vertex> vertex = find_vertex(name, g))
/// We found the vertex, so return it
return *vertex;
else
/// There is no vertex with the given name, so create one
return add_vertex(g.vertex_constructor(name), g.derived());
}
/// Add an edge using vertex names to refer to the vertices
template<BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
BGL_NAMED_GRAPH& g)
{
return add_edge(add_vertex(u_name, g.derived()),
add_vertex(v_name, g.derived()),
g.derived());
}
/// Add an edge using vertex descriptors or names to refer to the vertices
template<BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_descriptor const& u,
typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
BGL_NAMED_GRAPH& g)
{
return add_edge(u,
add_vertex(v_name, g.derived()),
g.derived());
}
/// Add an edge using vertex descriptors or names to refer to the vertices
template<BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
typename BGL_NAMED_GRAPH::vertex_descriptor const& v,
BGL_NAMED_GRAPH& g)
{
return add_edge(add_vertex(u_name, g.derived()),
v,
g.derived());
}
// Overloads to support EdgeMutablePropertyGraph graphs
template <BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_descriptor const& u,
typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
typename edge_property_type<Graph>::type const& p,
BGL_NAMED_GRAPH& g) {
return add_edge(u, add_vertex(v_name, g.derived()), p, g.derived());
}
template <BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
typename BGL_NAMED_GRAPH::vertex_descriptor const& v,
typename edge_property_type<Graph>::type const& p,
BGL_NAMED_GRAPH& g) {
return add_edge(add_vertex(u_name, g.derived()), v, p, g.derived());
}
template <BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
typename edge_property_type<Graph>::type const& p,
BGL_NAMED_GRAPH& g) {
return add_edge(add_vertex(u_name, g.derived()),
add_vertex(v_name, g.derived()), p, g.derived());
}
#undef BGL_NAMED_GRAPH
#undef BGL_NAMED_GRAPH_PARAMS
/*******************************************************************
* Maybe named graph mixin *
*******************************************************************/
/**
* A graph mixin that can provide a mapping from names to vertices,
* and use that mapping to simplify creation and manipulation of
* graphs.
*/
template<typename Graph, typename Vertex, typename VertexProperty,
typename ExtractName
= typename internal_vertex_name<VertexProperty>::type>
struct maybe_named_graph : public named_graph<Graph, Vertex, VertexProperty>
{
};
/**
* A graph mixin that can provide a mapping from names to vertices,
* and use that mapping to simplify creation and manipulation of
* graphs. This partial specialization turns off this functionality
* when the @c VertexProperty does not have an internal vertex name.
*/
template<typename Graph, typename Vertex, typename VertexProperty>
struct maybe_named_graph<Graph, Vertex, VertexProperty, void>
{
/// The type of the "bundled" property, from which the name can be
/// extracted.
typedef typename lookup_one_property<VertexProperty, vertex_bundle_t>::type
bundled_vertex_property_type;
/// Notify the named_graph that we have added the given vertex. This
/// is a no-op.
void added_vertex(Vertex) { }
/// Notify the named_graph that we are removing the given
/// vertex. This is a no-op.
template <typename VertexIterStability>
void removing_vertex(Vertex, VertexIterStability) { }
/// Notify the named_graph that we are clearing the graph. This is a
/// no-op.
void clearing_graph() { }
/// Search for a vertex that has the given property (based on its
/// name). This always returns an empty optional<>
optional<Vertex>
vertex_by_property(const bundled_vertex_property_type&)
{
return optional<Vertex>();
}
};
} } // end namespace boost::graph
#endif // BOOST_GRAPH_NAMED_GRAPH_HPP
+52
View File
@@ -0,0 +1,52 @@
// (C) Copyright 2007-2009 Andrew Sutton
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GRAPH_NUMERIC_VALUES_HPP
#define BOOST_GRAPH_NUMERIC_VALUES_HPP
#include <limits>
namespace boost
{
#define BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(type) \
template <> struct numeric_values<type> { \
typedef type value_type; \
static type zero() { return 0.0; } \
static type infinity() { return std::numeric_limits<type>::infinity(); } \
};
/**
* This generic type reports various numeric values for some type. In the
* general case, numeric values simply treat their maximum value as infinity
* and the default-constructed value as 0.
*
* Specializations of this template can redefine the notions of zero and
* infinity for various types. For example, the class is specialized for
* floating point types to use the built in notion of infinity.
*/
template <typename T>
struct numeric_values
{
typedef T value_type;
static T zero()
{ return T(); }
static T infinity()
{ return (std::numeric_limits<T>::max)(); }
};
// Specializations for floating point types refer to 0.0 and their infinity
// value defined by numeric_limits.
BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(float)
BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(double)
BOOST_GRAPH_SPECIALIZE_NUMERIC_FLOAT(long double)
#undef BOOST_GRAPH_SPECIALIZE_NUMERIC_VALUE
}
#endif
+46
View File
@@ -0,0 +1,46 @@
// 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
//
// This file contains helps that enable concept-based overloading
// within the Boost Graph Library.
//
#ifndef BOOST_GRAPH_OVERLOADING_HPP
#define BOOST_GRAPH_OVERLOADING_HPP
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/utility/enable_if.hpp>
namespace boost { namespace graph { namespace detail {
struct no_parameter {};
} } } // end namespace boost::graph::detail
#ifndef BOOST_NO_SFINAE
#define BOOST_GRAPH_ENABLE_IF_MODELS(Graph, Tag, Type) \
typename enable_if_c<(is_base_and_derived< \
Tag, \
typename graph_traits<Graph>::traversal_category>::value), \
Type>::type
#define BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, Tag) \
, BOOST_GRAPH_ENABLE_IF_MODELS(Graph, Tag, \
::boost::graph::detail::no_parameter) \
= ::boost::graph::detail::no_parameter()
#else
#define BOOST_GRAPH_ENABLE_IF_MODELS(Graph, Tag, Type) Type
#define BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, Tag)
#endif // no SFINAE support
#endif // BOOST_GRAPH_OVERLOADING_HPP
+84
View File
@@ -0,0 +1,84 @@
// 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_ALGORITHM_HPP
#define BOOST_PARALLEL_ALGORITHM_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/optional.hpp>
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
#include <vector>
#include <functional>
namespace boost { namespace parallel {
template<typename BinaryOp>
struct is_commutative
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename T>
struct minimum : std::binary_function<T, T, T>
{
const T& operator()(const T& x, const T& y) const { return x < y? x : y; }
};
template<typename T>
struct maximum : std::binary_function<T, T, T>
{
const T& operator()(const T& x, const T& y) const { return x < y? y : x; }
};
template<typename T>
struct sum : std::binary_function<T, T, T>
{
const T operator()(const T& x, const T& y) const { return x + y; }
};
template<typename ProcessGroup, typename InputIterator,
typename OutputIterator, typename BinaryOperation>
OutputIterator
reduce(ProcessGroup pg, typename ProcessGroup::process_id_type root,
InputIterator first, InputIterator last, OutputIterator out,
BinaryOperation bin_op);
template<typename ProcessGroup, typename T, typename BinaryOperation>
inline T
all_reduce(ProcessGroup pg, const T& value, BinaryOperation bin_op)
{
T result;
all_reduce(pg,
const_cast<T*>(&value), const_cast<T*>(&value+1),
&result, bin_op);
return result;
}
template<typename ProcessGroup, typename T, typename BinaryOperation>
inline T
scan(ProcessGroup pg, const T& value, BinaryOperation bin_op)
{
T result;
scan(pg,
const_cast<T*>(&value), const_cast<T*>(&value+1),
&result, bin_op);
return result;
}
template<typename ProcessGroup, typename InputIterator, typename T>
void
all_gather(ProcessGroup pg, InputIterator first, InputIterator last,
std::vector<T>& out);
} } // end namespace boost::parallel
#include <boost/graph/parallel/detail/inplace_all_to_all.hpp>
#endif // BOOST_PARALLEL_ALGORITHM_HPP
+45
View File
@@ -0,0 +1,45 @@
// 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
//
// This file contains traits that describe
//
#ifndef BOOST_GRAPH_PARALLEL_CONTAINER_TRAITS_HPP
#define BOOST_GRAPH_PARALLEL_CONTAINER_TRAITS_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 graph { namespace parallel {
template<typename T>
struct process_group_type
{
typedef typename T::process_group_type type;
};
template<typename T>
inline typename process_group_type<T>::type
process_group(const T& x)
{ return x.process_group(); }
// Helper function that algorithms should use to get the process group
// out of a container.
template<typename Container>
inline typename process_group_type<Container>::type
process_group_adl(const Container& container)
{
return process_group(container);
}
} } } // end namespace boost::graph::parallel
#endif // BOOST_GRAPH_PARALLEL_CONTAINER_TRAITS_HPP
@@ -0,0 +1,78 @@
// 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_GRAPH_PARALLEL_INPLACE_ALL_TO_ALL_HPP
#define BOOST_GRAPH_PARALLEL_INPLACE_ALL_TO_ALL_HPP
#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif
//
// Implements the inplace all-to-all communication algorithm.
//
#include <vector>
#include <iterator>
namespace boost { namespace parallel {
template<typename ProcessGroup, typename T>
// where {LinearProcessGroup<ProcessGroup>, MessagingProcessGroup<ProcessGroup>}
void
inplace_all_to_all(ProcessGroup pg,
const std::vector<std::vector<T> >& outgoing,
std::vector<std::vector<T> >& incoming)
{
typedef typename std::vector<T>::size_type size_type;
typedef typename ProcessGroup::process_size_type process_size_type;
typedef typename ProcessGroup::process_id_type process_id_type;
process_size_type p = num_processes(pg);
// Make sure there are no straggling messages
synchronize(pg);
// Send along the count (always) and the data (if count > 0)
for (process_id_type dest = 0; dest < p; ++dest) {
if (dest != process_id(pg)) {
send(pg, dest, 0, outgoing[dest].size());
if (!outgoing[dest].empty())
send(pg, dest, 1, &outgoing[dest].front(), outgoing[dest].size());
}
}
// Make sure all of the data gets transferred
synchronize(pg);
// Receive the sizes and data
for (process_id_type source = 0; source < p; ++source) {
if (source != process_id(pg)) {
size_type size;
receive(pg, source, 0, size);
incoming[source].resize(size);
if (size > 0)
receive(pg, source, 1, &incoming[source].front(), size);
} else if (&incoming != &outgoing) {
incoming[source] = outgoing[source];
}
}
}
template<typename ProcessGroup, typename T>
// where {LinearProcessGroup<ProcessGroup>, MessagingProcessGroup<ProcessGroup>}
void
inplace_all_to_all(ProcessGroup pg, std::vector<std::vector<T> >& data)
{
inplace_all_to_all(pg, data, data);
}
} } // end namespace boost::parallel
#endif // BOOST_GRAPH_PARALLEL_INPLACE_ALL_TO_ALL_HPP
+11
View File
@@ -0,0 +1,11 @@
// 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
// File moved
#include <boost/property_map/parallel/process_group.hpp>
+113
View File
@@ -0,0 +1,113 @@
// 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_GRAPH_PARALLEL_PROPERTIES_HPP
#define BOOST_GRAPH_PARALLEL_PROPERTIES_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/graph/properties.hpp>
#include <boost/property_map/parallel/distributed_property_map.hpp>
namespace boost {
/***************************************************************************
* Property map reduction operations
***************************************************************************/
/**
* Metafunction that produces a reduction operation for the given
* property. The default behavior merely forwards to @ref
* basic_reduce, but it is expected that this class template will be
* specified for important properties.
*/
template<typename Property>
struct property_reduce
{
template<typename Value>
class apply : public parallel::basic_reduce<Value> {};
};
/**
* Reduction of vertex colors can only darken, not lighten, the
* color. Black cannot turn black, grey can only turn black, and
* white can be changed to either color. The default color is white.
*/
template<>
struct property_reduce<vertex_color_t>
{
template<typename Color>
class apply
{
typedef color_traits<Color> traits;
public:
BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
template<typename Key>
Color operator()(const Key&) const { return traits::white(); }
template<typename Key>
Color operator()(const Key&, Color local, Color remote) const {
if (local == traits::white()) return remote;
else if (remote == traits::black()) return remote;
else return local;
}
};
};
/**
* Reduction of a distance always takes the shorter distance. The
* default distance value is the maximum value for the data type.
*/
template<>
struct property_reduce<vertex_distance_t>
{
template<typename T>
class apply
{
public:
BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
template<typename Key>
T operator()(const Key&) const { return (std::numeric_limits<T>::max)(); }
template<typename Key>
T operator()(const Key&, T x, T y) const { return x < y? x : y; }
};
};
template<>
struct property_reduce<vertex_predecessor_t>
{
template<typename T>
class apply
{
public:
BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
template<typename Key>
T operator()(Key key) const { return key; }
template<typename Key>
T operator()(Key key, T, T y) const { return y; }
};
};
template<typename Property, typename PropertyMap>
inline void set_property_map_role(Property p, PropertyMap pm)
{
typedef typename property_traits<PropertyMap>::value_type value_type;
typedef property_reduce<Property> property_red;
typedef typename property_red::template apply<value_type> reduce;
pm.set_reduce(reduce());
}
} // end namespace boost
#endif // BOOST_GRAPH_PARALLEL_PROPERTIES_HPP
+13
View File
@@ -0,0 +1,13 @@
// 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)
// This file contains a simplification of the "trigger" method for
// process groups. The simple trigger handles the common case where
// the handler associated with a trigger is a member function bound to
// a particular pointer.
// File moved
#include <boost/property_map/parallel/simple_trigger.hpp>
+356
View File
@@ -0,0 +1,356 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
#ifndef BOOST_GRAPH_PROPERTIES_HPP
#define BOOST_GRAPH_PROPERTIES_HPP
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/pending/property.hpp>
#include <boost/detail/workaround.hpp>
// Include the property map library and extensions in the BGL.
#include <boost/property_map/property_map.hpp>
#include <boost/graph/property_maps/constant_property_map.hpp>
#include <boost/graph/property_maps/null_property_map.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/type_traits.hpp>
#include <boost/limits.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/if.hpp>
namespace boost {
enum default_color_type { white_color, gray_color, green_color, red_color, black_color };
template <class ColorValue>
struct color_traits {
static default_color_type white() { return white_color; }
static default_color_type gray() { return gray_color; }
static default_color_type green() { return green_color; }
static default_color_type red() { return red_color; }
static default_color_type black() { return black_color; }
};
// These functions are now obsolete, replaced by color_traits.
inline default_color_type white(default_color_type) { return white_color; }
inline default_color_type gray(default_color_type) { return gray_color; }
inline default_color_type green(default_color_type) { return green_color; }
inline default_color_type red(default_color_type) { return red_color; }
inline default_color_type black(default_color_type) { return black_color; }
struct graph_property_tag { };
struct vertex_property_tag { };
struct edge_property_tag { };
// See examples/edge_property.cpp for how to use this.
#define BOOST_INSTALL_PROPERTY(KIND, NAME) \
template <> struct property_kind<KIND##_##NAME##_t> { \
typedef KIND##_property_tag type; \
}
#define BOOST_DEF_PROPERTY(KIND, NAME) \
enum KIND##_##NAME##_t { KIND##_##NAME }; \
BOOST_INSTALL_PROPERTY(KIND, NAME)
// These three are defined in boost/pending/property.hpp
BOOST_INSTALL_PROPERTY(vertex, all);
BOOST_INSTALL_PROPERTY(edge, all);
BOOST_INSTALL_PROPERTY(graph, all);
BOOST_DEF_PROPERTY(vertex, index);
BOOST_DEF_PROPERTY(vertex, index1);
BOOST_DEF_PROPERTY(vertex, index2);
BOOST_DEF_PROPERTY(vertex, root);
BOOST_DEF_PROPERTY(edge, index);
BOOST_DEF_PROPERTY(edge, name);
BOOST_DEF_PROPERTY(edge, weight);
BOOST_DEF_PROPERTY(edge, weight2);
BOOST_DEF_PROPERTY(edge, color);
BOOST_DEF_PROPERTY(vertex, name);
BOOST_DEF_PROPERTY(graph, name);
BOOST_DEF_PROPERTY(vertex, distance);
BOOST_DEF_PROPERTY(vertex, distance2);
BOOST_DEF_PROPERTY(vertex, color);
BOOST_DEF_PROPERTY(vertex, degree);
BOOST_DEF_PROPERTY(vertex, in_degree);
BOOST_DEF_PROPERTY(vertex, out_degree);
BOOST_DEF_PROPERTY(vertex, current_degree);
BOOST_DEF_PROPERTY(vertex, priority);
BOOST_DEF_PROPERTY(vertex, discover_time);
BOOST_DEF_PROPERTY(vertex, finish_time);
BOOST_DEF_PROPERTY(vertex, predecessor);
BOOST_DEF_PROPERTY(vertex, rank);
BOOST_DEF_PROPERTY(vertex, centrality);
BOOST_DEF_PROPERTY(vertex, lowpoint);
BOOST_DEF_PROPERTY(vertex, potential);
BOOST_DEF_PROPERTY(vertex, update);
BOOST_DEF_PROPERTY(vertex, underlying);
BOOST_DEF_PROPERTY(edge, reverse);
BOOST_DEF_PROPERTY(edge, capacity);
BOOST_DEF_PROPERTY(edge, flow);
BOOST_DEF_PROPERTY(edge, residual_capacity);
BOOST_DEF_PROPERTY(edge, centrality);
BOOST_DEF_PROPERTY(edge, discover_time);
BOOST_DEF_PROPERTY(edge, update);
BOOST_DEF_PROPERTY(edge, finished);
BOOST_DEF_PROPERTY(edge, underlying);
BOOST_DEF_PROPERTY(graph, visitor);
// These tags are used for property bundles
// These three are defined in boost/pending/property.hpp
BOOST_INSTALL_PROPERTY(graph, bundle);
BOOST_INSTALL_PROPERTY(vertex, bundle);
BOOST_INSTALL_PROPERTY(edge, bundle);
// These tags are used to denote the owners and local descriptors
// for the vertices and edges of a distributed graph.
BOOST_DEF_PROPERTY(vertex, global);
BOOST_DEF_PROPERTY(vertex, owner);
BOOST_DEF_PROPERTY(vertex, local);
BOOST_DEF_PROPERTY(edge, global);
BOOST_DEF_PROPERTY(edge, owner);
BOOST_DEF_PROPERTY(edge, local);
BOOST_DEF_PROPERTY(vertex, local_index);
BOOST_DEF_PROPERTY(edge, local_index);
#undef BOOST_DEF_PROPERTY
namespace detail {
template <typename G, typename Tag>
struct property_kind_from_graph: property_kind<Tag> {};
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
template <typename G, typename R, typename T>
struct property_kind_from_graph<G, R T::*> {
typedef typename boost::mpl::if_<
boost::is_base_of<T, typename vertex_bundle_type<G>::type>,
vertex_property_tag,
typename boost::mpl::if_<
boost::is_base_of<T, typename edge_bundle_type<G>::type>,
edge_property_tag,
typename boost::mpl::if_<
boost::is_base_of<T, typename graph_bundle_type<G>::type>,
graph_property_tag,
void>::type>::type>::type type;
};
#endif
struct dummy_edge_property_selector {
template <class Graph, class Property, class Tag>
struct bind_ {
typedef identity_property_map type;
typedef identity_property_map const_type;
};
};
struct dummy_vertex_property_selector {
template <class Graph, class Property, class Tag>
struct bind_ {
typedef identity_property_map type;
typedef identity_property_map const_type;
};
};
} // namespace detail
// Graph classes can either partially specialize property_map
// or they can specialize these two selector classes.
template <class GraphTag>
struct edge_property_selector {
typedef detail::dummy_edge_property_selector type;
};
template <class GraphTag>
struct vertex_property_selector {
typedef detail::dummy_vertex_property_selector type;
};
namespace detail {
template <typename A> struct return_void {typedef void type;};
template <typename Graph, typename Enable = void>
struct graph_tag_or_void {
typedef void type;
};
template <typename Graph>
struct graph_tag_or_void<Graph, typename return_void<typename Graph::graph_tag>::type> {
typedef typename Graph::graph_tag type;
};
template <class Graph, class PropertyTag>
struct edge_property_map
: edge_property_selector<
typename graph_tag_or_void<Graph>::type
>::type::template bind_<
Graph,
typename edge_property_type<Graph>::type,
PropertyTag>
{};
template <class Graph, class PropertyTag>
struct vertex_property_map
: vertex_property_selector<
typename graph_tag_or_void<Graph>::type
>::type::template bind_<
Graph,
typename vertex_property_type<Graph>::type,
PropertyTag>
{};
} // namespace detail
template <class Graph, class Property, class Enable = void>
struct property_map:
mpl::if_<
is_same<typename detail::property_kind_from_graph<Graph, Property>::type, edge_property_tag>,
detail::edge_property_map<Graph, Property>,
detail::vertex_property_map<Graph, Property> >::type
{};
// shortcut for accessing the value type of the property map
template <class Graph, class Property>
class property_map_value {
typedef typename property_map<Graph, Property>::const_type PMap;
public:
typedef typename property_traits<PMap>::value_type type;
};
template <class Graph, class Property>
class graph_property {
public:
typedef typename property_value<
typename boost::graph_property_type<Graph>::type, Property
>::type type;
};
template <typename Graph> struct vertex_property: vertex_property_type<Graph> {};
template <typename Graph> struct edge_property: edge_property_type<Graph> {};
template <typename Graph>
class degree_property_map
: public put_get_helper<typename graph_traits<Graph>::degree_size_type,
degree_property_map<Graph> >
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor key_type;
typedef typename graph_traits<Graph>::degree_size_type value_type;
typedef value_type reference;
typedef readable_property_map_tag category;
degree_property_map(const Graph& g) : m_g(g) { }
value_type operator[](const key_type& v) const {
return degree(v, m_g);
}
private:
const Graph& m_g;
};
template <typename Graph>
inline degree_property_map<Graph>
make_degree_map(const Graph& g) {
return degree_property_map<Graph>(g);
}
//========================================================================
// Iterator Property Map Generating Functions contributed by
// Kevin Vanhorn. (see also the property map generating functions
// in boost/property_map/property_map.hpp)
#if !defined(BOOST_NO_STD_ITERATOR_TRAITS)
// A helper function for creating a vertex property map out of a
// random access iterator and the internal vertex index map from a
// graph.
template <class PropertyGraph, class RandomAccessIterator>
inline
iterator_property_map<
RandomAccessIterator,
typename property_map<PropertyGraph, vertex_index_t>::type,
typename std::iterator_traits<RandomAccessIterator>::value_type,
typename std::iterator_traits<RandomAccessIterator>::reference
>
make_iterator_vertex_map(RandomAccessIterator iter, const PropertyGraph& g)
{
return make_iterator_property_map(iter, get(vertex_index, g));
}
// Use this next function when vertex_descriptor is known to be an
// integer type, with values ranging from 0 to num_vertices(g).
//
template <class RandomAccessIterator>
inline
iterator_property_map<
RandomAccessIterator,
identity_property_map,
typename std::iterator_traits<RandomAccessIterator>::value_type,
typename std::iterator_traits<RandomAccessIterator>::reference
>
make_iterator_vertex_map(RandomAccessIterator iter)
{
return make_iterator_property_map(iter, identity_property_map());
}
#endif
template <class PropertyGraph, class RandomAccessContainer>
inline
iterator_property_map<
typename RandomAccessContainer::iterator,
typename property_map<PropertyGraph, vertex_index_t>::type,
typename RandomAccessContainer::value_type,
typename RandomAccessContainer::reference
>
make_container_vertex_map(RandomAccessContainer& c, const PropertyGraph& g)
{
BOOST_ASSERT(c.size() >= num_vertices(g));
return make_iterator_vertex_map(c.begin(), g);
}
template <class RandomAccessContainer> inline
iterator_property_map<
typename RandomAccessContainer::iterator,
identity_property_map,
typename RandomAccessContainer::value_type,
typename RandomAccessContainer::reference
>
make_container_vertex_map(RandomAccessContainer& c)
{
return make_iterator_vertex_map(c.begin());
}
// NOTE: These functions are declared, but never defined since they need to
// be overloaded by graph implementations. However, we need them to be
// declared for the functions below.
template<typename Graph, typename Tag>
typename graph_property<Graph, graph_bundle_t>::type&
get_property(Graph& g, Tag);
template<typename Graph, typename Tag>
typename graph_property<Graph, graph_bundle_t>::type const&
get_property(Graph const& g, Tag);
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
// NOTE: This operation is a simple adaptor over the overloaded get_property
// operations.
template<typename Graph>
inline typename graph_property<Graph, graph_bundle_t>::type&
get_property(Graph& g) {
return get_property(g, graph_bundle);
}
template<typename Graph>
inline typename graph_property<Graph, graph_bundle_t>::type const&
get_property(const Graph& g) {
return get_property(g, graph_bundle);
}
#endif
} // namespace boost
#endif /* BOOST_GRAPH_PROPERTIES_HPP */
@@ -0,0 +1,92 @@
// (C) Copyright 2007-2009 Andrew Sutton
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GRAPH_CONSTANT_PROPERTY_HPP
#define BOOST_GRAPH_CONSTANT_PROPERTY_HPP
#include <boost/property_map/property_map.hpp>
// TODO: This should really be part of the property maps library rather than
// the Boost.Graph library.
namespace boost {
/**
* A constant property is one, that regardless of the edge or vertex given,
* will always return a constant value.
*/
template <typename Key, typename Value>
struct constant_property_map
: public boost::put_get_helper<
const Value&,
constant_property_map<Key, Value>
>
{
typedef Key key_type;
typedef Value value_type;
typedef const Value& reference;
typedef boost::readable_property_map_tag category;
constant_property_map()
: m_value()
{ }
constant_property_map(const value_type &value)
: m_value(value)
{ }
constant_property_map(const constant_property_map& copy)
: m_value(copy.m_value)
{ }
inline reference operator [](const key_type&) const
{ return m_value; }
value_type m_value;
};
template <typename Key, typename Value>
inline constant_property_map<Key, Value>
make_constant_property(const Value& value)
{ return constant_property_map<Key, Value>(value); }
/**
* Same as above, but pretends to be writable as well.
*/
template <typename Key, typename Value>
struct constant_writable_property_map {
typedef Key key_type;
typedef Value value_type;
typedef Value& reference;
typedef boost::read_write_property_map_tag category;
constant_writable_property_map()
: m_value()
{ }
constant_writable_property_map(const value_type &value)
: m_value(value)
{ }
constant_writable_property_map(const constant_writable_property_map& copy)
: m_value(copy.m_value)
{ }
friend Value get(const constant_writable_property_map& me, Key) {return me.m_value;}
friend void put(const constant_writable_property_map&, Key, Value) {}
value_type m_value;
};
template <typename Key, typename Value>
inline constant_writable_property_map<Key, Value>
make_constant_writable_property(const Value& value)
{ return constant_writable_property_map<Key, Value>(value); }
} /* namespace boost */
#endif
@@ -0,0 +1,41 @@
// (C) Copyright Andrew Sutton 2007
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GRAPH_NULL_PROPERTY_HPP
#define BOOST_GRAPH_NULL_PROPERTY_HPP
#include <boost/property_map/property_map.hpp>
// TODO: This should really be part of the property maps library rather than
// the Boost.Graph library.
namespace boost
{
// A null property is somewhat like the inverse of the constant
// property map except that instead of returning a single value,
// this eats any writes and cannot be read from.
template <typename Key, typename Value>
struct null_property_map
{
typedef Key key_type;
typedef Value value_type;
typedef void reference;
typedef boost::writable_property_map_tag category;
};
// The null_property_map<K,V> only has a put() function.
template <typename K, typename V>
void put(null_property_map<K,V>& /*pm*/, const K& /*key*/, const V& /*value*/)
{ }
// A helper function for intantiating null property maps.
template <typename Key, typename Value>
inline null_property_map<Key, Value> make_null_property()
{ return null_property_map<Key, Value>(); }
}
#endif
+527
View File
@@ -0,0 +1,527 @@
// (C) Copyright David Abrahams 2000.
// 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)
#ifndef REVERSE_GRAPH_DWA092300_H_
# define REVERSE_GRAPH_DWA092300_H_
#include <boost/graph/adjacency_iterator.hpp>
#include <boost/graph/properties.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
namespace boost {
struct reverse_graph_tag { };
namespace detail {
template <typename EdgeDesc>
class reverse_graph_edge_descriptor {
public:
EdgeDesc underlying_descx; // Odd name is because this needs to be public but shouldn't be exposed to users anymore
private:
typedef EdgeDesc base_descriptor_type;
public:
explicit reverse_graph_edge_descriptor(const EdgeDesc& underlying_descx = EdgeDesc())
: underlying_descx(underlying_descx) {}
friend bool operator==(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
return a.underlying_descx == b.underlying_descx;
}
friend bool operator!=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
return a.underlying_descx != b.underlying_descx;
}
friend bool operator<(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
return a.underlying_descx < b.underlying_descx;
}
friend bool operator>(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
return a.underlying_descx > b.underlying_descx;
}
friend bool operator<=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
return a.underlying_descx <= b.underlying_descx;
}
friend bool operator>=(const reverse_graph_edge_descriptor& a, const reverse_graph_edge_descriptor& b) {
return a.underlying_descx >= b.underlying_descx;
}
};
template <typename EdgeDesc>
struct reverse_graph_edge_descriptor_maker {
typedef reverse_graph_edge_descriptor<EdgeDesc> result_type;
reverse_graph_edge_descriptor<EdgeDesc> operator()(const EdgeDesc& ed) const {
return reverse_graph_edge_descriptor<EdgeDesc>(ed);
}
};
template <typename EdgeDesc, typename Iter>
std::pair<transform_iterator<reverse_graph_edge_descriptor_maker<EdgeDesc>, Iter>,
transform_iterator<reverse_graph_edge_descriptor_maker<EdgeDesc>, Iter> >
reverse_edge_iter_pair(const std::pair<Iter, Iter>& ip) {
return std::make_pair(make_transform_iterator(ip.first, reverse_graph_edge_descriptor_maker<EdgeDesc>()),
make_transform_iterator(ip.second, reverse_graph_edge_descriptor_maker<EdgeDesc>()));
}
// Get the underlying descriptor from a vertex or edge descriptor
template <typename Desc>
struct get_underlying_descriptor_from_reverse_descriptor {
typedef Desc type;
static Desc convert(const Desc& d) {return d;}
};
template <typename Desc>
struct get_underlying_descriptor_from_reverse_descriptor<reverse_graph_edge_descriptor<Desc> > {
typedef Desc type;
static Desc convert(const reverse_graph_edge_descriptor<Desc>& d) {return d.underlying_descx;}
};
template <bool isEdgeList> struct choose_rev_edge_iter { };
template <> struct choose_rev_edge_iter<true> {
template <class G> struct bind_ {
typedef transform_iterator<reverse_graph_edge_descriptor_maker<typename graph_traits<G>::edge_descriptor>, typename graph_traits<G>::edge_iterator> type;
};
};
template <> struct choose_rev_edge_iter<false> {
template <class G> struct bind_ {
typedef void type;
};
};
} // namespace detail
template <class BidirectionalGraph, class GraphRef = const BidirectionalGraph&>
class reverse_graph {
typedef reverse_graph<BidirectionalGraph, GraphRef> Self;
typedef graph_traits<BidirectionalGraph> Traits;
public:
typedef BidirectionalGraph base_type;
typedef GraphRef base_ref_type;
// Constructor
reverse_graph(GraphRef g) : m_g(g) {}
// Conversion from reverse_graph on non-const reference to one on const reference
reverse_graph(const reverse_graph<BidirectionalGraph, BidirectionalGraph&>& o): m_g(o.m_g) {}
// Graph requirements
typedef typename Traits::vertex_descriptor vertex_descriptor;
typedef detail::reverse_graph_edge_descriptor<typename Traits::edge_descriptor> edge_descriptor;
typedef typename Traits::directed_category directed_category;
typedef typename Traits::edge_parallel_category edge_parallel_category;
typedef typename Traits::traversal_category traversal_category;
// IncidenceGraph requirements
typedef transform_iterator<detail::reverse_graph_edge_descriptor_maker<typename Traits::edge_descriptor>, typename Traits::in_edge_iterator> out_edge_iterator;
typedef typename Traits::degree_size_type degree_size_type;
// BidirectionalGraph requirements
typedef transform_iterator<detail::reverse_graph_edge_descriptor_maker<typename Traits::edge_descriptor>, typename Traits::out_edge_iterator> in_edge_iterator;
// AdjacencyGraph requirements
typedef typename adjacency_iterator_generator<Self, vertex_descriptor, out_edge_iterator>::type adjacency_iterator;
// VertexListGraph requirements
typedef typename Traits::vertex_iterator vertex_iterator;
// EdgeListGraph requirements
enum { is_edge_list = is_convertible<traversal_category,
edge_list_graph_tag>::value };
typedef detail::choose_rev_edge_iter<is_edge_list> ChooseEdgeIter;
typedef typename ChooseEdgeIter::
template bind_<BidirectionalGraph>::type edge_iterator;
typedef typename Traits::vertices_size_type vertices_size_type;
typedef typename Traits::edges_size_type edges_size_type;
typedef reverse_graph_tag graph_tag;
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
// Bundled properties support
template<typename Descriptor>
typename graph::detail::bundled_result<
BidirectionalGraph,
typename detail::get_underlying_descriptor_from_reverse_descriptor<Descriptor>::type
>::type&
operator[](Descriptor x)
{ return m_g[detail::get_underlying_descriptor_from_reverse_descriptor<Descriptor>::convert(x)]; }
template<typename Descriptor>
typename graph::detail::bundled_result<
BidirectionalGraph,
typename detail::get_underlying_descriptor_from_reverse_descriptor<Descriptor>::type
>::type const&
operator[](Descriptor x) const
{ return m_g[detail::get_underlying_descriptor_from_reverse_descriptor<Descriptor>::convert(x)]; }
#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
static vertex_descriptor null_vertex()
{ return Traits::null_vertex(); }
// would be private, but template friends aren't portable enough.
// private:
GraphRef m_g;
};
// These are separate so they are not instantiated unless used (see bug 1021)
template <class BidirectionalGraph, class GraphRef>
struct vertex_property_type<reverse_graph<BidirectionalGraph, GraphRef> > {
typedef typename boost::vertex_property_type<BidirectionalGraph>::type type;
};
template <class BidirectionalGraph, class GraphRef>
struct edge_property_type<reverse_graph<BidirectionalGraph, GraphRef> > {
typedef typename boost::edge_property_type<BidirectionalGraph>::type type;
};
template <class BidirectionalGraph, class GraphRef>
struct graph_property_type<reverse_graph<BidirectionalGraph, GraphRef> > {
typedef typename boost::graph_property_type<BidirectionalGraph>::type type;
};
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
template<typename Graph, typename GraphRef>
struct vertex_bundle_type<reverse_graph<Graph, GraphRef> >
: vertex_bundle_type<Graph> { };
template<typename Graph, typename GraphRef>
struct edge_bundle_type<reverse_graph<Graph, GraphRef> >
: edge_bundle_type<Graph> { };
template<typename Graph, typename GraphRef>
struct graph_bundle_type<reverse_graph<Graph, GraphRef> >
: graph_bundle_type<Graph> { };
#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
template <class BidirectionalGraph>
inline reverse_graph<BidirectionalGraph>
make_reverse_graph(const BidirectionalGraph& g)
{
return reverse_graph<BidirectionalGraph>(g);
}
template <class BidirectionalGraph>
inline reverse_graph<BidirectionalGraph, BidirectionalGraph&>
make_reverse_graph(BidirectionalGraph& g)
{
return reverse_graph<BidirectionalGraph, BidirectionalGraph&>(g);
}
template <class BidirectionalGraph, class GRef>
std::pair<typename reverse_graph<BidirectionalGraph>::vertex_iterator,
typename reverse_graph<BidirectionalGraph>::vertex_iterator>
vertices(const reverse_graph<BidirectionalGraph,GRef>& g)
{
return vertices(g.m_g);
}
template <class BidirectionalGraph, class GRef>
std::pair<typename reverse_graph<BidirectionalGraph>::edge_iterator,
typename reverse_graph<BidirectionalGraph>::edge_iterator>
edges(const reverse_graph<BidirectionalGraph,GRef>& g)
{
return detail::reverse_edge_iter_pair<typename graph_traits<BidirectionalGraph>::edge_descriptor>(edges(g.m_g));
}
template <class BidirectionalGraph, class GRef>
inline std::pair<typename reverse_graph<BidirectionalGraph>::out_edge_iterator,
typename reverse_graph<BidirectionalGraph>::out_edge_iterator>
out_edges(const typename graph_traits<BidirectionalGraph>::vertex_descriptor u,
const reverse_graph<BidirectionalGraph,GRef>& g)
{
return detail::reverse_edge_iter_pair<typename graph_traits<BidirectionalGraph>::edge_descriptor>(in_edges(u, g.m_g));
}
template <class BidirectionalGraph, class GRef>
inline typename graph_traits<BidirectionalGraph>::vertices_size_type
num_vertices(const reverse_graph<BidirectionalGraph,GRef>& g)
{
return num_vertices(g.m_g);
}
template <class BidirectionalGraph, class GRef>
inline typename reverse_graph<BidirectionalGraph>::edges_size_type
num_edges(const reverse_graph<BidirectionalGraph,GRef>& g)
{
return num_edges(g.m_g);
}
template <class BidirectionalGraph, class GRef>
inline typename graph_traits<BidirectionalGraph>::degree_size_type
out_degree(const typename graph_traits<BidirectionalGraph>::vertex_descriptor u,
const reverse_graph<BidirectionalGraph,GRef>& g)
{
return in_degree(u, g.m_g);
}
template <class BidirectionalGraph, class GRef>
inline typename graph_traits<BidirectionalGraph>::vertex_descriptor
vertex(const typename graph_traits<BidirectionalGraph>::vertices_size_type v,
const reverse_graph<BidirectionalGraph,GRef>& g)
{
return vertex(v, g.m_g);
}
template <class BidirectionalGraph, class GRef>
inline std::pair< typename graph_traits<reverse_graph<BidirectionalGraph,GRef> >::edge_descriptor,
bool>
edge(const typename graph_traits<BidirectionalGraph>::vertex_descriptor u,
const typename graph_traits<BidirectionalGraph>::vertex_descriptor v,
const reverse_graph<BidirectionalGraph,GRef>& g)
{
typedef typename graph_traits<BidirectionalGraph>::edge_descriptor underlying_edge_descriptor;
std::pair<underlying_edge_descriptor, bool> e = edge(v, u, g.m_g);
return std::make_pair(detail::reverse_graph_edge_descriptor<underlying_edge_descriptor>(e.first), e.second);
}
template <class BidirectionalGraph, class GRef>
inline std::pair<typename reverse_graph<BidirectionalGraph>::in_edge_iterator,
typename reverse_graph<BidirectionalGraph>::in_edge_iterator>
in_edges(const typename graph_traits<BidirectionalGraph>::vertex_descriptor u,
const reverse_graph<BidirectionalGraph,GRef>& g)
{
return detail::reverse_edge_iter_pair<typename graph_traits<BidirectionalGraph>::edge_descriptor>(out_edges(u, g.m_g));
}
template <class BidirectionalGraph, class GRef>
inline std::pair<typename reverse_graph<BidirectionalGraph,GRef>::adjacency_iterator,
typename reverse_graph<BidirectionalGraph,GRef>::adjacency_iterator>
adjacent_vertices(typename graph_traits<BidirectionalGraph>::vertex_descriptor u,
const reverse_graph<BidirectionalGraph,GRef>& g)
{
typedef reverse_graph<BidirectionalGraph,GRef> Graph;
typename graph_traits<Graph>::out_edge_iterator first, last;
boost::tie(first, last) = out_edges(u, g);
typedef typename graph_traits<Graph>::adjacency_iterator adjacency_iterator;
return std::make_pair(adjacency_iterator(first, const_cast<Graph*>(&g)),
adjacency_iterator(last, const_cast<Graph*>(&g)));
}
template <class BidirectionalGraph, class GRef>
inline typename graph_traits<BidirectionalGraph>::degree_size_type
in_degree(const typename graph_traits<BidirectionalGraph>::vertex_descriptor u,
const reverse_graph<BidirectionalGraph,GRef>& g)
{
return out_degree(u, g.m_g);
}
template <class Edge, class BidirectionalGraph, class GRef>
inline typename graph_traits<BidirectionalGraph>::vertex_descriptor
source(const detail::reverse_graph_edge_descriptor<Edge>& e, const reverse_graph<BidirectionalGraph,GRef>& g)
{
return target(e.underlying_descx, g.m_g);
}
template <class Edge, class BidirectionalGraph, class GRef>
inline typename graph_traits<BidirectionalGraph>::vertex_descriptor
target(const detail::reverse_graph_edge_descriptor<Edge>& e, const reverse_graph<BidirectionalGraph,GRef>& g)
{
return source(e.underlying_descx, g.m_g);
}
template <class BidirectionalGraph, class GRef>
inline typename graph_traits<BidirectionalGraph>::degree_size_type
degree(const typename graph_traits<BidirectionalGraph>::vertex_descriptor u,
const reverse_graph<BidirectionalGraph,GRef>& g)
{
return degree(u, g.m_g);
}
namespace detail {
template <typename PM>
struct reverse_graph_edge_property_map {
private:
PM underlying_pm;
public:
typedef reverse_graph_edge_descriptor<typename property_traits<PM>::key_type> key_type;
typedef typename property_traits<PM>::value_type value_type;
typedef typename property_traits<PM>::reference reference;
typedef typename property_traits<PM>::category category;
explicit reverse_graph_edge_property_map(const PM& pm): underlying_pm(pm) {}
friend reference
get(const reverse_graph_edge_property_map& m,
const key_type& e) {
return get(m.underlying_pm, e.underlying_descx);
}
friend void
put(const reverse_graph_edge_property_map& m,
const key_type& e,
const value_type& v) {
put(m.underlying_pm, e.underlying_descx, v);
}
reference operator[](const key_type& k) const {
return (this->underlying_pm)[k.underlying_descx];
}
};
} // namespace detail
template <class BidirGraph, class GRef, class Property>
struct property_map<reverse_graph<BidirGraph, GRef>, Property> {
typedef boost::is_same<typename detail::property_kind_from_graph<BidirGraph, Property>::type, edge_property_tag> is_edge_prop;
typedef boost::is_const<typename boost::remove_reference<GRef>::type> is_ref_const;
typedef typename boost::mpl::if_<
is_ref_const,
typename property_map<BidirGraph, Property>::const_type,
typename property_map<BidirGraph, Property>::type>::type
orig_type;
typedef typename property_map<BidirGraph, Property>::const_type orig_const_type;
typedef typename boost::mpl::if_<is_edge_prop, detail::reverse_graph_edge_property_map<orig_type>, orig_type>::type type;
typedef typename boost::mpl::if_<is_edge_prop, detail::reverse_graph_edge_property_map<orig_const_type>, orig_const_type>::type const_type;
};
template <class BidirGraph, class GRef, class Property>
struct property_map<const reverse_graph<BidirGraph, GRef>, Property> {
typedef boost::is_same<typename detail::property_kind_from_graph<BidirGraph, Property>::type, edge_property_tag> is_edge_prop;
typedef typename property_map<BidirGraph, Property>::const_type orig_const_type;
typedef typename boost::mpl::if_<is_edge_prop, detail::reverse_graph_edge_property_map<orig_const_type>, orig_const_type>::type const_type;
typedef const_type type;
};
template <class BidirGraph, class GRef, class Property>
typename disable_if<
is_same<Property, edge_underlying_t>,
typename property_map<reverse_graph<BidirGraph,GRef>, Property>::type>::type
get(Property p, reverse_graph<BidirGraph,GRef>& g)
{
return typename property_map<reverse_graph<BidirGraph,GRef>, Property>::type(get(p, g.m_g));
}
template <class BidirGraph, class GRef, class Property>
typename disable_if<
is_same<Property, edge_underlying_t>,
typename property_map<reverse_graph<BidirGraph,GRef>, Property>::const_type>::type
get(Property p, const reverse_graph<BidirGraph,GRef>& g)
{
const BidirGraph& gref = g.m_g; // in case GRef is non-const
return typename property_map<reverse_graph<BidirGraph,GRef>, Property>::const_type(get(p, gref));
}
template <class BidirectionalGraph, class GRef, class Property, class Key>
typename disable_if<
is_same<Property, edge_underlying_t>,
typename property_traits<
typename property_map<reverse_graph<BidirectionalGraph, GRef>, Property>::const_type
>::value_type>::type
get(Property p, const reverse_graph<BidirectionalGraph,GRef>& g, const Key& k)
{
return get(get(p, g), k);
}
template <class BidirectionalGraph, class GRef, class Property, class Key, class Value>
void
put(Property p, reverse_graph<BidirectionalGraph,GRef>& g, const Key& k,
const Value& val)
{
put(get(p, g), k, val);
}
// Get the underlying descriptor from a reverse_graph's wrapped edge descriptor
namespace detail {
template <class E>
struct underlying_edge_desc_map_type {
E operator[](const reverse_graph_edge_descriptor<E>& k) const {
return k.underlying_descx;
}
};
template <class E>
E
get(underlying_edge_desc_map_type<E> m,
const reverse_graph_edge_descriptor<E>& k)
{
return m[k];
}
}
template <class E>
struct property_traits<detail::underlying_edge_desc_map_type<E> > {
typedef detail::reverse_graph_edge_descriptor<E> key_type;
typedef E value_type;
typedef const E& reference;
typedef readable_property_map_tag category;
};
template <class Graph, class GRef>
struct property_map<reverse_graph<Graph, GRef>, edge_underlying_t> {
private:
typedef typename graph_traits<Graph>::edge_descriptor ed;
public:
typedef detail::underlying_edge_desc_map_type<ed> type;
typedef detail::underlying_edge_desc_map_type<ed> const_type;
};
template <typename T> struct is_reverse_graph: boost::mpl::false_ {};
template <typename G, typename R> struct is_reverse_graph<reverse_graph<G, R> >: boost::mpl::true_ {};
template <class G>
typename enable_if<is_reverse_graph<G>,
detail::underlying_edge_desc_map_type<typename graph_traits<typename G::base_type>::edge_descriptor> >::type
get(edge_underlying_t,
G&)
{
return detail::underlying_edge_desc_map_type<typename graph_traits<typename G::base_type>::edge_descriptor>();
}
template <class G>
typename enable_if<is_reverse_graph<G>, typename graph_traits<typename G::base_type>::edge_descriptor>::type
get(edge_underlying_t,
G&,
const typename graph_traits<G>::edge_descriptor& k)
{
return k.underlying_descx;
}
template <class G>
typename enable_if<is_reverse_graph<G>, detail::underlying_edge_desc_map_type<typename graph_traits<typename G::base_type>::edge_descriptor> >::type
get(edge_underlying_t,
const G&)
{
return detail::underlying_edge_desc_map_type<typename graph_traits<typename G::base_type>::edge_descriptor>();
}
template <class G>
typename enable_if<is_reverse_graph<G>, typename graph_traits<typename G::base_type>::edge_descriptor>::type
get(edge_underlying_t,
const G&,
const typename graph_traits<G>::edge_descriptor& k)
{
return k.underlying_descx;
}
// Access to wrapped graph's graph properties
template<typename BidirectionalGraph, typename GRef, typename Tag,
typename Value>
inline void
set_property(const reverse_graph<BidirectionalGraph,GRef>& g, Tag tag,
const Value& value)
{
set_property(g.m_g, tag, value);
}
template<typename BidirectionalGraph, typename GRef, typename Tag>
inline
typename boost::mpl::if_<
boost::is_const<typename boost::remove_reference<GRef>::type>,
const typename graph_property<BidirectionalGraph, Tag>::type&,
typename graph_property<BidirectionalGraph, Tag>::type& >::type
get_property(const reverse_graph<BidirectionalGraph,GRef>& g, Tag tag)
{
return get_property(g.m_g, tag);
}
} // namespace boost
#endif
+109
View File
@@ -0,0 +1,109 @@
// Copyright (C) 2005-2006 The Trustees of Indiana University.
// 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)
// Authors: Jeremiah Willcock
// Douglas Gregor
// Andrew Lumsdaine
// Two bit per color property map
#ifndef BOOST_TWO_BIT_COLOR_MAP_HPP
#define BOOST_TWO_BIT_COLOR_MAP_HPP
#include <boost/property_map/property_map.hpp>
#include <boost/graph/properties.hpp>
#include <boost/shared_array.hpp>
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <algorithm>
#include <limits>
namespace boost {
enum two_bit_color_type {
two_bit_white = 0,
two_bit_gray = 1,
two_bit_green = 2,
two_bit_black = 3
};
template <>
struct color_traits<two_bit_color_type>
{
static two_bit_color_type white() { return two_bit_white; }
static two_bit_color_type gray() { return two_bit_gray; }
static two_bit_color_type green() { return two_bit_green; }
static two_bit_color_type black() { return two_bit_black; }
};
template<typename IndexMap = identity_property_map>
struct two_bit_color_map
{
std::size_t n;
IndexMap index;
shared_array<unsigned char> data;
BOOST_STATIC_CONSTANT(int, bits_per_char = std::numeric_limits<unsigned char>::digits);
BOOST_STATIC_CONSTANT(int, elements_per_char = bits_per_char / 2);
typedef typename property_traits<IndexMap>::key_type key_type;
typedef two_bit_color_type value_type;
typedef void reference;
typedef read_write_property_map_tag category;
explicit two_bit_color_map(std::size_t n, const IndexMap& index = IndexMap())
: n(n), index(index), data(new unsigned char[(n + elements_per_char - 1) / elements_per_char])
{
// Fill to white
std::fill(data.get(), data.get() + (n + elements_per_char - 1) / elements_per_char, 0);
}
};
template<typename IndexMap>
inline two_bit_color_type
get(const two_bit_color_map<IndexMap>& pm,
typename property_traits<IndexMap>::key_type key)
{
BOOST_STATIC_CONSTANT(int, elements_per_char = two_bit_color_map<IndexMap>::elements_per_char);
typename property_traits<IndexMap>::value_type i = get(pm.index, key);
BOOST_ASSERT ((std::size_t)i < pm.n);
std::size_t byte_num = i / elements_per_char;
std::size_t bit_position = ((i % elements_per_char) * 2);
return two_bit_color_type((pm.data.get()[byte_num] >> bit_position) & 3);
}
template<typename IndexMap>
inline void
put(const two_bit_color_map<IndexMap>& pm,
typename property_traits<IndexMap>::key_type key,
two_bit_color_type value)
{
BOOST_STATIC_CONSTANT(int, elements_per_char = two_bit_color_map<IndexMap>::elements_per_char);
typename property_traits<IndexMap>::value_type i = get(pm.index, key);
BOOST_ASSERT ((std::size_t)i < pm.n);
BOOST_ASSERT (value >= 0 && value < 4);
std::size_t byte_num = i / elements_per_char;
std::size_t bit_position = ((i % elements_per_char) * 2);
pm.data.get()[byte_num] =
(unsigned char)
((pm.data.get()[byte_num] & ~(3 << bit_position))
| (value << bit_position));
}
template<typename IndexMap>
inline two_bit_color_map<IndexMap>
make_two_bit_color_map(std::size_t n, const IndexMap& index_map)
{
return two_bit_color_map<IndexMap>(n, index_map);
}
} // end namespace boost
#endif // BOOST_TWO_BIT_COLOR_MAP_HPP
#ifdef BOOST_GRAPH_USE_MPI
# include <boost/graph/distributed/two_bit_color_map.hpp>
#endif
+300
View File
@@ -0,0 +1,300 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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)
//=======================================================================
//
// Revision History:
// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)
//
#ifndef BOOST_GRAPH_GRAPH_SEARCH_VISITORS_HPP
#define BOOST_GRAPH_GRAPH_SEARCH_VISITORS_HPP
#include <iosfwd>
#include <boost/config.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/limits.hpp>
namespace boost {
// This is a bit more convenient than std::numeric_limits because
// you don't have to explicitly provide type T.
template <class T>
inline T numeric_limits_max(T) { return (std::numeric_limits<T>::max)(); }
//========================================================================
// Event Tags
namespace detail {
// For partial specialization workaround
enum event_visitor_enum
{ on_no_event_num,
on_initialize_vertex_num, on_start_vertex_num,
on_discover_vertex_num, on_finish_vertex_num, on_examine_vertex_num,
on_examine_edge_num, on_tree_edge_num, on_non_tree_edge_num,
on_gray_target_num, on_black_target_num,
on_forward_or_cross_edge_num, on_back_edge_num, on_finish_edge_num,
on_edge_relaxed_num, on_edge_not_relaxed_num,
on_edge_minimized_num, on_edge_not_minimized_num
};
template<typename Event, typename Visitor>
struct functor_to_visitor : Visitor
{
typedef Event event_filter;
functor_to_visitor(const Visitor& visitor) : Visitor(visitor) {}
};
} // namespace detail
struct on_no_event { enum { num = detail::on_no_event_num }; };
struct on_initialize_vertex {
enum { num = detail::on_initialize_vertex_num }; };
struct on_start_vertex { enum { num = detail::on_start_vertex_num }; };
struct on_discover_vertex { enum { num = detail::on_discover_vertex_num }; };
struct on_examine_vertex { enum { num = detail::on_examine_vertex_num }; };
struct on_finish_vertex { enum { num = detail::on_finish_vertex_num }; };
struct on_examine_edge { enum { num = detail::on_examine_edge_num }; };
struct on_tree_edge { enum { num = detail::on_tree_edge_num }; };
struct on_non_tree_edge { enum { num = detail::on_non_tree_edge_num }; };
struct on_gray_target { enum { num = detail::on_gray_target_num }; };
struct on_black_target { enum { num = detail::on_black_target_num }; };
struct on_forward_or_cross_edge {
enum { num = detail::on_forward_or_cross_edge_num }; };
struct on_back_edge { enum { num = detail::on_back_edge_num }; };
struct on_finish_edge { enum { num = detail::on_finish_edge_num }; };
struct on_edge_relaxed { enum { num = detail::on_edge_relaxed_num }; };
struct on_edge_not_relaxed {
enum { num = detail::on_edge_not_relaxed_num }; };
struct on_edge_minimized { enum { num = detail::on_edge_minimized_num }; };
struct on_edge_not_minimized {
enum { num = detail::on_edge_not_minimized_num }; };
//========================================================================
// base_visitor and null_visitor
// needed for MSVC workaround
template <class Visitor>
struct base_visitor {
typedef on_no_event event_filter;
template <class T, class Graph>
void operator()(T, Graph&) { }
};
struct null_visitor : public base_visitor<null_visitor> {
typedef on_no_event event_filter;
template <class T, class Graph>
void operator()(T, Graph&) { }
};
//========================================================================
// The invoke_visitors() function
namespace detail {
template <class Visitor, class T, class Graph>
inline void invoke_dispatch(Visitor& v, T x, Graph& g, mpl::true_) {
v(x, g);
}
template <class Visitor, class T, class Graph>
inline void invoke_dispatch(Visitor&, T, Graph&, mpl::false_)
{ }
} // namespace detail
template <class Visitor, class Rest, class T, class Graph, class Tag>
inline void
invoke_visitors(std::pair<Visitor, Rest>& vlist, T x, Graph& g, Tag tag) {
typedef typename Visitor::event_filter Category;
typedef typename is_same<Category, Tag>::type IsSameTag;
detail::invoke_dispatch(vlist.first, x, g, IsSameTag());
invoke_visitors(vlist.second, x, g, tag);
}
template <class Visitor, class T, class Graph, class Tag>
inline void
invoke_visitors(Visitor& v, T x, Graph& g, Tag) {
typedef typename Visitor::event_filter Category;
typedef typename is_same<Category, Tag>::type IsSameTag;
detail::invoke_dispatch(v, x, g, IsSameTag());
}
//========================================================================
// predecessor_recorder
template <class PredecessorMap, class Tag>
struct predecessor_recorder
: public base_visitor<predecessor_recorder<PredecessorMap, Tag> >
{
typedef Tag event_filter;
predecessor_recorder(PredecessorMap pa) : m_predecessor(pa) { }
template <class Edge, class Graph>
void operator()(Edge e, const Graph& g) {
put(m_predecessor, target(e, g), source(e, g));
}
PredecessorMap m_predecessor;
};
template <class PredecessorMap, class Tag>
predecessor_recorder<PredecessorMap, Tag>
record_predecessors(PredecessorMap pa, Tag) {
return predecessor_recorder<PredecessorMap, Tag> (pa);
}
//========================================================================
// edge_predecessor_recorder
template <class PredEdgeMap, class Tag>
struct edge_predecessor_recorder
: public base_visitor<edge_predecessor_recorder<PredEdgeMap, Tag> >
{
typedef Tag event_filter;
edge_predecessor_recorder(PredEdgeMap pa) : m_predecessor(pa) { }
template <class Edge, class Graph>
void operator()(Edge e, const Graph& g) {
put(m_predecessor, target(e, g), e);
}
PredEdgeMap m_predecessor;
};
template <class PredEdgeMap, class Tag>
edge_predecessor_recorder<PredEdgeMap, Tag>
record_edge_predecessors(PredEdgeMap pa, Tag) {
return edge_predecessor_recorder<PredEdgeMap, Tag> (pa);
}
//========================================================================
// distance_recorder
template <class DistanceMap, class Tag>
struct distance_recorder
: public base_visitor<distance_recorder<DistanceMap, Tag> >
{
typedef Tag event_filter;
distance_recorder(DistanceMap pa) : m_distance(pa) { }
template <class Edge, class Graph>
void operator()(Edge e, const Graph& g) {
typename graph_traits<Graph>::vertex_descriptor
u = source(e, g), v = target(e, g);
put(m_distance, v, get(m_distance, u) + 1);
}
DistanceMap m_distance;
};
template <class DistanceMap, class Tag>
distance_recorder<DistanceMap, Tag>
record_distances(DistanceMap pa, Tag) {
return distance_recorder<DistanceMap, Tag> (pa);
}
//========================================================================
// time_stamper
template <class TimeMap, class TimeT, class Tag>
struct time_stamper
: public base_visitor<time_stamper<TimeMap, TimeT, Tag> >
{
typedef Tag event_filter;
time_stamper(TimeMap pa, TimeT& t) : m_time_pa(pa), m_time(t) { }
template <class Vertex, class Graph>
void operator()(Vertex u, const Graph&) {
put(m_time_pa, u, ++m_time);
}
TimeMap m_time_pa;
TimeT& m_time;
};
template <class TimeMap, class TimeT, class Tag>
time_stamper<TimeMap, TimeT, Tag>
stamp_times(TimeMap pa, TimeT& time_counter, Tag) {
return time_stamper<TimeMap, TimeT, Tag>(pa, time_counter);
}
//========================================================================
// property_writer
template <class PA, class OutputIterator, class Tag>
struct property_writer
: public base_visitor<property_writer<PA, OutputIterator, Tag> >
{
typedef Tag event_filter;
property_writer(PA pa, OutputIterator out) : m_pa(pa), m_out(out) { }
template <class T, class Graph>
void operator()(T x, Graph&) { *m_out++ = get(m_pa, x); }
PA m_pa;
OutputIterator m_out;
};
template <class PA, class OutputIterator, class Tag>
property_writer<PA, OutputIterator, Tag>
write_property(PA pa, OutputIterator out, Tag) {
return property_writer<PA, OutputIterator, Tag>(pa, out);
}
//========================================================================
// property_put
/**
* Functor which just sets a given value to a vertex or edge in a property map.
*/
template <typename PropertyMap, typename EventTag>
struct property_put
{
typedef EventTag event_filter;
property_put (PropertyMap property_map,
typename property_traits <PropertyMap>::value_type value) :
property_map_ (property_map), value_ (value)
{}
template <typename VertexOrEdge, typename Graph>
void operator() (VertexOrEdge v, const Graph&)
{
put (property_map_, v, value_);
}
private:
PropertyMap property_map_;
typename property_traits <PropertyMap>::value_type value_;
};
/**
* Creates a property_put functor which just sets a given value to a vertex or edge.
*
* @param property_map Given writeable property map
* @param value Fixed value of the map
* @param tag Event Filter
* @return The functor.
*/
template <typename PropertyMap, typename EventTag>
inline property_put <PropertyMap, EventTag>
put_property (PropertyMap property_map,
typename property_traits <PropertyMap>::value_type value,
EventTag)
{
return property_put <PropertyMap, EventTag> (property_map, value);
}
#define BOOST_GRAPH_EVENT_STUB(Event,Kind) \
typedef ::boost::Event Event##_type; \
template<typename Visitor> \
Kind##_visitor<std::pair<detail::functor_to_visitor<Event##_type, \
Visitor>, Visitors> > \
do_##Event(Visitor visitor) \
{ \
typedef std::pair<detail::functor_to_visitor<Event##_type, Visitor>, \
Visitors> visitor_list; \
typedef Kind##_visitor<visitor_list> result_type; \
return result_type(visitor_list(visitor, m_vis)); \
}
} /* namespace boost */
#endif