mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-06-26 13:33:15 -04:00
Squashed 'boost/' content from commit b4feb19f2
git-subtree-dir: boost git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user