Imported existing code
This commit is contained in:
114
libraries/include/boost/graph/adj_list_serialize.hpp
Normal file
114
libraries/include/boost/graph/adj_list_serialize.hpp
Normal file
@@ -0,0 +1,114 @@
|
||||
//=======================================================================
|
||||
// Copyright 2005 Jeremy G. Siek
|
||||
// Authors: 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 ADJ_LIST_SERIALIZE_HPP
|
||||
#define ADJ_LIST_SERIALIZE_HPP
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/pending/property_serialize.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/serialization/collections_save_imp.hpp>
|
||||
#include <boost/serialization/collections_load_imp.hpp>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
// Turn off tracking for adjacency_list. It's not polymorphic, and we
|
||||
// need to do this to enable saving of non-const adjacency lists.
|
||||
template<class OEL, class VL, class D, class VP, class EP, class GP, class EL>
|
||||
struct tracking_level<boost::adjacency_list<OEL,VL,D,VP,EP,GP,EL> > {
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_<track_never> type;
|
||||
BOOST_STATIC_CONSTANT(int, value = tracking_level::type::value);
|
||||
};
|
||||
|
||||
template<class Archive, class OEL, class VL, class D,
|
||||
class VP, class EP, class GP, class EL>
|
||||
inline void save(
|
||||
Archive & ar,
|
||||
const boost::adjacency_list<OEL,VL,D,VP,EP,GP,EL> &graph,
|
||||
const unsigned int /* file_version */
|
||||
){
|
||||
typedef adjacency_list<OEL,VL,D,VP,EP,GP,EL> Graph;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
|
||||
int V = num_vertices(graph);
|
||||
int E = num_edges(graph);
|
||||
ar << BOOST_SERIALIZATION_NVP(V);
|
||||
ar << BOOST_SERIALIZATION_NVP(E);
|
||||
|
||||
// assign indices to vertices
|
||||
std::map<Vertex,int> indices;
|
||||
int num = 0;
|
||||
typename graph_traits<Graph>::vertex_iterator vi;
|
||||
for (vi = vertices(graph).first; vi != vertices(graph).second; ++vi) {
|
||||
indices[*vi] = num++;
|
||||
ar << serialization::make_nvp("vertex_property", get(vertex_all_t(), graph, *vi) );
|
||||
}
|
||||
|
||||
// write edges
|
||||
typename graph_traits<Graph>::edge_iterator ei;
|
||||
for (ei = edges(graph).first; ei != edges(graph).second; ++ei){
|
||||
ar << serialization::make_nvp("u" , indices[source(*ei,graph)]);
|
||||
ar << serialization::make_nvp("v" , indices[target(*ei,graph)]);
|
||||
ar << serialization::make_nvp("edge_property", get(edge_all_t(), graph, *ei) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Archive, class OEL, class VL, class D,
|
||||
class VP, class EP, class GP, class EL>
|
||||
inline void load(
|
||||
Archive & ar,
|
||||
boost::adjacency_list<OEL,VL,D,VP,EP,GP,EL> &graph,
|
||||
const unsigned int /* file_version */
|
||||
){
|
||||
typedef adjacency_list<OEL,VL,D,VP,EP,GP,EL> Graph;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor Edge;
|
||||
|
||||
unsigned int V;
|
||||
ar >> BOOST_SERIALIZATION_NVP(V);
|
||||
unsigned int E;
|
||||
ar >> BOOST_SERIALIZATION_NVP(E);
|
||||
|
||||
std::vector<Vertex> verts(V);
|
||||
int i = 0;
|
||||
while(V-- > 0){
|
||||
Vertex v = add_vertex(graph);
|
||||
verts[i++] = v;
|
||||
ar >> serialization::make_nvp("vertex_property", get(vertex_all_t(), graph, v) );
|
||||
}
|
||||
while(E-- > 0){
|
||||
int u; int v;
|
||||
ar >> BOOST_SERIALIZATION_NVP(u);
|
||||
ar >> BOOST_SERIALIZATION_NVP(v);
|
||||
Edge e; bool inserted;
|
||||
tie(e,inserted) = add_edge(verts[u], verts[v], graph);
|
||||
ar >> serialization::make_nvp("edge_property", get(edge_all_t(), graph, e) );
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive, class OEL, class VL, class D, class VP, class EP, class GP, class EL>
|
||||
inline void serialize(
|
||||
Archive & ar,
|
||||
boost::adjacency_list<OEL,VL,D,VP,EP,GP,EL> &graph,
|
||||
const unsigned int file_version
|
||||
){
|
||||
boost::serialization::split_free(ar, graph, file_version);
|
||||
}
|
||||
|
||||
}//serialization
|
||||
}//boost
|
||||
|
||||
|
||||
#endif // ADJ_LIST_SERIALIZE_HPP
|
||||
102
libraries/include/boost/graph/adjacency_iterator.hpp
Normal file
102
libraries/include/boost/graph/adjacency_iterator.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
//=======================================================================
|
||||
// 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/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
|
||||
581
libraries/include/boost/graph/adjacency_list.hpp
Normal file
581
libraries/include/boost/graph/adjacency_list.hpp
Normal file
@@ -0,0 +1,581 @@
|
||||
//=======================================================================
|
||||
// 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_ADJACENCY_LIST_HPP
|
||||
#define BOOST_GRAPH_ADJACENCY_LIST_HPP
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
// TODO: Deprecating this requires some cooperation from Boost.Config. It's not
|
||||
// a good idea to just refuse the inclusion because it could break otherwise
|
||||
// functioning code.
|
||||
#if !defined BOOST_NO_HASH
|
||||
# ifdef BOOST_HASH_SET_HEADER
|
||||
# include BOOST_HASH_SET_HEADER
|
||||
# else
|
||||
# include <hash_set>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined BOOST_NO_SLIST
|
||||
# ifdef BOOST_SLIST_HEADER
|
||||
# include BOOST_SLIST_HEADER
|
||||
# else
|
||||
# include <slist>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/graph_selectors.hpp>
|
||||
#include <boost/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.
|
||||
//
|
||||
// The main container_gen traits class uses partial specialization,
|
||||
// so we also include a workaround.
|
||||
|
||||
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
#if !defined BOOST_NO_SLIST
|
||||
struct slistS {};
|
||||
#endif
|
||||
|
||||
struct vecS { };
|
||||
struct listS { };
|
||||
struct setS { };
|
||||
struct multisetS { };
|
||||
struct mapS { };
|
||||
#if !defined BOOST_NO_HASH
|
||||
struct hash_mapS { };
|
||||
struct hash_setS { };
|
||||
#endif
|
||||
|
||||
template <class Selector, class ValueType>
|
||||
struct container_gen { };
|
||||
|
||||
template <class ValueType>
|
||||
struct container_gen<listS, ValueType> {
|
||||
typedef std::list<ValueType> type;
|
||||
};
|
||||
#if !defined BOOST_NO_SLIST
|
||||
template <class ValueType>
|
||||
struct container_gen<slistS, ValueType> {
|
||||
typedef BOOST_STD_EXTENSION_NAMESPACE::slist<ValueType> type;
|
||||
};
|
||||
#endif
|
||||
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;
|
||||
};
|
||||
|
||||
#if !defined BOOST_NO_HASH
|
||||
template <class ValueType>
|
||||
struct container_gen<hash_mapS, ValueType> {
|
||||
typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set<ValueType> type;
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct container_gen<hash_setS, ValueType> {
|
||||
typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set<ValueType> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
#else // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
#if !defined BOOST_NO_SLIST
|
||||
struct slistS {
|
||||
template <class T>
|
||||
struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::slist<T> type; };
|
||||
};
|
||||
#endif
|
||||
|
||||
struct vecS {
|
||||
template <class T>
|
||||
struct bind_ { typedef std::vector<T> type; };
|
||||
};
|
||||
|
||||
struct listS {
|
||||
template <class T>
|
||||
struct bind_ { typedef std::list<T> type; };
|
||||
};
|
||||
|
||||
struct setS {
|
||||
template <class T>
|
||||
struct bind_ { typedef std::set<T, std::less<T> > type; };
|
||||
};
|
||||
|
||||
struct multisetS {
|
||||
template <class T>
|
||||
struct bind_ { typedef std::multiset<T, std::less<T> > type; };
|
||||
};
|
||||
|
||||
#if !defined BOOST_NO_HASH
|
||||
struct hash_setS {
|
||||
template <class T>
|
||||
struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set<T, std::less<T> > type; };
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mapS {
|
||||
template <class T>
|
||||
struct bind_ { typedef std::set<T, std::less<T> > type; };
|
||||
};
|
||||
|
||||
#if !defined BOOST_NO_HASH
|
||||
struct hash_mapS {
|
||||
template <class T>
|
||||
struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set<T, std::less<T> > type; };
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class Selector> struct container_selector {
|
||||
typedef vecS type;
|
||||
};
|
||||
|
||||
#define BOOST_CONTAINER_SELECTOR(NAME) \
|
||||
template <> struct container_selector<NAME> { \
|
||||
typedef NAME type; \
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_SELECTOR(vecS);
|
||||
BOOST_CONTAINER_SELECTOR(listS);
|
||||
BOOST_CONTAINER_SELECTOR(mapS);
|
||||
BOOST_CONTAINER_SELECTOR(setS);
|
||||
BOOST_CONTAINER_SELECTOR(multisetS);
|
||||
#if !defined BOOST_NO_HASH
|
||||
BOOST_CONTAINER_SELECTOR(hash_mapS);
|
||||
#endif
|
||||
#if !defined BOOST_NO_SLIST
|
||||
BOOST_CONTAINER_SELECTOR(slistS);
|
||||
#endif
|
||||
|
||||
template <class Selector, class ValueType>
|
||||
struct container_gen {
|
||||
typedef typename container_selector<Selector>::type Select;
|
||||
typedef typename Select:: template bind_<ValueType>::type type;
|
||||
};
|
||||
|
||||
#endif // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
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; };
|
||||
|
||||
#if !defined BOOST_NO_SLIST
|
||||
template <>
|
||||
struct parallel_edge_traits<slistS> {
|
||||
typedef allow_parallel_edge_tag type; };
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct parallel_edge_traits<setS> {
|
||||
typedef disallow_parallel_edge_tag type; };
|
||||
|
||||
template <>
|
||||
struct parallel_edge_traits<multisetS> {
|
||||
typedef allow_parallel_edge_tag type; };
|
||||
|
||||
#if !defined BOOST_NO_HASH
|
||||
template <>
|
||||
struct parallel_edge_traits<hash_setS> {
|
||||
typedef disallow_parallel_edge_tag type;
|
||||
};
|
||||
#endif
|
||||
|
||||
// mapS is obsolete, replaced with setS
|
||||
template <>
|
||||
struct parallel_edge_traits<mapS> {
|
||||
typedef disallow_parallel_edge_tag type; };
|
||||
|
||||
#if !defined BOOST_NO_HASH
|
||||
template <>
|
||||
struct parallel_edge_traits<hash_mapS> {
|
||||
typedef disallow_parallel_edge_tag type;
|
||||
};
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// 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 void* vertex_ptr;
|
||||
typedef typename mpl::if_<is_rand_access,
|
||||
std::size_t, vertex_ptr>::type vertex_descriptor;
|
||||
typedef detail::edge_desc_impl<directed_category, vertex_descriptor>
|
||||
edge_descriptor;
|
||||
|
||||
typedef std::size_t vertices_size_type;
|
||||
|
||||
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,
|
||||
#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
|
||||
typename detail::retag_property_list<vertex_bundle_t,
|
||||
VertexProperty>::type,
|
||||
typename detail::retag_property_list<edge_bundle_t, EdgeProperty>::type,
|
||||
#else
|
||||
VertexProperty, EdgeProperty,
|
||||
#endif
|
||||
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>
|
||||
{
|
||||
#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
|
||||
typedef typename detail::retag_property_list<vertex_bundle_t,
|
||||
VertexProperty>::retagged
|
||||
maybe_vertex_bundled;
|
||||
|
||||
typedef typename detail::retag_property_list<edge_bundle_t,
|
||||
EdgeProperty>::retagged
|
||||
maybe_edge_bundled;
|
||||
#endif
|
||||
|
||||
public:
|
||||
#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
|
||||
typedef typename detail::retag_property_list<vertex_bundle_t,
|
||||
VertexProperty>::type
|
||||
vertex_property_type;
|
||||
typedef typename detail::retag_property_list<edge_bundle_t,
|
||||
EdgeProperty>::type
|
||||
edge_property_type;
|
||||
|
||||
// The types that are actually bundled
|
||||
typedef typename mpl::if_c<(is_same<maybe_vertex_bundled, no_property>::value),
|
||||
no_vertex_bundle,
|
||||
maybe_vertex_bundled>::type vertex_bundled;
|
||||
typedef typename mpl::if_c<(is_same<maybe_edge_bundled, no_property>::value),
|
||||
no_edge_bundle,
|
||||
maybe_edge_bundled>::type edge_bundled;
|
||||
#else
|
||||
typedef VertexProperty vertex_property_type;
|
||||
typedef EdgeProperty edge_property_type;
|
||||
typedef no_vertex_bundle vertex_bundled;
|
||||
typedef no_edge_bundle edge_bundled;
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
typedef GraphProperty graph_property_type;
|
||||
|
||||
inline adjacency_list(const GraphProperty& p = GraphProperty())
|
||||
: m_property(p) { }
|
||||
|
||||
inline adjacency_list(const adjacency_list& x)
|
||||
: Base(x), m_property(x.m_property) { }
|
||||
|
||||
inline adjacency_list& operator=(const adjacency_list& x) {
|
||||
// TBD: probably should give the strong guarantee
|
||||
if (&x != this) {
|
||||
Base::operator=(x);
|
||||
m_property = x.m_property;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Required by Mutable Graph
|
||||
inline adjacency_list(vertices_size_type num_vertices,
|
||||
const GraphProperty& p = GraphProperty())
|
||||
: Base(num_vertices), m_property(p) { }
|
||||
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
|
||||
// Required by Iterator Constructible Graph
|
||||
template <class EdgeIterator>
|
||||
inline adjacency_list(EdgeIterator first, EdgeIterator last,
|
||||
vertices_size_type n,
|
||||
edges_size_type = 0,
|
||||
const GraphProperty& p = GraphProperty())
|
||||
: Base(n, first, last), m_property(p) { }
|
||||
|
||||
template <class EdgeIterator, class EdgePropertyIterator>
|
||||
inline 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(p) { }
|
||||
#endif
|
||||
|
||||
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]; }
|
||||
#endif
|
||||
|
||||
// protected: (would be protected if friends were more portable)
|
||||
GraphProperty m_property;
|
||||
};
|
||||
|
||||
template <class OEL, class VL, class DirS, class VP,class EP, class GP,
|
||||
class EL, class Tag, class Value>
|
||||
inline void
|
||||
set_property(adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>& g, Tag,
|
||||
const Value& value) {
|
||||
get_property_value(g.m_property, Tag()) = value;;
|
||||
}
|
||||
|
||||
template <class OEL, class VL, class DirS, class VP, class EP, class GP,
|
||||
class Tag, class EL>
|
||||
inline
|
||||
typename graph_property<adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>, Tag>::type&
|
||||
get_property(adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>& g, Tag) {
|
||||
return get_property_value(g.m_property, Tag());
|
||||
}
|
||||
|
||||
template <class OEL, class VL, class DirS, class VP, class EP, class GP,
|
||||
class Tag, class EL>
|
||||
inline
|
||||
const
|
||||
typename graph_property<adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>, Tag>::type&
|
||||
get_property(const adjacency_list<OEL,VL,DirS,VP,EP,GP,EL>& g, 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;
|
||||
}
|
||||
|
||||
// Support for bundled properties
|
||||
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
||||
template<typename OutEdgeListS, typename VertexListS, typename DirectedS, typename VertexProperty,
|
||||
typename EdgeProperty, typename GraphProperty, typename EdgeListS, typename T, typename Bundle>
|
||||
inline
|
||||
typename property_map<adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
|
||||
GraphProperty, EdgeListS>, T Bundle::*>::type
|
||||
get(T Bundle::* p, adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
|
||||
GraphProperty, EdgeListS>& g)
|
||||
{
|
||||
typedef typename property_map<adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty,
|
||||
EdgeProperty, GraphProperty, EdgeListS>, T Bundle::*>::type
|
||||
result_type;
|
||||
return result_type(&g, p);
|
||||
}
|
||||
|
||||
template<typename OutEdgeListS, typename VertexListS, typename DirectedS, typename VertexProperty,
|
||||
typename EdgeProperty, typename GraphProperty, typename EdgeListS, typename T, typename Bundle>
|
||||
inline
|
||||
typename property_map<adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
|
||||
GraphProperty, EdgeListS>, T Bundle::*>::const_type
|
||||
get(T Bundle::* p, adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
|
||||
GraphProperty, EdgeListS> const & g)
|
||||
{
|
||||
typedef typename property_map<adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty,
|
||||
EdgeProperty, GraphProperty, EdgeListS>, T Bundle::*>::const_type
|
||||
result_type;
|
||||
return result_type(&g, p);
|
||||
}
|
||||
|
||||
template<typename OutEdgeListS, typename VertexListS, typename DirectedS, typename VertexProperty,
|
||||
typename EdgeProperty, typename GraphProperty, typename EdgeListS, typename T, typename Bundle,
|
||||
typename Key>
|
||||
inline T
|
||||
get(T Bundle::* p, adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
|
||||
GraphProperty, EdgeListS> const & g, const Key& key)
|
||||
{
|
||||
return get(get(p, g), key);
|
||||
}
|
||||
|
||||
template<typename OutEdgeListS, typename VertexListS, typename DirectedS, typename VertexProperty,
|
||||
typename EdgeProperty, typename GraphProperty, typename EdgeListS, typename T, typename Bundle,
|
||||
typename Key>
|
||||
inline void
|
||||
put(T Bundle::* p, adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty, EdgeProperty,
|
||||
GraphProperty, EdgeListS>& g, const Key& key, const T& value)
|
||||
{
|
||||
put(get(p, g), key, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_ADJACENCY_LIST_HPP
|
||||
408
libraries/include/boost/graph/adjacency_list_io.hpp
Normal file
408
libraries/include/boost/graph/adjacency_list_io.hpp
Normal file
@@ -0,0 +1,408 @@
|
||||
//=======================================================================
|
||||
// Copyright 2001 Universite Joseph Fourier, Grenoble.
|
||||
// Author: Fran<61>ois Faure
|
||||
//
|
||||
// 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_IO_HPP
|
||||
#define BOOST_GRAPH_ADJACENCY_LIST_IO_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <cctype>
|
||||
|
||||
// Method read to parse an adjacency list from an input stream. Examples:
|
||||
// cin >> read( G );
|
||||
// cin >> read( G, NodePropertySubset(), EdgepropertySubset() );
|
||||
//
|
||||
// Method write to print an adjacency list to an output stream. Examples:
|
||||
// cout << write( G );
|
||||
// cout << write( G, NodePropertySubset(), EdgepropertySubset() );
|
||||
|
||||
namespace boost {
|
||||
|
||||
/* outline
|
||||
- basic property input
|
||||
- get property subset
|
||||
- graph parser
|
||||
- property printer
|
||||
- graph printer
|
||||
- user methods
|
||||
*/
|
||||
|
||||
//===========================================================================
|
||||
// basic property input
|
||||
|
||||
template<class Tag, class Value, class Next>
|
||||
std::istream& operator >> ( std::istream& in, property<Tag,Value,Next>& p )
|
||||
{
|
||||
in >> p.m_value >> *(static_cast<Next*>(&p)); // houpla !!
|
||||
return in;
|
||||
}
|
||||
|
||||
template<class Tag, class Value>
|
||||
std::istream& operator >> ( std::istream& in, property<Tag,Value,no_property>& p )
|
||||
{
|
||||
in >> p.m_value;
|
||||
return in;
|
||||
}
|
||||
|
||||
inline std::istream& operator >> ( std::istream& in, no_property& )
|
||||
{
|
||||
return in;
|
||||
}
|
||||
|
||||
// basic property input
|
||||
//===========================================================================
|
||||
// get property subsets
|
||||
|
||||
// get a single property tagged Stag
|
||||
template<class Tag, class Value, class Next, class V, class Stag>
|
||||
void get
|
||||
( property<Tag,Value,Next>& p, const V& v, Stag s )
|
||||
{
|
||||
get( *(static_cast<Next*>(&p)),v,s );
|
||||
}
|
||||
|
||||
template<class Value, class Next, class V, class Stag>
|
||||
void get
|
||||
( property<Stag,Value,Next>& p, const V& v, Stag )
|
||||
{
|
||||
p.m_value = v;
|
||||
}
|
||||
|
||||
// get a subset of properties tagged Stag
|
||||
template<class Tag, class Value, class Next,
|
||||
class Stag, class Svalue, class Snext>
|
||||
void getSubset
|
||||
( property<Tag,Value,Next>& p, const property<Stag,Svalue,Snext>& s )
|
||||
{
|
||||
get( p, s.m_value, Stag() );
|
||||
getSubset( p, Snext(s) );
|
||||
}
|
||||
|
||||
template<class Tag, class Value, class Next,
|
||||
class Stag, class Svalue>
|
||||
void getSubset
|
||||
( property<Tag,Value,Next>& p, const property<Stag,Svalue,no_property>& s)
|
||||
{
|
||||
get( p, s.m_value, Stag() );
|
||||
}
|
||||
|
||||
inline void getSubset
|
||||
( no_property& p, const no_property& s )
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
|
||||
template<typename T, typename U>
|
||||
void getSubset(T& p, const U& s)
|
||||
{
|
||||
p = s;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void getSubset(T&, const no_property&)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// get property subset
|
||||
//===========================================================================
|
||||
// graph parser
|
||||
typedef enum{ PARSE_NUM_NODES, PARSE_VERTEX, PARSE_EDGE } GraphParserState;
|
||||
|
||||
template<class Graph_t, class VertexProperty, class EdgeProperty, class VertexPropertySubset,
|
||||
class EdgePropertySubset>
|
||||
struct GraphParser
|
||||
{
|
||||
|
||||
typedef Graph_t Graph;
|
||||
|
||||
GraphParser( Graph* g ): graph(g)
|
||||
{}
|
||||
|
||||
GraphParser& operator () ( std::istream& in )
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
std::vector<Vertex> nodes;
|
||||
|
||||
GraphParserState state = PARSE_VERTEX;
|
||||
|
||||
unsigned int numLine = 1;
|
||||
char c;
|
||||
while ( in.get(c) )
|
||||
{
|
||||
if( c== '#' ) skip(in);
|
||||
else if( c== 'n' ) state = PARSE_NUM_NODES;
|
||||
else if( c== 'v' ) state = PARSE_VERTEX;
|
||||
else if( c== 'e' ) state = PARSE_EDGE;
|
||||
else if( c== '\n' ) numLine++;
|
||||
else if( !std::isspace(c) ){
|
||||
in.putback(c);
|
||||
if( state == PARSE_VERTEX ){
|
||||
VertexPropertySubset readProp;
|
||||
if( in >> readProp )
|
||||
{
|
||||
VertexProperty vp;
|
||||
getSubset( vp, readProp );
|
||||
nodes.push_back( add_vertex(vp, *graph) );
|
||||
}
|
||||
else
|
||||
std::cerr<<"read vertex, parse error at line"<<numLine<<std::endl;
|
||||
}
|
||||
else if( state == PARSE_EDGE ) {
|
||||
int source, target;
|
||||
EdgePropertySubset readProp;
|
||||
in >> source >> target;
|
||||
if( in >> readProp )
|
||||
{
|
||||
EdgeProperty ep;
|
||||
getSubset( ep, readProp );
|
||||
add_edge(nodes[source], nodes[target], ep, *graph);
|
||||
}
|
||||
else
|
||||
std::cerr<<"read edge, parse error at line"<<numLine<<std::endl;
|
||||
}
|
||||
else { // state == PARSE_NUM_NODES
|
||||
int n;
|
||||
if( in >> n ){
|
||||
for( int i=0; i<n; ++i )
|
||||
nodes.push_back( add_vertex( *graph ));
|
||||
}
|
||||
else
|
||||
std::cerr<<"read num_nodes, parse error at line "<< numLine << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
Graph* graph;
|
||||
|
||||
void skip( std::istream& in )
|
||||
{
|
||||
char c = 0;
|
||||
while( c!='\n' && !in.eof() )
|
||||
in.get(c);
|
||||
in.putback(c);
|
||||
}
|
||||
};
|
||||
|
||||
// parser
|
||||
//=======================================================================
|
||||
// property printer
|
||||
|
||||
#if defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
|
||||
template<class Graph, class Property>
|
||||
struct PropertyPrinter
|
||||
{
|
||||
typedef typename Property::value_type Value;
|
||||
typedef typename Property::tag_type Tag;
|
||||
typedef typename Property::next_type Next;
|
||||
|
||||
PropertyPrinter( const Graph& g ):graph(&g){}
|
||||
|
||||
template<class Iterator>
|
||||
PropertyPrinter& operator () ( std::ostream& out, Iterator it )
|
||||
{
|
||||
typename property_map<Graph,Tag>::type ps = get(Tag(), *graph);
|
||||
out << ps[ *it ] <<" ";
|
||||
PropertyPrinter<Graph,Next> print(*graph);
|
||||
print(out, it);
|
||||
return (*this);
|
||||
}
|
||||
private:
|
||||
const Graph* graph;
|
||||
};
|
||||
#else
|
||||
template<class Graph, typename Property>
|
||||
struct PropertyPrinter
|
||||
{
|
||||
PropertyPrinter( const Graph& g ):graph(&g){}
|
||||
|
||||
template<class Iterator>
|
||||
PropertyPrinter& operator () ( std::ostream& out, Iterator it )
|
||||
{
|
||||
out << (*graph)[ *it ] <<" ";
|
||||
return (*this);
|
||||
}
|
||||
private:
|
||||
const Graph* graph;
|
||||
};
|
||||
|
||||
template<class Graph, typename Tag, typename Value, typename Next>
|
||||
struct PropertyPrinter<Graph, property<Tag, Value, Next> >
|
||||
{
|
||||
PropertyPrinter( const Graph& g ):graph(&g){}
|
||||
|
||||
template<class Iterator>
|
||||
PropertyPrinter& operator () ( std::ostream& out, Iterator it )
|
||||
{
|
||||
typename property_map<Graph,Tag>::type ps = get(Tag(), *graph);
|
||||
out << ps[ *it ] <<" ";
|
||||
PropertyPrinter<Graph,Next> print(*graph);
|
||||
print(out, it);
|
||||
return (*this);
|
||||
}
|
||||
private:
|
||||
const Graph* graph;
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class Graph>
|
||||
struct PropertyPrinter<Graph, no_property>
|
||||
{
|
||||
PropertyPrinter( const Graph& ){}
|
||||
|
||||
template<class Iterator>
|
||||
PropertyPrinter& operator () ( std::ostream&, Iterator it ){ return *this; }
|
||||
};
|
||||
|
||||
// property printer
|
||||
//=========================================================================
|
||||
// graph printer
|
||||
|
||||
template<class Graph_t, class EdgeProperty>
|
||||
struct EdgePrinter
|
||||
{
|
||||
|
||||
typedef Graph_t Graph;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
|
||||
EdgePrinter( const Graph& g )
|
||||
: graph(g)
|
||||
{}
|
||||
|
||||
const EdgePrinter& operator () ( std::ostream& out ) const
|
||||
{
|
||||
// assign indices to vertices
|
||||
std::map<Vertex,int> indices;
|
||||
int num = 0;
|
||||
typename graph_traits<Graph>::vertex_iterator vi;
|
||||
for (vi = vertices(graph).first; vi != vertices(graph).second; ++vi){
|
||||
indices[*vi] = num++;
|
||||
}
|
||||
|
||||
// write edges
|
||||
PropertyPrinter<Graph, EdgeProperty> print_Edge(graph);
|
||||
out << "e" << std::endl;
|
||||
typename graph_traits<Graph>::edge_iterator ei;
|
||||
for (ei = edges(graph).first; ei != edges(graph).second; ++ei){
|
||||
out << indices[source(*ei,graph)] << " " << indices[target(*ei,graph)] << " ";
|
||||
print_Edge(out,ei);
|
||||
out << std::endl;
|
||||
}
|
||||
out << std::endl;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
const Graph& graph;
|
||||
|
||||
};
|
||||
|
||||
template<class Graph, class V, class E>
|
||||
struct GraphPrinter: public EdgePrinter<Graph,E>
|
||||
{
|
||||
GraphPrinter( const Graph& g )
|
||||
: EdgePrinter<Graph,E>(g)
|
||||
{}
|
||||
|
||||
const GraphPrinter& operator () ( std::ostream& out ) const
|
||||
{
|
||||
PropertyPrinter<Graph, V> printNode(this->graph);
|
||||
out << "v"<<std::endl;
|
||||
typename graph_traits<Graph>::vertex_iterator vi;
|
||||
for (vi = vertices(this->graph).first; vi != vertices(this->graph).second; ++vi){
|
||||
printNode(out,vi);
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
EdgePrinter<Graph,E>::operator ()( out );
|
||||
return (*this);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Graph, class E>
|
||||
struct GraphPrinter<Graph,no_property,E>
|
||||
: public EdgePrinter<Graph,E>
|
||||
{
|
||||
GraphPrinter( const Graph& g )
|
||||
: EdgePrinter<Graph,E>(g)
|
||||
{}
|
||||
|
||||
const GraphPrinter& operator () ( std::ostream& out ) const
|
||||
{
|
||||
out << "n "<< num_vertices(this->graph) << std::endl;
|
||||
EdgePrinter<Graph,E>::operator ()( out );
|
||||
return (*this);
|
||||
}
|
||||
};
|
||||
|
||||
// graph printer
|
||||
//=========================================================================
|
||||
// user methods
|
||||
|
||||
/// input stream for reading a graph
|
||||
template<class Graph, class VP, class EP, class VPS, class EPS>
|
||||
std::istream& operator >> ( std::istream& in, GraphParser<Graph,VP,EP,VPS,EPS> gp )
|
||||
{
|
||||
gp(in);
|
||||
return in;
|
||||
}
|
||||
|
||||
/// graph parser for given subsets of internal vertex and edge properties
|
||||
template<class EL, class VL, class D, class VP, class EP, class GP, class VPS, class EPS>
|
||||
GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VPS,EPS>
|
||||
read( adjacency_list<EL,VL,D,VP,EP,GP>& g, VPS vps, EPS eps )
|
||||
{
|
||||
return GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VPS,EPS>(&g);
|
||||
}
|
||||
|
||||
/// graph parser for all internal vertex and edge properties
|
||||
template<class EL, class VL, class D, class VP, class EP, class GP>
|
||||
GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VP,EP>
|
||||
read( adjacency_list<EL,VL,D,VP,EP,GP>& g )
|
||||
{
|
||||
return GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VP,EP>(&g);
|
||||
}
|
||||
|
||||
|
||||
/// output stream for writing a graph
|
||||
template<class Graph, class VP, class EP>
|
||||
std::ostream& operator << ( std::ostream& out, const GraphPrinter<Graph,VP,EP>& gp )
|
||||
{
|
||||
gp(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
/// write the graph with given property subsets
|
||||
template<class EL, class VL, class D, class VP, class EP, class GP, class VPS, class EPS>
|
||||
GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VPS,EPS>
|
||||
write( const adjacency_list<EL,VL,D,VP,EP,GP>& g, VPS, EPS )
|
||||
{
|
||||
return GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VPS,EPS>(g);
|
||||
}
|
||||
|
||||
/// write the graph with all internal vertex and edge properties
|
||||
template<class EL, class VL, class D, class VP, class EP, class GP>
|
||||
GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP>
|
||||
write( const adjacency_list<EL,VL,D,VP,EP,GP>& g )
|
||||
{
|
||||
return GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP>(g);
|
||||
}
|
||||
|
||||
// user methods
|
||||
//=========================================================================
|
||||
}// boost
|
||||
#endif
|
||||
1283
libraries/include/boost/graph/adjacency_matrix.hpp
Normal file
1283
libraries/include/boost/graph/adjacency_matrix.hpp
Normal file
File diff suppressed because it is too large
Load Diff
407
libraries/include/boost/graph/astar_search.hpp
Normal file
407
libraries/include/boost/graph/astar_search.hpp
Normal file
@@ -0,0 +1,407 @@
|
||||
|
||||
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright (c) 2004 Kristopher Beevers
|
||||
//
|
||||
// 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_ASTAR_SEARCH_HPP
|
||||
#define BOOST_GRAPH_ASTAR_SEARCH_HPP
|
||||
|
||||
|
||||
#include <functional>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
#include <boost/pending/mutable_queue.hpp>
|
||||
#include <boost/graph/relax.hpp>
|
||||
#include <boost/pending/indirect_cmp.hpp>
|
||||
#include <boost/graph/exception.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
|
||||
template <class Heuristic, class Graph>
|
||||
struct AStarHeuristicConcept {
|
||||
void constraints()
|
||||
{
|
||||
function_requires< CopyConstructibleConcept<Heuristic> >();
|
||||
h(u);
|
||||
}
|
||||
Heuristic h;
|
||||
typename graph_traits<Graph>::vertex_descriptor u;
|
||||
};
|
||||
|
||||
|
||||
template <class Graph, class CostType>
|
||||
class astar_heuristic : public std::unary_function<
|
||||
typename graph_traits<Graph>::vertex_descriptor, CostType>
|
||||
{
|
||||
public:
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
astar_heuristic() {}
|
||||
CostType operator()(Vertex u) { return static_cast<CostType>(0); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <class Visitor, class Graph>
|
||||
struct AStarVisitorConcept {
|
||||
void constraints()
|
||||
{
|
||||
function_requires< CopyConstructibleConcept<Visitor> >();
|
||||
vis.initialize_vertex(u, g);
|
||||
vis.discover_vertex(u, g);
|
||||
vis.examine_vertex(u, g);
|
||||
vis.examine_edge(e, g);
|
||||
vis.edge_relaxed(e, g);
|
||||
vis.edge_not_relaxed(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;
|
||||
};
|
||||
|
||||
|
||||
template <class Visitors = null_visitor>
|
||||
class astar_visitor : public bfs_visitor<Visitors> {
|
||||
public:
|
||||
astar_visitor() {}
|
||||
astar_visitor(Visitors vis)
|
||||
: bfs_visitor<Visitors>(vis) {}
|
||||
|
||||
template <class Edge, class Graph>
|
||||
void edge_relaxed(Edge e, Graph& g) {
|
||||
invoke_visitors(this->m_vis, e, g, on_edge_relaxed());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void edge_not_relaxed(Edge e, Graph& g) {
|
||||
invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed());
|
||||
}
|
||||
private:
|
||||
template <class Edge, class Graph>
|
||||
void tree_edge(Edge e, Graph& g) {}
|
||||
template <class Edge, class Graph>
|
||||
void non_tree_edge(Edge e, Graph& g) {}
|
||||
};
|
||||
template <class Visitors>
|
||||
astar_visitor<Visitors>
|
||||
make_astar_visitor(Visitors vis) {
|
||||
return astar_visitor<Visitors>(vis);
|
||||
}
|
||||
typedef astar_visitor<> default_astar_visitor;
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class AStarHeuristic, class UniformCostVisitor,
|
||||
class UpdatableQueue, class PredecessorMap,
|
||||
class CostMap, class DistanceMap, class WeightMap,
|
||||
class ColorMap, class BinaryFunction,
|
||||
class BinaryPredicate>
|
||||
struct astar_bfs_visitor
|
||||
{
|
||||
|
||||
typedef typename property_traits<CostMap>::value_type C;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typedef typename property_traits<DistanceMap>::value_type distance_type;
|
||||
|
||||
astar_bfs_visitor(AStarHeuristic h, UniformCostVisitor vis,
|
||||
UpdatableQueue& Q, PredecessorMap p,
|
||||
CostMap c, DistanceMap d, WeightMap w,
|
||||
ColorMap col, BinaryFunction combine,
|
||||
BinaryPredicate compare, C zero)
|
||||
: m_h(h), m_vis(vis), m_Q(Q), m_predecessor(p), m_cost(c),
|
||||
m_distance(d), m_weight(w), m_color(col),
|
||||
m_combine(combine), m_compare(compare), m_zero(zero) {}
|
||||
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void initialize_vertex(Vertex u, Graph& g) {
|
||||
m_vis.initialize_vertex(u, g);
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph& g) {
|
||||
m_vis.discover_vertex(u, g);
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void examine_vertex(Vertex u, Graph& g) {
|
||||
m_vis.examine_vertex(u, g);
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void finish_vertex(Vertex u, Graph& g) {
|
||||
m_vis.finish_vertex(u, g);
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void examine_edge(Edge e, Graph& g) {
|
||||
if (m_compare(get(m_weight, e), m_zero))
|
||||
throw negative_edge();
|
||||
m_vis.examine_edge(e, g);
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void non_tree_edge(Edge, Graph&) {}
|
||||
|
||||
|
||||
|
||||
template <class Edge, class Graph>
|
||||
void tree_edge(Edge e, Graph& g) {
|
||||
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
|
||||
m_combine, m_compare);
|
||||
|
||||
if(m_decreased) {
|
||||
m_vis.edge_relaxed(e, g);
|
||||
put(m_cost, target(e, g),
|
||||
m_combine(get(m_distance, target(e, g)),
|
||||
m_h(target(e, g))));
|
||||
} else
|
||||
m_vis.edge_not_relaxed(e, g);
|
||||
}
|
||||
|
||||
|
||||
template <class Edge, class Graph>
|
||||
void gray_target(Edge e, Graph& g) {
|
||||
distance_type old_distance = get(m_distance, target(e, g));
|
||||
|
||||
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
|
||||
m_combine, m_compare);
|
||||
|
||||
/* On x86 Linux with optimization, we sometimes get into a
|
||||
horrible case where m_decreased is true but the distance hasn't
|
||||
actually changed. This occurs when the comparison inside
|
||||
relax() occurs with the 80-bit precision of the x87 floating
|
||||
point unit, but the difference is lost when the resulting
|
||||
values are written back to lower-precision memory (e.g., a
|
||||
double). With the eager Dijkstra's implementation, this results
|
||||
in looping. */
|
||||
if(m_decreased && old_distance != get(m_distance, target(e, g))) {
|
||||
put(m_cost, target(e, g),
|
||||
m_combine(get(m_distance, target(e, g)),
|
||||
m_h(target(e, g))));
|
||||
m_Q.update(target(e, g));
|
||||
m_vis.edge_relaxed(e, g);
|
||||
} else
|
||||
m_vis.edge_not_relaxed(e, g);
|
||||
}
|
||||
|
||||
|
||||
template <class Edge, class Graph>
|
||||
void black_target(Edge e, Graph& g) {
|
||||
distance_type old_distance = get(m_distance, target(e, g));
|
||||
|
||||
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
|
||||
m_combine, m_compare);
|
||||
|
||||
/* See comment in gray_target */
|
||||
if(m_decreased && old_distance != get(m_distance, target(e, g))) {
|
||||
m_vis.edge_relaxed(e, g);
|
||||
put(m_cost, target(e, g),
|
||||
m_combine(get(m_distance, target(e, g)),
|
||||
m_h(target(e, g))));
|
||||
m_Q.push(target(e, g));
|
||||
put(m_color, target(e, g), Color::gray());
|
||||
m_vis.black_target(e, g);
|
||||
} else
|
||||
m_vis.edge_not_relaxed(e, g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AStarHeuristic m_h;
|
||||
UniformCostVisitor m_vis;
|
||||
UpdatableQueue& m_Q;
|
||||
PredecessorMap m_predecessor;
|
||||
CostMap m_cost;
|
||||
DistanceMap m_distance;
|
||||
WeightMap m_weight;
|
||||
ColorMap m_color;
|
||||
BinaryFunction m_combine;
|
||||
BinaryPredicate m_compare;
|
||||
bool m_decreased;
|
||||
C m_zero;
|
||||
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
|
||||
template <typename VertexListGraph, typename AStarHeuristic,
|
||||
typename AStarVisitor, typename PredecessorMap,
|
||||
typename CostMap, typename DistanceMap,
|
||||
typename WeightMap, typename ColorMap,
|
||||
typename VertexIndexMap,
|
||||
typename CompareFunction, typename CombineFunction,
|
||||
typename CostInf, typename CostZero>
|
||||
inline void
|
||||
astar_search_no_init
|
||||
(VertexListGraph &g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
AStarHeuristic h, AStarVisitor vis,
|
||||
PredecessorMap predecessor, CostMap cost,
|
||||
DistanceMap distance, WeightMap weight,
|
||||
ColorMap color, VertexIndexMap index_map,
|
||||
CompareFunction compare, CombineFunction combine,
|
||||
CostInf inf, CostZero zero)
|
||||
{
|
||||
typedef indirect_cmp<CostMap, CompareFunction> IndirectCmp;
|
||||
IndirectCmp icmp(cost, compare);
|
||||
|
||||
typedef typename graph_traits<VertexListGraph>::vertex_descriptor
|
||||
Vertex;
|
||||
typedef mutable_queue<Vertex, std::vector<Vertex>,
|
||||
IndirectCmp, VertexIndexMap>
|
||||
MutableQueue;
|
||||
MutableQueue Q(num_vertices(g), icmp, index_map);
|
||||
|
||||
detail::astar_bfs_visitor<AStarHeuristic, AStarVisitor,
|
||||
MutableQueue, PredecessorMap, CostMap, DistanceMap,
|
||||
WeightMap, ColorMap, CombineFunction, CompareFunction>
|
||||
bfs_vis(h, vis, Q, predecessor, cost, distance, weight,
|
||||
color, combine, compare, zero);
|
||||
|
||||
breadth_first_visit(g, s, Q, bfs_vis, color);
|
||||
}
|
||||
|
||||
|
||||
// Non-named parameter interface
|
||||
template <typename VertexListGraph, typename AStarHeuristic,
|
||||
typename AStarVisitor, typename PredecessorMap,
|
||||
typename CostMap, typename DistanceMap,
|
||||
typename WeightMap, typename VertexIndexMap,
|
||||
typename ColorMap,
|
||||
typename CompareFunction, typename CombineFunction,
|
||||
typename CostInf, typename CostZero>
|
||||
inline void
|
||||
astar_search
|
||||
(VertexListGraph &g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
AStarHeuristic h, AStarVisitor vis,
|
||||
PredecessorMap predecessor, CostMap cost,
|
||||
DistanceMap distance, WeightMap weight,
|
||||
VertexIndexMap index_map, ColorMap color,
|
||||
CompareFunction compare, CombineFunction combine,
|
||||
CostInf inf, CostZero zero)
|
||||
{
|
||||
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
||||
put(color, *ui, Color::white());
|
||||
put(distance, *ui, inf);
|
||||
put(cost, *ui, inf);
|
||||
put(predecessor, *ui, *ui);
|
||||
vis.initialize_vertex(*ui, g);
|
||||
}
|
||||
put(distance, s, zero);
|
||||
put(cost, s, h(s));
|
||||
|
||||
astar_search_no_init
|
||||
(g, s, h, vis, predecessor, cost, distance, weight,
|
||||
color, index_map, compare, combine, inf, zero);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace detail {
|
||||
template <class VertexListGraph, class AStarHeuristic,
|
||||
class CostMap, class DistanceMap, class WeightMap,
|
||||
class IndexMap, class ColorMap, class Params>
|
||||
inline void
|
||||
astar_dispatch2
|
||||
(VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
AStarHeuristic h, CostMap cost, DistanceMap distance,
|
||||
WeightMap weight, IndexMap index_map, ColorMap color,
|
||||
const Params& params)
|
||||
{
|
||||
dummy_property_map p_map;
|
||||
typedef typename property_traits<CostMap>::value_type C;
|
||||
astar_search
|
||||
(g, s, h,
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_astar_visitor(null_visitor())),
|
||||
choose_param(get_param(params, vertex_predecessor), p_map),
|
||||
cost, distance, weight, index_map, color,
|
||||
choose_param(get_param(params, distance_compare_t()),
|
||||
std::less<C>()),
|
||||
choose_param(get_param(params, distance_combine_t()),
|
||||
closed_plus<C>()),
|
||||
choose_param(get_param(params, distance_inf_t()),
|
||||
std::numeric_limits<C>::max BOOST_PREVENT_MACRO_SUBSTITUTION ()),
|
||||
choose_param(get_param(params, distance_zero_t()),
|
||||
C()));
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class AStarHeuristic,
|
||||
class CostMap, class DistanceMap, class WeightMap,
|
||||
class IndexMap, class ColorMap, class Params>
|
||||
inline void
|
||||
astar_dispatch1
|
||||
(VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
AStarHeuristic h, CostMap cost, DistanceMap distance,
|
||||
WeightMap weight, IndexMap index_map, ColorMap color,
|
||||
const Params& params)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type D;
|
||||
typename std::vector<D>::size_type
|
||||
n = is_default_param(distance) ? num_vertices(g) : 1;
|
||||
std::vector<D> distance_map(n);
|
||||
n = is_default_param(cost) ? num_vertices(g) : 1;
|
||||
std::vector<D> cost_map(n);
|
||||
std::vector<default_color_type> color_map(num_vertices(g));
|
||||
default_color_type c = white_color;
|
||||
|
||||
detail::astar_dispatch2
|
||||
(g, s, h,
|
||||
choose_param(cost, make_iterator_property_map
|
||||
(cost_map.begin(), index_map,
|
||||
cost_map[0])),
|
||||
choose_param(distance, make_iterator_property_map
|
||||
(distance_map.begin(), index_map,
|
||||
distance_map[0])),
|
||||
weight, index_map,
|
||||
choose_param(color, make_iterator_property_map
|
||||
(color_map.begin(), index_map, c)),
|
||||
params);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// Named parameter interface
|
||||
template <typename VertexListGraph,
|
||||
typename AStarHeuristic,
|
||||
typename P, typename T, typename R>
|
||||
void
|
||||
astar_search
|
||||
(VertexListGraph &g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
AStarHeuristic h, const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
|
||||
detail::astar_dispatch1
|
||||
(g, s, h,
|
||||
get_param(params, vertex_rank),
|
||||
get_param(params, vertex_distance),
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
|
||||
get_param(params, vertex_color),
|
||||
params);
|
||||
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_ASTAR_SEARCH_HPP
|
||||
83
libraries/include/boost/graph/bandwidth.hpp
Normal file
83
libraries/include/boost/graph/bandwidth.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) Jeremy Siek 2001, Marc Wintermantel 2002
|
||||
//
|
||||
// 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_BANDWIDTH_HPP
|
||||
#define BOOST_GRAPH_BANDWIDTH_HPP
|
||||
|
||||
#include <algorithm> // for std::min and std::max
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/detail/numeric_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
ith_bandwidth(typename graph_traits<Graph>::vertex_descriptor i,
|
||||
const Graph& g,
|
||||
VertexIndexMap index)
|
||||
{
|
||||
BOOST_USING_STD_MAX();
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
size_type b = 0;
|
||||
typename graph_traits<Graph>::out_edge_iterator e, end;
|
||||
for (tie(e, end) = out_edges(i, g); e != end; ++e) {
|
||||
int f_i = get(index, i);
|
||||
int f_j = get(index, target(*e, g));
|
||||
using namespace std; // to call abs() unqualified
|
||||
if(f_i > f_j)
|
||||
b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, size_type(f_i - f_j));
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
ith_bandwidth(typename graph_traits<Graph>::vertex_descriptor i,
|
||||
const Graph& g)
|
||||
{
|
||||
return ith_bandwidth(i, g, get(vertex_index, g));
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
bandwidth(const Graph& g, VertexIndexMap index)
|
||||
{
|
||||
BOOST_USING_STD_MAX();
|
||||
typename graph_traits<Graph>::vertices_size_type b = 0;
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
for (tie(i, end) = vertices(g); i != end; ++i)
|
||||
b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, ith_bandwidth(*i, g, index));
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
bandwidth(const Graph& g)
|
||||
{
|
||||
return bandwidth(g, get(vertex_index, g));
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
edgesum(const Graph& g, VertexIndexMap index_map)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
typedef typename detail::numeric_traits<size_type>::difference_type diff_t;
|
||||
size_type sum = 0;
|
||||
typename graph_traits<Graph>::edge_iterator i, end;
|
||||
for (tie(i, end) = edges(g); i != end; ++i) {
|
||||
diff_t f_u = get(index_map, source(*i, g));
|
||||
diff_t f_v = get(index_map, target(*i, g));
|
||||
using namespace std; // to call abs() unqualified
|
||||
sum += abs(f_u - f_v);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_BANDWIDTH_HPP
|
||||
164
libraries/include/boost/graph/bc_clustering.hpp
Normal file
164
libraries/include/boost/graph/bc_clustering.hpp
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright 2004 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: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP
|
||||
#define BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP
|
||||
|
||||
#include <boost/graph/betweenness_centrality.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/pending/indirect_cmp.hpp>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
/** Threshold termination function for the betweenness centrality
|
||||
* clustering algorithm.
|
||||
*/
|
||||
template<typename T>
|
||||
struct bc_clustering_threshold
|
||||
{
|
||||
typedef T centrality_type;
|
||||
|
||||
/// Terminate clustering when maximum absolute edge centrality is
|
||||
/// below the given threshold.
|
||||
explicit bc_clustering_threshold(T threshold)
|
||||
: threshold(threshold), dividend(1.0) {}
|
||||
|
||||
/**
|
||||
* Terminate clustering when the maximum edge centrality is below
|
||||
* the given threshold.
|
||||
*
|
||||
* @param threshold the threshold value
|
||||
*
|
||||
* @param g the graph on which the threshold will be calculated
|
||||
*
|
||||
* @param normalize when true, the threshold is compared against the
|
||||
* normalized edge centrality based on the input graph; otherwise,
|
||||
* the threshold is compared against the absolute edge centrality.
|
||||
*/
|
||||
template<typename Graph>
|
||||
bc_clustering_threshold(T threshold, const Graph& g, bool normalize = true)
|
||||
: threshold(threshold), dividend(1.0)
|
||||
{
|
||||
if (normalize) {
|
||||
typename graph_traits<Graph>::vertices_size_type n = num_vertices(g);
|
||||
dividend = T((n - 1) * (n - 2)) / T(2);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true when the given maximum edge centrality (potentially
|
||||
* normalized) falls below the threshold.
|
||||
*/
|
||||
template<typename Graph, typename Edge>
|
||||
bool operator()(T max_centrality, Edge, const Graph&)
|
||||
{
|
||||
return (max_centrality / dividend) < threshold;
|
||||
}
|
||||
|
||||
protected:
|
||||
T threshold;
|
||||
T dividend;
|
||||
};
|
||||
|
||||
/** Graph clustering based on edge betweenness centrality.
|
||||
*
|
||||
* This algorithm implements graph clustering based on edge
|
||||
* betweenness centrality. It is an iterative algorithm, where in each
|
||||
* step it compute the edge betweenness centrality (via @ref
|
||||
* brandes_betweenness_centrality) and removes the edge with the
|
||||
* maximum betweenness centrality. The @p done function object
|
||||
* determines when the algorithm terminates (the edge found when the
|
||||
* algorithm terminates will not be removed).
|
||||
*
|
||||
* @param g The graph on which clustering will be performed. The type
|
||||
* of this parameter (@c MutableGraph) must be a model of the
|
||||
* VertexListGraph, IncidenceGraph, EdgeListGraph, and Mutable Graph
|
||||
* concepts.
|
||||
*
|
||||
* @param done The function object that indicates termination of the
|
||||
* algorithm. It must be a ternary function object thats accepts the
|
||||
* maximum centrality, the descriptor of the edge that will be
|
||||
* removed, and the graph @p g.
|
||||
*
|
||||
* @param edge_centrality (UTIL/OUT) The property map that will store
|
||||
* the betweenness centrality for each edge. When the algorithm
|
||||
* terminates, it will contain the edge centralities for the
|
||||
* graph. The type of this property map must model the
|
||||
* ReadWritePropertyMap concept. Defaults to an @c
|
||||
* iterator_property_map whose value type is
|
||||
* @c Done::centrality_type and using @c get(edge_index, g) for the
|
||||
* index map.
|
||||
*
|
||||
* @param vertex_index (IN) The property map that maps vertices to
|
||||
* indices in the range @c [0, num_vertices(g)). This type of this
|
||||
* property map must model the ReadablePropertyMap concept and its
|
||||
* value type must be an integral type. Defaults to
|
||||
* @c get(vertex_index, g).
|
||||
*/
|
||||
template<typename MutableGraph, typename Done, typename EdgeCentralityMap,
|
||||
typename VertexIndexMap>
|
||||
void
|
||||
betweenness_centrality_clustering(MutableGraph& g, Done done,
|
||||
EdgeCentralityMap edge_centrality,
|
||||
VertexIndexMap vertex_index)
|
||||
{
|
||||
typedef typename property_traits<EdgeCentralityMap>::value_type
|
||||
centrality_type;
|
||||
typedef typename graph_traits<MutableGraph>::edge_iterator edge_iterator;
|
||||
typedef typename graph_traits<MutableGraph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<MutableGraph>::vertices_size_type
|
||||
vertices_size_type;
|
||||
|
||||
if (edges(g).first == edges(g).second) return;
|
||||
|
||||
// Function object that compares the centrality of edges
|
||||
indirect_cmp<EdgeCentralityMap, std::less<centrality_type> >
|
||||
cmp(edge_centrality);
|
||||
|
||||
bool is_done;
|
||||
do {
|
||||
brandes_betweenness_centrality(g,
|
||||
edge_centrality_map(edge_centrality)
|
||||
.vertex_index_map(vertex_index));
|
||||
edge_descriptor e = *max_element(edges(g).first, edges(g).second, cmp);
|
||||
is_done = done(get(edge_centrality, e), e, g);
|
||||
if (!is_done) remove_edge(e, g);
|
||||
} while (!is_done && edges(g).first != edges(g).second);
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
template<typename MutableGraph, typename Done, typename EdgeCentralityMap>
|
||||
void
|
||||
betweenness_centrality_clustering(MutableGraph& g, Done done,
|
||||
EdgeCentralityMap edge_centrality)
|
||||
{
|
||||
betweenness_centrality_clustering(g, done, edge_centrality,
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
template<typename MutableGraph, typename Done>
|
||||
void
|
||||
betweenness_centrality_clustering(MutableGraph& g, Done done)
|
||||
{
|
||||
typedef typename Done::centrality_type centrality_type;
|
||||
std::vector<centrality_type> edge_centrality(num_edges(g));
|
||||
betweenness_centrality_clustering(g, done,
|
||||
make_iterator_property_map(edge_centrality.begin(), get(edge_index, g)),
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP
|
||||
241
libraries/include/boost/graph/bellman_ford_shortest_paths.hpp
Normal file
241
libraries/include/boost/graph/bellman_ford_shortest_paths.hpp
Normal file
@@ -0,0 +1,241 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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)
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
/*
|
||||
This file implements the function
|
||||
|
||||
template <class EdgeListGraph, class Size, class P, class T, class R>
|
||||
bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP
|
||||
#define BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/relax.hpp>
|
||||
#include <boost/graph/visitors.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Visitor, class Graph>
|
||||
struct BellmanFordVisitorConcept {
|
||||
void constraints() {
|
||||
function_requires< CopyConstructibleConcept<Visitor> >();
|
||||
vis.examine_edge(e, g);
|
||||
vis.edge_relaxed(e, g);
|
||||
vis.edge_not_relaxed(e, g);
|
||||
vis.edge_minimized(e, g);
|
||||
vis.edge_not_minimized(e, g);
|
||||
}
|
||||
Visitor vis;
|
||||
Graph g;
|
||||
typename graph_traits<Graph>::edge_descriptor e;
|
||||
};
|
||||
|
||||
template <class Visitors = null_visitor>
|
||||
class bellman_visitor {
|
||||
public:
|
||||
bellman_visitor() { }
|
||||
bellman_visitor(Visitors vis) : m_vis(vis) { }
|
||||
|
||||
template <class Edge, class Graph>
|
||||
void examine_edge(Edge u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_examine_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void edge_relaxed(Edge u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_edge_relaxed());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void edge_not_relaxed(Edge u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_edge_not_relaxed());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void edge_minimized(Edge u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_edge_minimized());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void edge_not_minimized(Edge u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_edge_not_minimized());
|
||||
}
|
||||
protected:
|
||||
Visitors m_vis;
|
||||
};
|
||||
template <class Visitors>
|
||||
bellman_visitor<Visitors>
|
||||
make_bellman_visitor(Visitors vis) {
|
||||
return bellman_visitor<Visitors>(vis);
|
||||
}
|
||||
typedef bellman_visitor<> default_bellman_visitor;
|
||||
|
||||
template <class EdgeListGraph, class Size, class WeightMap,
|
||||
class PredecessorMap, class DistanceMap,
|
||||
class BinaryFunction, class BinaryPredicate,
|
||||
class BellmanFordVisitor>
|
||||
bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N,
|
||||
WeightMap weight,
|
||||
PredecessorMap pred,
|
||||
DistanceMap distance,
|
||||
BinaryFunction combine,
|
||||
BinaryPredicate compare,
|
||||
BellmanFordVisitor v)
|
||||
{
|
||||
function_requires<EdgeListGraphConcept<EdgeListGraph> >();
|
||||
typedef graph_traits<EdgeListGraph> GTraits;
|
||||
typedef typename GTraits::edge_descriptor Edge;
|
||||
typedef typename GTraits::vertex_descriptor Vertex;
|
||||
function_requires<ReadWritePropertyMapConcept<DistanceMap, Vertex> >();
|
||||
function_requires<ReadablePropertyMapConcept<WeightMap, Edge> >();
|
||||
typedef typename property_traits<DistanceMap>::value_type D_value;
|
||||
typedef typename property_traits<WeightMap>::value_type W_value;
|
||||
|
||||
typename GTraits::edge_iterator i, end;
|
||||
|
||||
for (Size k = 0; k < N; ++k) {
|
||||
bool at_least_one_edge_relaxed = false;
|
||||
for (tie(i, end) = edges(g); i != end; ++i) {
|
||||
v.examine_edge(*i, g);
|
||||
if (relax(*i, g, weight, pred, distance, combine, compare)) {
|
||||
at_least_one_edge_relaxed = true;
|
||||
v.edge_relaxed(*i, g);
|
||||
} else
|
||||
v.edge_not_relaxed(*i, g);
|
||||
}
|
||||
if (!at_least_one_edge_relaxed)
|
||||
break;
|
||||
}
|
||||
|
||||
for (tie(i, end) = edges(g); i != end; ++i)
|
||||
if (compare(combine(get(distance, source(*i, g)), get(weight, *i)),
|
||||
get(distance, target(*i,g))))
|
||||
{
|
||||
v.edge_not_minimized(*i, g);
|
||||
return false;
|
||||
} else
|
||||
v.edge_minimized(*i, g);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename VertexAndEdgeListGraph, typename Size,
|
||||
typename WeightMap, typename PredecessorMap, typename DistanceMap,
|
||||
typename P, typename T, typename R>
|
||||
bool
|
||||
bellman_dispatch2
|
||||
(VertexAndEdgeListGraph& g,
|
||||
typename graph_traits<VertexAndEdgeListGraph>::vertex_descriptor s,
|
||||
Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename property_traits<DistanceMap>::value_type D;
|
||||
bellman_visitor<> null_vis;
|
||||
typedef typename property_traits<WeightMap>::value_type weight_type;
|
||||
typename graph_traits<VertexAndEdgeListGraph>::vertex_iterator v, v_end;
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
|
||||
put(distance, *v, (std::numeric_limits<weight_type>::max)());
|
||||
put(pred, *v, *v);
|
||||
}
|
||||
put(distance, s, weight_type(0));
|
||||
return bellman_ford_shortest_paths
|
||||
(g, N, weight, pred, distance,
|
||||
choose_param(get_param(params, distance_combine_t()),
|
||||
closed_plus<D>()),
|
||||
choose_param(get_param(params, distance_compare_t()),
|
||||
std::less<D>()),
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
null_vis)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename VertexAndEdgeListGraph, typename Size,
|
||||
typename WeightMap, typename PredecessorMap, typename DistanceMap,
|
||||
typename P, typename T, typename R>
|
||||
bool
|
||||
bellman_dispatch2
|
||||
(VertexAndEdgeListGraph& g,
|
||||
detail::error_property_not_found,
|
||||
Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename property_traits<DistanceMap>::value_type D;
|
||||
bellman_visitor<> null_vis;
|
||||
return bellman_ford_shortest_paths
|
||||
(g, N, weight, pred, distance,
|
||||
choose_param(get_param(params, distance_combine_t()),
|
||||
closed_plus<D>()),
|
||||
choose_param(get_param(params, distance_compare_t()),
|
||||
std::less<D>()),
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
null_vis)
|
||||
);
|
||||
}
|
||||
|
||||
template <class EdgeListGraph, class Size, class WeightMap,
|
||||
class DistanceMap, class P, class T, class R>
|
||||
bool bellman_dispatch(EdgeListGraph& g, Size N,
|
||||
WeightMap weight, DistanceMap distance,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
dummy_property_map dummy_pred;
|
||||
return
|
||||
detail::bellman_dispatch2
|
||||
(g,
|
||||
get_param(params, root_vertex_t()),
|
||||
N, weight,
|
||||
choose_param(get_param(params, vertex_predecessor), dummy_pred),
|
||||
distance,
|
||||
params);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <class EdgeListGraph, class Size, class P, class T, class R>
|
||||
bool bellman_ford_shortest_paths
|
||||
(EdgeListGraph& g, Size N,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return detail::bellman_dispatch
|
||||
(g, N,
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
|
||||
choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
|
||||
params);
|
||||
}
|
||||
|
||||
template <class EdgeListGraph, class Size>
|
||||
bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N)
|
||||
{
|
||||
bgl_named_params<int,int> params(0);
|
||||
return bellman_ford_shortest_paths(g, N, params);
|
||||
}
|
||||
|
||||
template <class VertexAndEdgeListGraph, class P, class T, class R>
|
||||
bool bellman_ford_shortest_paths
|
||||
(VertexAndEdgeListGraph& g,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
function_requires<VertexListGraphConcept<VertexAndEdgeListGraph> >();
|
||||
return detail::bellman_dispatch
|
||||
(g, num_vertices(g),
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
|
||||
choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
|
||||
params);
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP
|
||||
597
libraries/include/boost/graph/betweenness_centrality.hpp
Normal file
597
libraries/include/boost/graph/betweenness_centrality.hpp
Normal file
@@ -0,0 +1,597 @@
|
||||
// Copyright 2004 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: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP
|
||||
#define BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP
|
||||
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <boost/graph/dijkstra_shortest_paths.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include <boost/graph/relax.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail { namespace graph {
|
||||
|
||||
/**
|
||||
* Customized visitor passed to Dijkstra's algorithm by Brandes'
|
||||
* betweenness centrality algorithm. This visitor is responsible for
|
||||
* keeping track of the order in which vertices are discovered, the
|
||||
* predecessors on the shortest path(s) to a vertex, and the number
|
||||
* of shortest paths.
|
||||
*/
|
||||
template<typename Graph, typename WeightMap, typename IncomingMap,
|
||||
typename DistanceMap, typename PathCountMap>
|
||||
struct brandes_dijkstra_visitor : public bfs_visitor<>
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
|
||||
brandes_dijkstra_visitor(std::stack<vertex_descriptor>& ordered_vertices,
|
||||
WeightMap weight,
|
||||
IncomingMap incoming,
|
||||
DistanceMap distance,
|
||||
PathCountMap path_count)
|
||||
: ordered_vertices(ordered_vertices), weight(weight),
|
||||
incoming(incoming), distance(distance),
|
||||
path_count(path_count)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Whenever an edge e = (v, w) is relaxed, the incoming edge list
|
||||
* for w is set to {(v, w)} and the shortest path count of w is set to
|
||||
* the number of paths that reach {v}.
|
||||
*/
|
||||
void edge_relaxed(edge_descriptor e, const Graph& g)
|
||||
{
|
||||
vertex_descriptor v = source(e, g), w = target(e, g);
|
||||
incoming[w].clear();
|
||||
incoming[w].push_back(e);
|
||||
put(path_count, w, get(path_count, v));
|
||||
}
|
||||
|
||||
/**
|
||||
* If an edge e = (v, w) was not relaxed, it may still be the case
|
||||
* that we've found more equally-short paths, so include {(v, w)} in the
|
||||
* incoming edges of w and add all of the shortest paths to v to the
|
||||
* shortest path count of w.
|
||||
*/
|
||||
void edge_not_relaxed(edge_descriptor e, const Graph& g)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type weight_type;
|
||||
typedef typename property_traits<DistanceMap>::value_type distance_type;
|
||||
vertex_descriptor v = source(e, g), w = target(e, g);
|
||||
distance_type d_v = get(distance, v), d_w = get(distance, w);
|
||||
weight_type w_e = get(weight, e);
|
||||
|
||||
closed_plus<distance_type> combine;
|
||||
if (d_w == combine(d_v, w_e)) {
|
||||
put(path_count, w, get(path_count, w) + get(path_count, v));
|
||||
incoming[w].push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Keep track of vertices as they are reached
|
||||
void examine_vertex(vertex_descriptor w, const Graph&)
|
||||
{
|
||||
ordered_vertices.push(w);
|
||||
}
|
||||
|
||||
private:
|
||||
std::stack<vertex_descriptor>& ordered_vertices;
|
||||
WeightMap weight;
|
||||
IncomingMap incoming;
|
||||
DistanceMap distance;
|
||||
PathCountMap path_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function object that calls Dijkstra's shortest paths algorithm
|
||||
* using the Dijkstra visitor for the Brandes betweenness centrality
|
||||
* algorithm.
|
||||
*/
|
||||
template<typename WeightMap>
|
||||
struct brandes_dijkstra_shortest_paths
|
||||
{
|
||||
brandes_dijkstra_shortest_paths(WeightMap weight_map)
|
||||
: weight_map(weight_map) { }
|
||||
|
||||
template<typename Graph, typename IncomingMap, typename DistanceMap,
|
||||
typename PathCountMap, typename VertexIndexMap>
|
||||
void
|
||||
operator()(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
std::stack<typename graph_traits<Graph>::vertex_descriptor>& ov,
|
||||
IncomingMap incoming,
|
||||
DistanceMap distance,
|
||||
PathCountMap path_count,
|
||||
VertexIndexMap vertex_index)
|
||||
{
|
||||
typedef brandes_dijkstra_visitor<Graph, WeightMap, IncomingMap,
|
||||
DistanceMap, PathCountMap> visitor_type;
|
||||
visitor_type visitor(ov, weight_map, incoming, distance, path_count);
|
||||
|
||||
dijkstra_shortest_paths(g, s,
|
||||
boost::weight_map(weight_map)
|
||||
.vertex_index_map(vertex_index)
|
||||
.distance_map(distance)
|
||||
.visitor(visitor));
|
||||
}
|
||||
|
||||
private:
|
||||
WeightMap weight_map;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function object that invokes breadth-first search for the
|
||||
* unweighted form of the Brandes betweenness centrality algorithm.
|
||||
*/
|
||||
struct brandes_unweighted_shortest_paths
|
||||
{
|
||||
/**
|
||||
* Customized visitor passed to breadth-first search, which
|
||||
* records predecessor and the number of shortest paths to each
|
||||
* vertex.
|
||||
*/
|
||||
template<typename Graph, typename IncomingMap, typename DistanceMap,
|
||||
typename PathCountMap>
|
||||
struct visitor_type : public bfs_visitor<>
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor
|
||||
vertex_descriptor;
|
||||
|
||||
visitor_type(IncomingMap incoming, DistanceMap distance,
|
||||
PathCountMap path_count,
|
||||
std::stack<vertex_descriptor>& ordered_vertices)
|
||||
: incoming(incoming), distance(distance),
|
||||
path_count(path_count), ordered_vertices(ordered_vertices) { }
|
||||
|
||||
/// Keep track of vertices as they are reached
|
||||
void examine_vertex(vertex_descriptor v, Graph&)
|
||||
{
|
||||
ordered_vertices.push(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whenever an edge e = (v, w) is labelled a tree edge, the
|
||||
* incoming edge list for w is set to {(v, w)} and the shortest
|
||||
* path count of w is set to the number of paths that reach {v}.
|
||||
*/
|
||||
void tree_edge(edge_descriptor e, Graph& g)
|
||||
{
|
||||
vertex_descriptor v = source(e, g);
|
||||
vertex_descriptor w = target(e, g);
|
||||
put(distance, w, get(distance, v) + 1);
|
||||
|
||||
put(path_count, w, get(path_count, v));
|
||||
incoming[w].push_back(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* If an edge e = (v, w) is not a tree edge, it may still be the
|
||||
* case that we've found more equally-short paths, so include (v, w)
|
||||
* in the incoming edge list of w and add all of the shortest
|
||||
* paths to v to the shortest path count of w.
|
||||
*/
|
||||
void non_tree_edge(edge_descriptor e, Graph& g)
|
||||
{
|
||||
vertex_descriptor v = source(e, g);
|
||||
vertex_descriptor w = target(e, g);
|
||||
if (get(distance, w) == get(distance, v) + 1) {
|
||||
put(path_count, w, get(path_count, w) + get(path_count, v));
|
||||
incoming[w].push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
IncomingMap incoming;
|
||||
DistanceMap distance;
|
||||
PathCountMap path_count;
|
||||
std::stack<vertex_descriptor>& ordered_vertices;
|
||||
};
|
||||
|
||||
template<typename Graph, typename IncomingMap, typename DistanceMap,
|
||||
typename PathCountMap, typename VertexIndexMap>
|
||||
void
|
||||
operator()(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
std::stack<typename graph_traits<Graph>::vertex_descriptor>& ov,
|
||||
IncomingMap incoming,
|
||||
DistanceMap distance,
|
||||
PathCountMap path_count,
|
||||
VertexIndexMap vertex_index)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor
|
||||
vertex_descriptor;
|
||||
|
||||
visitor_type<Graph, IncomingMap, DistanceMap, PathCountMap>
|
||||
visitor(incoming, distance, path_count, ov);
|
||||
|
||||
std::vector<default_color_type>
|
||||
colors(num_vertices(g), color_traits<default_color_type>::white());
|
||||
boost::queue<vertex_descriptor> Q;
|
||||
breadth_first_visit(g, s, Q, visitor,
|
||||
make_iterator_property_map(colors.begin(),
|
||||
vertex_index));
|
||||
}
|
||||
};
|
||||
|
||||
// When the edge centrality map is a dummy property map, no
|
||||
// initialization is needed.
|
||||
template<typename Iter>
|
||||
inline void
|
||||
init_centrality_map(std::pair<Iter, Iter>, dummy_property_map) { }
|
||||
|
||||
// When we have a real edge centrality map, initialize all of the
|
||||
// centralities to zero.
|
||||
template<typename Iter, typename Centrality>
|
||||
void
|
||||
init_centrality_map(std::pair<Iter, Iter> keys, Centrality centrality_map)
|
||||
{
|
||||
typedef typename property_traits<Centrality>::value_type
|
||||
centrality_type;
|
||||
while (keys.first != keys.second) {
|
||||
put(centrality_map, *keys.first, centrality_type(0));
|
||||
++keys.first;
|
||||
}
|
||||
}
|
||||
|
||||
// When the edge centrality map is a dummy property map, no update
|
||||
// is performed.
|
||||
template<typename Key, typename T>
|
||||
inline void
|
||||
update_centrality(dummy_property_map, const Key&, const T&) { }
|
||||
|
||||
// When we have a real edge centrality map, add the value to the map
|
||||
template<typename CentralityMap, typename Key, typename T>
|
||||
inline void
|
||||
update_centrality(CentralityMap centrality_map, Key k, const T& x)
|
||||
{ put(centrality_map, k, get(centrality_map, k) + x); }
|
||||
|
||||
template<typename Iter>
|
||||
inline void
|
||||
divide_centrality_by_two(std::pair<Iter, Iter>, dummy_property_map) {}
|
||||
|
||||
template<typename Iter, typename CentralityMap>
|
||||
inline void
|
||||
divide_centrality_by_two(std::pair<Iter, Iter> keys,
|
||||
CentralityMap centrality_map)
|
||||
{
|
||||
typename property_traits<CentralityMap>::value_type two(2);
|
||||
while (keys.first != keys.second) {
|
||||
put(centrality_map, *keys.first, get(centrality_map, *keys.first) / two);
|
||||
++keys.first;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
|
||||
typename IncomingMap, typename DistanceMap,
|
||||
typename DependencyMap, typename PathCountMap,
|
||||
typename VertexIndexMap, typename ShortestPaths>
|
||||
void
|
||||
brandes_betweenness_centrality_impl(const Graph& g,
|
||||
CentralityMap centrality, // C_B
|
||||
EdgeCentralityMap edge_centrality_map,
|
||||
IncomingMap incoming, // P
|
||||
DistanceMap distance, // d
|
||||
DependencyMap dependency, // delta
|
||||
PathCountMap path_count, // sigma
|
||||
VertexIndexMap vertex_index,
|
||||
ShortestPaths shortest_paths)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
// Initialize centrality
|
||||
init_centrality_map(vertices(g), centrality);
|
||||
init_centrality_map(edges(g), edge_centrality_map);
|
||||
|
||||
std::stack<vertex_descriptor> ordered_vertices;
|
||||
vertex_iterator s, s_end;
|
||||
for (tie(s, s_end) = vertices(g); s != s_end; ++s) {
|
||||
// Initialize for this iteration
|
||||
vertex_iterator w, w_end;
|
||||
for (tie(w, w_end) = vertices(g); w != w_end; ++w) {
|
||||
incoming[*w].clear();
|
||||
put(path_count, *w, 0);
|
||||
put(dependency, *w, 0);
|
||||
}
|
||||
put(path_count, *s, 1);
|
||||
|
||||
// Execute the shortest paths algorithm. This will be either
|
||||
// Dijkstra's algorithm or a customized breadth-first search,
|
||||
// depending on whether the graph is weighted or unweighted.
|
||||
shortest_paths(g, *s, ordered_vertices, incoming, distance,
|
||||
path_count, vertex_index);
|
||||
|
||||
while (!ordered_vertices.empty()) {
|
||||
vertex_descriptor w = ordered_vertices.top();
|
||||
ordered_vertices.pop();
|
||||
|
||||
typedef typename property_traits<IncomingMap>::value_type
|
||||
incoming_type;
|
||||
typedef typename incoming_type::iterator incoming_iterator;
|
||||
typedef typename property_traits<DependencyMap>::value_type
|
||||
dependency_type;
|
||||
|
||||
for (incoming_iterator vw = incoming[w].begin();
|
||||
vw != incoming[w].end(); ++vw) {
|
||||
vertex_descriptor v = source(*vw, g);
|
||||
dependency_type factor = dependency_type(get(path_count, v))
|
||||
/ dependency_type(get(path_count, w));
|
||||
factor *= (dependency_type(1) + get(dependency, w));
|
||||
put(dependency, v, get(dependency, v) + factor);
|
||||
update_centrality(edge_centrality_map, *vw, factor);
|
||||
}
|
||||
|
||||
if (w != *s) {
|
||||
update_centrality(centrality, w, get(dependency, w));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::directed_category directed_category;
|
||||
const bool is_undirected =
|
||||
is_convertible<directed_category*, undirected_tag*>::value;
|
||||
if (is_undirected) {
|
||||
divide_centrality_by_two(vertices(g), centrality);
|
||||
divide_centrality_by_two(edges(g), edge_centrality_map);
|
||||
}
|
||||
}
|
||||
|
||||
} } // end namespace detail::graph
|
||||
|
||||
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
|
||||
typename IncomingMap, typename DistanceMap,
|
||||
typename DependencyMap, typename PathCountMap,
|
||||
typename VertexIndexMap>
|
||||
void
|
||||
brandes_betweenness_centrality(const Graph& g,
|
||||
CentralityMap centrality, // C_B
|
||||
EdgeCentralityMap edge_centrality_map,
|
||||
IncomingMap incoming, // P
|
||||
DistanceMap distance, // d
|
||||
DependencyMap dependency, // delta
|
||||
PathCountMap path_count, // sigma
|
||||
VertexIndexMap vertex_index)
|
||||
{
|
||||
detail::graph::brandes_unweighted_shortest_paths shortest_paths;
|
||||
|
||||
detail::graph::brandes_betweenness_centrality_impl(g, centrality,
|
||||
edge_centrality_map,
|
||||
incoming, distance,
|
||||
dependency, path_count,
|
||||
vertex_index,
|
||||
shortest_paths);
|
||||
}
|
||||
|
||||
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
|
||||
typename IncomingMap, typename DistanceMap,
|
||||
typename DependencyMap, typename PathCountMap,
|
||||
typename VertexIndexMap, typename WeightMap>
|
||||
void
|
||||
brandes_betweenness_centrality(const Graph& g,
|
||||
CentralityMap centrality, // C_B
|
||||
EdgeCentralityMap edge_centrality_map,
|
||||
IncomingMap incoming, // P
|
||||
DistanceMap distance, // d
|
||||
DependencyMap dependency, // delta
|
||||
PathCountMap path_count, // sigma
|
||||
VertexIndexMap vertex_index,
|
||||
WeightMap weight_map)
|
||||
{
|
||||
detail::graph::brandes_dijkstra_shortest_paths<WeightMap>
|
||||
shortest_paths(weight_map);
|
||||
|
||||
detail::graph::brandes_betweenness_centrality_impl(g, centrality,
|
||||
edge_centrality_map,
|
||||
incoming, distance,
|
||||
dependency, path_count,
|
||||
vertex_index,
|
||||
shortest_paths);
|
||||
}
|
||||
|
||||
namespace detail { namespace graph {
|
||||
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
|
||||
typename WeightMap, typename VertexIndexMap>
|
||||
void
|
||||
brandes_betweenness_centrality_dispatch2(const Graph& g,
|
||||
CentralityMap centrality,
|
||||
EdgeCentralityMap edge_centrality_map,
|
||||
WeightMap weight_map,
|
||||
VertexIndexMap vertex_index)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename mpl::if_c<(is_same<CentralityMap,
|
||||
dummy_property_map>::value),
|
||||
EdgeCentralityMap,
|
||||
CentralityMap>::type a_centrality_map;
|
||||
typedef typename property_traits<a_centrality_map>::value_type
|
||||
centrality_type;
|
||||
|
||||
typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
|
||||
|
||||
std::vector<std::vector<edge_descriptor> > incoming(V);
|
||||
std::vector<centrality_type> distance(V);
|
||||
std::vector<centrality_type> dependency(V);
|
||||
std::vector<unsigned long long> path_count(V);
|
||||
|
||||
brandes_betweenness_centrality(
|
||||
g, centrality, edge_centrality_map,
|
||||
make_iterator_property_map(incoming.begin(), vertex_index),
|
||||
make_iterator_property_map(distance.begin(), vertex_index),
|
||||
make_iterator_property_map(dependency.begin(), vertex_index),
|
||||
make_iterator_property_map(path_count.begin(), vertex_index),
|
||||
vertex_index,
|
||||
weight_map);
|
||||
}
|
||||
|
||||
|
||||
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap,
|
||||
typename VertexIndexMap>
|
||||
void
|
||||
brandes_betweenness_centrality_dispatch2(const Graph& g,
|
||||
CentralityMap centrality,
|
||||
EdgeCentralityMap edge_centrality_map,
|
||||
VertexIndexMap vertex_index)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename mpl::if_c<(is_same<CentralityMap,
|
||||
dummy_property_map>::value),
|
||||
EdgeCentralityMap,
|
||||
CentralityMap>::type a_centrality_map;
|
||||
typedef typename property_traits<a_centrality_map>::value_type
|
||||
centrality_type;
|
||||
|
||||
typename graph_traits<Graph>::vertices_size_type V = num_vertices(g);
|
||||
|
||||
std::vector<std::vector<edge_descriptor> > incoming(V);
|
||||
std::vector<centrality_type> distance(V);
|
||||
std::vector<centrality_type> dependency(V);
|
||||
std::vector<unsigned long long> path_count(V);
|
||||
|
||||
brandes_betweenness_centrality(
|
||||
g, centrality, edge_centrality_map,
|
||||
make_iterator_property_map(incoming.begin(), vertex_index),
|
||||
make_iterator_property_map(distance.begin(), vertex_index),
|
||||
make_iterator_property_map(dependency.begin(), vertex_index),
|
||||
make_iterator_property_map(path_count.begin(), vertex_index),
|
||||
vertex_index);
|
||||
}
|
||||
|
||||
template<typename WeightMap>
|
||||
struct brandes_betweenness_centrality_dispatch1
|
||||
{
|
||||
template<typename Graph, typename CentralityMap,
|
||||
typename EdgeCentralityMap, typename VertexIndexMap>
|
||||
static void
|
||||
run(const Graph& g, CentralityMap centrality,
|
||||
EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
|
||||
WeightMap weight_map)
|
||||
{
|
||||
brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map,
|
||||
weight_map, vertex_index);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct brandes_betweenness_centrality_dispatch1<error_property_not_found>
|
||||
{
|
||||
template<typename Graph, typename CentralityMap,
|
||||
typename EdgeCentralityMap, typename VertexIndexMap>
|
||||
static void
|
||||
run(const Graph& g, CentralityMap centrality,
|
||||
EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index,
|
||||
error_property_not_found)
|
||||
{
|
||||
brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map,
|
||||
vertex_index);
|
||||
}
|
||||
};
|
||||
|
||||
} } // end namespace detail::graph
|
||||
|
||||
template<typename Graph, typename Param, typename Tag, typename Rest>
|
||||
void
|
||||
brandes_betweenness_centrality(const Graph& g,
|
||||
const bgl_named_params<Param,Tag,Rest>& params)
|
||||
{
|
||||
typedef bgl_named_params<Param,Tag,Rest> named_params;
|
||||
|
||||
typedef typename property_value<named_params, edge_weight_t>::type ew;
|
||||
detail::graph::brandes_betweenness_centrality_dispatch1<ew>::run(
|
||||
g,
|
||||
choose_param(get_param(params, vertex_centrality),
|
||||
dummy_property_map()),
|
||||
choose_param(get_param(params, edge_centrality),
|
||||
dummy_property_map()),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
|
||||
get_param(params, edge_weight));
|
||||
}
|
||||
|
||||
template<typename Graph, typename CentralityMap>
|
||||
void
|
||||
brandes_betweenness_centrality(const Graph& g, CentralityMap centrality)
|
||||
{
|
||||
detail::graph::brandes_betweenness_centrality_dispatch2(
|
||||
g, centrality, dummy_property_map(), get(vertex_index, g));
|
||||
}
|
||||
|
||||
template<typename Graph, typename CentralityMap, typename EdgeCentralityMap>
|
||||
void
|
||||
brandes_betweenness_centrality(const Graph& g, CentralityMap centrality,
|
||||
EdgeCentralityMap edge_centrality_map)
|
||||
{
|
||||
detail::graph::brandes_betweenness_centrality_dispatch2(
|
||||
g, centrality, edge_centrality_map, get(vertex_index, g));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts "absolute" betweenness centrality (as computed by the
|
||||
* brandes_betweenness_centrality algorithm) in the centrality map
|
||||
* into "relative" centrality. The result is placed back into the
|
||||
* given centrality map.
|
||||
*/
|
||||
template<typename Graph, typename CentralityMap>
|
||||
void
|
||||
relative_betweenness_centrality(const Graph& g, CentralityMap centrality)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
typedef typename property_traits<CentralityMap>::value_type centrality_type;
|
||||
|
||||
typename graph_traits<Graph>::vertices_size_type n = num_vertices(g);
|
||||
centrality_type factor = centrality_type(2)/centrality_type(n*n - 3*n + 2);
|
||||
vertex_iterator v, v_end;
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
|
||||
put(centrality, *v, factor * get(centrality, *v));
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the central point dominance of a graph.
|
||||
template<typename Graph, typename CentralityMap>
|
||||
typename property_traits<CentralityMap>::value_type
|
||||
central_point_dominance(const Graph& g, CentralityMap centrality)
|
||||
{
|
||||
using std::max;
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
typedef typename property_traits<CentralityMap>::value_type centrality_type;
|
||||
|
||||
typename graph_traits<Graph>::vertices_size_type n = num_vertices(g);
|
||||
|
||||
// Find max centrality
|
||||
centrality_type max_centrality(0);
|
||||
vertex_iterator v, v_end;
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
|
||||
max_centrality = (max)(max_centrality, get(centrality, *v));
|
||||
}
|
||||
|
||||
// Compute central point dominance
|
||||
centrality_type sum(0);
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
|
||||
sum += (max_centrality - get(centrality, *v));
|
||||
}
|
||||
return sum/(n-1);
|
||||
}
|
||||
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP
|
||||
415
libraries/include/boost/graph/biconnected_components.hpp
Normal file
415
libraries/include/boost/graph/biconnected_components.hpp
Normal file
@@ -0,0 +1,415 @@
|
||||
// Copyright (c) Jeremy Siek 2001
|
||||
// Copyright (c) Douglas Gregor 2004
|
||||
//
|
||||
// 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)
|
||||
|
||||
// NOTE: this final is generated by libs/graph/doc/biconnected_components.w
|
||||
|
||||
#ifndef BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP
|
||||
#define BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP
|
||||
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <algorithm> // for std::min and std::max
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
#include <boost/graph/graph_utility.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename ComponentMap, typename DiscoverTimeMap,
|
||||
typename LowPointMap, typename PredecessorMap,
|
||||
typename OutputIterator, typename Stack,
|
||||
typename DFSVisitor>
|
||||
struct biconnected_components_visitor : public dfs_visitor<>
|
||||
{
|
||||
biconnected_components_visitor
|
||||
(ComponentMap comp, std::size_t& c, DiscoverTimeMap dtm,
|
||||
std::size_t& dfs_time, LowPointMap lowpt, PredecessorMap pred,
|
||||
OutputIterator out, Stack& S, DFSVisitor vis)
|
||||
: comp(comp), c(c), dtm(dtm), dfs_time(dfs_time), lowpt(lowpt),
|
||||
pred(pred), out(out), S(S), vis(vis) { }
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void initialize_vertex(const Vertex& u, Graph& g)
|
||||
{
|
||||
vis.initialize_vertex(u, g);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void start_vertex(const Vertex& u, Graph& g)
|
||||
{
|
||||
put(pred, u, u);
|
||||
vis.start_vertex(u, g);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void discover_vertex(const Vertex& u, Graph& g)
|
||||
{
|
||||
put(dtm, u, ++dfs_time);
|
||||
put(lowpt, u, get(dtm, u));
|
||||
vis.discover_vertex(u, g);
|
||||
}
|
||||
|
||||
template <typename Edge, typename Graph>
|
||||
void examine_edge(const Edge& e, Graph& g)
|
||||
{
|
||||
vis.examine_edge(e, g);
|
||||
}
|
||||
|
||||
template <typename Edge, typename Graph>
|
||||
void tree_edge(const Edge& e, Graph& g)
|
||||
{
|
||||
S.push(e);
|
||||
put(pred, target(e, g), source(e, g));
|
||||
vis.tree_edge(e, g);
|
||||
}
|
||||
|
||||
template <typename Edge, typename Graph>
|
||||
void back_edge(const Edge& e, Graph& g)
|
||||
{
|
||||
BOOST_USING_STD_MIN();
|
||||
|
||||
if ( target(e, g) != get(pred, source(e, g)) ) {
|
||||
S.push(e);
|
||||
put(lowpt, source(e, g),
|
||||
min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, source(e, g)),
|
||||
get(dtm, target(e, g))));
|
||||
vis.back_edge(e, g);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Edge, typename Graph>
|
||||
void forward_or_cross_edge(const Edge& e, Graph& g)
|
||||
{
|
||||
vis.forward_or_cross_edge(e, g);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void finish_vertex(const Vertex& u, Graph& g)
|
||||
{
|
||||
BOOST_USING_STD_MIN();
|
||||
Vertex parent = get(pred, u);
|
||||
const std::size_t dtm_of_dubious_parent = get(dtm, parent);
|
||||
bool is_art_point = false;
|
||||
if ( dtm_of_dubious_parent > get(dtm, u) ) {
|
||||
parent = get(pred, parent);
|
||||
is_art_point = true;
|
||||
put(pred, get(pred, u), u);
|
||||
put(pred, u, parent);
|
||||
}
|
||||
|
||||
if ( parent == u ) { // at top
|
||||
if ( get(dtm, u) + 1 == dtm_of_dubious_parent )
|
||||
is_art_point = false;
|
||||
} else {
|
||||
put(lowpt, parent,
|
||||
min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent),
|
||||
get(lowpt, u)));
|
||||
|
||||
if (get(lowpt, u) >= get(dtm, parent)) {
|
||||
if ( get(dtm, parent) > get(dtm, get(pred, parent)) ) {
|
||||
put(pred, u, get(pred, parent));
|
||||
put(pred, parent, u);
|
||||
}
|
||||
|
||||
while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) {
|
||||
put(comp, S.top(), c);
|
||||
S.pop();
|
||||
}
|
||||
put(comp, S.top(), c);
|
||||
S.pop();
|
||||
++c;
|
||||
if ( S.empty() ) {
|
||||
put(pred, u, parent);
|
||||
put(pred, parent, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( is_art_point )
|
||||
*out++ = u;
|
||||
vis.finish_vertex(u, g);
|
||||
}
|
||||
|
||||
ComponentMap comp;
|
||||
std::size_t& c;
|
||||
DiscoverTimeMap dtm;
|
||||
std::size_t& dfs_time;
|
||||
LowPointMap lowpt;
|
||||
PredecessorMap pred;
|
||||
OutputIterator out;
|
||||
Stack& S;
|
||||
DFSVisitor vis;
|
||||
};
|
||||
|
||||
template<typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename VertexIndexMap, typename DiscoverTimeMap, typename LowPointMap,
|
||||
typename PredecessorMap, typename DFSVisitor>
|
||||
std::pair<std::size_t, OutputIterator>
|
||||
biconnected_components_impl(const Graph & g, ComponentMap comp,
|
||||
OutputIterator out, VertexIndexMap index_map, DiscoverTimeMap dtm,
|
||||
LowPointMap lowpt, PredecessorMap pred, DFSVisitor dfs_vis)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
function_requires<VertexListGraphConcept<Graph> >();
|
||||
function_requires<IncidenceGraphConcept<Graph> >();
|
||||
function_requires<WritablePropertyMapConcept<ComponentMap, edge_t> >();
|
||||
function_requires<ReadWritePropertyMapConcept<DiscoverTimeMap,
|
||||
vertex_t> >();
|
||||
function_requires<ReadWritePropertyMapConcept<LowPointMap, vertex_t > >();
|
||||
function_requires<ReadWritePropertyMapConcept<PredecessorMap,
|
||||
vertex_t> >();
|
||||
|
||||
std::size_t num_components = 0;
|
||||
std::size_t dfs_time = 0;
|
||||
std::stack<edge_t> S;
|
||||
|
||||
biconnected_components_visitor<ComponentMap, DiscoverTimeMap,
|
||||
LowPointMap, PredecessorMap, OutputIterator, std::stack<edge_t>,
|
||||
DFSVisitor>
|
||||
vis(comp, num_components, dtm, dfs_time, lowpt, pred, out,
|
||||
S, dfs_vis);
|
||||
|
||||
depth_first_search(g, visitor(vis).vertex_index_map(index_map));
|
||||
|
||||
return std::pair<std::size_t, OutputIterator>(num_components, vis.out);
|
||||
}
|
||||
|
||||
template <typename PredecessorMap>
|
||||
struct bicomp_dispatch3
|
||||
{
|
||||
template<typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename VertexIndexMap, typename DiscoverTimeMap,
|
||||
typename LowPointMap, class P, class T, class R>
|
||||
static std::pair<std::size_t, OutputIterator> apply (const Graph & g,
|
||||
ComponentMap comp, OutputIterator out, VertexIndexMap index_map,
|
||||
DiscoverTimeMap dtm, LowPointMap lowpt,
|
||||
const bgl_named_params<P, T, R>& params, PredecessorMap pred)
|
||||
{
|
||||
return biconnected_components_impl
|
||||
(g, comp, out, index_map, dtm, lowpt, pred,
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_dfs_visitor(null_visitor())));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct bicomp_dispatch3<error_property_not_found>
|
||||
{
|
||||
template<typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename VertexIndexMap, typename DiscoverTimeMap,
|
||||
typename LowPointMap, class P, class T, class R>
|
||||
static std::pair<std::size_t, OutputIterator> apply (const Graph & g,
|
||||
ComponentMap comp, OutputIterator out, VertexIndexMap index_map,
|
||||
DiscoverTimeMap dtm, LowPointMap lowpt,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
error_property_not_found)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
std::vector<vertex_t> pred(num_vertices(g));
|
||||
vertex_t vert = graph_traits<Graph>::null_vertex();
|
||||
|
||||
return biconnected_components_impl
|
||||
(g, comp, out, index_map, dtm, lowpt,
|
||||
make_iterator_property_map(pred.begin(), index_map, vert),
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_dfs_visitor(null_visitor())));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename LowPointMap>
|
||||
struct bicomp_dispatch2
|
||||
{
|
||||
template<typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename VertexIndexMap, typename DiscoverTimeMap,
|
||||
typename P, typename T, typename R>
|
||||
static std::pair<std::size_t, OutputIterator> apply (const Graph& g,
|
||||
ComponentMap comp, OutputIterator out, VertexIndexMap index_map,
|
||||
DiscoverTimeMap dtm, const bgl_named_params<P, T, R>& params,
|
||||
LowPointMap lowpt)
|
||||
{
|
||||
typedef typename property_value< bgl_named_params<P,T,R>,
|
||||
vertex_predecessor_t>::type dispatch_type;
|
||||
|
||||
return bicomp_dispatch3<dispatch_type>::apply
|
||||
(g, comp, out, index_map, dtm, lowpt, params,
|
||||
get_param(params, vertex_predecessor));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct bicomp_dispatch2<error_property_not_found>
|
||||
{
|
||||
template<typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename VertexIndexMap, typename DiscoverTimeMap,
|
||||
typename P, typename T, typename R>
|
||||
static std::pair<std::size_t, OutputIterator> apply (const Graph& g,
|
||||
ComponentMap comp, OutputIterator out, VertexIndexMap index_map,
|
||||
DiscoverTimeMap dtm, const bgl_named_params<P, T, R>& params,
|
||||
error_property_not_found)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertices_size_type
|
||||
vertices_size_type;
|
||||
std::vector<vertices_size_type> lowpt(num_vertices(g));
|
||||
vertices_size_type vst(0);
|
||||
|
||||
typedef typename property_value< bgl_named_params<P,T,R>,
|
||||
vertex_predecessor_t>::type dispatch_type;
|
||||
|
||||
return bicomp_dispatch3<dispatch_type>::apply
|
||||
(g, comp, out, index_map, dtm,
|
||||
make_iterator_property_map(lowpt.begin(), index_map, vst),
|
||||
params, get_param(params, vertex_predecessor));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DiscoverTimeMap>
|
||||
struct bicomp_dispatch1
|
||||
{
|
||||
template<typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename VertexIndexMap, class P, class T, class R>
|
||||
static std::pair<std::size_t, OutputIterator> apply(const Graph& g,
|
||||
ComponentMap comp, OutputIterator out, VertexIndexMap index_map,
|
||||
const bgl_named_params<P, T, R>& params, DiscoverTimeMap dtm)
|
||||
{
|
||||
typedef typename property_value< bgl_named_params<P,T,R>,
|
||||
vertex_lowpoint_t>::type dispatch_type;
|
||||
|
||||
return bicomp_dispatch2<dispatch_type>::apply
|
||||
(g, comp, out, index_map, dtm, params,
|
||||
get_param(params, vertex_lowpoint));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct bicomp_dispatch1<error_property_not_found>
|
||||
{
|
||||
template<typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename VertexIndexMap, class P, class T, class R>
|
||||
static std::pair<std::size_t, OutputIterator> apply(const Graph& g,
|
||||
ComponentMap comp, OutputIterator out, VertexIndexMap index_map,
|
||||
const bgl_named_params<P, T, R>& params, error_property_not_found)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertices_size_type
|
||||
vertices_size_type;
|
||||
std::vector<vertices_size_type> discover_time(num_vertices(g));
|
||||
vertices_size_type vst(0);
|
||||
|
||||
typedef typename property_value< bgl_named_params<P,T,R>,
|
||||
vertex_lowpoint_t>::type dispatch_type;
|
||||
|
||||
return bicomp_dispatch2<dispatch_type>::apply
|
||||
(g, comp, out, index_map,
|
||||
make_iterator_property_map(discover_time.begin(), index_map, vst),
|
||||
params, get_param(params, vertex_lowpoint));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename DiscoverTimeMap, typename LowPointMap>
|
||||
std::pair<std::size_t, OutputIterator>
|
||||
biconnected_components(const Graph& g, ComponentMap comp,
|
||||
OutputIterator out, DiscoverTimeMap dtm, LowPointMap lowpt)
|
||||
{
|
||||
typedef detail::error_property_not_found dispatch_type;
|
||||
|
||||
return detail::bicomp_dispatch3<dispatch_type>::apply
|
||||
(g, comp, out,
|
||||
get(vertex_index, g),
|
||||
dtm, lowpt,
|
||||
bgl_named_params<int, buffer_param_t>(0),
|
||||
detail::error_property_not_found());
|
||||
}
|
||||
|
||||
template <typename Graph, typename ComponentMap, typename OutputIterator,
|
||||
typename P, typename T, typename R>
|
||||
std::pair<std::size_t, OutputIterator>
|
||||
biconnected_components(const Graph& g, ComponentMap comp, OutputIterator out,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename property_value< bgl_named_params<P,T,R>,
|
||||
vertex_discover_time_t>::type dispatch_type;
|
||||
|
||||
return detail::bicomp_dispatch1<dispatch_type>::apply(g, comp, out,
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
|
||||
params, get_param(params, vertex_discover_time));
|
||||
}
|
||||
|
||||
template < typename Graph, typename ComponentMap, typename OutputIterator>
|
||||
std::pair<std::size_t, OutputIterator>
|
||||
biconnected_components(const Graph& g, ComponentMap comp, OutputIterator out)
|
||||
{
|
||||
return biconnected_components(g, comp, out,
|
||||
bgl_named_params<int, buffer_param_t>(0));
|
||||
}
|
||||
|
||||
namespace graph_detail {
|
||||
struct dummy_output_iterator
|
||||
{
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
typedef void value_type;
|
||||
typedef void pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
struct reference {
|
||||
template<typename T>
|
||||
reference& operator=(const T&) { return *this; }
|
||||
};
|
||||
|
||||
reference operator*() const { return reference(); }
|
||||
dummy_output_iterator& operator++() { return *this; }
|
||||
dummy_output_iterator operator++(int) { return *this; }
|
||||
};
|
||||
} // end namespace graph_detail
|
||||
|
||||
template <typename Graph, typename ComponentMap,
|
||||
typename P, typename T, typename R>
|
||||
std::size_t
|
||||
biconnected_components(const Graph& g, ComponentMap comp,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return biconnected_components(g, comp,
|
||||
graph_detail::dummy_output_iterator(), params).first;
|
||||
}
|
||||
|
||||
template <typename Graph, typename ComponentMap>
|
||||
std::size_t
|
||||
biconnected_components(const Graph& g, ComponentMap comp)
|
||||
{
|
||||
return biconnected_components(g, comp,
|
||||
graph_detail::dummy_output_iterator()).first;
|
||||
}
|
||||
|
||||
template<typename Graph, typename OutputIterator,
|
||||
typename P, typename T, typename R>
|
||||
OutputIterator
|
||||
articulation_points(const Graph& g, OutputIterator out,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return biconnected_components(g, dummy_property_map(), out,
|
||||
params).second;
|
||||
}
|
||||
|
||||
template<typename Graph, typename OutputIterator>
|
||||
OutputIterator
|
||||
articulation_points(const Graph& g, OutputIterator out)
|
||||
{
|
||||
return biconnected_components(g, dummy_property_map(), out,
|
||||
bgl_named_params<int, buffer_param_t>(0)).second;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif /* BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP */
|
||||
322
libraries/include/boost/graph/boyer_myrvold_planar_test.hpp
Normal file
322
libraries/include/boost/graph/boyer_myrvold_planar_test.hpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// 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 __BOYER_MYRVOLD_PLANAR_TEST_HPP__
|
||||
#define __BOYER_MYRVOLD_PLANAR_TEST_HPP__
|
||||
|
||||
#include <boost/graph/planar_detail/boyer_myrvold_impl.hpp>
|
||||
#include <boost/parameter.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
struct no_kuratowski_subgraph_isolation {};
|
||||
struct no_planar_embedding {};
|
||||
|
||||
namespace boyer_myrvold_params
|
||||
{
|
||||
|
||||
BOOST_PARAMETER_KEYWORD(tag, graph)
|
||||
BOOST_PARAMETER_KEYWORD(tag, embedding)
|
||||
BOOST_PARAMETER_KEYWORD(tag, kuratowski_subgraph)
|
||||
BOOST_PARAMETER_KEYWORD(tag, vertex_index_map)
|
||||
BOOST_PARAMETER_KEYWORD(tag, edge_index_map)
|
||||
|
||||
typedef parameter::parameters< parameter::required<tag::graph>,
|
||||
tag::embedding,
|
||||
tag::kuratowski_subgraph,
|
||||
tag::vertex_index_map,
|
||||
tag::edge_index_map
|
||||
> boyer_myrvold_params_t;
|
||||
|
||||
namespace core
|
||||
{
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool dispatched_boyer_myrvold(ArgumentPack const& args,
|
||||
mpl::true_,
|
||||
mpl::true_
|
||||
)
|
||||
{
|
||||
//Dispatch for no planar embedding, no kuratowski subgraph isolation
|
||||
|
||||
typedef typename remove_const
|
||||
<
|
||||
typename remove_reference
|
||||
< typename parameter::binding
|
||||
< ArgumentPack, tag::graph>::type
|
||||
>::type
|
||||
>::type graph_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::vertex_index_map,
|
||||
typename property_map
|
||||
< typename remove_reference<graph_t>::type,
|
||||
vertex_index_t>::const_type
|
||||
>::type vertex_index_map_t;
|
||||
|
||||
boyer_myrvold_impl
|
||||
<graph_t,
|
||||
vertex_index_map_t,
|
||||
graph::detail::no_old_handles,
|
||||
graph::detail::no_embedding
|
||||
>
|
||||
planarity_tester(args[graph],
|
||||
args[vertex_index_map |
|
||||
get(vertex_index, args[graph])
|
||||
]
|
||||
);
|
||||
|
||||
return planarity_tester.is_planar() ? true : false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool dispatched_boyer_myrvold(ArgumentPack const& args,
|
||||
mpl::true_,
|
||||
mpl::false_
|
||||
)
|
||||
{
|
||||
//Dispatch for no planar embedding, kuratowski subgraph isolation
|
||||
typedef typename remove_const
|
||||
<
|
||||
typename remove_reference
|
||||
< typename parameter::binding
|
||||
< ArgumentPack, tag::graph>::type
|
||||
>::type
|
||||
>::type graph_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::vertex_index_map,
|
||||
typename property_map<graph_t, vertex_index_t>::type
|
||||
>::type vertex_index_map_t;
|
||||
|
||||
boyer_myrvold_impl
|
||||
<graph_t,
|
||||
vertex_index_map_t,
|
||||
graph::detail::store_old_handles,
|
||||
graph::detail::no_embedding
|
||||
>
|
||||
planarity_tester(args[graph],
|
||||
args[vertex_index_map |
|
||||
get(vertex_index, args[graph])
|
||||
]
|
||||
);
|
||||
|
||||
if (planarity_tester.is_planar())
|
||||
return true;
|
||||
else
|
||||
{
|
||||
planarity_tester.extract_kuratowski_subgraph
|
||||
(args[kuratowski_subgraph],
|
||||
args[edge_index_map|get(edge_index, args[graph])]
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool dispatched_boyer_myrvold(ArgumentPack const& args,
|
||||
mpl::false_,
|
||||
mpl::true_
|
||||
)
|
||||
{
|
||||
//Dispatch for planar embedding, no kuratowski subgraph isolation
|
||||
typedef typename remove_const
|
||||
<
|
||||
typename remove_reference
|
||||
< typename parameter::binding
|
||||
< ArgumentPack, tag::graph>::type
|
||||
>::type
|
||||
>::type graph_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::vertex_index_map,
|
||||
typename property_map<graph_t, vertex_index_t>::type
|
||||
>::type vertex_index_map_t;
|
||||
|
||||
boyer_myrvold_impl
|
||||
<graph_t,
|
||||
vertex_index_map_t,
|
||||
graph::detail::no_old_handles,
|
||||
#ifdef BOOST_GRAPH_PREFER_STD_LIB
|
||||
graph::detail::std_list
|
||||
#else
|
||||
graph::detail::recursive_lazy_list
|
||||
#endif
|
||||
>
|
||||
planarity_tester(args[graph],
|
||||
args[vertex_index_map |
|
||||
get(vertex_index, args[graph])
|
||||
]
|
||||
);
|
||||
|
||||
if (planarity_tester.is_planar())
|
||||
{
|
||||
planarity_tester.make_edge_permutation(args[embedding]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool dispatched_boyer_myrvold(ArgumentPack const& args,
|
||||
mpl::false_,
|
||||
mpl::false_
|
||||
)
|
||||
{
|
||||
//Dispatch for planar embedding, kuratowski subgraph isolation
|
||||
typedef typename remove_const
|
||||
<
|
||||
typename remove_reference
|
||||
< typename parameter::binding
|
||||
< ArgumentPack, tag::graph>::type
|
||||
>::type
|
||||
>::type graph_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::vertex_index_map,
|
||||
typename property_map<graph_t, vertex_index_t>::type
|
||||
>::type vertex_index_map_t;
|
||||
|
||||
boyer_myrvold_impl
|
||||
<graph_t,
|
||||
vertex_index_map_t,
|
||||
graph::detail::store_old_handles,
|
||||
#ifdef BOOST_BGL_PREFER_STD_LIB
|
||||
graph::detail::std_list
|
||||
#else
|
||||
graph::detail::recursive_lazy_list
|
||||
#endif
|
||||
>
|
||||
planarity_tester(args[graph],
|
||||
args[vertex_index_map |
|
||||
get(vertex_index, args[graph])
|
||||
]
|
||||
);
|
||||
|
||||
if (planarity_tester.is_planar())
|
||||
{
|
||||
planarity_tester.make_edge_permutation(args[embedding]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
planarity_tester.extract_kuratowski_subgraph
|
||||
(args[kuratowski_subgraph],
|
||||
args[edge_index_map | get(edge_index, args[graph])]
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool boyer_myrvold_planarity_test(ArgumentPack const& args)
|
||||
{
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::kuratowski_subgraph,
|
||||
const no_kuratowski_subgraph_isolation&
|
||||
>::type
|
||||
kuratowski_arg_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::embedding,
|
||||
const no_planar_embedding&
|
||||
>::type
|
||||
embedding_arg_t;
|
||||
|
||||
return dispatched_boyer_myrvold
|
||||
(args,
|
||||
boost::is_same
|
||||
<embedding_arg_t, const no_planar_embedding&>(),
|
||||
boost::is_same
|
||||
<kuratowski_arg_t, const no_kuratowski_subgraph_isolation&>()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} //namespace core
|
||||
|
||||
} //namespace boyer_myrvold_params
|
||||
|
||||
|
||||
template <typename A0>
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0));
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
// bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1)
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1));
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0,
|
||||
A1 const& arg1,
|
||||
A2 const& arg2
|
||||
)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1,arg2));
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2, typename A3>
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0,
|
||||
A1 const& arg1,
|
||||
A2 const& arg2,
|
||||
A3 const& arg3
|
||||
)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1,arg2,arg3));
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2, typename A3, typename A4>
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0,
|
||||
A1 const& arg1,
|
||||
A2 const& arg2,
|
||||
A3 const& arg3,
|
||||
A4 const& arg4
|
||||
)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()
|
||||
(arg0,arg1,arg2,arg3,arg4)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //__BOYER_MYRVOLD_PLANAR_TEST_HPP__
|
||||
293
libraries/include/boost/graph/breadth_first_search.hpp
Normal file
293
libraries/include/boost/graph/breadth_first_search.hpp
Normal file
@@ -0,0 +1,293 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Visitor, class Graph>
|
||||
struct BFSVisitorConcept {
|
||||
void constraints() {
|
||||
function_requires< 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;
|
||||
};
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
function_requires< IncidenceGraphConcept<IncidenceGraph> >();
|
||||
typedef graph_traits<IncidenceGraph> GTraits;
|
||||
typedef typename GTraits::vertex_descriptor Vertex;
|
||||
typedef typename GTraits::edge_descriptor Edge;
|
||||
function_requires< BFSVisitorConcept<BFSVisitor, IncidenceGraph> >();
|
||||
function_requires< ReadWritePropertyMapConcept<ColorMap, Vertex> >();
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typename GTraits::out_edge_iterator ei, ei_end;
|
||||
|
||||
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 (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
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
// 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 (tie(i, i_end) = vertices(g); i != i_end; ++i) {
|
||||
vis.initialize_vertex(*i, g);
|
||||
put(color, *i, Color::white());
|
||||
}
|
||||
breadth_first_visit(g, s, Q, vis, color);
|
||||
}
|
||||
|
||||
|
||||
template <class Visitors = null_visitor>
|
||||
class bfs_visitor {
|
||||
public:
|
||||
bfs_visitor() { }
|
||||
bfs_visitor(Visitors vis) : m_vis(vis) { }
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void initialize_vertex(Vertex u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_discover_vertex());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void examine_vertex(Vertex u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_examine_vertex());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void examine_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, ::boost::on_examine_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void tree_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, ::boost::on_tree_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void non_tree_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, ::boost::on_non_tree_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void gray_target(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, ::boost::on_gray_target());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void black_target(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, ::boost::on_black_target());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void finish_vertex(Vertex u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
typedef graph_traits<VertexListGraph> Traits;
|
||||
// Buffer default
|
||||
typedef typename Traits::vertex_descriptor Vertex;
|
||||
typedef boost::queue<Vertex> queue_t;
|
||||
queue_t Q;
|
||||
detail::wrap_ref<queue_t> Qref(Q);
|
||||
breadth_first_search
|
||||
(g, s,
|
||||
choose_param(get_param(params, buffer_param_t()), Qref).ref,
|
||||
vis, color);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct bfs_dispatch<detail::error_property_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,
|
||||
detail::error_property_not_found)
|
||||
{
|
||||
std::vector<default_color_type> color_vec(num_vertices(g));
|
||||
default_color_type c = white_color;
|
||||
null_visitor null_vis;
|
||||
|
||||
bfs_helper
|
||||
(g, s,
|
||||
make_iterator_property_map
|
||||
(color_vec.begin(),
|
||||
choose_const_pmap(get_param(params, vertex_index),
|
||||
g, vertex_index), c),
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_bfs_visitor(null_vis)),
|
||||
params);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// 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 property_value< bgl_named_params<P,T,R>,
|
||||
vertex_color_t>::type C;
|
||||
detail::bfs_dispatch<C>::apply(ng, s, params,
|
||||
get_param(params, vertex_color));
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
detail::wrap_ref<queue_t> Qref(Q);
|
||||
|
||||
breadth_first_visit
|
||||
(ng, s,
|
||||
choose_param(get_param(params, buffer_param_t()), Qref).ref,
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_bfs_visitor(null_visitor())),
|
||||
choose_pmap(get_param(params, vertex_color), ng, vertex_color)
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP
|
||||
|
||||
270
libraries/include/boost/graph/chrobak_payne_drawing.hpp
Normal file
270
libraries/include/boost/graph/chrobak_payne_drawing.hpp
Normal file
@@ -0,0 +1,270 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// 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 __CHROBAK_PAYNE_DRAWING_HPP__
|
||||
#define __CHROBAK_PAYNE_DRAWING_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next and prior
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace graph { namespace detail
|
||||
{
|
||||
|
||||
template<typename Graph,
|
||||
typename VertexToVertexMap,
|
||||
typename VertexTo1DCoordMap>
|
||||
void accumulate_offsets(typename graph_traits<Graph>::vertex_descriptor v,
|
||||
std::size_t offset,
|
||||
const Graph& g,
|
||||
VertexTo1DCoordMap x,
|
||||
VertexTo1DCoordMap delta_x,
|
||||
VertexToVertexMap left,
|
||||
VertexToVertexMap right)
|
||||
{
|
||||
if (v != graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
x[v] += delta_x[v] + offset;
|
||||
accumulate_offsets(left[v], x[v], g, x, delta_x, left, right);
|
||||
accumulate_offsets(right[v], x[v], g, x, delta_x, left, right);
|
||||
}
|
||||
}
|
||||
|
||||
} /*namespace detail*/ } /*namespace graph*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename ForwardIterator,
|
||||
typename GridPositionMap,
|
||||
typename VertexIndexMap>
|
||||
void chrobak_payne_straight_line_drawing(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
ForwardIterator ordering_begin,
|
||||
ForwardIterator ordering_end,
|
||||
GridPositionMap drawing,
|
||||
VertexIndexMap vm
|
||||
)
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename PlanarEmbedding::value_type::const_iterator
|
||||
edge_permutation_iterator_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef std::vector<vertex_t> vertex_vector_t;
|
||||
typedef std::vector<v_size_t> vsize_vector_t;
|
||||
typedef std::vector<bool> bool_vector_t;
|
||||
typedef boost::iterator_property_map
|
||||
<typename vertex_vector_t::iterator, VertexIndexMap>
|
||||
vertex_to_vertex_map_t;
|
||||
typedef boost::iterator_property_map
|
||||
<typename vsize_vector_t::iterator, VertexIndexMap>
|
||||
vertex_to_vsize_map_t;
|
||||
typedef boost::iterator_property_map
|
||||
<typename bool_vector_t::iterator, VertexIndexMap>
|
||||
vertex_to_bool_map_t;
|
||||
|
||||
vertex_vector_t left_vector(num_vertices(g),
|
||||
graph_traits<Graph>::null_vertex()
|
||||
);
|
||||
vertex_vector_t right_vector(num_vertices(g),
|
||||
graph_traits<Graph>::null_vertex()
|
||||
);
|
||||
vsize_vector_t seen_as_right_vector(num_vertices(g), 0);
|
||||
vsize_vector_t seen_vector(num_vertices(g), 0);
|
||||
vsize_vector_t delta_x_vector(num_vertices(g),0);
|
||||
vsize_vector_t y_vector(num_vertices(g));
|
||||
vsize_vector_t x_vector(num_vertices(g),0);
|
||||
bool_vector_t installed_vector(num_vertices(g),false);
|
||||
|
||||
vertex_to_vertex_map_t left(left_vector.begin(), vm);
|
||||
vertex_to_vertex_map_t right(right_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t seen_as_right(seen_as_right_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t seen(seen_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t delta_x(delta_x_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t y(y_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t x(x_vector.begin(), vm);
|
||||
vertex_to_bool_map_t installed(installed_vector.begin(), vm);
|
||||
|
||||
v_size_t timestamp = 1;
|
||||
vertex_vector_t installed_neighbors;
|
||||
|
||||
ForwardIterator itr = ordering_begin;
|
||||
vertex_t v1 = *itr; ++itr;
|
||||
vertex_t v2 = *itr; ++itr;
|
||||
vertex_t v3 = *itr; ++itr;
|
||||
|
||||
delta_x[v2] = 1;
|
||||
delta_x[v3] = 1;
|
||||
|
||||
y[v1] = 0;
|
||||
y[v2] = 0;
|
||||
y[v3] = 1;
|
||||
|
||||
right[v1] = v3;
|
||||
right[v3] = v2;
|
||||
|
||||
installed[v1] = installed[v2] = installed[v3] = true;
|
||||
|
||||
for(ForwardIterator itr_end = ordering_end; itr != itr_end; ++itr)
|
||||
{
|
||||
vertex_t v = *itr;
|
||||
|
||||
// First, find the leftmost and rightmost neighbor of v on the outer
|
||||
// cycle of the embedding.
|
||||
// Note: since we're moving clockwise through the edges adjacent to v,
|
||||
// we're actually moving from right to left among v's neighbors on the
|
||||
// outer face (since v will be installed above them all) looking for
|
||||
// the leftmost and rightmost installed neigbhors
|
||||
|
||||
vertex_t leftmost = graph_traits<Graph>::null_vertex();
|
||||
vertex_t rightmost = graph_traits<Graph>::null_vertex();
|
||||
|
||||
installed_neighbors.clear();
|
||||
|
||||
vertex_t prev_vertex = graph_traits<Graph>::null_vertex();
|
||||
edge_permutation_iterator_t pi, pi_end;
|
||||
pi_end = embedding[v].end();
|
||||
for(pi = embedding[v].begin(); pi != pi_end; ++pi)
|
||||
{
|
||||
vertex_t curr_vertex = source(*pi,g) == v ?
|
||||
target(*pi,g) : source(*pi,g);
|
||||
|
||||
// Skip any self-loops or parallel edges
|
||||
if (curr_vertex == v || curr_vertex == prev_vertex)
|
||||
continue;
|
||||
|
||||
if (installed[curr_vertex])
|
||||
{
|
||||
seen[curr_vertex] = timestamp;
|
||||
|
||||
if (right[curr_vertex] != graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
seen_as_right[right[curr_vertex]] = timestamp;
|
||||
}
|
||||
installed_neighbors.push_back(curr_vertex);
|
||||
}
|
||||
|
||||
prev_vertex = curr_vertex;
|
||||
}
|
||||
|
||||
typename vertex_vector_t::iterator vi, vi_end;
|
||||
vi_end = installed_neighbors.end();
|
||||
for(vi = installed_neighbors.begin(); vi != vi_end; ++vi)
|
||||
{
|
||||
if (right[*vi] == graph_traits<Graph>::null_vertex() ||
|
||||
seen[right[*vi]] != timestamp
|
||||
)
|
||||
rightmost = *vi;
|
||||
if (seen_as_right[*vi] != timestamp)
|
||||
leftmost = *vi;
|
||||
}
|
||||
|
||||
++timestamp;
|
||||
|
||||
//stretch gaps
|
||||
++delta_x[right[leftmost]];
|
||||
++delta_x[rightmost];
|
||||
|
||||
//adjust offsets
|
||||
std::size_t delta_p_q = 0;
|
||||
vertex_t stopping_vertex = right[rightmost];
|
||||
for(vertex_t temp = right[leftmost]; temp != stopping_vertex;
|
||||
temp = right[temp]
|
||||
)
|
||||
{
|
||||
delta_p_q += delta_x[temp];
|
||||
}
|
||||
|
||||
delta_x[v] = ((y[rightmost] + delta_p_q) - y[leftmost])/2;
|
||||
y[v] = y[leftmost] + delta_x[v];
|
||||
delta_x[rightmost] = delta_p_q - delta_x[v];
|
||||
|
||||
bool leftmost_and_rightmost_adjacent = right[leftmost] == rightmost;
|
||||
if (!leftmost_and_rightmost_adjacent)
|
||||
delta_x[right[leftmost]] -= delta_x[v];
|
||||
|
||||
//install v
|
||||
if (!leftmost_and_rightmost_adjacent)
|
||||
{
|
||||
left[v] = right[leftmost];
|
||||
vertex_t next_to_rightmost;
|
||||
for(vertex_t temp = leftmost; temp != rightmost;
|
||||
temp = right[temp]
|
||||
)
|
||||
{
|
||||
next_to_rightmost = temp;
|
||||
}
|
||||
|
||||
right[next_to_rightmost] = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
else
|
||||
{
|
||||
left[v] = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
|
||||
right[leftmost] = v;
|
||||
right[v] = rightmost;
|
||||
installed[v] = true;
|
||||
|
||||
}
|
||||
|
||||
graph::detail::accumulate_offsets
|
||||
(*ordering_begin,0,g,x,delta_x,left,right);
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_t v(*vi);
|
||||
drawing[v].x = x[v];
|
||||
drawing[v].y = y[v];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename ForwardIterator,
|
||||
typename GridPositionMap>
|
||||
inline void chrobak_payne_straight_line_drawing(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
ForwardIterator ord_begin,
|
||||
ForwardIterator ord_end,
|
||||
GridPositionMap drawing
|
||||
)
|
||||
{
|
||||
chrobak_payne_straight_line_drawing(g,
|
||||
embedding,
|
||||
ord_begin,
|
||||
ord_end,
|
||||
drawing,
|
||||
get(vertex_index,g)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //__CHROBAK_PAYNE_DRAWING_HPP__
|
||||
55
libraries/include/boost/graph/circle_layout.hpp
Normal file
55
libraries/include/boost/graph/circle_layout.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2004 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: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_CIRCLE_LAYOUT_HPP
|
||||
#define BOOST_GRAPH_CIRCLE_LAYOUT_HPP
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <utility>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
/**
|
||||
* \brief Layout the graph with the vertices at the points of a regular
|
||||
* n-polygon.
|
||||
*
|
||||
* The distance from the center of the polygon to each point is
|
||||
* determined by the @p radius parameter. The @p position parameter
|
||||
* must be an Lvalue Property Map whose value type is a class type
|
||||
* containing @c x and @c y members that will be set to the @c x and
|
||||
* @c y coordinates.
|
||||
*/
|
||||
template<typename VertexListGraph, typename PositionMap, typename Radius>
|
||||
void
|
||||
circle_graph_layout(const VertexListGraph& g, PositionMap position,
|
||||
Radius radius)
|
||||
{
|
||||
const double pi = 3.14159;
|
||||
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
#endif // BOOST_NO_STDC_NAMESPACE
|
||||
|
||||
typedef typename graph_traits<VertexListGraph>::vertices_size_type
|
||||
vertices_size_type;
|
||||
|
||||
vertices_size_type n = num_vertices(g);
|
||||
|
||||
typedef typename graph_traits<VertexListGraph>::vertex_iterator
|
||||
vertex_iterator;
|
||||
|
||||
vertices_size_type i = 0;
|
||||
for(std::pair<vertex_iterator, vertex_iterator> v = vertices(g);
|
||||
v.first != v.second; ++v.first, ++i) {
|
||||
position[*v.first].x = radius * cos(i * 2 * pi / n);
|
||||
position[*v.first].y = radius * sin(i * 2 * pi / n);
|
||||
}
|
||||
}
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_CIRCLE_LAYOUT_HPP
|
||||
801
libraries/include/boost/graph/compressed_sparse_row_graph.hpp
Normal file
801
libraries/include/boost/graph/compressed_sparse_row_graph.hpp
Normal file
@@ -0,0 +1,801 @@
|
||||
// Copyright 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
|
||||
|
||||
// Compressed sparse row graph type
|
||||
|
||||
#ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
|
||||
#define BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <iterator>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/detail/indexed_properties.hpp>
|
||||
#include <boost/iterator/counting_iterator.hpp>
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/graph/graph_selectors.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
||||
# error The Compressed Sparse Row graph only supports bundled properties.
|
||||
# error You will need a compiler that conforms better to the C++ standard.
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
// A tag type indicating that the graph in question is a compressed
|
||||
// sparse row graph. This is an internal detail of the BGL.
|
||||
struct csr_graph_tag;
|
||||
|
||||
/****************************************************************************
|
||||
* Local helper macros to reduce typing and clutter later on. *
|
||||
****************************************************************************/
|
||||
#define BOOST_CSR_GRAPH_TEMPLATE_PARMS \
|
||||
typename Directed, typename VertexProperty, typename EdgeProperty, \
|
||||
typename GraphProperty, typename Vertex, typename EdgeIndex
|
||||
#define BOOST_CSR_GRAPH_TYPE \
|
||||
compressed_sparse_row_graph<Directed, VertexProperty, EdgeProperty, \
|
||||
GraphProperty, Vertex, EdgeIndex>
|
||||
|
||||
// Forward declaration of CSR edge descriptor type, needed to pass to
|
||||
// indexed_edge_properties.
|
||||
template<typename Vertex, typename EdgeIndex>
|
||||
class csr_edge_descriptor;
|
||||
|
||||
/** Compressed sparse row graph.
|
||||
*
|
||||
* Vertex and EdgeIndex should be unsigned integral types and should
|
||||
* specialize numeric_limits.
|
||||
*/
|
||||
template<typename Directed = directedS,
|
||||
typename VertexProperty = void,
|
||||
typename EdgeProperty = void,
|
||||
typename GraphProperty = no_property,
|
||||
typename Vertex = std::size_t,
|
||||
typename EdgeIndex = Vertex>
|
||||
class compressed_sparse_row_graph
|
||||
: public detail::indexed_vertex_properties<BOOST_CSR_GRAPH_TYPE, VertexProperty,
|
||||
Vertex>,
|
||||
public detail::indexed_edge_properties<BOOST_CSR_GRAPH_TYPE, EdgeProperty,
|
||||
csr_edge_descriptor<Vertex,
|
||||
EdgeIndex> >
|
||||
|
||||
{
|
||||
typedef detail::indexed_vertex_properties<compressed_sparse_row_graph,
|
||||
VertexProperty, Vertex>
|
||||
inherited_vertex_properties;
|
||||
|
||||
typedef detail::indexed_edge_properties<BOOST_CSR_GRAPH_TYPE, EdgeProperty,
|
||||
csr_edge_descriptor<Vertex, EdgeIndex> >
|
||||
inherited_edge_properties;
|
||||
|
||||
public:
|
||||
// For Property Graph
|
||||
typedef GraphProperty graph_property_type;
|
||||
|
||||
protected:
|
||||
template<typename InputIterator>
|
||||
void
|
||||
maybe_reserve_edge_list_storage(InputIterator, InputIterator,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
// Do nothing: we have no idea how much storage to reserve.
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
void
|
||||
maybe_reserve_edge_list_storage(InputIterator first, InputIterator last,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
using std::distance;
|
||||
typename std::iterator_traits<InputIterator>::difference_type n =
|
||||
distance(first, last);
|
||||
m_column.reserve(n);
|
||||
inherited_edge_properties::reserve(n);
|
||||
}
|
||||
|
||||
public:
|
||||
/* At this time, the compressed sparse row graph can only be used to
|
||||
* create a directed graph. In the future, bidirectional and
|
||||
* undirected CSR graphs will also be supported.
|
||||
*/
|
||||
BOOST_STATIC_ASSERT((is_same<Directed, directedS>::value));
|
||||
|
||||
// Concept requirements:
|
||||
// For Graph
|
||||
typedef Vertex vertex_descriptor;
|
||||
typedef csr_edge_descriptor<Vertex, EdgeIndex> edge_descriptor;
|
||||
typedef directed_tag directed_category;
|
||||
typedef allow_parallel_edge_tag edge_parallel_category;
|
||||
|
||||
class traversal_category: public incidence_graph_tag,
|
||||
public adjacency_graph_tag,
|
||||
public vertex_list_graph_tag,
|
||||
public edge_list_graph_tag {};
|
||||
|
||||
static vertex_descriptor null_vertex() { return vertex_descriptor(-1); }
|
||||
|
||||
// For VertexListGraph
|
||||
typedef counting_iterator<Vertex> vertex_iterator;
|
||||
typedef Vertex vertices_size_type;
|
||||
|
||||
// For EdgeListGraph
|
||||
typedef EdgeIndex edges_size_type;
|
||||
|
||||
// For IncidenceGraph
|
||||
class out_edge_iterator;
|
||||
typedef EdgeIndex degree_size_type;
|
||||
|
||||
// For AdjacencyGraph
|
||||
typedef typename std::vector<Vertex>::const_iterator adjacency_iterator;
|
||||
|
||||
// For EdgeListGraph
|
||||
class edge_iterator;
|
||||
|
||||
// For BidirectionalGraph (not implemented)
|
||||
typedef void in_edge_iterator;
|
||||
|
||||
// For internal use
|
||||
typedef csr_graph_tag graph_tag;
|
||||
|
||||
// Constructors
|
||||
|
||||
// Default constructor: an empty graph.
|
||||
compressed_sparse_row_graph()
|
||||
: m_rowstart(1, EdgeIndex(0)), m_column(0), m_property(),
|
||||
m_last_source(0) {}
|
||||
|
||||
// From number of vertices and sorted list of edges
|
||||
template<typename InputIterator>
|
||||
compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
|
||||
vertices_size_type numverts,
|
||||
edges_size_type numedges = 0,
|
||||
const GraphProperty& prop = GraphProperty())
|
||||
: inherited_vertex_properties(numverts), m_rowstart(numverts + 1),
|
||||
m_column(0), m_property(prop), m_last_source(numverts)
|
||||
{
|
||||
// Reserving storage in advance can save us lots of time and
|
||||
// memory, but it can only be done if we have forward iterators or
|
||||
// the user has supplied the number of edges.
|
||||
if (numedges == 0) {
|
||||
typedef typename std::iterator_traits<InputIterator>::iterator_category
|
||||
category;
|
||||
maybe_reserve_edge_list_storage(edge_begin, edge_end, category());
|
||||
} else {
|
||||
m_column.reserve(numedges);
|
||||
}
|
||||
|
||||
EdgeIndex current_edge = 0;
|
||||
Vertex current_vertex_plus_one = 1;
|
||||
m_rowstart[0] = 0;
|
||||
for (InputIterator ei = edge_begin; ei != edge_end; ++ei) {
|
||||
Vertex src = ei->first;
|
||||
Vertex tgt = ei->second;
|
||||
for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
|
||||
m_rowstart[current_vertex_plus_one] = current_edge;
|
||||
m_column.push_back(tgt);
|
||||
++current_edge;
|
||||
}
|
||||
|
||||
// The remaining vertices have no edges
|
||||
for (; current_vertex_plus_one != numverts + 1; ++current_vertex_plus_one)
|
||||
m_rowstart[current_vertex_plus_one] = current_edge;
|
||||
|
||||
// Default-construct properties for edges
|
||||
inherited_edge_properties::resize(m_column.size());
|
||||
}
|
||||
|
||||
// From number of vertices and sorted list of edges
|
||||
template<typename InputIterator, typename EdgePropertyIterator>
|
||||
compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
|
||||
EdgePropertyIterator ep_iter,
|
||||
vertices_size_type numverts,
|
||||
edges_size_type numedges = 0,
|
||||
const GraphProperty& prop = GraphProperty())
|
||||
: inherited_vertex_properties(numverts), m_rowstart(numverts + 1),
|
||||
m_column(0), m_property(prop), m_last_source(numverts)
|
||||
{
|
||||
// Reserving storage in advance can save us lots of time and
|
||||
// memory, but it can only be done if we have forward iterators or
|
||||
// the user has supplied the number of edges.
|
||||
if (numedges == 0) {
|
||||
typedef typename std::iterator_traits<InputIterator>::iterator_category
|
||||
category;
|
||||
maybe_reserve_edge_list_storage(edge_begin, edge_end, category());
|
||||
} else {
|
||||
m_column.reserve(numedges);
|
||||
}
|
||||
|
||||
EdgeIndex current_edge = 0;
|
||||
Vertex current_vertex_plus_one = 1;
|
||||
m_rowstart[0] = 0;
|
||||
for (InputIterator ei = edge_begin; ei != edge_end; ++ei, ++ep_iter) {
|
||||
Vertex src = ei->first;
|
||||
Vertex tgt = ei->second;
|
||||
for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
|
||||
m_rowstart[current_vertex_plus_one] = current_edge;
|
||||
m_column.push_back(tgt);
|
||||
inherited_edge_properties::push_back(*ep_iter);
|
||||
++current_edge;
|
||||
}
|
||||
|
||||
// The remaining vertices have no edges
|
||||
for (; current_vertex_plus_one != numverts + 1; ++current_vertex_plus_one)
|
||||
m_rowstart[current_vertex_plus_one] = current_edge;
|
||||
}
|
||||
|
||||
// Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function
|
||||
template<typename Graph, typename VertexIndexMap>
|
||||
compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi,
|
||||
vertices_size_type numverts,
|
||||
edges_size_type numedges)
|
||||
: m_property(), m_last_source(0)
|
||||
{
|
||||
assign(g, vi, numverts, numedges);
|
||||
}
|
||||
|
||||
// Requires VertexListGraph and EdgeListGraph
|
||||
template<typename Graph, typename VertexIndexMap>
|
||||
compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi)
|
||||
: m_property(), m_last_source(0)
|
||||
{
|
||||
assign(g, vi, num_vertices(g), num_edges(g));
|
||||
}
|
||||
|
||||
// Requires vertex index map plus requirements of previous constructor
|
||||
template<typename Graph>
|
||||
explicit compressed_sparse_row_graph(const Graph& g)
|
||||
: m_property(), m_last_source(0)
|
||||
{
|
||||
assign(g, get(vertex_index, g), num_vertices(g), num_edges(g));
|
||||
}
|
||||
|
||||
// From any graph (slow and uses a lot of memory)
|
||||
// Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function
|
||||
// Internal helper function
|
||||
template<typename Graph, typename VertexIndexMap>
|
||||
void
|
||||
assign(const Graph& g, const VertexIndexMap& vi,
|
||||
vertices_size_type numverts, edges_size_type numedges)
|
||||
{
|
||||
inherited_vertex_properties::resize(numverts);
|
||||
m_rowstart.resize(numverts + 1);
|
||||
m_column.resize(numedges);
|
||||
EdgeIndex current_edge = 0;
|
||||
typedef typename boost::graph_traits<Graph>::vertex_descriptor g_vertex;
|
||||
typedef typename boost::graph_traits<Graph>::edge_descriptor g_edge;
|
||||
typedef typename boost::graph_traits<Graph>::out_edge_iterator
|
||||
g_out_edge_iter;
|
||||
|
||||
for (Vertex i = 0; i != numverts; ++i) {
|
||||
m_rowstart[i] = current_edge;
|
||||
g_vertex v = vertex(i, g);
|
||||
EdgeIndex num_edges_before_this_vertex = current_edge;
|
||||
g_out_edge_iter ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) {
|
||||
m_column[current_edge++] = get(vi, target(*ei, g));
|
||||
}
|
||||
std::sort(m_column.begin() + num_edges_before_this_vertex,
|
||||
m_column.begin() + current_edge);
|
||||
}
|
||||
m_rowstart[numverts] = current_edge;
|
||||
m_last_source = numverts;
|
||||
}
|
||||
|
||||
// Requires the above, plus VertexListGraph and EdgeListGraph
|
||||
template<typename Graph, typename VertexIndexMap>
|
||||
void assign(const Graph& g, const VertexIndexMap& vi)
|
||||
{
|
||||
assign(g, vi, num_vertices(g), num_edges(g));
|
||||
}
|
||||
|
||||
// Requires the above, plus a vertex_index map.
|
||||
template<typename Graph>
|
||||
void assign(const Graph& g)
|
||||
{
|
||||
assign(g, get(vertex_index, g), num_vertices(g), num_edges(g));
|
||||
}
|
||||
|
||||
using inherited_vertex_properties::operator[];
|
||||
using inherited_edge_properties::operator[];
|
||||
|
||||
// private: non-portable, requires friend templates
|
||||
inherited_vertex_properties& vertex_properties() {return *this;}
|
||||
const inherited_vertex_properties& vertex_properties() const {return *this;}
|
||||
inherited_edge_properties& edge_properties() { return *this; }
|
||||
const inherited_edge_properties& edge_properties() const { return *this; }
|
||||
|
||||
std::vector<EdgeIndex> m_rowstart;
|
||||
std::vector<Vertex> m_column;
|
||||
GraphProperty m_property;
|
||||
Vertex m_last_source; // Last source of added edge, plus one
|
||||
};
|
||||
|
||||
template<typename Vertex, typename EdgeIndex>
|
||||
class csr_edge_descriptor
|
||||
{
|
||||
public:
|
||||
Vertex src;
|
||||
EdgeIndex idx;
|
||||
|
||||
csr_edge_descriptor(Vertex src, EdgeIndex idx): src(src), idx(idx) {}
|
||||
csr_edge_descriptor(): src(0), idx(0) {}
|
||||
|
||||
bool operator==(const csr_edge_descriptor& e) const {return idx == e.idx;}
|
||||
bool operator!=(const csr_edge_descriptor& e) const {return idx != e.idx;}
|
||||
bool operator<(const csr_edge_descriptor& e) const {return idx < e.idx;}
|
||||
bool operator>(const csr_edge_descriptor& e) const {return idx > e.idx;}
|
||||
bool operator<=(const csr_edge_descriptor& e) const {return idx <= e.idx;}
|
||||
bool operator>=(const csr_edge_descriptor& e) const {return idx >= e.idx;}
|
||||
};
|
||||
|
||||
// Construction functions
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline Vertex
|
||||
add_vertex(BOOST_CSR_GRAPH_TYPE& g) {
|
||||
Vertex old_num_verts_plus_one = g.m_rowstart.size();
|
||||
g.m_rowstart.push_back(EdgeIndex(0));
|
||||
g.vertex_properties().resize(num_vertices(g));
|
||||
return old_num_verts_plus_one - 1;
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline Vertex
|
||||
add_vertices(typename BOOST_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_CSR_GRAPH_TYPE& g) {
|
||||
Vertex old_num_verts_plus_one = g.m_rowstart.size();
|
||||
g.m_rowstart.resize(old_num_verts_plus_one + count, EdgeIndex(0));
|
||||
g.vertex_properties().resize(num_vertices(g));
|
||||
return old_num_verts_plus_one - 1;
|
||||
}
|
||||
|
||||
// This function requires that (src, tgt) be lexicographically at least as
|
||||
// large as the largest edge in the graph so far
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
|
||||
add_edge(Vertex src, Vertex tgt, BOOST_CSR_GRAPH_TYPE& g) {
|
||||
assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) &&
|
||||
src < num_vertices(g));
|
||||
EdgeIndex num_edges_orig = g.m_column.size();
|
||||
for (; g.m_last_source <= src; ++g.m_last_source)
|
||||
g.m_rowstart[g.m_last_source] = num_edges_orig;
|
||||
g.m_rowstart[src + 1] = num_edges_orig + 1;
|
||||
g.m_column.push_back(tgt);
|
||||
typedef typename BOOST_CSR_GRAPH_TYPE::edge_push_back_type push_back_type;
|
||||
g.edge_properties().push_back(push_back_type());
|
||||
return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig);
|
||||
}
|
||||
|
||||
// This function requires that (src, tgt) be lexicographically at least as
|
||||
// large as the largest edge in the graph so far
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
|
||||
add_edge(Vertex src, Vertex tgt,
|
||||
typename BOOST_CSR_GRAPH_TYPE::edge_bundled const& p,
|
||||
BOOST_CSR_GRAPH_TYPE& g) {
|
||||
assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) &&
|
||||
src < num_vertices(g));
|
||||
EdgeIndex num_edges_orig = g.m_column.size();
|
||||
for (; g.m_last_source <= src; ++g.m_last_source)
|
||||
g.m_rowstart[g.m_last_source] = num_edges_orig;
|
||||
g.m_rowstart[src + 1] = num_edges_orig + 1;
|
||||
g.m_column.push_back(tgt);
|
||||
g.edge_properties().push_back(p);
|
||||
return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig);
|
||||
}
|
||||
|
||||
|
||||
// From VertexListGraph
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline Vertex
|
||||
num_vertices(const BOOST_CSR_GRAPH_TYPE& g) {
|
||||
return g.m_rowstart.size() - 1;
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
std::pair<counting_iterator<Vertex>, counting_iterator<Vertex> >
|
||||
inline vertices(const BOOST_CSR_GRAPH_TYPE& g) {
|
||||
return std::make_pair(counting_iterator<Vertex>(0),
|
||||
counting_iterator<Vertex>(num_vertices(g)));
|
||||
}
|
||||
|
||||
// From IncidenceGraph
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
class BOOST_CSR_GRAPH_TYPE::out_edge_iterator
|
||||
: public iterator_facade<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
|
||||
typename BOOST_CSR_GRAPH_TYPE::edge_descriptor,
|
||||
std::random_access_iterator_tag,
|
||||
const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor&,
|
||||
typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast>
|
||||
{
|
||||
public:
|
||||
typedef typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast difference_type;
|
||||
|
||||
out_edge_iterator() {}
|
||||
// Implicit copy constructor OK
|
||||
explicit out_edge_iterator(edge_descriptor edge) : m_edge(edge) { }
|
||||
|
||||
private:
|
||||
// iterator_facade requirements
|
||||
const edge_descriptor& dereference() const { return m_edge; }
|
||||
|
||||
bool equal(const out_edge_iterator& other) const
|
||||
{ return m_edge == other.m_edge; }
|
||||
|
||||
void increment() { ++m_edge.idx; }
|
||||
void decrement() { ++m_edge.idx; }
|
||||
void advance(difference_type n) { m_edge.idx += n; }
|
||||
|
||||
difference_type distance_to(const out_edge_iterator& other) const
|
||||
{ return other.m_edge.idx - m_edge.idx; }
|
||||
|
||||
edge_descriptor m_edge;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline Vertex
|
||||
source(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,
|
||||
const BOOST_CSR_GRAPH_TYPE&)
|
||||
{
|
||||
return e.src;
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline Vertex
|
||||
target(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,
|
||||
const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
return g.m_column[e.idx];
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline std::pair<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
|
||||
typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator>
|
||||
out_edges(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor ed;
|
||||
typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator it;
|
||||
EdgeIndex v_row_start = g.m_rowstart[v];
|
||||
EdgeIndex next_row_start = g.m_rowstart[v + 1];
|
||||
return std::make_pair(it(ed(v, v_row_start)),
|
||||
it(ed(v, (std::max)(v_row_start, next_row_start))));
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline EdgeIndex
|
||||
out_degree(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
EdgeIndex v_row_start = g.m_rowstart[v];
|
||||
EdgeIndex next_row_start = g.m_rowstart[v + 1];
|
||||
return (std::max)(v_row_start, next_row_start) - v_row_start;
|
||||
}
|
||||
|
||||
// From AdjacencyGraph
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline std::pair<typename BOOST_CSR_GRAPH_TYPE::adjacency_iterator,
|
||||
typename BOOST_CSR_GRAPH_TYPE::adjacency_iterator>
|
||||
adjacent_vertices(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
EdgeIndex v_row_start = g.m_rowstart[v];
|
||||
EdgeIndex next_row_start = g.m_rowstart[v + 1];
|
||||
return std::make_pair(g.m_column.begin() + v_row_start,
|
||||
g.m_column.begin() +
|
||||
(std::max)(v_row_start, next_row_start));
|
||||
}
|
||||
|
||||
// Extra, common functions
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline typename graph_traits<BOOST_CSR_GRAPH_TYPE>::vertex_descriptor
|
||||
vertex(typename graph_traits<BOOST_CSR_GRAPH_TYPE>::vertex_descriptor i,
|
||||
const BOOST_CSR_GRAPH_TYPE&)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
// Unlike for an adjacency_matrix, edge_range and edge take lg(out_degree(i))
|
||||
// time
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline std::pair<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
|
||||
typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator>
|
||||
edge_range(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
typedef typename std::vector<Vertex>::const_iterator adj_iter;
|
||||
typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter;
|
||||
typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_desc;
|
||||
std::pair<adj_iter, adj_iter> raw_adjacencies = adjacent_vertices(i, g);
|
||||
std::pair<adj_iter, adj_iter> adjacencies =
|
||||
std::equal_range(raw_adjacencies.first, raw_adjacencies.second, j);
|
||||
EdgeIndex idx_begin = adjacencies.first - g.m_column.begin();
|
||||
EdgeIndex idx_end = adjacencies.second - g.m_column.begin();
|
||||
return std::make_pair(out_edge_iter(edge_desc(i, idx_begin)),
|
||||
out_edge_iter(edge_desc(i, idx_end)));
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline std::pair<typename BOOST_CSR_GRAPH_TYPE::edge_descriptor, bool>
|
||||
edge(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter;
|
||||
std::pair<out_edge_iter, out_edge_iter> range = edge_range(i, j, g);
|
||||
if (range.first == range.second)
|
||||
return std::make_pair(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(),
|
||||
false);
|
||||
else
|
||||
return std::make_pair(*range.first, true);
|
||||
}
|
||||
|
||||
// Find an edge given its index in the graph
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
|
||||
edge_from_index(EdgeIndex idx, const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
typedef typename std::vector<EdgeIndex>::const_iterator row_start_iter;
|
||||
assert (idx < num_edges(g));
|
||||
row_start_iter src_plus_1 =
|
||||
std::upper_bound(g.m_rowstart.begin(),
|
||||
g.m_rowstart.begin() + g.m_last_source + 1,
|
||||
idx);
|
||||
// Get last source whose rowstart is at most idx
|
||||
// upper_bound returns this position plus 1
|
||||
Vertex src = (src_plus_1 - g.m_rowstart.begin()) - 1;
|
||||
return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, idx);
|
||||
}
|
||||
|
||||
// From EdgeListGraph
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
class BOOST_CSR_GRAPH_TYPE::edge_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef edge_descriptor value_type;
|
||||
|
||||
typedef const edge_descriptor* pointer;
|
||||
|
||||
typedef edge_descriptor reference;
|
||||
typedef typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast difference_type;
|
||||
|
||||
edge_iterator() : rowstart_array(0), current_edge(), end_of_this_vertex(0) {}
|
||||
|
||||
edge_iterator(const compressed_sparse_row_graph& graph,
|
||||
edge_descriptor current_edge,
|
||||
EdgeIndex end_of_this_vertex)
|
||||
: rowstart_array(&graph.m_rowstart[0]), current_edge(current_edge),
|
||||
end_of_this_vertex(end_of_this_vertex) {}
|
||||
|
||||
// From InputIterator
|
||||
reference operator*() const { return current_edge; }
|
||||
pointer operator->() const { return ¤t_edge; }
|
||||
|
||||
bool operator==(const edge_iterator& o) const {
|
||||
return current_edge == o.current_edge;
|
||||
}
|
||||
bool operator!=(const edge_iterator& o) const {
|
||||
return current_edge != o.current_edge;
|
||||
}
|
||||
|
||||
edge_iterator& operator++() {
|
||||
++current_edge.idx;
|
||||
while (current_edge.idx == end_of_this_vertex) {
|
||||
++current_edge.src;
|
||||
end_of_this_vertex = rowstart_array[current_edge.src + 1];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
edge_iterator operator++(int) {
|
||||
edge_iterator temp = *this;
|
||||
++*this;
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const EdgeIndex* rowstart_array;
|
||||
edge_descriptor current_edge;
|
||||
EdgeIndex end_of_this_vertex;
|
||||
};
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline EdgeIndex
|
||||
num_edges(const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
return g.m_column.size();
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
std::pair<typename BOOST_CSR_GRAPH_TYPE::edge_iterator,
|
||||
typename BOOST_CSR_GRAPH_TYPE::edge_iterator>
|
||||
edges(const BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
typedef typename BOOST_CSR_GRAPH_TYPE::edge_iterator ei;
|
||||
typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edgedesc;
|
||||
if (g.m_rowstart.size() == 1 || g.m_column.empty()) {
|
||||
return std::make_pair(ei(), ei());
|
||||
} else {
|
||||
// Find the first vertex that has outgoing edges
|
||||
Vertex src = 0;
|
||||
while (g.m_rowstart[src + 1] == 0) ++src;
|
||||
return std::make_pair(ei(g, edgedesc(src, 0), g.m_rowstart[src + 1]),
|
||||
ei(g, edgedesc(num_vertices(g), g.m_column.size()), 0));
|
||||
}
|
||||
}
|
||||
|
||||
// For Property Graph
|
||||
|
||||
// Graph properties
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag, class Value>
|
||||
inline void
|
||||
set_property(BOOST_CSR_GRAPH_TYPE& g, Tag, const Value& value)
|
||||
{
|
||||
get_property_value(g.m_property, Tag()) = value;
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag>
|
||||
inline
|
||||
typename graph_property<BOOST_CSR_GRAPH_TYPE, Tag>::type&
|
||||
get_property(BOOST_CSR_GRAPH_TYPE& g, Tag)
|
||||
{
|
||||
return get_property_value(g.m_property, Tag());
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag>
|
||||
inline
|
||||
const
|
||||
typename graph_property<BOOST_CSR_GRAPH_TYPE, Tag>::type&
|
||||
get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag)
|
||||
{
|
||||
return get_property_value(g.m_property, Tag());
|
||||
}
|
||||
|
||||
// Add edge_index property map
|
||||
template<typename Index, typename Descriptor>
|
||||
struct csr_edge_index_map
|
||||
{
|
||||
typedef Index value_type;
|
||||
typedef Index reference;
|
||||
typedef Descriptor key_type;
|
||||
typedef readable_property_map_tag category;
|
||||
};
|
||||
|
||||
template<typename Index, typename Descriptor>
|
||||
inline Index
|
||||
get(const csr_edge_index_map<Index, Descriptor>&,
|
||||
const typename csr_edge_index_map<Index, Descriptor>::key_type& key)
|
||||
{
|
||||
return key.idx;
|
||||
}
|
||||
|
||||
// Doing the right thing here (by unifying with vertex_index_t and
|
||||
// edge_index_t) breaks GCC.
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag>
|
||||
struct property_map<BOOST_CSR_GRAPH_TYPE, Tag>
|
||||
{
|
||||
private:
|
||||
typedef identity_property_map vertex_index_type;
|
||||
typedef typename graph_traits<BOOST_CSR_GRAPH_TYPE>::edge_descriptor
|
||||
edge_descriptor;
|
||||
typedef csr_edge_index_map<EdgeIndex, edge_descriptor> edge_index_type;
|
||||
|
||||
typedef typename mpl::if_<is_same<Tag, edge_index_t>,
|
||||
edge_index_type,
|
||||
detail::error_property_not_found>::type
|
||||
edge_or_none;
|
||||
|
||||
public:
|
||||
typedef typename mpl::if_<is_same<Tag, vertex_index_t>,
|
||||
vertex_index_type,
|
||||
edge_or_none>::type type;
|
||||
|
||||
typedef type const_type;
|
||||
};
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline identity_property_map
|
||||
get(vertex_index_t, const BOOST_CSR_GRAPH_TYPE&)
|
||||
{
|
||||
return identity_property_map();
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline Vertex
|
||||
get(vertex_index_t,
|
||||
const BOOST_CSR_GRAPH_TYPE&, Vertex v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline typename property_map<BOOST_CSR_GRAPH_TYPE, edge_index_t>::const_type
|
||||
get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&)
|
||||
{
|
||||
typedef typename property_map<BOOST_CSR_GRAPH_TYPE, edge_index_t>::const_type
|
||||
result_type;
|
||||
return result_type();
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
|
||||
inline EdgeIndex
|
||||
get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&,
|
||||
typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e)
|
||||
{
|
||||
return e.idx;
|
||||
}
|
||||
|
||||
// Support for bundled properties
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
|
||||
struct property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>
|
||||
{
|
||||
private:
|
||||
typedef graph_traits<BOOST_CSR_GRAPH_TYPE> traits;
|
||||
typedef VertexProperty vertex_bundled;
|
||||
typedef EdgeProperty edge_bundled;
|
||||
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
|
||||
typename traits::vertex_descriptor,
|
||||
typename traits::edge_descriptor>::type
|
||||
descriptor;
|
||||
|
||||
public:
|
||||
typedef bundle_property_map<BOOST_CSR_GRAPH_TYPE, descriptor, Bundle, T>
|
||||
type;
|
||||
typedef bundle_property_map<const BOOST_CSR_GRAPH_TYPE, descriptor, Bundle,
|
||||
const T> const_type;
|
||||
};
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
|
||||
inline
|
||||
typename property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>::type
|
||||
get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g)
|
||||
{
|
||||
typedef typename property_map<BOOST_CSR_GRAPH_TYPE,
|
||||
T Bundle::*>::type
|
||||
result_type;
|
||||
return result_type(&g, p);
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
|
||||
inline
|
||||
typename property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>::const_type
|
||||
get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g)
|
||||
{
|
||||
typedef typename property_map<BOOST_CSR_GRAPH_TYPE,
|
||||
T Bundle::*>::const_type
|
||||
result_type;
|
||||
return result_type(&g, p);
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle,
|
||||
typename Key>
|
||||
inline T
|
||||
get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g,
|
||||
const Key& key)
|
||||
{
|
||||
return get(get(p, g), key);
|
||||
}
|
||||
|
||||
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle,
|
||||
typename Key>
|
||||
inline void
|
||||
put(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g,
|
||||
const Key& key, const T& value)
|
||||
{
|
||||
put(get(p, g), key, value);
|
||||
}
|
||||
|
||||
#undef BOOST_CSR_GRAPH_TYPE
|
||||
#undef BOOST_CSR_GRAPH_TEMPLATE_PARMS
|
||||
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
|
||||
101
libraries/include/boost/graph/connected_components.hpp
Normal file
101
libraries/include/boost/graph/connected_components.hpp
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 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_CONNECTED_COMPONENTS_HPP
|
||||
#define BOOST_GRAPH_CONNECTED_COMPONENTS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This visitor is used both in the connected_components algorithm
|
||||
// and in the kosaraju strong components algorithm during the
|
||||
// second DFS traversal.
|
||||
template <class ComponentsMap>
|
||||
class components_recorder : public dfs_visitor<>
|
||||
{
|
||||
typedef typename property_traits<ComponentsMap>::value_type comp_type;
|
||||
public:
|
||||
components_recorder(ComponentsMap c,
|
||||
comp_type& c_count)
|
||||
: m_component(c), m_count(c_count) {}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void start_vertex(Vertex, Graph&) {
|
||||
if (m_count == (std::numeric_limits<comp_type>::max)())
|
||||
m_count = 0; // start counting components at zero
|
||||
else
|
||||
++m_count;
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph&) {
|
||||
put(m_component, u, m_count);
|
||||
}
|
||||
protected:
|
||||
ComponentsMap m_component;
|
||||
comp_type& m_count;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// This function computes the connected components of an undirected
|
||||
// graph using a single application of depth first search.
|
||||
|
||||
template <class Graph, class ComponentMap, class P, class T, class R>
|
||||
inline typename property_traits<ComponentMap>::value_type
|
||||
connected_components(const Graph& g, ComponentMap c,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
if (num_vertices(g) == 0) return 0;
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
function_requires< WritablePropertyMapConcept<ComponentMap, Vertex> >();
|
||||
typedef typename boost::graph_traits<Graph>::directed_category directed;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<directed, undirected_tag>::value));
|
||||
|
||||
typedef typename property_traits<ComponentMap>::value_type comp_type;
|
||||
// c_count initialized to "nil" (with nil represented by (max)())
|
||||
comp_type c_count((std::numeric_limits<comp_type>::max)());
|
||||
detail::components_recorder<ComponentMap> vis(c, c_count);
|
||||
depth_first_search(g, params.visitor(vis));
|
||||
return c_count + 1;
|
||||
}
|
||||
|
||||
template <class Graph, class ComponentMap>
|
||||
inline typename property_traits<ComponentMap>::value_type
|
||||
connected_components(const Graph& g, ComponentMap c)
|
||||
{
|
||||
if (num_vertices(g) == 0) return 0;
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
function_requires< WritablePropertyMapConcept<ComponentMap, Vertex> >();
|
||||
typedef typename boost::graph_traits<Graph>::directed_category directed;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<directed, undirected_tag>::value));
|
||||
|
||||
typedef typename property_traits<ComponentMap>::value_type comp_type;
|
||||
// c_count initialized to "nil" (with nil represented by (max)())
|
||||
comp_type c_count((std::numeric_limits<comp_type>::max)());
|
||||
detail::components_recorder<ComponentMap> vis(c, c_count);
|
||||
depth_first_search(g, visitor(vis));
|
||||
return c_count + 1;
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_CONNECTED_COMPONENTS_HPP
|
||||
450
libraries/include/boost/graph/copy.hpp
Normal file
450
libraries/include/boost/graph/copy.hpp
Normal file
@@ -0,0 +1,450 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Lie-Quan Lee, 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)
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
/*
|
||||
This file implements the following functions:
|
||||
|
||||
|
||||
template <typename VertexListGraph, typename MutableGraph>
|
||||
void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out)
|
||||
|
||||
template <typename VertexListGraph, typename MutableGraph,
|
||||
class P, class T, class R>
|
||||
void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
|
||||
|
||||
template <typename IncidenceGraph, typename MutableGraph>
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor
|
||||
copy_component(IncidenceGraph& g_in,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor src,
|
||||
MutableGraph& g_out)
|
||||
|
||||
template <typename IncidenceGraph, typename MutableGraph,
|
||||
typename P, typename T, typename R>
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor
|
||||
copy_component(IncidenceGraph& g_in,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor src,
|
||||
MutableGraph& g_out,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_GRAPH_COPY_HPP
|
||||
#define BOOST_GRAPH_COPY_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include <boost/type_traits/conversion_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Default edge and vertex property copiers
|
||||
|
||||
template <typename Graph1, typename Graph2>
|
||||
struct edge_copier {
|
||||
edge_copier(const Graph1& g1, Graph2& g2)
|
||||
: edge_all_map1(get(edge_all, g1)),
|
||||
edge_all_map2(get(edge_all, g2)) { }
|
||||
|
||||
template <typename Edge1, typename Edge2>
|
||||
void operator()(const Edge1& e1, Edge2& e2) const {
|
||||
put(edge_all_map2, e2, get(edge_all_map1, e1));
|
||||
}
|
||||
typename property_map<Graph1, edge_all_t>::const_type edge_all_map1;
|
||||
mutable typename property_map<Graph2, edge_all_t>::type edge_all_map2;
|
||||
};
|
||||
template <typename Graph1, typename Graph2>
|
||||
inline edge_copier<Graph1,Graph2>
|
||||
make_edge_copier(const Graph1& g1, Graph2& g2)
|
||||
{
|
||||
return edge_copier<Graph1,Graph2>(g1, g2);
|
||||
}
|
||||
|
||||
template <typename Graph1, typename Graph2>
|
||||
struct vertex_copier {
|
||||
vertex_copier(const Graph1& g1, Graph2& g2)
|
||||
: vertex_all_map1(get(vertex_all, g1)),
|
||||
vertex_all_map2(get(vertex_all, g2)) { }
|
||||
|
||||
template <typename Vertex1, typename Vertex2>
|
||||
void operator()(const Vertex1& v1, Vertex2& v2) const {
|
||||
put(vertex_all_map2, v2, get(vertex_all_map1, v1));
|
||||
}
|
||||
typename property_map<Graph1, vertex_all_t>::const_type vertex_all_map1;
|
||||
mutable typename property_map<Graph2, vertex_all_t>::type
|
||||
vertex_all_map2;
|
||||
};
|
||||
template <typename Graph1, typename Graph2>
|
||||
inline vertex_copier<Graph1,Graph2>
|
||||
make_vertex_copier(const Graph1& g1, Graph2& g2)
|
||||
{
|
||||
return vertex_copier<Graph1,Graph2>(g1, g2);
|
||||
}
|
||||
|
||||
// Copy all the vertices and edges of graph g_in into graph g_out.
|
||||
// The copy_vertex and copy_edge function objects control how vertex
|
||||
// and edge properties are copied.
|
||||
|
||||
template <int Version>
|
||||
struct copy_graph_impl { };
|
||||
|
||||
template <> struct copy_graph_impl<0>
|
||||
{
|
||||
template <typename Graph, typename MutableGraph,
|
||||
typename CopyVertex, typename CopyEdge, typename IndexMap,
|
||||
typename Orig2CopyVertexIndexMap>
|
||||
static void apply(const Graph& g_in, MutableGraph& g_out,
|
||||
CopyVertex copy_vertex, CopyEdge copy_edge,
|
||||
Orig2CopyVertexIndexMap orig2copy, IndexMap)
|
||||
{
|
||||
typename graph_traits<Graph>::vertex_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor
|
||||
new_v = add_vertex(g_out);
|
||||
put(orig2copy, *vi, new_v);
|
||||
copy_vertex(*vi, new_v);
|
||||
}
|
||||
typename graph_traits<Graph>::edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = edges(g_in); ei != ei_end; ++ei) {
|
||||
typename graph_traits<MutableGraph>::edge_descriptor new_e;
|
||||
bool inserted;
|
||||
tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)),
|
||||
get(orig2copy, target(*ei, g_in)),
|
||||
g_out);
|
||||
copy_edge(*ei, new_e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// for directed graphs
|
||||
template <> struct copy_graph_impl<1>
|
||||
{
|
||||
template <typename Graph, typename MutableGraph,
|
||||
typename CopyVertex, typename CopyEdge, typename IndexMap,
|
||||
typename Orig2CopyVertexIndexMap>
|
||||
static void apply(const Graph& g_in, MutableGraph& g_out,
|
||||
CopyVertex copy_vertex, CopyEdge copy_edge,
|
||||
Orig2CopyVertexIndexMap orig2copy, IndexMap)
|
||||
{
|
||||
typename graph_traits<Graph>::vertex_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor
|
||||
new_v = add_vertex(g_out);
|
||||
put(orig2copy, *vi, new_v);
|
||||
copy_vertex(*vi, new_v);
|
||||
}
|
||||
for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
|
||||
typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(*vi, g_in); ei != ei_end; ++ei) {
|
||||
typename graph_traits<MutableGraph>::edge_descriptor new_e;
|
||||
bool inserted;
|
||||
tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)),
|
||||
get(orig2copy, target(*ei, g_in)),
|
||||
g_out);
|
||||
copy_edge(*ei, new_e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// for undirected graphs
|
||||
template <> struct copy_graph_impl<2>
|
||||
{
|
||||
template <typename Graph, typename MutableGraph,
|
||||
typename CopyVertex, typename CopyEdge, typename IndexMap,
|
||||
typename Orig2CopyVertexIndexMap>
|
||||
static void apply(const Graph& g_in, MutableGraph& g_out,
|
||||
CopyVertex copy_vertex, CopyEdge copy_edge,
|
||||
Orig2CopyVertexIndexMap orig2copy,
|
||||
IndexMap index_map)
|
||||
{
|
||||
typedef color_traits<default_color_type> Color;
|
||||
std::vector<default_color_type>
|
||||
color(num_vertices(g_in), Color::white());
|
||||
typename graph_traits<Graph>::vertex_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor
|
||||
new_v = add_vertex(g_out);
|
||||
put(orig2copy, *vi, new_v);
|
||||
copy_vertex(*vi, new_v);
|
||||
}
|
||||
for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
|
||||
typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(*vi, g_in); ei != ei_end; ++ei) {
|
||||
typename graph_traits<MutableGraph>::edge_descriptor new_e;
|
||||
bool inserted;
|
||||
if (color[get(index_map, target(*ei, g_in))] == Color::white()) {
|
||||
tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei,g_in)),
|
||||
get(orig2copy, target(*ei,g_in)),
|
||||
g_out);
|
||||
copy_edge(*ei, new_e);
|
||||
}
|
||||
}
|
||||
color[get(index_map, *vi)] = Color::black();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class Graph>
|
||||
struct choose_graph_copy {
|
||||
typedef typename Graph::traversal_category Trv;
|
||||
typedef typename Graph::directed_category Dr;
|
||||
enum { algo =
|
||||
(is_convertible<Trv, vertex_list_graph_tag>::value
|
||||
&& is_convertible<Trv, edge_list_graph_tag>::value)
|
||||
? 0 : is_convertible<Dr, directed_tag>::value ? 1 : 2 };
|
||||
typedef copy_graph_impl<algo> type;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct choose_copier_parameter {
|
||||
template <class P, class G1, class G2>
|
||||
struct bind_ {
|
||||
typedef const P& result_type;
|
||||
static result_type apply(const P& p, const G1&, G2&)
|
||||
{ return p; }
|
||||
};
|
||||
};
|
||||
struct choose_default_edge_copier {
|
||||
template <class P, class G1, class G2>
|
||||
struct bind_ {
|
||||
typedef edge_copier<G1, G2> result_type;
|
||||
static result_type apply(const P&, const G1& g1, G2& g2) {
|
||||
return result_type(g1, g2);
|
||||
}
|
||||
};
|
||||
};
|
||||
template <class Param>
|
||||
struct choose_edge_copy {
|
||||
typedef choose_copier_parameter type;
|
||||
};
|
||||
template <>
|
||||
struct choose_edge_copy<detail::error_property_not_found> {
|
||||
typedef choose_default_edge_copier type;
|
||||
};
|
||||
template <class Param, class G1, class G2>
|
||||
struct choose_edge_copier_helper {
|
||||
typedef typename choose_edge_copy<Param>::type Selector;
|
||||
typedef typename Selector:: template bind_<Param, G1, G2> Bind;
|
||||
typedef Bind type;
|
||||
typedef typename Bind::result_type result_type;
|
||||
};
|
||||
template <typename Param, typename G1, typename G2>
|
||||
typename detail::choose_edge_copier_helper<Param,G1,G2>::result_type
|
||||
choose_edge_copier(const Param& params, const G1& g_in, G2& g_out)
|
||||
{
|
||||
typedef typename
|
||||
detail::choose_edge_copier_helper<Param,G1,G2>::type Choice;
|
||||
return Choice::apply(params, g_in, g_out);
|
||||
}
|
||||
|
||||
|
||||
struct choose_default_vertex_copier {
|
||||
template <class P, class G1, class G2>
|
||||
struct bind_ {
|
||||
typedef vertex_copier<G1, G2> result_type;
|
||||
static result_type apply(const P&, const G1& g1, G2& g2) {
|
||||
return result_type(g1, g2);
|
||||
}
|
||||
};
|
||||
};
|
||||
template <class Param>
|
||||
struct choose_vertex_copy {
|
||||
typedef choose_copier_parameter type;
|
||||
};
|
||||
template <>
|
||||
struct choose_vertex_copy<detail::error_property_not_found> {
|
||||
typedef choose_default_vertex_copier type;
|
||||
};
|
||||
template <class Param, class G1, class G2>
|
||||
struct choose_vertex_copier_helper {
|
||||
typedef typename choose_vertex_copy<Param>::type Selector;
|
||||
typedef typename Selector:: template bind_<Param, G1, G2> Bind;
|
||||
typedef Bind type;
|
||||
typedef typename Bind::result_type result_type;
|
||||
};
|
||||
template <typename Param, typename G1, typename G2>
|
||||
typename detail::choose_vertex_copier_helper<Param,G1,G2>::result_type
|
||||
choose_vertex_copier(const Param& params, const G1& g_in, G2& g_out)
|
||||
{
|
||||
typedef typename
|
||||
detail::choose_vertex_copier_helper<Param,G1,G2>::type Choice;
|
||||
return Choice::apply(params, g_in, g_out);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template <typename VertexListGraph, typename MutableGraph>
|
||||
void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out)
|
||||
{
|
||||
if (num_vertices(g_in) == 0)
|
||||
return;
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_t;
|
||||
std::vector<vertex_t> orig2copy(num_vertices(g_in));
|
||||
typedef typename detail::choose_graph_copy<VertexListGraph>::type
|
||||
copy_impl;
|
||||
copy_impl::apply
|
||||
(g_in, g_out,
|
||||
detail::make_vertex_copier(g_in, g_out),
|
||||
detail::make_edge_copier(g_in, g_out),
|
||||
make_iterator_property_map(orig2copy.begin(),
|
||||
get(vertex_index, g_in), orig2copy[0]),
|
||||
get(vertex_index, g_in)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename VertexListGraph, typename MutableGraph,
|
||||
class P, class T, class R>
|
||||
void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typename std::vector<T>::size_type n;
|
||||
n = is_default_param(get_param(params, orig_to_copy_t()))
|
||||
? num_vertices(g_in) : 1;
|
||||
if (n == 0)
|
||||
return;
|
||||
std::vector<BOOST_DEDUCED_TYPENAME graph_traits<MutableGraph>::vertex_descriptor>
|
||||
orig2copy(n);
|
||||
|
||||
typedef typename detail::choose_graph_copy<VertexListGraph>::type
|
||||
copy_impl;
|
||||
copy_impl::apply
|
||||
(g_in, g_out,
|
||||
detail::choose_vertex_copier(get_param(params, vertex_copy_t()),
|
||||
g_in, g_out),
|
||||
detail::choose_edge_copier(get_param(params, edge_copy_t()),
|
||||
g_in, g_out),
|
||||
choose_param(get_param(params, orig_to_copy_t()),
|
||||
make_iterator_property_map
|
||||
(orig2copy.begin(),
|
||||
choose_const_pmap(get_param(params, vertex_index),
|
||||
g_in, vertex_index), orig2copy[0])),
|
||||
choose_const_pmap(get_param(params, vertex_index), g_in, vertex_index)
|
||||
);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class NewGraph, class Copy2OrigIndexMap,
|
||||
class CopyVertex, class CopyEdge>
|
||||
struct graph_copy_visitor : public bfs_visitor<>
|
||||
{
|
||||
graph_copy_visitor(NewGraph& graph, Copy2OrigIndexMap c,
|
||||
CopyVertex cv, CopyEdge ce)
|
||||
: g_out(graph), orig2copy(c), copy_vertex(cv), copy_edge(ce) { }
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void examine_vertex(Vertex u, const Graph& g_in) const {
|
||||
typename graph_traits<NewGraph>::vertex_descriptor
|
||||
new_u = add_vertex(g_out);
|
||||
put(orig2copy, u, new_u);
|
||||
copy_vertex(u, new_u);
|
||||
}
|
||||
|
||||
template <class Edge, class Graph>
|
||||
void examine_edge(Edge e, const Graph& g_in) const {
|
||||
typename graph_traits<NewGraph>::edge_descriptor new_e;
|
||||
bool inserted;
|
||||
tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)),
|
||||
get(orig2copy, target(e, g_in)),
|
||||
g_out);
|
||||
copy_edge(e, new_e);
|
||||
}
|
||||
private:
|
||||
NewGraph& g_out;
|
||||
Copy2OrigIndexMap orig2copy;
|
||||
CopyVertex copy_vertex;
|
||||
CopyEdge copy_edge;
|
||||
};
|
||||
|
||||
template <typename Graph, typename MutableGraph,
|
||||
typename CopyVertex, typename CopyEdge,
|
||||
typename Orig2CopyVertexIndexMap, typename Params>
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor
|
||||
copy_component_impl
|
||||
(const Graph& g_in,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
MutableGraph& g_out,
|
||||
CopyVertex copy_vertex, CopyEdge copy_edge,
|
||||
Orig2CopyVertexIndexMap orig2copy,
|
||||
const Params& params)
|
||||
{
|
||||
graph_copy_visitor<MutableGraph, Orig2CopyVertexIndexMap,
|
||||
CopyVertex, CopyEdge> vis(g_out, orig2copy, copy_vertex, copy_edge);
|
||||
breadth_first_search(g_in, src, params.visitor(vis));
|
||||
return get(orig2copy, src);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// Copy all the vertices and edges of graph g_in that are reachable
|
||||
// from the source vertex into graph g_out. Return the vertex
|
||||
// in g_out that matches the source vertex of g_in.
|
||||
template <typename IncidenceGraph, typename MutableGraph,
|
||||
typename P, typename T, typename R>
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor
|
||||
copy_component(IncidenceGraph& g_in,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor src,
|
||||
MutableGraph& g_out,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typename std::vector<T>::size_type n;
|
||||
n = is_default_param(get_param(params, orig_to_copy_t()))
|
||||
? num_vertices(g_in) : 1;
|
||||
std::vector<typename graph_traits<IncidenceGraph>::vertex_descriptor>
|
||||
orig2copy(n);
|
||||
|
||||
return detail::copy_component_impl
|
||||
(g_in, src, g_out,
|
||||
detail::choose_vertex_copier(get_param(params, vertex_copy_t()),
|
||||
g_in, g_out),
|
||||
detail::choose_edge_copier(get_param(params, edge_copy_t()),
|
||||
g_in, g_out),
|
||||
choose_param(get_param(params, orig_to_copy_t()),
|
||||
make_iterator_property_map
|
||||
(orig2copy.begin(),
|
||||
choose_pmap(get_param(params, vertex_index),
|
||||
g_in, vertex_index), orig2copy[0])),
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
template <typename IncidenceGraph, typename MutableGraph>
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor
|
||||
copy_component(IncidenceGraph& g_in,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor src,
|
||||
MutableGraph& g_out)
|
||||
{
|
||||
std::vector<typename graph_traits<IncidenceGraph>::vertex_descriptor>
|
||||
orig2copy(num_vertices(g_in));
|
||||
|
||||
return detail::copy_component_impl
|
||||
(g_in, src, g_out,
|
||||
make_vertex_copier(g_in, g_out),
|
||||
make_edge_copier(g_in, g_out),
|
||||
make_iterator_property_map(orig2copy.begin(),
|
||||
get(vertex_index, g_in), orig2copy[0]),
|
||||
bgl_named_params<char,char>('x') // dummy param object
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_COPY_HPP
|
||||
83
libraries/include/boost/graph/create_condensation_graph.hpp
Normal file
83
libraries/include/boost/graph/create_condensation_graph.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
//=======================================================================
|
||||
// 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_CREATE_CONDENSATION_GRAPH_HPP
|
||||
#define BOOST_CREATE_CONDENSATION_GRAPH_HPP
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename Graph, typename ComponentLists,
|
||||
typename ComponentNumberMap,
|
||||
typename CondensationGraph, typename EdgeMultiplicityMap>
|
||||
void create_condensation_graph(const Graph& g,
|
||||
const ComponentLists& components,
|
||||
ComponentNumberMap component_number,
|
||||
CondensationGraph& cg,
|
||||
EdgeMultiplicityMap edge_mult_map)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
typedef typename graph_traits<CondensationGraph>::vertex_descriptor
|
||||
cg_vertex;
|
||||
std::vector<cg_vertex> to_cg_vertex(components.size());
|
||||
for (size_type s = 0; s < components.size(); ++s)
|
||||
to_cg_vertex[s] = add_vertex(cg);
|
||||
|
||||
for (size_type si = 0; si < components.size(); ++si) {
|
||||
cg_vertex s = to_cg_vertex[si];
|
||||
std::vector<cg_vertex> adj;
|
||||
for (size_type i = 0; i < components[si].size(); ++i) {
|
||||
vertex u = components[s][i];
|
||||
typename graph_traits<Graph>::adjacency_iterator v, v_end;
|
||||
for (tie(v, v_end) = adjacent_vertices(u, g); v != v_end; ++v) {
|
||||
cg_vertex t = to_cg_vertex[component_number[*v]];
|
||||
if (s != t) // Avoid loops in the condensation graph
|
||||
adj.push_back(t);
|
||||
}
|
||||
}
|
||||
std::sort(adj.begin(), adj.end());
|
||||
if (! adj.empty()) {
|
||||
size_type i = 0;
|
||||
cg_vertex t = adj[i];
|
||||
typename graph_traits<CondensationGraph>::edge_descriptor e;
|
||||
bool inserted;
|
||||
tie(e, inserted) = add_edge(s, t, cg);
|
||||
put(edge_mult_map, e, 1);
|
||||
++i;
|
||||
while (i < adj.size()) {
|
||||
if (adj[i] == t)
|
||||
put(edge_mult_map, e, get(edge_mult_map, e) + 1);
|
||||
else {
|
||||
t = adj[i];
|
||||
tie(e, inserted) = add_edge(s, t, cg);
|
||||
put(edge_mult_map, e, 1);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Graph, typename ComponentLists,
|
||||
typename ComponentNumberMap, typename CondensationGraph>
|
||||
void create_condensation_graph(const Graph& g,
|
||||
const ComponentLists& components,
|
||||
ComponentNumberMap component_number,
|
||||
CondensationGraph& cg)
|
||||
{
|
||||
create_condensation_graph(g, components, component_number, cg,
|
||||
dummy_property_map());
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_CREATE_CONDENSATION_GRAPH_HPP
|
||||
190
libraries/include/boost/graph/cuthill_mckee_ordering.hpp
Normal file
190
libraries/include/boost/graph/cuthill_mckee_ordering.hpp
Normal file
@@ -0,0 +1,190 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Copyright 2004, 2005 Trustees of Indiana University
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek,
|
||||
// Doug Gregor, D. Kevin McGrath
|
||||
//
|
||||
// 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_CUTHILL_MCKEE_HPP
|
||||
#define BOOST_GRAPH_CUTHILL_MCKEE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/detail/sparse_ordering.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
/*
|
||||
(Reverse) Cuthill-McKee Algorithm for matrix reordering
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
template < typename OutputIterator, typename Buffer, typename DegreeMap >
|
||||
class bfs_rcm_visitor:public default_bfs_visitor
|
||||
{
|
||||
public:
|
||||
bfs_rcm_visitor(OutputIterator *iter, Buffer *b, DegreeMap deg):
|
||||
permutation(iter), Qptr(b), degree(deg) { }
|
||||
template <class Vertex, class Graph>
|
||||
void examine_vertex(Vertex u, Graph&) {
|
||||
*(*permutation)++ = u;
|
||||
index_begin = Qptr->size();
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void finish_vertex(Vertex, Graph&) {
|
||||
using std::sort;
|
||||
|
||||
typedef typename property_traits<DegreeMap>::value_type ds_type;
|
||||
|
||||
typedef indirect_cmp<DegreeMap, std::less<ds_type> > Compare;
|
||||
Compare comp(degree);
|
||||
|
||||
sort(Qptr->begin()+index_begin, Qptr->end(), comp);
|
||||
}
|
||||
protected:
|
||||
OutputIterator *permutation;
|
||||
int index_begin;
|
||||
Buffer *Qptr;
|
||||
DegreeMap degree;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// Reverse Cuthill-McKee algorithm with a given starting Vertex.
|
||||
//
|
||||
// If user provides a reverse iterator, this will be a reverse-cuthill-mckee
|
||||
// algorithm, otherwise it will be a standard CM algorithm
|
||||
|
||||
template <class Graph, class OutputIterator,
|
||||
class ColorMap, class DegreeMap>
|
||||
OutputIterator
|
||||
cuthill_mckee_ordering(const Graph& g,
|
||||
std::deque< typename
|
||||
graph_traits<Graph>::vertex_descriptor > vertex_queue,
|
||||
OutputIterator permutation,
|
||||
ColorMap color, DegreeMap degree)
|
||||
{
|
||||
|
||||
//create queue, visitor...don't forget namespaces!
|
||||
typedef typename property_traits<DegreeMap>::value_type ds_type;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename boost::sparse::sparse_ordering_queue<Vertex> queue;
|
||||
typedef typename detail::bfs_rcm_visitor<OutputIterator, queue, DegreeMap> Visitor;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
|
||||
queue Q;
|
||||
|
||||
//create a bfs_rcm_visitor as defined above
|
||||
Visitor vis(&permutation, &Q, degree);
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
|
||||
// Copy degree to pseudo_degree
|
||||
// initialize the color map
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui){
|
||||
put(color, *ui, Color::white());
|
||||
}
|
||||
|
||||
|
||||
while( !vertex_queue.empty() ) {
|
||||
Vertex s = vertex_queue.front();
|
||||
vertex_queue.pop_front();
|
||||
|
||||
//call BFS with visitor
|
||||
breadth_first_visit(g, s, Q, vis, color);
|
||||
}
|
||||
return permutation;
|
||||
}
|
||||
|
||||
|
||||
// This is the case where only a single starting vertex is supplied.
|
||||
template <class Graph, class OutputIterator,
|
||||
class ColorMap, class DegreeMap>
|
||||
OutputIterator
|
||||
cuthill_mckee_ordering(const Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
OutputIterator permutation,
|
||||
ColorMap color, DegreeMap degree)
|
||||
{
|
||||
|
||||
std::deque< typename graph_traits<Graph>::vertex_descriptor > vertex_queue;
|
||||
vertex_queue.push_front( s );
|
||||
|
||||
return cuthill_mckee_ordering(g, vertex_queue, permutation, color, degree);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// This is the version of CM which selects its own starting vertex
|
||||
template < class Graph, class OutputIterator,
|
||||
class ColorMap, class DegreeMap>
|
||||
OutputIterator
|
||||
cuthill_mckee_ordering(const Graph& G, OutputIterator permutation,
|
||||
ColorMap color, DegreeMap degree)
|
||||
{
|
||||
if (vertices(G).first == vertices(G).second)
|
||||
return permutation;
|
||||
|
||||
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename boost::graph_traits<Graph>::vertex_iterator VerIter;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
std::deque<Vertex> vertex_queue;
|
||||
|
||||
// Mark everything white
|
||||
BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white());
|
||||
|
||||
// Find one vertex from each connected component
|
||||
BGL_FORALL_VERTICES_T(v, G, Graph) {
|
||||
if (get(color, v) == Color::white()) {
|
||||
depth_first_visit(G, v, dfs_visitor<>(), color);
|
||||
vertex_queue.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
// Find starting nodes for all vertices
|
||||
// TBD: How to do this with a directed graph?
|
||||
for (typename std::deque<Vertex>::iterator i = vertex_queue.begin();
|
||||
i != vertex_queue.end(); ++i)
|
||||
*i = find_starting_node(G, *i, color, degree);
|
||||
|
||||
return cuthill_mckee_ordering(G, vertex_queue, permutation,
|
||||
color, degree);
|
||||
}
|
||||
|
||||
template<typename Graph, typename OutputIterator, typename VertexIndexMap>
|
||||
OutputIterator
|
||||
cuthill_mckee_ordering(const Graph& G, OutputIterator permutation,
|
||||
VertexIndexMap index_map)
|
||||
{
|
||||
if (vertices(G).first == vertices(G).second)
|
||||
return permutation;
|
||||
|
||||
typedef out_degree_property_map<Graph> DegreeMap;
|
||||
std::vector<default_color_type> colors(num_vertices(G));
|
||||
return cuthill_mckee_ordering(G, permutation,
|
||||
make_iterator_property_map(&colors[0],
|
||||
index_map,
|
||||
colors[0]),
|
||||
make_out_degree_map(G));
|
||||
}
|
||||
|
||||
template<typename Graph, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
cuthill_mckee_ordering(const Graph& G, OutputIterator permutation)
|
||||
{ return cuthill_mckee_ordering(G, permutation, get(vertex_index, G)); }
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_CUTHILL_MCKEE_HPP
|
||||
157
libraries/include/boost/graph/dag_shortest_paths.hpp
Normal file
157
libraries/include/boost/graph/dag_shortest_paths.hpp
Normal file
@@ -0,0 +1,157 @@
|
||||
//=======================================================================
|
||||
// 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_DAG_SHORTEST_PATHS_HPP
|
||||
#define BOOST_GRAPH_DAG_SHORTEST_PATHS_HPP
|
||||
|
||||
#include <boost/graph/topological_sort.hpp>
|
||||
#include <boost/graph/dijkstra_shortest_paths.hpp>
|
||||
|
||||
// single-source shortest paths for a Directed Acyclic Graph (DAG)
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Initalize distances and call depth first search
|
||||
template <class VertexListGraph, class DijkstraVisitor,
|
||||
class DistanceMap, class WeightMap, class ColorMap,
|
||||
class PredecessorMap,
|
||||
class Compare, class Combine,
|
||||
class DistInf, class DistZero>
|
||||
inline void
|
||||
dag_shortest_paths
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
DistanceMap distance, WeightMap weight, ColorMap color,
|
||||
PredecessorMap pred,
|
||||
DijkstraVisitor vis, Compare compare, Combine combine,
|
||||
DistInf inf, DistZero zero)
|
||||
{
|
||||
typedef typename graph_traits<VertexListGraph>::vertex_descriptor Vertex;
|
||||
std::vector<Vertex> rev_topo_order;
|
||||
rev_topo_order.reserve(num_vertices(g));
|
||||
|
||||
// Call 'depth_first_visit', not 'topological_sort', because we don't
|
||||
// want to traverse the entire graph, only vertices reachable from 's',
|
||||
// and 'topological_sort' will traverse everything. The logic below
|
||||
// is the same as for 'topological_sort', only we call 'depth_first_visit'
|
||||
// and 'topological_sort' calls 'depth_first_search'.
|
||||
topo_sort_visitor<std::back_insert_iterator<std::vector<Vertex> > >
|
||||
topo_visitor(std::back_inserter(rev_topo_order));
|
||||
depth_first_visit(g, s, topo_visitor, color);
|
||||
|
||||
typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
||||
put(distance, *ui, inf);
|
||||
put(pred, *ui, *ui);
|
||||
}
|
||||
|
||||
put(distance, s, zero);
|
||||
vis.discover_vertex(s, g);
|
||||
typename std::vector<Vertex>::reverse_iterator i;
|
||||
for (i = rev_topo_order.rbegin(); i != rev_topo_order.rend(); ++i) {
|
||||
Vertex u = *i;
|
||||
vis.examine_vertex(u, g);
|
||||
typename graph_traits<VertexListGraph>::out_edge_iterator e, e_end;
|
||||
for (tie(e, e_end) = out_edges(u, g); e != e_end; ++e) {
|
||||
vis.discover_vertex(target(*e, g), g);
|
||||
bool decreased = relax(*e, g, weight, pred, distance,
|
||||
combine, compare);
|
||||
if (decreased)
|
||||
vis.edge_relaxed(*e, g);
|
||||
else
|
||||
vis.edge_not_relaxed(*e, g);
|
||||
}
|
||||
vis.finish_vertex(u, g);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Defaults are the same as Dijkstra's algorithm
|
||||
|
||||
// Handle Distance Compare, Combine, Inf and Zero defaults
|
||||
template <class VertexListGraph, class DijkstraVisitor,
|
||||
class DistanceMap, class WeightMap, class ColorMap,
|
||||
class IndexMap, class Params>
|
||||
inline void
|
||||
dag_sp_dispatch2
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
DistanceMap distance, WeightMap weight, ColorMap color, IndexMap id,
|
||||
DijkstraVisitor vis, const Params& params)
|
||||
{
|
||||
typedef typename property_traits<DistanceMap>::value_type D;
|
||||
dummy_property_map p_map;
|
||||
dag_shortest_paths
|
||||
(g, s, distance, weight, color,
|
||||
choose_param(get_param(params, vertex_predecessor), p_map),
|
||||
vis,
|
||||
choose_param(get_param(params, distance_compare_t()), std::less<D>()),
|
||||
choose_param(get_param(params, distance_combine_t()), closed_plus<D>()),
|
||||
choose_param(get_param(params, distance_inf_t()),
|
||||
(std::numeric_limits<D>::max)()),
|
||||
choose_param(get_param(params, distance_zero_t()),
|
||||
D()));
|
||||
}
|
||||
|
||||
// Handle DistanceMap and ColorMap defaults
|
||||
template <class VertexListGraph, class DijkstraVisitor,
|
||||
class DistanceMap, class WeightMap, class ColorMap,
|
||||
class IndexMap, class Params>
|
||||
inline void
|
||||
dag_sp_dispatch1
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
DistanceMap distance, WeightMap weight, ColorMap color, IndexMap id,
|
||||
DijkstraVisitor vis, const Params& params)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type T;
|
||||
typename std::vector<T>::size_type n;
|
||||
n = is_default_param(distance) ? num_vertices(g) : 1;
|
||||
std::vector<T> distance_map(n);
|
||||
n = is_default_param(color) ? num_vertices(g) : 1;
|
||||
std::vector<default_color_type> color_map(n);
|
||||
|
||||
dag_sp_dispatch2
|
||||
(g, s,
|
||||
choose_param(distance,
|
||||
make_iterator_property_map(distance_map.begin(), id,
|
||||
distance_map[0])),
|
||||
weight,
|
||||
choose_param(color,
|
||||
make_iterator_property_map(color_map.begin(), id,
|
||||
color_map[0])),
|
||||
id, vis, params);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class VertexListGraph, class Param, class Tag, class Rest>
|
||||
inline void
|
||||
dag_shortest_paths
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
const bgl_named_params<Param,Tag,Rest>& params)
|
||||
{
|
||||
// assert that the graph is directed...
|
||||
null_visitor null_vis;
|
||||
detail::dag_sp_dispatch1
|
||||
(g, s,
|
||||
get_param(params, vertex_distance),
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
|
||||
get_param(params, vertex_color),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_dijkstra_visitor(null_vis)),
|
||||
params);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_DAG_SHORTEST_PATHS_HPP
|
||||
365
libraries/include/boost/graph/depth_first_search.hpp
Normal file
365
libraries/include/boost/graph/depth_first_search.hpp
Normal file
@@ -0,0 +1,365 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Copyright 2003 Bruce Barr
|
||||
// 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)
|
||||
//=======================================================================
|
||||
|
||||
// Nonrecursive implementation of depth_first_visit_impl submitted by
|
||||
// Bruce Barr, schmoost <at> yahoo.com, May/June 2003.
|
||||
#ifndef BOOST_GRAPH_RECURSIVE_DFS_HPP
|
||||
#define BOOST_GRAPH_RECURSIVE_DFS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/visitors.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/implicit_cast.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Visitor, class Graph>
|
||||
class DFSVisitorConcept {
|
||||
public:
|
||||
void constraints() {
|
||||
function_requires< CopyConstructibleConcept<Visitor> >();
|
||||
vis.initialize_vertex(u, g);
|
||||
vis.start_vertex(u, g);
|
||||
vis.discover_vertex(u, g);
|
||||
vis.examine_edge(e, g);
|
||||
vis.tree_edge(e, g);
|
||||
vis.back_edge(e, g);
|
||||
vis.forward_or_cross_edge(e, g);
|
||||
vis.finish_vertex(u, g);
|
||||
}
|
||||
private:
|
||||
Visitor vis;
|
||||
Graph g;
|
||||
typename graph_traits<Graph>::vertex_descriptor u;
|
||||
typename graph_traits<Graph>::edge_descriptor e;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct nontruth2 {
|
||||
template<class T, class T2>
|
||||
bool operator()(const T&, const T2&) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
// Define BOOST_RECURSIVE_DFS to use older, recursive version.
|
||||
// It is retained for a while in order to perform performance
|
||||
// comparison.
|
||||
#ifndef BOOST_RECURSIVE_DFS
|
||||
|
||||
// If the vertex u and the iterators ei and ei_end are thought of as the
|
||||
// context of the algorithm, each push and pop from the stack could
|
||||
// be thought of as a context shift.
|
||||
// Each pass through "while (ei != ei_end)" may refer to the out-edges of
|
||||
// an entirely different vertex, because the context of the algorithm
|
||||
// shifts every time a white adjacent vertex is discovered.
|
||||
// The corresponding context shift back from the adjacent vertex occurs
|
||||
// after all of its out-edges have been examined.
|
||||
//
|
||||
// See http://lists.boost.org/MailArchives/boost/msg48752.php for FAQ.
|
||||
|
||||
template <class IncidenceGraph, class DFSVisitor, class ColorMap,
|
||||
class TerminatorFunc>
|
||||
void depth_first_visit_impl
|
||||
(const IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
||||
DFSVisitor& vis,
|
||||
ColorMap color, TerminatorFunc func = TerminatorFunc())
|
||||
{
|
||||
function_requires<IncidenceGraphConcept<IncidenceGraph> >();
|
||||
function_requires<DFSVisitorConcept<DFSVisitor, IncidenceGraph> >();
|
||||
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
||||
function_requires< ReadWritePropertyMapConcept<ColorMap, Vertex> >();
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
function_requires< ColorValueConcept<ColorValue> >();
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typedef typename graph_traits<IncidenceGraph>::out_edge_iterator Iter;
|
||||
typedef std::pair<Vertex, std::pair<Iter, Iter> > VertexInfo;
|
||||
|
||||
Iter ei, ei_end;
|
||||
std::vector<VertexInfo> stack;
|
||||
|
||||
// Possible optimization for vector
|
||||
//stack.reserve(num_vertices(g));
|
||||
|
||||
typedef typename unwrap_reference<TerminatorFunc>::type TF;
|
||||
|
||||
put(color, u, Color::gray());
|
||||
vis.discover_vertex(u, g);
|
||||
tie(ei, ei_end) = out_edges(u, g);
|
||||
// Variable is needed to workaround a borland bug.
|
||||
TF& fn = static_cast<TF&>(func);
|
||||
if (fn(u, g)) {
|
||||
// If this vertex terminates the search, we push empty range
|
||||
stack.push_back(std::make_pair(u, std::make_pair(ei_end, ei_end)));
|
||||
} else {
|
||||
stack.push_back(std::make_pair(u, std::make_pair(ei, ei_end)));
|
||||
}
|
||||
while (!stack.empty()) {
|
||||
VertexInfo& back = stack.back();
|
||||
u = back.first;
|
||||
tie(ei, ei_end) = back.second;
|
||||
stack.pop_back();
|
||||
while (ei != ei_end) {
|
||||
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);
|
||||
stack.push_back(std::make_pair(u, std::make_pair(++ei, ei_end)));
|
||||
u = v;
|
||||
put(color, u, Color::gray());
|
||||
vis.discover_vertex(u, g);
|
||||
tie(ei, ei_end) = out_edges(u, g);
|
||||
if (fn(u, g)) {
|
||||
ei = ei_end;
|
||||
}
|
||||
} else if (v_color == Color::gray()) {
|
||||
vis.back_edge(*ei, g);
|
||||
++ei;
|
||||
} else {
|
||||
vis.forward_or_cross_edge(*ei, g);
|
||||
++ei;
|
||||
}
|
||||
}
|
||||
put(color, u, Color::black());
|
||||
vis.finish_vertex(u, g);
|
||||
}
|
||||
}
|
||||
|
||||
#else // BOOST_RECURSIVE_DFS is defined
|
||||
|
||||
template <class IncidenceGraph, class DFSVisitor, class ColorMap,
|
||||
class TerminatorFunc>
|
||||
void depth_first_visit_impl
|
||||
(const IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
||||
DFSVisitor& vis, // pass-by-reference here, important!
|
||||
ColorMap color, TerminatorFunc func)
|
||||
{
|
||||
function_requires<IncidenceGraphConcept<IncidenceGraph> >();
|
||||
function_requires<DFSVisitorConcept<DFSVisitor, IncidenceGraph> >();
|
||||
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
||||
function_requires< ReadWritePropertyMapConcept<ColorMap, Vertex> >();
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
function_requires< ColorValueConcept<ColorValue> >();
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typename graph_traits<IncidenceGraph>::out_edge_iterator ei, ei_end;
|
||||
|
||||
put(color, u, Color::gray()); vis.discover_vertex(u, g);
|
||||
|
||||
typedef typename unwrap_reference<TerminatorFunc>::type TF;
|
||||
// Variable is needed to workaround a borland bug.
|
||||
TF& fn = static_cast<TF&>(func);
|
||||
if (!fn(u, g))
|
||||
for (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);
|
||||
depth_first_visit_impl(g, v, vis, color, func);
|
||||
} else if (v_color == Color::gray()) vis.back_edge(*ei, g);
|
||||
else vis.forward_or_cross_edge(*ei, g);
|
||||
}
|
||||
put(color, u, Color::black()); vis.finish_vertex(u, g);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class VertexListGraph, class DFSVisitor, class ColorMap>
|
||||
void
|
||||
depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor start_vertex)
|
||||
{
|
||||
typedef typename graph_traits<VertexListGraph>::vertex_descriptor Vertex;
|
||||
function_requires<DFSVisitorConcept<DFSVisitor, VertexListGraph> >();
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
||||
put(color, *ui, Color::white()); vis.initialize_vertex(*ui, g);
|
||||
}
|
||||
|
||||
if (start_vertex != implicit_cast<Vertex>(*vertices(g).first)){ vis.start_vertex(start_vertex, g);
|
||||
detail::depth_first_visit_impl(g, start_vertex, vis, color,
|
||||
detail::nontruth2());
|
||||
}
|
||||
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
||||
ColorValue u_color = get(color, *ui);
|
||||
if (u_color == Color::white()) { vis.start_vertex(*ui, g);
|
||||
detail::depth_first_visit_impl(g, *ui, vis, color, detail::nontruth2());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class DFSVisitor, class ColorMap>
|
||||
void
|
||||
depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color)
|
||||
{
|
||||
if (vertices(g).first == vertices(g).second)
|
||||
return;
|
||||
|
||||
depth_first_search(g, vis, color, *vertices(g).first);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <class ColorMap>
|
||||
struct dfs_dispatch {
|
||||
|
||||
template <class VertexListGraph, class Vertex, class DFSVisitor,
|
||||
class P, class T, class R>
|
||||
static void
|
||||
apply(const VertexListGraph& g, DFSVisitor vis, Vertex start_vertex,
|
||||
const bgl_named_params<P, T, R>&,
|
||||
ColorMap color)
|
||||
{
|
||||
depth_first_search(g, vis, color, start_vertex);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct dfs_dispatch<detail::error_property_not_found> {
|
||||
template <class VertexListGraph, class Vertex, class DFSVisitor,
|
||||
class P, class T, class R>
|
||||
static void
|
||||
apply(const VertexListGraph& g, DFSVisitor vis, Vertex start_vertex,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
detail::error_property_not_found)
|
||||
{
|
||||
std::vector<default_color_type> color_vec(num_vertices(g));
|
||||
default_color_type c = white_color; // avoid warning about un-init
|
||||
depth_first_search
|
||||
(g, vis, make_iterator_property_map
|
||||
(color_vec.begin(),
|
||||
choose_const_pmap(get_param(params, vertex_index),
|
||||
g, vertex_index), c),
|
||||
start_vertex);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template <class Visitors = null_visitor>
|
||||
class dfs_visitor {
|
||||
public:
|
||||
dfs_visitor() { }
|
||||
dfs_visitor(Visitors vis) : m_vis(vis) { }
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void initialize_vertex(Vertex u, const Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void start_vertex(Vertex u, const Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_start_vertex());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, const Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_discover_vertex());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void examine_edge(Edge u, const Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_examine_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void tree_edge(Edge u, const Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_tree_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void back_edge(Edge u, const Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_back_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void forward_or_cross_edge(Edge u, const Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_forward_or_cross_edge());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void finish_vertex(Vertex u, const Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex());
|
||||
}
|
||||
|
||||
BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,dfs)
|
||||
BOOST_GRAPH_EVENT_STUB(on_start_vertex,dfs)
|
||||
BOOST_GRAPH_EVENT_STUB(on_discover_vertex,dfs)
|
||||
BOOST_GRAPH_EVENT_STUB(on_examine_edge,dfs)
|
||||
BOOST_GRAPH_EVENT_STUB(on_tree_edge,dfs)
|
||||
BOOST_GRAPH_EVENT_STUB(on_back_edge,dfs)
|
||||
BOOST_GRAPH_EVENT_STUB(on_forward_or_cross_edge,dfs)
|
||||
BOOST_GRAPH_EVENT_STUB(on_finish_vertex,dfs)
|
||||
|
||||
protected:
|
||||
Visitors m_vis;
|
||||
};
|
||||
template <class Visitors>
|
||||
dfs_visitor<Visitors>
|
||||
make_dfs_visitor(Visitors vis) {
|
||||
return dfs_visitor<Visitors>(vis);
|
||||
}
|
||||
typedef dfs_visitor<> default_dfs_visitor;
|
||||
|
||||
|
||||
// Named Parameter Variant
|
||||
template <class VertexListGraph, class P, class T, class R>
|
||||
void
|
||||
depth_first_search(const VertexListGraph& g,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename property_value< bgl_named_params<P, T, R>,
|
||||
vertex_color_t>::type C;
|
||||
if (vertices(g).first == vertices(g).second)
|
||||
return;
|
||||
detail::dfs_dispatch<C>::apply
|
||||
(g,
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_dfs_visitor(null_visitor())),
|
||||
choose_param(get_param(params, root_vertex_t()),
|
||||
*vertices(g).first),
|
||||
params,
|
||||
get_param(params, vertex_color)
|
||||
);
|
||||
}
|
||||
|
||||
template <class IncidenceGraph, class DFSVisitor, class ColorMap>
|
||||
void depth_first_visit
|
||||
(const IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
||||
DFSVisitor vis, ColorMap color)
|
||||
{
|
||||
vis.start_vertex(u, g);
|
||||
detail::depth_first_visit_impl(g, u, vis, color, detail::nontruth2());
|
||||
}
|
||||
|
||||
template <class IncidenceGraph, class DFSVisitor, class ColorMap,
|
||||
class TerminatorFunc>
|
||||
void depth_first_visit
|
||||
(const IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
||||
DFSVisitor vis, ColorMap color, TerminatorFunc func = TerminatorFunc())
|
||||
{
|
||||
vis.start_vertex(u, g);
|
||||
detail::depth_first_visit_impl(g, u, vis, color, func);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif
|
||||
117
libraries/include/boost/graph/detail/adj_list_edge_iterator.hpp
Normal file
117
libraries/include/boost/graph/detail/adj_list_edge_iterator.hpp
Normal file
@@ -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
|
||||
2867
libraries/include/boost/graph/detail/adjacency_list.hpp
Normal file
2867
libraries/include/boost/graph/detail/adjacency_list.hpp
Normal file
File diff suppressed because it is too large
Load Diff
182
libraries/include/boost/graph/detail/array_binary_tree.hpp
Normal file
182
libraries/include/boost/graph/detail/array_binary_tree.hpp
Normal file
@@ -0,0 +1,182 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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 ADSTL_ARRAY_BINARY_TREE_HPP
|
||||
#define ADSTL_ARRAY_BINARY_TREE_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace adstl {
|
||||
/*
|
||||
Note: array_binary_tree is a completey balanced binary tree
|
||||
*/
|
||||
|
||||
#if !defined BOOST_NO_STD_ITERATOR_TRAITS
|
||||
template <class RandomAccessIterator, class ID>
|
||||
#else
|
||||
template <class RandomAccessIterator, class ValueType, class ID>
|
||||
#endif
|
||||
class array_binary_tree_node {
|
||||
public:
|
||||
typedef array_binary_tree_node ArrayBinaryTreeNode;
|
||||
typedef RandomAccessIterator rep_iterator;
|
||||
#if !defined BOOST_NO_STD_ITERATOR_TRAITS
|
||||
typedef typename std::iterator_traits<RandomAccessIterator>::difference_type
|
||||
difference_type;
|
||||
typedef typename std::iterator_traits<RandomAccessIterator>::value_type
|
||||
value_type;
|
||||
#else
|
||||
typedef int difference_type;
|
||||
typedef ValueType value_type;
|
||||
#endif
|
||||
typedef difference_type size_type;
|
||||
|
||||
struct children_type {
|
||||
struct iterator
|
||||
: boost::iterator<std::bidirectional_iterator_tag, ArrayBinaryTreeNode,
|
||||
difference_type, array_binary_tree_node*, ArrayBinaryTreeNode&>
|
||||
{ // replace with iterator_adaptor implementation -JGS
|
||||
|
||||
inline iterator() : i(0), n(0) { }
|
||||
inline iterator(const iterator& x) : r(x.r), i(x.i), n(x.n), id(x.id) { }
|
||||
inline iterator& operator=(const iterator& x) {
|
||||
r = x.r; i = x.i; n = x.n;
|
||||
/*egcs generate a warning*/
|
||||
id = x.id;
|
||||
return *this;
|
||||
}
|
||||
inline iterator(rep_iterator rr,
|
||||
size_type ii,
|
||||
size_type nn,
|
||||
const ID& _id) : r(rr), i(ii), n(nn), id(_id) { }
|
||||
inline array_binary_tree_node operator*() {
|
||||
return ArrayBinaryTreeNode(r, i, n, id); }
|
||||
inline iterator& operator++() { ++i; return *this; }
|
||||
inline iterator operator++(int)
|
||||
{ iterator t = *this; ++(*this); return t; }
|
||||
inline bool operator==(const iterator& x) const { return i == x.i; }
|
||||
inline bool operator!=(const iterator& x) const
|
||||
{ return !(*this == x); }
|
||||
rep_iterator r;
|
||||
size_type i;
|
||||
size_type n;
|
||||
ID id;
|
||||
};
|
||||
inline children_type() : i(0), n(0) { }
|
||||
inline children_type(const children_type& x)
|
||||
: r(x.r), i(x.i), n(x.n), id(x.id) { }
|
||||
inline children_type& operator=(const children_type& x) {
|
||||
r = x.r; i = x.i; n = x.n;
|
||||
/*egcs generate a warning*/
|
||||
id = x.id;
|
||||
return *this;
|
||||
}
|
||||
inline children_type(rep_iterator rr,
|
||||
size_type ii,
|
||||
size_type nn,
|
||||
const ID& _id) : r(rr), i(ii), n(nn), id(_id) { }
|
||||
inline iterator begin() { return iterator(r, 2 * i + 1, n, id); }
|
||||
inline iterator end() { return iterator(r, 2 * i + 1 + size(), n, id); }
|
||||
inline size_type size() const {
|
||||
size_type c = 2 * i + 1;
|
||||
size_type s;
|
||||
if (c + 1 < n) s = 2;
|
||||
else if (c < n) s = 1;
|
||||
else s = 0;
|
||||
return s;
|
||||
}
|
||||
rep_iterator r;
|
||||
size_type i;
|
||||
size_type n;
|
||||
ID id;
|
||||
};
|
||||
inline array_binary_tree_node() : i(0), n(0) { }
|
||||
inline array_binary_tree_node(const array_binary_tree_node& x)
|
||||
: r(x.r), i(x.i), n(x.n), id(x.id) { }
|
||||
inline ArrayBinaryTreeNode& operator=(const ArrayBinaryTreeNode& x) {
|
||||
r = x.r;
|
||||
i = x.i;
|
||||
n = x.n;
|
||||
/*egcs generate a warning*/
|
||||
id = x.id;
|
||||
return *this;
|
||||
}
|
||||
inline array_binary_tree_node(rep_iterator start,
|
||||
rep_iterator end,
|
||||
rep_iterator pos, const ID& _id)
|
||||
: r(start), i(pos - start), n(end - start), id(_id) { }
|
||||
inline array_binary_tree_node(rep_iterator rr,
|
||||
size_type ii,
|
||||
size_type nn, const ID& _id)
|
||||
: r(rr), i(ii), n(nn), id(_id) { }
|
||||
inline value_type& value() { return *(r + i); }
|
||||
inline const value_type& value() const { return *(r + i); }
|
||||
inline ArrayBinaryTreeNode parent() const {
|
||||
return ArrayBinaryTreeNode(r, (i - 1) / 2, n, id);
|
||||
}
|
||||
inline bool has_parent() const { return i != 0; }
|
||||
inline children_type children() { return children_type(r, i, n, id); }
|
||||
/*
|
||||
inline void swap(array_binary_tree_node x) {
|
||||
value_type tmp = x.value();
|
||||
x.value() = value();
|
||||
value() = tmp;
|
||||
i = x.i;
|
||||
}
|
||||
*/
|
||||
template <class ExternalData>
|
||||
inline void swap(ArrayBinaryTreeNode x, ExternalData& edata ) {
|
||||
using boost::get;
|
||||
|
||||
value_type tmp = x.value();
|
||||
|
||||
/*swap external data*/
|
||||
edata[ get(id, tmp) ] = i;
|
||||
edata[ get(id, value()) ] = x.i;
|
||||
|
||||
x.value() = value();
|
||||
value() = tmp;
|
||||
i = x.i;
|
||||
}
|
||||
inline const children_type children() const {
|
||||
return children_type(r, i, n);
|
||||
}
|
||||
inline size_type index() const { return i; }
|
||||
rep_iterator r;
|
||||
size_type i;
|
||||
size_type n;
|
||||
ID id;
|
||||
};
|
||||
|
||||
template <class RandomAccessContainer,
|
||||
class Compare = std::less<typename RandomAccessContainer::value_type> >
|
||||
struct compare_array_node {
|
||||
typedef typename RandomAccessContainer::value_type value_type;
|
||||
compare_array_node(const Compare& x) : comp(x) {}
|
||||
compare_array_node(const compare_array_node& x) : comp(x.comp) {}
|
||||
|
||||
template< class node_type >
|
||||
inline bool operator()(const node_type& x, const node_type& y) {
|
||||
return comp(x.value(), y.value());
|
||||
}
|
||||
|
||||
template< class node_type >
|
||||
inline bool operator()(const node_type& x, const node_type& y) const {
|
||||
return comp(x.value(), y.value());
|
||||
}
|
||||
Compare comp;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace adstl */
|
||||
|
||||
#endif /* ADSTL_ARRAY_BINARY_TREE_H */
|
||||
208
libraries/include/boost/graph/detail/connected_components.hpp
Normal file
208
libraries/include/boost/graph/detail/connected_components.hpp
Normal file
@@ -0,0 +1,208 @@
|
||||
//=======================================================================
|
||||
// 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_CONNECTED_COMPONENTS_HPP
|
||||
#define BOOST_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
#pragma set woff 1234
|
||||
#endif
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
//=========================================================================
|
||||
// Implementation details of connected_components
|
||||
|
||||
// This is used both in the connected_components algorithm and in
|
||||
// the kosaraju strong components algorithm during the second DFS
|
||||
// traversal.
|
||||
template <class ComponentsPA, class DFSVisitor>
|
||||
class components_recorder : public DFSVisitor
|
||||
{
|
||||
typedef typename property_traits<ComponentsPA>::value_type comp_type;
|
||||
public:
|
||||
components_recorder(ComponentsPA c,
|
||||
comp_type& c_count,
|
||||
DFSVisitor v)
|
||||
: DFSVisitor(v), m_component(c), m_count(c_count) {}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void start_vertex(Vertex u, Graph& g) {
|
||||
++m_count;
|
||||
DFSVisitor::start_vertex(u, g);
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph& g) {
|
||||
put(m_component, u, m_count);
|
||||
DFSVisitor::discover_vertex(u, g);
|
||||
}
|
||||
protected:
|
||||
ComponentsPA m_component;
|
||||
comp_type& m_count;
|
||||
};
|
||||
|
||||
template <class DiscoverTimeMap, class FinishTimeMap, class TimeT,
|
||||
class DFSVisitor>
|
||||
class time_recorder : public DFSVisitor
|
||||
{
|
||||
public:
|
||||
time_recorder(DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor v)
|
||||
: DFSVisitor(v), m_discover_time(d), m_finish_time(f), m_t(t) {}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph& g) {
|
||||
put(m_discover_time, u, ++m_t);
|
||||
DFSVisitor::discover_vertex(u, g);
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void finish_vertex(Vertex u, Graph& g) {
|
||||
put(m_finish_time, u, ++m_t);
|
||||
DFSVisitor::discover_vertex(u, g);
|
||||
}
|
||||
protected:
|
||||
DiscoverTimeMap m_discover_time;
|
||||
FinishTimeMap m_finish_time;
|
||||
TimeT m_t;
|
||||
};
|
||||
template <class DiscoverTimeMap, class FinishTimeMap, class TimeT,
|
||||
class DFSVisitor>
|
||||
time_recorder<DiscoverTimeMap, FinishTimeMap, TimeT, DFSVisitor>
|
||||
record_times(DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor vis)
|
||||
{
|
||||
return time_recorder<DiscoverTimeMap, FinishTimeMap, TimeT, DFSVisitor>
|
||||
(d, f, t, vis);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Implementation detail of dynamic_components
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Helper functions for the component_index class
|
||||
|
||||
// Record the representative vertices in the header array.
|
||||
// Representative vertices now point to the component number.
|
||||
|
||||
template <class Parent, class OutputIterator, class Integer>
|
||||
inline void
|
||||
build_components_header(Parent p,
|
||||
OutputIterator header,
|
||||
Integer num_nodes)
|
||||
{
|
||||
Parent component = p;
|
||||
Integer component_num = 0;
|
||||
for (Integer v = 0; v != num_nodes; ++v)
|
||||
if (p[v] == v) {
|
||||
*header++ = v;
|
||||
component[v] = component_num++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pushes x onto the front of the list. The list is represented in
|
||||
// an array.
|
||||
template <class Next, class T, class V>
|
||||
inline void push_front(Next next, T& head, V x)
|
||||
{
|
||||
T tmp = head;
|
||||
head = x;
|
||||
next[x] = tmp;
|
||||
}
|
||||
|
||||
|
||||
// Create a linked list of the vertices in each component
|
||||
// by reusing the representative array.
|
||||
template <class Parent1, class Parent2,
|
||||
class Integer>
|
||||
void
|
||||
link_components(Parent1 component, Parent2 header,
|
||||
Integer num_nodes, Integer num_components)
|
||||
{
|
||||
// Make the non-representative vertices point to their component
|
||||
Parent1 representative = component;
|
||||
for (Integer v = 0; v != num_nodes; ++v)
|
||||
if (component[v] >= num_components || header[component[v]] != v)
|
||||
component[v] = component[representative[v]];
|
||||
|
||||
// initialize the "head" of the lists to "NULL"
|
||||
std::fill_n(header, num_components, num_nodes);
|
||||
|
||||
// Add each vertex to the linked list for its component
|
||||
Parent1 next = component;
|
||||
for (Integer k = 0; k != num_nodes; ++k)
|
||||
push_front(next, header[component[k]], k);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class IndexContainer, class HeaderContainer>
|
||||
void
|
||||
construct_component_index(IndexContainer& index, HeaderContainer& header)
|
||||
{
|
||||
build_components_header(index.begin(),
|
||||
std::back_inserter(header),
|
||||
index.end() - index.begin());
|
||||
|
||||
link_components(index.begin(), header.begin(),
|
||||
index.end() - index.begin(),
|
||||
header.end() - header.begin());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class IndexIterator, class Integer, class Distance>
|
||||
class component_iterator
|
||||
: boost::forward_iterator_helper<
|
||||
component_iterator<IndexIterator,Integer,Distance>,
|
||||
Integer, Distance,Integer*, Integer&>
|
||||
{
|
||||
public:
|
||||
typedef component_iterator self;
|
||||
|
||||
IndexIterator next;
|
||||
Integer node;
|
||||
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Integer value_type;
|
||||
typedef Integer& reference;
|
||||
typedef Integer* pointer;
|
||||
typedef Distance difference_type;
|
||||
|
||||
component_iterator() {}
|
||||
component_iterator(IndexIterator x, Integer i)
|
||||
: next(x), node(i) {}
|
||||
Integer operator*() const {
|
||||
return node;
|
||||
}
|
||||
self& operator++() {
|
||||
node = next[node];
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class IndexIterator, class Integer, class Distance>
|
||||
inline bool
|
||||
operator==(const component_iterator<IndexIterator, Integer, Distance>& x,
|
||||
const component_iterator<IndexIterator, Integer, Distance>& y)
|
||||
{
|
||||
return x.node == y.node;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
#pragma reset woff 1234
|
||||
#endif
|
||||
|
||||
#endif
|
||||
124
libraries/include/boost/graph/detail/edge.hpp
Normal file
124
libraries/include/boost/graph/detail/edge.hpp
Normal file
@@ -0,0 +1,124 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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
|
||||
|
||||
#if __GNUC__ < 3
|
||||
#include <iostream>
|
||||
#else
|
||||
#include <iosfwd>
|
||||
#endif
|
||||
|
||||
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 {
|
||||
|
||||
#if __GNUC__ < 3
|
||||
template <class D, class V>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const boost::detail::edge_desc_impl<D,V>& e)
|
||||
{
|
||||
return os << "(" << e.m_source << "," << e.m_target << ")";
|
||||
}
|
||||
#else
|
||||
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 << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_DETAIL_DETAIL_EDGE_HPP
|
||||
79
libraries/include/boost/graph/detail/incidence_iterator.hpp
Normal file
79
libraries/include/boost/graph/detail/incidence_iterator.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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_INCIDENCE_ITERATOR_HPP
|
||||
#define BOOST_GRAPH_DETAIL_INCIDENCE_ITERATOR_HPP
|
||||
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
// OBSOLETE
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// EdgeDir tags
|
||||
struct in_edge_tag { };
|
||||
struct out_edge_tag { };
|
||||
|
||||
template <class Vertex, class Edge, class Iterator1D, class EdgeDir>
|
||||
struct bidir_incidence_iterator {
|
||||
typedef bidir_incidence_iterator self;
|
||||
typedef Edge edge_type;
|
||||
typedef typename Edge::property_type EdgeProperty;
|
||||
public:
|
||||
typedef int difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef edge_type reference;
|
||||
typedef edge_type value_type;
|
||||
typedef value_type* pointer;
|
||||
inline bidir_incidence_iterator() {}
|
||||
inline bidir_incidence_iterator(Iterator1D ii, Vertex src)
|
||||
: i(ii), _src(src) { }
|
||||
|
||||
inline self& operator++() { ++i; return *this; }
|
||||
inline self operator++(int) { self tmp = *this; ++(*this); return tmp; }
|
||||
|
||||
inline reference operator*() const {
|
||||
return deref_helper(EdgeDir());
|
||||
}
|
||||
inline self* operator->() { return this; }
|
||||
|
||||
Iterator1D& iter() { return i; }
|
||||
const Iterator1D& iter() const { return i; }
|
||||
|
||||
Iterator1D i;
|
||||
Vertex _src;
|
||||
protected:
|
||||
inline reference deref_helper(out_edge_tag) const {
|
||||
return edge_type( _src, (*i).get_target(), &(*i).get_property() );
|
||||
}
|
||||
inline reference deref_helper(in_edge_tag) const {
|
||||
return edge_type((*i).get_target(), _src, &(*i).get_property() );
|
||||
}
|
||||
};
|
||||
|
||||
template <class V, class E, class Iter, class Dir>
|
||||
inline bool operator==(const bidir_incidence_iterator<V,E,Iter,Dir>& x,
|
||||
const bidir_incidence_iterator<V,E,Iter,Dir>& y)
|
||||
{
|
||||
return x.i == y.i;
|
||||
}
|
||||
template <class V, class E, class Iter, class Dir>
|
||||
inline bool operator!=(const bidir_incidence_iterator<V,E,Iter,Dir>& x,
|
||||
const bidir_incidence_iterator<V,E,Iter,Dir>& y)
|
||||
{
|
||||
return x.i != y.i;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
141
libraries/include/boost/graph/detail/incremental_components.hpp
Normal file
141
libraries/include/boost/graph/detail/incremental_components.hpp
Normal file
@@ -0,0 +1,141 @@
|
||||
//=======================================================================
|
||||
// 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_DETAIL_INCREMENTAL_COMPONENTS_HPP
|
||||
#define BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/pending/disjoint_sets.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
//=========================================================================
|
||||
// Implementation detail of incremental_components
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Helper functions for the component_index class
|
||||
|
||||
// Record the representative vertices in the header array.
|
||||
// Representative vertices now point to the component number.
|
||||
|
||||
template <class Parent, class OutputIterator, class Integer>
|
||||
inline void
|
||||
build_components_header(Parent p,
|
||||
OutputIterator header,
|
||||
Integer num_nodes)
|
||||
{
|
||||
Parent component = p;
|
||||
Integer component_num = 0;
|
||||
for (Integer v = 0; v != num_nodes; ++v)
|
||||
if (p[v] == v) {
|
||||
*header++ = v;
|
||||
component[v] = component_num++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pushes x onto the front of the list. The list is represented in
|
||||
// an array.
|
||||
template <class Next, class T, class V>
|
||||
inline void array_push_front(Next next, T& head, V x)
|
||||
{
|
||||
T tmp = head;
|
||||
head = x;
|
||||
next[x] = tmp;
|
||||
}
|
||||
|
||||
|
||||
// Create a linked list of the vertices in each component
|
||||
// by reusing the representative array.
|
||||
template <class Parent1, class Parent2,
|
||||
class Integer>
|
||||
void
|
||||
link_components(Parent1 component, Parent2 header,
|
||||
Integer num_nodes, Integer num_components)
|
||||
{
|
||||
// Make the non-representative vertices point to their component
|
||||
Parent1 representative = component;
|
||||
for (Integer v = 0; v != num_nodes; ++v)
|
||||
if (component[v] >= num_components
|
||||
|| header[component[v]] != v)
|
||||
component[v] = component[representative[v]];
|
||||
|
||||
// initialize the "head" of the lists to "NULL"
|
||||
std::fill_n(header, num_components, num_nodes);
|
||||
|
||||
// Add each vertex to the linked list for its component
|
||||
Parent1 next = component;
|
||||
for (Integer k = 0; k != num_nodes; ++k)
|
||||
array_push_front(next, header[component[k]], k);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class IndexContainer, class HeaderContainer>
|
||||
void
|
||||
construct_component_index(IndexContainer& index, HeaderContainer& header)
|
||||
{
|
||||
typedef typename IndexContainer::value_type Integer;
|
||||
build_components_header(index.begin(),
|
||||
std::back_inserter(header),
|
||||
Integer(index.end() - index.begin()));
|
||||
|
||||
link_components(index.begin(), header.begin(),
|
||||
Integer(index.end() - index.begin()),
|
||||
Integer(header.end() - header.begin()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class IndexIterator, class Integer, class Distance>
|
||||
class component_iterator
|
||||
: boost::forward_iterator_helper<
|
||||
component_iterator<IndexIterator,Integer,Distance>,
|
||||
Integer, Distance,Integer*, Integer&>
|
||||
{
|
||||
public:
|
||||
typedef component_iterator self;
|
||||
|
||||
IndexIterator next;
|
||||
Integer node;
|
||||
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Integer value_type;
|
||||
typedef Integer& reference;
|
||||
typedef Integer* pointer;
|
||||
typedef Distance difference_type;
|
||||
|
||||
component_iterator() {}
|
||||
component_iterator(IndexIterator x, Integer i)
|
||||
: next(x), node(i) {}
|
||||
Integer operator*() const {
|
||||
return node;
|
||||
}
|
||||
self& operator++() {
|
||||
node = next[node];
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class IndexIterator, class Integer, class Distance>
|
||||
inline bool
|
||||
operator==(const component_iterator<IndexIterator, Integer, Distance>& x,
|
||||
const component_iterator<IndexIterator, Integer, Distance>& y)
|
||||
{
|
||||
return x.node == y.node;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#endif // BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP
|
||||
180
libraries/include/boost/graph/detail/indexed_properties.hpp
Normal file
180
libraries/include/boost/graph/detail/indexed_properties.hpp
Normal file
@@ -0,0 +1,180 @@
|
||||
// Copyright 2005 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
|
||||
|
||||
// Indexed properties -- used for CSR and CSR-like graphs
|
||||
|
||||
#ifndef BOOST_GRAPH_INDEXED_PROPERTIES_HPP
|
||||
#define BOOST_GRAPH_INDEXED_PROPERTIES_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <iterator>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/iterator/counting_iterator.hpp>
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template<typename Derived, typename Property, typename Descriptor>
|
||||
class indexed_vertex_properties
|
||||
{
|
||||
public:
|
||||
typedef no_property vertex_property_type;
|
||||
typedef Property vertex_bundled;
|
||||
|
||||
// Directly access a vertex or edge bundle
|
||||
Property& operator[](Descriptor v)
|
||||
{ return m_vertex_properties[get(vertex_index, derived(), v)]; }
|
||||
|
||||
const Property& operator[](Descriptor v) const
|
||||
{ return m_vertex_properties[get(vertex_index, derived(), v)]; }
|
||||
|
||||
protected:
|
||||
// Default-construct with no property values
|
||||
indexed_vertex_properties() {}
|
||||
|
||||
// Initialize with n default-constructed property values
|
||||
indexed_vertex_properties(std::size_t n) : m_vertex_properties(n) { }
|
||||
|
||||
public:
|
||||
// Resize the properties vector
|
||||
void resize(std::size_t n)
|
||||
{
|
||||
m_vertex_properties.resize(n);
|
||||
}
|
||||
|
||||
// Reserve space in the vector of properties
|
||||
void reserve(std::size_t n)
|
||||
{
|
||||
m_vertex_properties.reserve(n);
|
||||
}
|
||||
|
||||
// Add a new property value to the back
|
||||
void push_back(const Property& prop)
|
||||
{
|
||||
m_vertex_properties.push_back(prop);
|
||||
}
|
||||
|
||||
// Access to the derived object
|
||||
Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
|
||||
const Derived& derived() const
|
||||
{ return *static_cast<const Derived*>(this); }
|
||||
|
||||
public: // should be private, but friend templates not portable
|
||||
std::vector<Property> m_vertex_properties;
|
||||
};
|
||||
|
||||
template<typename Derived, typename Descriptor>
|
||||
class indexed_vertex_properties<Derived, void, Descriptor>
|
||||
{
|
||||
struct secret {};
|
||||
|
||||
public:
|
||||
typedef no_property vertex_property_type;
|
||||
typedef void vertex_bundled;
|
||||
|
||||
secret operator[](secret) { return secret(); }
|
||||
|
||||
protected:
|
||||
// All operations do nothing.
|
||||
indexed_vertex_properties() { }
|
||||
indexed_vertex_properties(std::size_t) { }
|
||||
|
||||
public:
|
||||
void resize(std::size_t) { }
|
||||
void reserve(std::size_t) { }
|
||||
};
|
||||
|
||||
template<typename Derived, typename Property, typename Descriptor>
|
||||
class indexed_edge_properties
|
||||
{
|
||||
public:
|
||||
typedef no_property edge_property_type;
|
||||
typedef Property edge_bundled;
|
||||
typedef Property edge_push_back_type;
|
||||
|
||||
// Directly access a edge or edge bundle
|
||||
Property& operator[](Descriptor v)
|
||||
{ return m_edge_properties[get(edge_index, derived(), v)]; }
|
||||
|
||||
const Property& operator[](Descriptor v) const
|
||||
{ return m_edge_properties[get(edge_index, derived(), v)]; }
|
||||
|
||||
protected:
|
||||
// Default-construct with no property values
|
||||
indexed_edge_properties() {}
|
||||
|
||||
// Initialize with n default-constructed property values
|
||||
indexed_edge_properties(std::size_t n) : m_edge_properties(n) { }
|
||||
|
||||
// Resize the properties vector
|
||||
void resize(std::size_t n)
|
||||
{
|
||||
m_edge_properties.resize(n);
|
||||
}
|
||||
|
||||
// Reserve space in the vector of properties
|
||||
void reserve(std::size_t n)
|
||||
{
|
||||
m_edge_properties.reserve(n);
|
||||
}
|
||||
|
||||
public:
|
||||
// Add a new property value to the back
|
||||
void push_back(const Property& prop)
|
||||
{
|
||||
m_edge_properties.push_back(prop);
|
||||
}
|
||||
|
||||
private:
|
||||
// Access to the derived object
|
||||
Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
|
||||
const Derived& derived() const
|
||||
{ return *static_cast<const Derived*>(this); }
|
||||
|
||||
public: // should be private, but friend templates not portable
|
||||
std::vector<Property> m_edge_properties;
|
||||
};
|
||||
|
||||
template<typename Derived, typename Descriptor>
|
||||
class indexed_edge_properties<Derived, void, Descriptor>
|
||||
{
|
||||
struct secret {};
|
||||
|
||||
public:
|
||||
typedef no_property edge_property_type;
|
||||
typedef void edge_bundled;
|
||||
typedef void* edge_push_back_type;
|
||||
|
||||
secret operator[](secret) { return secret(); }
|
||||
|
||||
protected:
|
||||
// All operations do nothing.
|
||||
indexed_edge_properties() { }
|
||||
indexed_edge_properties(std::size_t) { }
|
||||
void resize(std::size_t) { }
|
||||
void reserve(std::size_t) { }
|
||||
|
||||
public:
|
||||
void push_back(const edge_push_back_type&) { }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_GRAPH_INDEXED_PROPERTIES_HPP
|
||||
40
libraries/include/boost/graph/detail/is_same.hpp
Normal file
40
libraries/include/boost/graph/detail/is_same.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//=======================================================================
|
||||
// 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_IS_SAME_HPP
|
||||
#define BOOST_GRAPH_DETAIL_IS_SAME_HPP
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
struct false_tag;
|
||||
struct true_tag;
|
||||
|
||||
namespace graph_detail {
|
||||
|
||||
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class U, class V>
|
||||
struct is_same {
|
||||
typedef boost::false_tag is_same_tag;
|
||||
};
|
||||
template <class U>
|
||||
struct is_same<U, U> {
|
||||
typedef boost::true_tag is_same_tag;
|
||||
};
|
||||
#else
|
||||
template <class U, class V>
|
||||
struct is_same {
|
||||
enum { Unum = U::num, Vnum = V::num };
|
||||
typedef typename mpl::if_c< (Unum == Vnum),
|
||||
boost::true_tag, boost::false_tag>::type is_same_tag;
|
||||
};
|
||||
#endif
|
||||
} // namespace graph_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
220
libraries/include/boost/graph/detail/list_base.hpp
Normal file
220
libraries/include/boost/graph/detail/list_base.hpp
Normal file
@@ -0,0 +1,220 @@
|
||||
//=======================================================================
|
||||
// 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_LIST_BASE_HPP
|
||||
#define BOOST_LIST_BASE_HPP
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
// Perhaps this should go through formal review, and move to <boost/>.
|
||||
|
||||
/*
|
||||
An alternate interface idea:
|
||||
Extend the std::list functionality by creating remove/insert
|
||||
functions that do not require the container object!
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
//=========================================================================
|
||||
// Linked-List Generic Implementation Functions
|
||||
|
||||
template <class Node, class Next>
|
||||
inline Node
|
||||
slist_insert_after(Node pos, Node x,
|
||||
Next next)
|
||||
{
|
||||
next(x) = next(pos);
|
||||
next(pos) = x;
|
||||
return x;
|
||||
}
|
||||
|
||||
// return next(pos) or next(next(pos)) ?
|
||||
template <class Node, class Next>
|
||||
inline Node
|
||||
slist_remove_after(Node pos,
|
||||
Next next)
|
||||
{
|
||||
Node n = next(pos);
|
||||
next(pos) = next(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
template <class Node, class Next>
|
||||
inline Node
|
||||
slist_remove_range(Node before_first, Node last,
|
||||
Next next)
|
||||
{
|
||||
next(before_first) = last;
|
||||
return last;
|
||||
}
|
||||
|
||||
template <class Node, class Next>
|
||||
inline Node
|
||||
slist_previous(Node head, Node x, Node nil,
|
||||
Next next)
|
||||
{
|
||||
while (head != nil && next(head) != x)
|
||||
head = next(head);
|
||||
return head;
|
||||
}
|
||||
|
||||
template<class Node, class Next>
|
||||
inline void
|
||||
slist_splice_after(Node pos, Node before_first, Node before_last,
|
||||
Next next)
|
||||
{
|
||||
if (pos != before_first && pos != before_last) {
|
||||
Node first = next(before_first);
|
||||
Node after = next(pos);
|
||||
next(before_first) = next(before_last);
|
||||
next(pos) = first;
|
||||
next(before_last) = after;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Node, class Next>
|
||||
inline Node
|
||||
slist_reverse(Node node, Node nil,
|
||||
Next next)
|
||||
{
|
||||
Node result = node;
|
||||
node = next(node);
|
||||
next(result) = nil;
|
||||
while(node) {
|
||||
Node next = next(node);
|
||||
next(node) = result;
|
||||
result = node;
|
||||
node = next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Node, class Next>
|
||||
inline std::size_t
|
||||
slist_size(Node head, Node nil,
|
||||
Next next)
|
||||
{
|
||||
std::size_t s = 0;
|
||||
for ( ; head != nil; head = next(head))
|
||||
++s;
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class Next, class Data>
|
||||
class slist_iterator_policies
|
||||
{
|
||||
public:
|
||||
explicit slist_iterator_policies(const Next& n, const Data& d)
|
||||
: m_next(n), m_data(d) { }
|
||||
|
||||
template <class Reference, class Node>
|
||||
Reference dereference(type<Reference>, const Node& x) const
|
||||
{ return m_data(x); }
|
||||
|
||||
template <class Node>
|
||||
void increment(Node& x) const
|
||||
{ x = m_next(x); }
|
||||
|
||||
template <class Node>
|
||||
bool equal(Node& x, Node& y) const
|
||||
{ return x == y; }
|
||||
|
||||
protected:
|
||||
Next m_next;
|
||||
Data m_data;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// Doubly-Linked List Generic Implementation Functions
|
||||
|
||||
template <class Node, class Next, class Prev>
|
||||
inline void
|
||||
dlist_insert_before(Node pos, Node x,
|
||||
Next next, Prev prev)
|
||||
{
|
||||
next(x) = pos;
|
||||
prev(x) = prev(pos);
|
||||
next(prev(pos)) = x;
|
||||
prev(pos) = x;
|
||||
}
|
||||
|
||||
template <class Node, class Next, class Prev>
|
||||
void
|
||||
dlist_remove(Node pos,
|
||||
Next next, Prev prev)
|
||||
{
|
||||
Node next_node = next(pos);
|
||||
Node prev_node = prev(pos);
|
||||
next(prev_node) = next_node;
|
||||
prev(next_node) = prev_node;
|
||||
}
|
||||
|
||||
// This deletes every node in the list except the
|
||||
// sentinel node.
|
||||
template <class Node, class Delete>
|
||||
inline void
|
||||
dlist_clear(Node sentinel, Delete del)
|
||||
{
|
||||
Node i, tmp;
|
||||
i = next(sentinel);
|
||||
while (i != sentinel) {
|
||||
tmp = i;
|
||||
i = next(i);
|
||||
del(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Node>
|
||||
inline bool
|
||||
dlist_empty(Node dummy)
|
||||
{
|
||||
return next(dummy) == dummy;
|
||||
}
|
||||
|
||||
template <class Node, class Next, class Prev>
|
||||
void
|
||||
dlist_transfer(Node pos, Node first, Node last,
|
||||
Next next, Prev prev)
|
||||
{
|
||||
if (pos != last) {
|
||||
// Remove [first,last) from its old position
|
||||
next(prev(last)) = pos;
|
||||
next(prev(first)) = last;
|
||||
next(prev(pos)) = first;
|
||||
|
||||
// Splice [first,last) into its new position
|
||||
Node tmp = prev(pos);
|
||||
prev(pos) = prev(last);
|
||||
prev(last) = prev(first);
|
||||
prev(first) = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Next, class Prev, class Data>
|
||||
class dlist_iterator_policies
|
||||
: public slist_iterator_policies<Next, Data>
|
||||
{
|
||||
typedef slist_iterator_policies<Next, Data> Base;
|
||||
public:
|
||||
template <class Node>
|
||||
void decrement(Node& x) const
|
||||
{ x = m_prev(x); }
|
||||
|
||||
dlist_iterator_policies(Next n, Prev p, Data d)
|
||||
: Base(n,d), m_prev(p) { }
|
||||
protected:
|
||||
Prev m_prev;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_LIST_BASE_HPP
|
||||
205
libraries/include/boost/graph/detail/permutation.hpp
Normal file
205
libraries/include/boost/graph/detail/permutation.hpp
Normal file
@@ -0,0 +1,205 @@
|
||||
// (C) Copyright Jeremy Siek 2001.
|
||||
// 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_PERMUTATION_HPP
|
||||
#define BOOST_PERMUTATION_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <boost/graph/detail/shadow_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Iter1, class Iter2>
|
||||
void permute_serial(Iter1 permuter, Iter1 last, Iter2 result)
|
||||
{
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
typedef std::ptrdiff_t D:
|
||||
#else
|
||||
typedef typename std::iterator_traits<Iter1>::difference_type D;
|
||||
#endif
|
||||
|
||||
D n = 0;
|
||||
while (permuter != last) {
|
||||
std::swap(result[n], result[*permuter]);
|
||||
++n;
|
||||
++permuter;
|
||||
}
|
||||
}
|
||||
|
||||
template <class InIter, class RandIterP, class RandIterR>
|
||||
void permute_copy(InIter first, InIter last, RandIterP p, RandIterR result)
|
||||
{
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
typedef std::ptrdiff_t i = 0;
|
||||
#else
|
||||
typename std::iterator_traits<RandIterP>::difference_type i = 0;
|
||||
#endif
|
||||
for (; first != last; ++first, ++i)
|
||||
result[p[i]] = *first;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class RandIter, class RandIterPerm, class D, class T>
|
||||
void permute_helper(RandIter first, RandIter last, RandIterPerm p, D, T)
|
||||
{
|
||||
D i = 0, pi, n = last - first, cycle_start;
|
||||
T tmp;
|
||||
std::vector<int> visited(n, false);
|
||||
|
||||
while (i != n) { // continue until all elements have been processed
|
||||
cycle_start = i;
|
||||
tmp = first[i];
|
||||
do { // walk around a cycle
|
||||
pi = p[i];
|
||||
visited[pi] = true;
|
||||
std::swap(tmp, first[pi]);
|
||||
i = pi;
|
||||
} while (i != cycle_start);
|
||||
|
||||
// find the next cycle
|
||||
for (i = 0; i < n; ++i)
|
||||
if (visited[i] == false)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class RandIter, class RandIterPerm>
|
||||
void permute(RandIter first, RandIter last, RandIterPerm p)
|
||||
{
|
||||
detail::permute_helper(first, last, p, last - first, *first);
|
||||
}
|
||||
|
||||
|
||||
// Knuth 1.3.3, Vol. 1 p 176
|
||||
// modified for zero-based arrays
|
||||
// time complexity?
|
||||
//
|
||||
// WARNING: T must be a signed integer!
|
||||
template <class PermIter>
|
||||
void invert_permutation(PermIter X, PermIter Xend)
|
||||
{
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
typedef std::ptrdiff_t T:
|
||||
#else
|
||||
typedef typename std::iterator_traits<PermIter>::value_type T;
|
||||
#endif
|
||||
T n = Xend - X;
|
||||
T m = n;
|
||||
T j = -1;
|
||||
|
||||
while (m > 0) {
|
||||
T i = X[m-1] + 1;
|
||||
if (i > 0) {
|
||||
do {
|
||||
X[m-1] = j - 1;
|
||||
j = -m;
|
||||
m = i;
|
||||
i = X[m-1] + 1;
|
||||
} while (i > 0);
|
||||
i = j;
|
||||
}
|
||||
X[m-1] = -i - 1;
|
||||
--m;
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a "normal" permutation array (and its inverse), and turns it
|
||||
// into a BLAS-style permutation array (which can be thought of as a
|
||||
// serialized permutation).
|
||||
template <class Iter1, class Iter2, class Iter3>
|
||||
inline void serialize_permutation(Iter1 q, Iter1 q_end, Iter2 q_inv, Iter3 p)
|
||||
{
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
typedef std::ptrdiff_t P1;
|
||||
typedef std::ptrdiff_t P2;
|
||||
typedef std::ptrdiff_t D;
|
||||
#else
|
||||
typedef typename std::iterator_traits<Iter1>::value_type P1;
|
||||
typedef typename std::iterator_traits<Iter2>::value_type P2;
|
||||
typedef typename std::iterator_traits<Iter1>::difference_type D;
|
||||
#endif
|
||||
D n = q_end - q;
|
||||
for (D i = 0; i < n; ++i) {
|
||||
P1 qi = q[i];
|
||||
P2 qii = q_inv[i];
|
||||
*p++ = qii;
|
||||
std::swap(q[i], q[qii]);
|
||||
std::swap(q_inv[i], q_inv[qi]);
|
||||
}
|
||||
}
|
||||
|
||||
// Not used anymore, leaving it here for future reference.
|
||||
template <typename Iter, typename Compare>
|
||||
void merge_sort(Iter first, Iter last, Compare cmp)
|
||||
{
|
||||
if (first + 1 < last) {
|
||||
Iter mid = first + (last - first)/2;
|
||||
merge_sort(first, mid, cmp);
|
||||
merge_sort(mid, last, cmp);
|
||||
std::inplace_merge(first, mid, last, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// time: N log N + 3N + ?
|
||||
// space: 2N
|
||||
template <class Iter, class IterP, class Cmp, class Alloc>
|
||||
inline void sortp(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc)
|
||||
{
|
||||
typedef typename std::iterator_traits<IterP>::value_type P;
|
||||
typedef typename std::iterator_traits<IterP>::difference_type D;
|
||||
D n = last - first;
|
||||
std::vector<P, Alloc> q(n);
|
||||
for (D i = 0; i < n; ++i)
|
||||
q[i] = i;
|
||||
std::sort(make_shadow_iter(first, q.begin()),
|
||||
make_shadow_iter(last, q.end()),
|
||||
shadow_cmp<Cmp>(cmp));
|
||||
invert_permutation(q.begin(), q.end());
|
||||
std::copy(q.begin(), q.end(), p);
|
||||
}
|
||||
|
||||
template <class Iter, class IterP, class Cmp>
|
||||
inline void sortp(Iter first, Iter last, IterP p, Cmp cmp)
|
||||
{
|
||||
typedef typename std::iterator_traits<IterP>::value_type P;
|
||||
sortp(first, last, p, cmp, std::allocator<P>());
|
||||
}
|
||||
|
||||
template <class Iter, class IterP>
|
||||
inline void sortp(Iter first, Iter last, IterP p)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iter>::value_type T;
|
||||
typedef typename std::iterator_traits<IterP>::value_type P;
|
||||
sortp(first, last, p, std::less<T>(), std::allocator<P>());
|
||||
}
|
||||
|
||||
template <class Iter, class IterP, class Cmp, class Alloc>
|
||||
inline void sortv(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc)
|
||||
{
|
||||
typedef typename std::iterator_traits<IterP>::value_type P;
|
||||
typedef typename std::iterator_traits<IterP>::difference_type D;
|
||||
D n = last - first;
|
||||
std::vector<P, Alloc> q(n), q_inv(n);
|
||||
for (D i = 0; i < n; ++i)
|
||||
q_inv[i] = i;
|
||||
std::sort(make_shadow_iter(first, q_inv.begin()),
|
||||
make_shadow_iter(last, q_inv.end()),
|
||||
shadow_cmp<Cmp>(cmp));
|
||||
std::copy(q_inv, q_inv.end(), q.begin());
|
||||
invert_permutation(q.begin(), q.end());
|
||||
serialize_permutation(q.begin(), q.end(), q_inv.end(), p);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_PERMUTATION_HPP
|
||||
612
libraries/include/boost/graph/detail/read_graphviz_spirit.hpp
Normal file
612
libraries/include/boost/graph/detail/read_graphviz_spirit.hpp
Normal file
@@ -0,0 +1,612 @@
|
||||
// Copyright 2004-9 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)
|
||||
|
||||
//
|
||||
// read_graphviz_spirit.hpp -
|
||||
// Initialize a model of the BGL's MutableGraph concept and an associated
|
||||
// collection of property maps using a graph expressed in the GraphViz
|
||||
// DOT Language.
|
||||
//
|
||||
// Based on the grammar found at:
|
||||
// http://www.graphviz.org/cvs/doc/info/lang.html
|
||||
//
|
||||
// See documentation for this code at:
|
||||
// http://www.boost.org/libs/graph/doc/read-graphviz.html
|
||||
//
|
||||
|
||||
// Author: Ronald Garcia
|
||||
//
|
||||
|
||||
#ifndef BOOST_READ_GRAPHVIZ_SPIRIT_HPP
|
||||
#define BOOST_READ_GRAPHVIZ_SPIRIT_HPP
|
||||
|
||||
// Phoenix/Spirit set these limits to 3, but I need more.
|
||||
#define PHOENIX_LIMIT 6
|
||||
#define BOOST_SPIRIT_CLOSURE_LIMIT 6
|
||||
|
||||
|
||||
#include <boost/spirit/include/classic_multi_pass.hpp>
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_confix.hpp>
|
||||
#include <boost/spirit/include/classic_distinct.hpp>
|
||||
#include <boost/spirit/include/classic_lists.hpp>
|
||||
#include <boost/spirit/include/classic_escape_char.hpp>
|
||||
#include <boost/spirit/include/classic_attribute.hpp>
|
||||
#include <boost/spirit/include/classic_dynamic.hpp>
|
||||
#include <boost/spirit/include/classic_actor.hpp>
|
||||
#include <boost/spirit/include/classic_closure.hpp>
|
||||
#include <boost/spirit/include/phoenix1.hpp>
|
||||
#include <boost/spirit/include/phoenix1_binders.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/function/function2.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/dynamic_property_map.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <algorithm>
|
||||
#include <exception> // for std::exception
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <boost/graph/graphviz.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
namespace phoenix {
|
||||
// Workaround: std::map::operator[] uses a different return type than all
|
||||
// other standard containers. Phoenix doesn't account for that.
|
||||
template <typename TK, typename T0, typename T1>
|
||||
struct binary_operator<index_op, std::map<TK,T0>, T1>
|
||||
{
|
||||
typedef typename std::map<TK,T0>::mapped_type& result_type;
|
||||
static result_type eval(std::map<TK,T0>& container, T1 const& index)
|
||||
{ return container[index]; }
|
||||
};
|
||||
} // namespace phoenix
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
namespace graph {
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Application-specific type definitions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::set<edge_t> edges_t;
|
||||
typedef std::set<node_t> nodes_t;
|
||||
typedef std::set<id_t> ids_t;
|
||||
typedef std::map<edge_t,ids_t> edge_map_t;
|
||||
typedef std::map<node_t,ids_t> node_map_t;
|
||||
typedef std::map<id_t,id_t> props_t;
|
||||
typedef std::map<id_t,props_t> subgraph_props_t;
|
||||
typedef boost::function2<void, id_t const&, id_t const&> actor_t;
|
||||
typedef std::vector<edge_t> edge_stack_t;
|
||||
typedef std::map<id_t,nodes_t> subgraph_nodes_t;
|
||||
typedef std::map<id_t,edges_t> subgraph_edges_t;
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Stack frames used by semantic actions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
struct id_closure : boost::spirit::classic::closure<id_closure, node_t> {
|
||||
member1 name;
|
||||
};
|
||||
|
||||
|
||||
struct node_id_closure : boost::spirit::classic::closure<node_id_closure, node_t> {
|
||||
member1 name;
|
||||
};
|
||||
|
||||
struct attr_list_closure : boost::spirit::classic::closure<attr_list_closure, actor_t> {
|
||||
member1 prop_actor;
|
||||
};
|
||||
|
||||
struct property_closure : boost::spirit::classic::closure<property_closure, id_t, id_t> {
|
||||
member1 key;
|
||||
member2 value;
|
||||
};
|
||||
|
||||
struct data_stmt_closure : boost::spirit::classic::closure<data_stmt_closure,
|
||||
nodes_t,nodes_t,edge_stack_t,bool,node_t> {
|
||||
member1 sources;
|
||||
member2 dests;
|
||||
member3 edge_stack;
|
||||
member4 saw_node;
|
||||
member5 active_node;
|
||||
};
|
||||
|
||||
struct subgraph_closure : boost::spirit::classic::closure<subgraph_closure,
|
||||
nodes_t, edges_t, node_t> {
|
||||
member1 nodes;
|
||||
member2 edges;
|
||||
member3 name;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Grammar and Actions for the DOT Language
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Grammar for a dot file.
|
||||
struct dot_grammar : public boost::spirit::classic::grammar<dot_grammar> {
|
||||
mutate_graph& graph_;
|
||||
explicit dot_grammar(mutate_graph& graph) : graph_(graph) { }
|
||||
|
||||
template <class ScannerT>
|
||||
struct definition {
|
||||
|
||||
definition(dot_grammar const& self) : self(self), subgraph_depth(0),
|
||||
keyword_p("0-9a-zA-Z_") {
|
||||
using namespace boost::spirit::classic;
|
||||
using namespace phoenix;
|
||||
|
||||
// RG - Future Work
|
||||
// - Handle multi-line strings using \ line continuation
|
||||
// - Make keywords case insensitive
|
||||
ID
|
||||
= ( lexeme_d[((alpha_p | ch_p('_')) >> *(alnum_p | ch_p('_')))]
|
||||
| real_p
|
||||
| lexeme_d[confix_p('"', *c_escape_ch_p, '"')]
|
||||
| comment_nest_p('<', '>')
|
||||
)[ID.name = construct_<std::string>(arg1,arg2)]
|
||||
;
|
||||
|
||||
a_list
|
||||
= list_p( ID[(a_list.key = arg1),
|
||||
(a_list.value = "true")
|
||||
]
|
||||
>> !( ch_p('=')
|
||||
>> ID[a_list.value = arg1])
|
||||
[phoenix::bind(&definition::call_prop_actor)
|
||||
(var(*this),a_list.key,a_list.value)],!ch_p(','));
|
||||
|
||||
attr_list = +(ch_p('[') >> !a_list >> ch_p(']'));
|
||||
|
||||
// RG - disregard port id's for now.
|
||||
port_location
|
||||
= (ch_p(':') >> ID)
|
||||
| (ch_p(':') >> ch_p('(') >> ID >> ch_p(',') >> ID >> ch_p(')'))
|
||||
;
|
||||
|
||||
port_angle = ch_p('@') >> ID;
|
||||
|
||||
port
|
||||
= port_location >> (!port_angle)
|
||||
| port_angle >> (!port_location);
|
||||
|
||||
|
||||
node_id
|
||||
= ( ID[node_id.name = arg1] >> (!port) )
|
||||
[phoenix::bind(&definition::memoize_node)(var(*this))];
|
||||
|
||||
graph_stmt
|
||||
= (ID[graph_stmt.key = arg1] >>
|
||||
ch_p('=') >>
|
||||
ID[graph_stmt.value = arg1])
|
||||
[phoenix::bind(&definition::call_graph_prop)
|
||||
(var(*this),graph_stmt.key,graph_stmt.value)]
|
||||
; // Graph property.
|
||||
|
||||
attr_stmt
|
||||
= (as_lower_d[keyword_p("graph")]
|
||||
>> attr_list(actor_t(phoenix::bind(&definition::default_graph_prop)
|
||||
(var(*this),arg1,arg2))))
|
||||
| (as_lower_d[keyword_p("node")]
|
||||
>> attr_list(actor_t(phoenix::bind(&definition::default_node_prop)
|
||||
(var(*this),arg1,arg2))))
|
||||
| (as_lower_d[keyword_p("edge")]
|
||||
>> attr_list(actor_t(phoenix::bind(&definition::default_edge_prop)
|
||||
(var(*this),arg1,arg2))))
|
||||
;
|
||||
|
||||
// edge_head is set depending on the graph type (directed/undirected)
|
||||
edgeop = ch_p('-') >> ch_p(boost::ref(edge_head));
|
||||
|
||||
edgeRHS
|
||||
= +( edgeop[(data_stmt.sources = data_stmt.dests),
|
||||
(data_stmt.dests = construct_<nodes_t>())]
|
||||
>> ( subgraph[data_stmt.dests = arg1]
|
||||
| node_id[phoenix::bind(&definition::insert_node)
|
||||
(var(*this),data_stmt.dests,arg1)]
|
||||
)
|
||||
[phoenix::bind(&definition::activate_edge)
|
||||
(var(*this),data_stmt.sources,data_stmt.dests,
|
||||
var(edges), var(default_edge_props))]
|
||||
);
|
||||
|
||||
|
||||
// To avoid backtracking, edge, node, and subgraph statements are
|
||||
// processed as one nonterminal.
|
||||
data_stmt
|
||||
= ( subgraph[(data_stmt.dests = arg1),// will get moved in rhs
|
||||
(data_stmt.saw_node = false)]
|
||||
| node_id[(phoenix::bind(&definition::insert_node)
|
||||
(var(*this),data_stmt.dests,arg1)),
|
||||
(data_stmt.saw_node = true),
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
(std::cout << val("AcTive Node: ") << arg1 << "\n"),
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
(data_stmt.active_node = arg1)]
|
||||
) >> if_p(edgeRHS)[
|
||||
!attr_list(
|
||||
actor_t(phoenix::bind(&definition::edge_prop)
|
||||
(var(*this),arg1,arg2)))
|
||||
].else_p[
|
||||
if_p(data_stmt.saw_node)[
|
||||
!attr_list(
|
||||
actor_t(phoenix::bind(&definition::node_prop)
|
||||
(var(*this),arg1,arg2)))
|
||||
] // otherwise it's a subgraph, nothing more to do.
|
||||
];
|
||||
|
||||
|
||||
stmt
|
||||
= graph_stmt
|
||||
| attr_stmt
|
||||
| data_stmt
|
||||
;
|
||||
|
||||
stmt_list = *( stmt >> !ch_p(';') );
|
||||
|
||||
subgraph
|
||||
= !( as_lower_d[keyword_p("subgraph")]
|
||||
>> (!ID[(subgraph.name = arg1),
|
||||
(subgraph.nodes = (var(subgraph_nodes))[arg1]),
|
||||
(subgraph.edges = (var(subgraph_edges))[arg1])])
|
||||
)
|
||||
>> ch_p('{')[++var(subgraph_depth)]
|
||||
>> stmt_list
|
||||
>> ch_p('}')[--var(subgraph_depth)]
|
||||
[(var(subgraph_nodes))[subgraph.name] = subgraph.nodes]
|
||||
[(var(subgraph_edges))[subgraph.name] = subgraph.edges]
|
||||
|
||||
| as_lower_d[keyword_p("subgraph")]
|
||||
>> ID[(subgraph.nodes = (var(subgraph_nodes))[arg1]),
|
||||
(subgraph.edges = (var(subgraph_edges))[arg1])]
|
||||
;
|
||||
|
||||
the_grammar
|
||||
= (!as_lower_d[keyword_p("strict")])
|
||||
>> ( as_lower_d[keyword_p("graph")][
|
||||
(var(edge_head) = '-'),
|
||||
(phoenix::bind(&definition::check_undirected)(var(*this)))]
|
||||
| as_lower_d[keyword_p("digraph")][
|
||||
(var(edge_head) = '>'),
|
||||
(phoenix::bind(&definition::check_directed)(var(*this)))]
|
||||
)
|
||||
>> (!ID) >> ch_p('{') >> stmt_list >> ch_p('}');
|
||||
|
||||
} // definition()
|
||||
|
||||
typedef boost::spirit::classic::rule<ScannerT> rule_t;
|
||||
|
||||
rule_t const& start() const { return the_grammar; }
|
||||
|
||||
|
||||
//
|
||||
// Semantic actions
|
||||
//
|
||||
|
||||
void check_undirected() {
|
||||
if(self.graph_.is_directed())
|
||||
boost::throw_exception(boost::undirected_graph_error());
|
||||
}
|
||||
|
||||
void check_directed() {
|
||||
if(!self.graph_.is_directed())
|
||||
boost::throw_exception(boost::directed_graph_error());
|
||||
}
|
||||
|
||||
void memoize_node() {
|
||||
id_t const& node = node_id.name();
|
||||
props_t& node_props = default_node_props;
|
||||
|
||||
if(nodes.find(node) == nodes.end()) {
|
||||
nodes.insert(node);
|
||||
self.graph_.do_add_vertex(node);
|
||||
|
||||
node_map.insert(std::make_pair(node,ids_t()));
|
||||
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
std::cout << "Add new node " << node << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
// Set the default properties for this edge
|
||||
// RG: Here I would actually set the properties
|
||||
for(props_t::iterator i = node_props.begin();
|
||||
i != node_props.end(); ++i) {
|
||||
set_node_property(node,i->first,i->second);
|
||||
}
|
||||
if(subgraph_depth > 0) {
|
||||
subgraph.nodes().insert(node);
|
||||
// Set the subgraph's default properties as well
|
||||
props_t& props = subgraph_node_props[subgraph.name()];
|
||||
for(props_t::iterator i = props.begin(); i != props.end(); ++i) {
|
||||
set_node_property(node,i->first,i->second);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
std::cout << "See node " << node << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
void activate_edge(nodes_t& sources, nodes_t& dests, edges_t& edges,
|
||||
props_t& edge_props) {
|
||||
edge_stack_t& edge_stack = data_stmt.edge_stack();
|
||||
for(nodes_t::iterator i = sources.begin(); i != sources.end(); ++i) {
|
||||
for(nodes_t::iterator j = dests.begin(); j != dests.end(); ++j) {
|
||||
// Create the edge and push onto the edge stack.
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
std::cout << "Edge " << *i << " to " << *j << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
|
||||
edge_t edge = edge_t::new_edge();
|
||||
edge_stack.push_back(edge);
|
||||
edges.insert(edge);
|
||||
edge_map.insert(std::make_pair(edge,ids_t()));
|
||||
|
||||
// Add the real edge.
|
||||
self.graph_.do_add_edge(edge, *i, *j);
|
||||
|
||||
// Set the default properties for this edge
|
||||
for(props_t::iterator k = edge_props.begin();
|
||||
k != edge_props.end(); ++k) {
|
||||
set_edge_property(edge,k->first,k->second);
|
||||
}
|
||||
if(subgraph_depth > 0) {
|
||||
subgraph.edges().insert(edge);
|
||||
// Set the subgraph's default properties as well
|
||||
props_t& props = subgraph_edge_props[subgraph.name()];
|
||||
for(props_t::iterator k = props.begin(); k != props.end(); ++k) {
|
||||
set_edge_property(edge,k->first,k->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// node_prop - Assign the property for the current active node.
|
||||
void node_prop(id_t const& key, id_t const& value) {
|
||||
node_t& active_object = data_stmt.active_node();
|
||||
set_node_property(active_object, key, value);
|
||||
}
|
||||
|
||||
// edge_prop - Assign the property for the current active edges.
|
||||
void edge_prop(id_t const& key, id_t const& value) {
|
||||
edge_stack_t const& active_edges_ = data_stmt.edge_stack();
|
||||
for (edge_stack_t::const_iterator i = active_edges_.begin();
|
||||
i != active_edges_.end(); ++i) {
|
||||
set_edge_property(*i,key,value);
|
||||
}
|
||||
}
|
||||
|
||||
// default_graph_prop - Store as a graph property.
|
||||
void default_graph_prop(id_t const& key, id_t const& value) {
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
std::cout << key << " = " << value << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
self.graph_.set_graph_property(key, value);
|
||||
}
|
||||
|
||||
// default_node_prop - declare default properties for any future new nodes
|
||||
void default_node_prop(id_t const& key, id_t const& value) {
|
||||
nodes_t& nodes_ =
|
||||
subgraph_depth == 0 ? nodes : subgraph.nodes();
|
||||
props_t& node_props_ =
|
||||
subgraph_depth == 0 ?
|
||||
default_node_props :
|
||||
subgraph_node_props[subgraph.name()];
|
||||
|
||||
// add this to the selected list of default node properties.
|
||||
node_props_[key] = value;
|
||||
// for each node, set its property to default-constructed value
|
||||
// if it hasn't been set already.
|
||||
// set the dynamic property map value
|
||||
for(nodes_t::iterator i = nodes_.begin(); i != nodes_.end(); ++i)
|
||||
if(node_map[*i].find(key) == node_map[*i].end()) {
|
||||
set_node_property(*i,key,id_t());
|
||||
}
|
||||
}
|
||||
|
||||
// default_edge_prop - declare default properties for any future new edges
|
||||
void default_edge_prop(id_t const& key, id_t const& value) {
|
||||
edges_t& edges_ =
|
||||
subgraph_depth == 0 ? edges : subgraph.edges();
|
||||
props_t& edge_props_ =
|
||||
subgraph_depth == 0 ?
|
||||
default_edge_props :
|
||||
subgraph_edge_props[subgraph.name()];
|
||||
|
||||
// add this to the list of default edge properties.
|
||||
edge_props_[key] = value;
|
||||
// for each edge, set its property to be empty string
|
||||
// set the dynamic property map value
|
||||
for(edges_t::iterator i = edges_.begin(); i != edges_.end(); ++i)
|
||||
if(edge_map[*i].find(key) == edge_map[*i].end())
|
||||
set_edge_property(*i,key,id_t());
|
||||
}
|
||||
|
||||
// helper function
|
||||
void insert_node(nodes_t& nodes, id_t const& name) {
|
||||
nodes.insert(name);
|
||||
}
|
||||
|
||||
void call_prop_actor(std::string const& lhs, std::string const& rhs) {
|
||||
actor_t& actor = attr_list.prop_actor();
|
||||
// If first and last characters of the rhs are double-quotes,
|
||||
// remove them.
|
||||
if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"')
|
||||
actor(lhs, rhs.substr(1, rhs.size()-2));
|
||||
else
|
||||
actor(lhs,rhs);
|
||||
}
|
||||
|
||||
void call_graph_prop(std::string const& lhs, std::string const& rhs) {
|
||||
// If first and last characters of the rhs are double-quotes,
|
||||
// remove them.
|
||||
if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"')
|
||||
this->default_graph_prop(lhs, rhs.substr(1, rhs.size()-2));
|
||||
else
|
||||
this->default_graph_prop(lhs,rhs);
|
||||
}
|
||||
|
||||
void set_node_property(node_t const& node, id_t const& key,
|
||||
id_t const& value) {
|
||||
|
||||
// Add the property key to the "set" table to avoid default overwrite
|
||||
node_map[node].insert(key);
|
||||
// Set the user's property map
|
||||
self.graph_.set_node_property(key, node, value);
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
// Tell the world
|
||||
std::cout << node << ": " << key << " = " << value << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
}
|
||||
|
||||
void set_edge_property(edge_t const& edge, id_t const& key,
|
||||
id_t const& value) {
|
||||
|
||||
// Add the property key to the "set" table to avoid default overwrite
|
||||
edge_map[edge].insert(key);
|
||||
// Set the user's property map
|
||||
self.graph_.set_edge_property(key, edge, value);
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
// Tell the world
|
||||
#if 0 // RG - edge representation changed,
|
||||
std::cout << "(" << edge.first << "," << edge.second << "): "
|
||||
#else
|
||||
std::cout << "an edge: "
|
||||
#endif // 0
|
||||
<< key << " = " << value << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
}
|
||||
|
||||
// Variables explicitly initialized
|
||||
dot_grammar const& self;
|
||||
// if subgraph_depth > 0, then we're processing a subgraph.
|
||||
int subgraph_depth;
|
||||
|
||||
// Keywords;
|
||||
const boost::spirit::classic::distinct_parser<> keyword_p;
|
||||
//
|
||||
// rules that make up the grammar
|
||||
//
|
||||
boost::spirit::classic::rule<ScannerT,id_closure::context_t> ID;
|
||||
boost::spirit::classic::rule<ScannerT,property_closure::context_t> a_list;
|
||||
boost::spirit::classic::rule<ScannerT,attr_list_closure::context_t> attr_list;
|
||||
rule_t port_location;
|
||||
rule_t port_angle;
|
||||
rule_t port;
|
||||
boost::spirit::classic::rule<ScannerT,node_id_closure::context_t> node_id;
|
||||
boost::spirit::classic::rule<ScannerT,property_closure::context_t> graph_stmt;
|
||||
rule_t attr_stmt;
|
||||
boost::spirit::classic::rule<ScannerT,data_stmt_closure::context_t> data_stmt;
|
||||
boost::spirit::classic::rule<ScannerT,subgraph_closure::context_t> subgraph;
|
||||
rule_t edgeop;
|
||||
rule_t edgeRHS;
|
||||
rule_t stmt;
|
||||
rule_t stmt_list;
|
||||
rule_t the_grammar;
|
||||
|
||||
|
||||
// The grammar uses edge_head to dynamically set the syntax for edges
|
||||
// directed graphs: edge_head = '>', and so edgeop = "->"
|
||||
// undirected graphs: edge_head = '-', and so edgeop = "--"
|
||||
char edge_head;
|
||||
|
||||
|
||||
//
|
||||
// Support data structures
|
||||
//
|
||||
|
||||
nodes_t nodes; // list of node names seen
|
||||
edges_t edges; // list of edges seen
|
||||
node_map_t node_map; // remember the properties set for each node
|
||||
edge_map_t edge_map; // remember the properties set for each edge
|
||||
|
||||
subgraph_nodes_t subgraph_nodes; // per-subgraph lists of nodes
|
||||
subgraph_edges_t subgraph_edges; // per-subgraph lists of edges
|
||||
|
||||
props_t default_node_props; // global default node properties
|
||||
props_t default_edge_props; // global default edge properties
|
||||
subgraph_props_t subgraph_node_props; // per-subgraph default node properties
|
||||
subgraph_props_t subgraph_edge_props; // per-subgraph default edge properties
|
||||
}; // struct definition
|
||||
}; // struct dot_grammar
|
||||
|
||||
|
||||
|
||||
//
|
||||
// dot_skipper - GraphViz whitespace and comment skipper
|
||||
//
|
||||
struct dot_skipper : public boost::spirit::classic::grammar<dot_skipper>
|
||||
{
|
||||
dot_skipper() {}
|
||||
|
||||
template <typename ScannerT>
|
||||
struct definition
|
||||
{
|
||||
definition(dot_skipper const& /*self*/) {
|
||||
using namespace boost::spirit::classic;
|
||||
using namespace phoenix;
|
||||
// comment forms
|
||||
skip = eol_p >> comment_p("#")
|
||||
| space_p
|
||||
| comment_p("//")
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
|
||||
| confix_p(str_p("/*") ,*anychar_p, str_p("*/"))
|
||||
#else
|
||||
| confix_p("/*" ,*anychar_p, "*/")
|
||||
#endif
|
||||
;
|
||||
|
||||
#ifdef BOOST_SPIRIT_DEBUG
|
||||
BOOST_SPIRIT_DEBUG_RULE(skip);
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::spirit::classic::rule<ScannerT> skip;
|
||||
boost::spirit::classic::rule<ScannerT> const&
|
||||
start() const { return skip; }
|
||||
}; // definition
|
||||
}; // dot_skipper
|
||||
|
||||
} // namespace graph
|
||||
} // namespace detail
|
||||
|
||||
template <typename MultiPassIterator, typename MutableGraph>
|
||||
bool read_graphviz(MultiPassIterator begin, MultiPassIterator end,
|
||||
MutableGraph& graph, dynamic_properties& dp,
|
||||
std::string const& node_id = "node_id") {
|
||||
using namespace boost;
|
||||
using namespace boost::spirit::classic;
|
||||
|
||||
typedef MultiPassIterator iterator_t;
|
||||
typedef skip_parser_iteration_policy< boost::detail::graph::dot_skipper>
|
||||
iter_policy_t;
|
||||
typedef scanner_policies<iter_policy_t> scanner_policies_t;
|
||||
typedef scanner<iterator_t, scanner_policies_t> scanner_t;
|
||||
|
||||
::boost::detail::graph::mutate_graph_impl<MutableGraph>
|
||||
m_graph(graph, dp, node_id);
|
||||
|
||||
::boost::detail::graph::dot_grammar p(m_graph);
|
||||
::boost::detail::graph::dot_skipper skip_p;
|
||||
|
||||
iter_policy_t iter_policy(skip_p);
|
||||
scanner_policies_t policies(iter_policy);
|
||||
|
||||
scanner_t scan(begin, end, policies);
|
||||
|
||||
return p.parse(scan);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_READ_GRAPHVIZ_SPIRIT_HPP
|
||||
418
libraries/include/boost/graph/detail/self_avoiding_walk.hpp
Normal file
418
libraries/include/boost/graph/detail/self_avoiding_walk.hpp
Normal file
@@ -0,0 +1,418 @@
|
||||
//=======================================================================
|
||||
// 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_SELF_AVOIDING_WALK_HPP
|
||||
#define BOOST_SELF_AVOIDING_WALK_HPP
|
||||
|
||||
/*
|
||||
This file defines necessary components for SAW.
|
||||
|
||||
mesh language: (defined by myself to clearify what is what)
|
||||
A triangle in mesh is called an triangle.
|
||||
An edge in mesh is called an line.
|
||||
A vertex in mesh is called a point.
|
||||
|
||||
A triangular mesh corresponds to a graph in which a vertex is a
|
||||
triangle and an edge(u, v) stands for triangle u and triangle v
|
||||
share an line.
|
||||
|
||||
After this point, a vertex always refers to vertex in graph,
|
||||
therefore it is a traingle in mesh.
|
||||
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
#define SAW_SENTINAL -1
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
struct triple {
|
||||
T1 first;
|
||||
T2 second;
|
||||
T3 third;
|
||||
triple(const T1& a, const T2& b, const T3& c) : first(a), second(b), third(c) {}
|
||||
triple() : first(SAW_SENTINAL), second(SAW_SENTINAL), third(SAW_SENTINAL) {}
|
||||
};
|
||||
|
||||
typedef triple<int, int, int> Triple;
|
||||
|
||||
/* Define a vertex property which has a triangle inside. Triangle is
|
||||
represented by a triple. */
|
||||
struct triangle_tag { enum { num = 100 }; };
|
||||
typedef property<triangle_tag,Triple> triangle_property;
|
||||
|
||||
/* Define an edge property with a line. A line is represented by a
|
||||
pair. This is not required for SAW though.
|
||||
*/
|
||||
struct line_tag { enum { num = 101 }; };
|
||||
template <class T> struct line_property
|
||||
: public property<line_tag, std::pair<T,T> > { };
|
||||
|
||||
/*Precondition: Points in a Triangle are in order */
|
||||
template <class Triangle, class Line>
|
||||
inline void get_sharing(const Triangle& a, const Triangle& b, Line& l)
|
||||
{
|
||||
l.first = SAW_SENTINAL;
|
||||
l.second = SAW_SENTINAL;
|
||||
|
||||
if ( a.first == b.first ) {
|
||||
l.first = a.first;
|
||||
if ( a.second == b.second || a.second == b.third )
|
||||
l.second = a.second;
|
||||
else if ( a.third == b.second || a.third == b.third )
|
||||
l.second = a.third;
|
||||
|
||||
} else if ( a.first == b.second ) {
|
||||
l.first = a.first;
|
||||
if ( a.second == b.third )
|
||||
l.second = a.second;
|
||||
else if ( a.third == b.third )
|
||||
l.second = a.third;
|
||||
|
||||
} else if ( a.first == b.third ) {
|
||||
l.first = a.first;
|
||||
|
||||
|
||||
} else if ( a.second == b.first ) {
|
||||
l.first = a.second;
|
||||
if ( a.third == b.second || a.third == b.third )
|
||||
l.second = a.third;
|
||||
|
||||
} else if ( a.second == b.second ) {
|
||||
l.first = a.second;
|
||||
if ( a.third == b.third )
|
||||
l.second = a.third;
|
||||
|
||||
} else if ( a.second == b.third ) {
|
||||
l.first = a.second;
|
||||
|
||||
|
||||
} else if ( a.third == b.first
|
||||
|| a.third == b.second
|
||||
|| a.third == b.third )
|
||||
l.first = a.third;
|
||||
|
||||
/*Make it in order*/
|
||||
if ( l.first > l.second ) {
|
||||
typename Line::first_type i = l.first;
|
||||
l.first = l.second;
|
||||
l.second = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class TriangleDecorator, class Vertex, class Line>
|
||||
struct get_vertex_sharing {
|
||||
typedef std::pair<Vertex, Line> Pair;
|
||||
get_vertex_sharing(const TriangleDecorator& _td) : td(_td) {}
|
||||
inline Line operator()(const Vertex& u, const Vertex& v) const {
|
||||
Line l;
|
||||
get_sharing(td[u], td[v], l);
|
||||
return l;
|
||||
}
|
||||
inline Line operator()(const Pair& u, const Vertex& v) const {
|
||||
Line l;
|
||||
get_sharing(td[u.first], td[v], l);
|
||||
return l;
|
||||
}
|
||||
inline Line operator()(const Pair& u, const Pair& v) const {
|
||||
Line l;
|
||||
get_sharing(td[u.first], td[v.first], l);
|
||||
return l;
|
||||
}
|
||||
TriangleDecorator td;
|
||||
};
|
||||
|
||||
/* HList has to be a handle of data holder so that pass-by-value is
|
||||
* in right logic.
|
||||
*
|
||||
* The element of HList is a pair of vertex and line. (remember a
|
||||
* line is a pair of two ints.). That indicates the walk w from
|
||||
* current vertex is across line. (If the first of line is -1, it is
|
||||
* a point though.
|
||||
*/
|
||||
template < class TriangleDecorator, class HList, class IteratorD>
|
||||
class SAW_visitor
|
||||
: public bfs_visitor<>, public dfs_visitor<>
|
||||
{
|
||||
typedef typename boost::property_traits<IteratorD>::value_type iter;
|
||||
/*use boost shared_ptr*/
|
||||
typedef typename HList::element_type::value_type::second_type Line;
|
||||
public:
|
||||
|
||||
typedef tree_edge_tag category;
|
||||
|
||||
inline SAW_visitor(TriangleDecorator _td, HList _hlist, IteratorD ia)
|
||||
: td(_td), hlist(_hlist), iter_d(ia) {}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
inline void start_vertex(Vertex v, Graph&) {
|
||||
Line l1;
|
||||
l1.first = SAW_SENTINAL;
|
||||
l1.second = SAW_SENTINAL;
|
||||
hlist->push_front(std::make_pair(v, l1));
|
||||
iter_d[v] = hlist->begin();
|
||||
}
|
||||
|
||||
/*Several symbols:
|
||||
w(i): i-th triangle in walk w
|
||||
w(i) |- w(i+1): w enter w(i+1) from w(i) over a line
|
||||
w(i) ~> w(i+1): w enter w(i+1) from w(i) over a point
|
||||
w(i) -> w(i+1): w enter w(i+1) from w(i)
|
||||
w(i) ^ w(i+1): the line or point w go over from w(i) to w(i+1)
|
||||
*/
|
||||
template <class Edge, class Graph>
|
||||
bool tree_edge(Edge e, Graph& G) {
|
||||
using std::make_pair;
|
||||
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
Vertex tau = target(e, G);
|
||||
Vertex i = source(e, G);
|
||||
|
||||
get_vertex_sharing<TriangleDecorator, Vertex, Line> get_sharing_line(td);
|
||||
|
||||
Line tau_i = get_sharing_line(tau, i);
|
||||
|
||||
iter w_end = hlist->end();
|
||||
|
||||
iter w_i = iter_d[i];
|
||||
|
||||
iter w_i_m_1 = w_i;
|
||||
iter w_i_p_1 = w_i;
|
||||
|
||||
/*----------------------------------------------------------
|
||||
* true false
|
||||
*==========================================================
|
||||
*a w(i-1) |- w(i) w(i-1) ~> w(i) or w(i-1) is null
|
||||
*----------------------------------------------------------
|
||||
*b w(i) |- w(i+1) w(i) ~> w(i+1) or no w(i+1) yet
|
||||
*----------------------------------------------------------
|
||||
*/
|
||||
|
||||
bool a = false, b = false;
|
||||
|
||||
--w_i_m_1;
|
||||
++w_i_p_1;
|
||||
b = ( w_i->second.first != SAW_SENTINAL );
|
||||
|
||||
if ( w_i_m_1 != w_end ) {
|
||||
a = ( w_i_m_1->second.first != SAW_SENTINAL );
|
||||
}
|
||||
|
||||
if ( a ) {
|
||||
|
||||
if ( b ) {
|
||||
/*Case 1:
|
||||
|
||||
w(i-1) |- w(i) |- w(i+1)
|
||||
*/
|
||||
Line l1 = get_sharing_line(*w_i_m_1, tau);
|
||||
|
||||
iter w_i_m_2 = w_i_m_1;
|
||||
--w_i_m_2;
|
||||
|
||||
bool c = true;
|
||||
|
||||
if ( w_i_m_2 != w_end ) {
|
||||
c = w_i_m_2->second != l1;
|
||||
}
|
||||
|
||||
if ( c ) { /* w(i-1) ^ tau != w(i-2) ^ w(i-1) */
|
||||
/*extension: w(i-1) -> tau |- w(i) */
|
||||
w_i_m_1->second = l1;
|
||||
/*insert(pos, const T&) is to insert before pos*/
|
||||
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
|
||||
|
||||
} else { /* w(i-1) ^ tau == w(i-2) ^ w(i-1) */
|
||||
/*must be w(i-2) ~> w(i-1) */
|
||||
|
||||
bool d = true;
|
||||
//need to handle the case when w_i_p_1 is null
|
||||
Line l3 = get_sharing_line(*w_i_p_1, tau);
|
||||
if ( w_i_p_1 != w_end )
|
||||
d = w_i_p_1->second != l3;
|
||||
if ( d ) { /* w(i+1) ^ tau != w(i+1) ^ w(i+2) */
|
||||
/*extension: w(i) |- tau -> w(i+1) */
|
||||
w_i->second = tau_i;
|
||||
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l3));
|
||||
} else { /* w(i+1) ^ tau == w(i+1) ^ w(i+2) */
|
||||
/*must be w(1+1) ~> w(i+2) */
|
||||
Line l5 = get_sharing_line(*w_i_m_1, *w_i_p_1);
|
||||
if ( l5 != w_i_p_1->second ) { /* w(i-1) ^ w(i+1) != w(i+1) ^ w(i+2) */
|
||||
/*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> w(i+1) */
|
||||
w_i_m_2->second = get_sharing_line(*w_i_m_2, tau);
|
||||
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
|
||||
w_i->second = w_i_m_1->second;
|
||||
w_i_m_1->second = l5;
|
||||
iter_d[w_i_m_1->first] = hlist->insert(w_i_p_1, *w_i_m_1);
|
||||
hlist->erase(w_i_m_1);
|
||||
} else {
|
||||
/*mesh is tetrahedral*/
|
||||
// dont know what that means.
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
/*Case 2:
|
||||
|
||||
w(i-1) |- w(i) ~> w(1+1)
|
||||
*/
|
||||
|
||||
if ( w_i->second.second == tau_i.first
|
||||
|| w_i->second.second == tau_i.second ) { /*w(i) ^ w(i+1) < w(i) ^ tau*/
|
||||
/*extension: w(i) |- tau -> w(i+1) */
|
||||
w_i->second = tau_i;
|
||||
Line l1 = get_sharing_line(*w_i_p_1, tau);
|
||||
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1));
|
||||
} else { /*w(i) ^ w(i+1) !< w(i) ^ tau*/
|
||||
Line l1 = get_sharing_line(*w_i_m_1, tau);
|
||||
bool c = true;
|
||||
iter w_i_m_2 = w_i_m_1;
|
||||
--w_i_m_2;
|
||||
if ( w_i_m_2 != w_end )
|
||||
c = l1 != w_i_m_2->second;
|
||||
if (c) { /*w(i-1) ^ tau != w(i-2) ^ w(i-1)*/
|
||||
/*extension: w(i-1) -> tau |- w(i)*/
|
||||
w_i_m_1->second = l1;
|
||||
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
|
||||
} else { /*w(i-1) ^ tau == w(i-2) ^ w(i-1)*/
|
||||
/*must be w(i-2)~>w(i-1)*/
|
||||
/*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> w(i+1)*/
|
||||
w_i_m_2->second = get_sharing_line(*w_i_m_2, tau);
|
||||
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
|
||||
w_i->second = w_i_m_1->second;
|
||||
w_i_m_1->second = get_sharing_line(*w_i_m_1, *w_i_p_1);
|
||||
iter_d[w_i_m_1->first] = hlist->insert(w_i_p_1, *w_i_m_1);
|
||||
hlist->erase(w_i_m_1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( b ) {
|
||||
/*Case 3:
|
||||
|
||||
w(i-1) ~> w(i) |- w(i+1)
|
||||
*/
|
||||
bool c = false;
|
||||
if ( w_i_m_1 != w_end )
|
||||
c = ( w_i_m_1->second.second == tau_i.first)
|
||||
|| ( w_i_m_1->second.second == tau_i.second);
|
||||
|
||||
if ( c ) { /*w(i-1) ^ w(i) < w(i) ^ tau*/
|
||||
/* extension: w(i-1) -> tau |- w(i) */
|
||||
if ( w_i_m_1 != w_end )
|
||||
w_i_m_1->second = get_sharing_line(*w_i_m_1, tau);
|
||||
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
|
||||
} else {
|
||||
bool d = true;
|
||||
Line l1;
|
||||
l1.first = SAW_SENTINAL;
|
||||
l1.second = SAW_SENTINAL;
|
||||
if ( w_i_p_1 != w_end ) {
|
||||
l1 = get_sharing_line(*w_i_p_1, tau);
|
||||
d = l1 != w_i_p_1->second;
|
||||
}
|
||||
if (d) { /*w(i+1) ^ tau != w(i+1) ^ w(i+2)*/
|
||||
/*extension: w(i) |- tau -> w(i+1) */
|
||||
w_i->second = tau_i;
|
||||
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1));
|
||||
} else {
|
||||
/*must be w(i+1) ~> w(i+2)*/
|
||||
/*extension: w(i-1) -> w(i+1) |- w(i) |- tau -> w(i+2) */
|
||||
iter w_i_p_2 = w_i_p_1;
|
||||
++w_i_p_2;
|
||||
|
||||
w_i_p_1->second = w_i->second;
|
||||
iter_d[i] = hlist->insert(w_i_p_2, make_pair(i, tau_i));
|
||||
hlist->erase(w_i);
|
||||
Line l2 = get_sharing_line(*w_i_p_2, tau);
|
||||
iter_d[tau] = hlist->insert(w_i_p_2, make_pair(tau, l2));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/*Case 4:
|
||||
|
||||
w(i-1) ~> w(i) ~> w(i+1)
|
||||
|
||||
*/
|
||||
bool c = false;
|
||||
if ( w_i_m_1 != w_end ) {
|
||||
c = (w_i_m_1->second.second == tau_i.first)
|
||||
|| (w_i_m_1->second.second == tau_i.second);
|
||||
}
|
||||
if ( c ) { /*w(i-1) ^ w(i) < w(i) ^ tau */
|
||||
/*extension: w(i-1) -> tau |- w(i) */
|
||||
if ( w_i_m_1 != w_end )
|
||||
w_i_m_1->second = get_sharing_line(*w_i_m_1, tau);
|
||||
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
|
||||
} else {
|
||||
/*extension: w(i) |- tau -> w(i+1) */
|
||||
w_i->second = tau_i;
|
||||
Line l1;
|
||||
l1.first = SAW_SENTINAL;
|
||||
l1.second = SAW_SENTINAL;
|
||||
if ( w_i_p_1 != w_end )
|
||||
l1 = get_sharing_line(*w_i_p_1, tau);
|
||||
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
TriangleDecorator td; /*a decorator for vertex*/
|
||||
HList hlist;
|
||||
/*This must be a handle of list to record the SAW
|
||||
The element type of the list is pair<Vertex, Line>
|
||||
*/
|
||||
|
||||
IteratorD iter_d;
|
||||
/*Problem statement: Need a fast access to w for triangle i.
|
||||
*Possible solution: mantain an array to record.
|
||||
iter_d[i] will return an iterator
|
||||
which points to w(i), where i is a vertex
|
||||
representing triangle i.
|
||||
*/
|
||||
};
|
||||
|
||||
template <class Triangle, class HList, class Iterator>
|
||||
inline
|
||||
SAW_visitor<Triangle, HList, Iterator>
|
||||
visit_SAW(Triangle t, HList hl, Iterator i) {
|
||||
return SAW_visitor<Triangle, HList, Iterator>(t, hl, i);
|
||||
}
|
||||
|
||||
template <class Tri, class HList, class Iter>
|
||||
inline
|
||||
SAW_visitor< random_access_iterator_property_map<Tri*,Tri,Tri&>,
|
||||
HList, random_access_iterator_property_map<Iter*,Iter,Iter&> >
|
||||
visit_SAW_ptr(Tri* t, HList hl, Iter* i) {
|
||||
typedef random_access_iterator_property_map<Tri*,Tri,Tri&> TriD;
|
||||
typedef random_access_iterator_property_map<Iter*,Iter,Iter&> IterD;
|
||||
return SAW_visitor<TriD, HList, IterD>(t, hl, i);
|
||||
}
|
||||
|
||||
// should also have combo's of pointers, and also const :(
|
||||
|
||||
}
|
||||
|
||||
#endif /*BOOST_SAW_H*/
|
||||
117
libraries/include/boost/graph/detail/set_adaptor.hpp
Normal file
117
libraries/include/boost/graph/detail/set_adaptor.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// (C) Copyright Jeremy Siek 2001.
|
||||
// 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_SET_ADAPTOR_HPP
|
||||
#define BOOST_SET_ADAPTOR_HPP
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class K, class C, class A, class T>
|
||||
bool set_contains(const std::set<K,C,A>& s, const T& x) {
|
||||
return s.find(x) != s.end();
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
bool set_equal(const std::set<K,C,A>& x,
|
||||
const std::set<K,C,A>& y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
// Not the same as lexicographical_compare_3way applied to std::set.
|
||||
// this is equivalent semantically to bitset::operator<()
|
||||
template <class K, class C, class A>
|
||||
int set_lex_order(const std::set<K,C,A>& x,
|
||||
const std::set<K,C,A>& y)
|
||||
{
|
||||
typename std::set<K,C,A>::iterator
|
||||
xi = x.begin(), yi = y.begin(), xend = x.end(), yend = y.end();
|
||||
for (; xi != xend && yi != yend; ++xi, ++yi) {
|
||||
if (*xi < *yi)
|
||||
return 1;
|
||||
else if (*yi < *xi)
|
||||
return -1;
|
||||
}
|
||||
if (xi == xend)
|
||||
return (yi == yend) ? 0 : -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
void set_clear(std::set<K,C,A>& x) {
|
||||
x.clear();
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
bool set_empty(const std::set<K,C,A>& x) {
|
||||
return x.empty();
|
||||
}
|
||||
|
||||
template <class K, class C, class A, class T>
|
||||
void set_insert(std::set<K,C,A>& x, const T& a) {
|
||||
x.insert(a);
|
||||
}
|
||||
|
||||
template <class K, class C, class A, class T>
|
||||
void set_remove(std::set<K,C,A>& x, const T& a) {
|
||||
x.erase(a);
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
void set_intersect(const std::set<K,C,A>& x,
|
||||
const std::set<K,C,A>& y,
|
||||
std::set<K,C,A>& z)
|
||||
{
|
||||
z.clear();
|
||||
std::set_intersection(x.begin(), x.end(),
|
||||
y.begin(), y.end(),
|
||||
std::inserter(z));
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
void set_union(const std::set<K,C,A>& x,
|
||||
const std::set<K,C,A>& y,
|
||||
std::set<K,C,A>& z)
|
||||
{
|
||||
z.clear();
|
||||
std::set_union(x.begin(), x.end(),
|
||||
y.begin(), y.end(),
|
||||
std::inserter(z));
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
void set_difference(const std::set<K,C,A>& x,
|
||||
const std::set<K,C,A>& y,
|
||||
std::set<K,C,A>& z)
|
||||
{
|
||||
z.clear();
|
||||
std::set_difference(x.begin(), x.end(),
|
||||
y.begin(), y.end(),
|
||||
std::inserter(z, z.begin()));
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
bool set_subset(const std::set<K,C,A>& x,
|
||||
const std::set<K,C,A>& y)
|
||||
{
|
||||
return std::includes(x.begin(), x.end(), y.begin(), y.end());
|
||||
}
|
||||
|
||||
// Shit, can't implement this without knowing the size of the
|
||||
// universe.
|
||||
template <class K, class C, class A>
|
||||
void set_compliment(const std::set<K,C,A>& x,
|
||||
std::set<K,C,A>& z)
|
||||
{
|
||||
z.clear();
|
||||
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_SET_ADAPTOR_HPP
|
||||
139
libraries/include/boost/graph/detail/shadow_iterator.hpp
Normal file
139
libraries/include/boost/graph/detail/shadow_iterator.hpp
Normal file
@@ -0,0 +1,139 @@
|
||||
// (C) Copyright Jeremy Siek 2001.
|
||||
// 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_SHADOW_ITERATOR_HPP
|
||||
#define BOOST_SHADOW_ITERATOR_HPP
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class A, class B, class D>
|
||||
class shadow_proxy
|
||||
: boost::operators< shadow_proxy<A,B,D> >
|
||||
{
|
||||
typedef shadow_proxy self;
|
||||
public:
|
||||
inline shadow_proxy(A aa, B bb) : a(aa), b(bb) { }
|
||||
inline shadow_proxy(const self& x) : a(x.a), b(x.b) { }
|
||||
template <class Self>
|
||||
inline shadow_proxy(Self x) : a(x.a), b(x.b) { }
|
||||
inline self& operator=(const self& x) { a = x.a; b = x.b; return *this; }
|
||||
inline self& operator++() { ++a; return *this; }
|
||||
inline self& operator--() { --a; return *this; }
|
||||
inline self& operator+=(const self& x) { a += x.a; return *this; }
|
||||
inline self& operator-=(const self& x) { a -= x.a; return *this; }
|
||||
inline self& operator*=(const self& x) { a *= x.a; return *this; }
|
||||
inline self& operator/=(const self& x) { a /= x.a; return *this; }
|
||||
inline self& operator%=(const self& x) { return *this; } // JGS
|
||||
inline self& operator&=(const self& x) { return *this; } // JGS
|
||||
inline self& operator|=(const self& x) { return *this; } // JGS
|
||||
inline self& operator^=(const self& x) { return *this; } // JGS
|
||||
inline friend D operator-(const self& x, const self& y) {
|
||||
return x.a - y.a;
|
||||
}
|
||||
inline bool operator==(const self& x) const { return a == x.a; }
|
||||
inline bool operator<(const self& x) const { return a < x.a; }
|
||||
// protected:
|
||||
A a;
|
||||
B b;
|
||||
};
|
||||
|
||||
struct shadow_iterator_policies
|
||||
{
|
||||
template <typename iter_pair>
|
||||
void initialize(const iter_pair&) { }
|
||||
|
||||
template <typename Iter>
|
||||
typename Iter::reference dereference(const Iter& i) const {
|
||||
typedef typename Iter::reference R;
|
||||
return R(*i.base().first, *i.base().second);
|
||||
}
|
||||
template <typename Iter>
|
||||
bool equal(const Iter& p1, const Iter& p2) const {
|
||||
return p1.base().first == p2.base().first;
|
||||
}
|
||||
template <typename Iter>
|
||||
void increment(Iter& i) { ++i.base().first; ++i.base().second; }
|
||||
|
||||
template <typename Iter>
|
||||
void decrement(Iter& i) { --i.base().first; --i.base().second; }
|
||||
|
||||
template <typename Iter>
|
||||
bool less(const Iter& x, const Iter& y) const {
|
||||
return x.base().first < y.base().first;
|
||||
}
|
||||
template <typename Iter>
|
||||
typename Iter::difference_type
|
||||
distance(const Iter& x, const Iter& y) const {
|
||||
return y.base().first - x.base().first;
|
||||
}
|
||||
template <typename D, typename Iter>
|
||||
void advance(Iter& p, D n) { p.base().first += n; p.base().second += n; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename IterA, typename IterB>
|
||||
struct shadow_iterator_generator {
|
||||
|
||||
// To use the iterator_adaptor we can't derive from
|
||||
// random_access_iterator because we don't have a real reference.
|
||||
// However, we want the STL algorithms to treat the shadow
|
||||
// iterator like a random access iterator.
|
||||
struct shadow_iterator_tag : public std::input_iterator_tag {
|
||||
operator std::random_access_iterator_tag() {
|
||||
return std::random_access_iterator_tag();
|
||||
};
|
||||
};
|
||||
typedef typename std::iterator_traits<IterA>::value_type Aval;
|
||||
typedef typename std::iterator_traits<IterB>::value_type Bval;
|
||||
typedef typename std::iterator_traits<IterA>::reference Aref;
|
||||
typedef typename std::iterator_traits<IterB>::reference Bref;
|
||||
typedef typename std::iterator_traits<IterA>::difference_type D;
|
||||
typedef detail::shadow_proxy<Aval,Bval,Aval> V;
|
||||
typedef detail::shadow_proxy<Aref,Bref,Aval> R;
|
||||
typedef iterator_adaptor< std::pair<IterA, IterB>,
|
||||
detail::shadow_iterator_policies,
|
||||
V, R, V*, shadow_iterator_tag,
|
||||
D> type;
|
||||
};
|
||||
|
||||
// short cut for creating a shadow iterator
|
||||
template <class IterA, class IterB>
|
||||
inline typename shadow_iterator_generator<IterA,IterB>::type
|
||||
make_shadow_iter(IterA a, IterB b) {
|
||||
typedef typename shadow_iterator_generator<IterA,IterB>::type Iter;
|
||||
return Iter(std::make_pair(a,b));
|
||||
}
|
||||
|
||||
template <class Cmp>
|
||||
struct shadow_cmp {
|
||||
inline shadow_cmp(const Cmp& c) : cmp(c) { }
|
||||
template <class ShadowProxy1, class ShadowProxy2>
|
||||
inline bool operator()(const ShadowProxy1& x, const ShadowProxy2& y) const
|
||||
{
|
||||
return cmp(x.a, y.a);
|
||||
}
|
||||
Cmp cmp;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace std {
|
||||
template <class A1, class B1, class D1,
|
||||
class A2, class B2, class D2>
|
||||
void swap(boost::detail::shadow_proxy<A1&,B1&,D1> x,
|
||||
boost::detail::shadow_proxy<A2&,B2&,D2> y)
|
||||
{
|
||||
std::swap(x.a, y.a);
|
||||
std::swap(x.b, y.b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_SHADOW_ITERATOR_HPP
|
||||
198
libraries/include/boost/graph/detail/sparse_ordering.hpp
Normal file
198
libraries/include/boost/graph/detail/sparse_ordering.hpp
Normal file
@@ -0,0 +1,198 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Copyright 2004, 2005 Trustees of Indiana University
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek,
|
||||
// Doug Gregor, D. Kevin McGrath
|
||||
//
|
||||
// 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_SPARSE_ORDERING_HPP
|
||||
#define BOOST_GRAPH_DETAIL_SPARSE_ORDERING_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <boost/pending/queue.hpp>
|
||||
#include <boost/pending/mutable_queue.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/pending/indirect_cmp.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/graph/iteration_macros.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace sparse {
|
||||
|
||||
// rcm_queue
|
||||
//
|
||||
// This is a custom queue type used in the
|
||||
// *_ordering algorithms.
|
||||
// In addition to the normal queue operations, the
|
||||
// rcm_queue provides:
|
||||
//
|
||||
// int eccentricity() const;
|
||||
// value_type spouse() const;
|
||||
//
|
||||
|
||||
// yes, it's a bad name...but it works, so use it
|
||||
template < class Vertex, class DegreeMap,
|
||||
class Container = std::deque<Vertex> >
|
||||
class rcm_queue : public std::queue<Vertex, Container> {
|
||||
typedef std::queue<Vertex> base;
|
||||
public:
|
||||
typedef typename base::value_type value_type;
|
||||
typedef typename base::size_type size_type;
|
||||
|
||||
/* SGI queue has not had a contructor queue(const Container&) */
|
||||
inline rcm_queue(DegreeMap deg)
|
||||
: _size(0), Qsize(1), eccen(-1), degree(deg) { }
|
||||
|
||||
inline void pop() {
|
||||
if ( !_size )
|
||||
Qsize = base::size();
|
||||
|
||||
base::pop();
|
||||
if ( _size == Qsize-1 ) {
|
||||
_size = 0;
|
||||
++eccen;
|
||||
} else
|
||||
++_size;
|
||||
|
||||
}
|
||||
|
||||
inline value_type& front() {
|
||||
value_type& u = base::front();
|
||||
if ( _size == 0 )
|
||||
w = u;
|
||||
else if (get(degree,u) < get(degree,w) )
|
||||
w = u;
|
||||
return u;
|
||||
}
|
||||
|
||||
inline const value_type& front() const {
|
||||
const value_type& u = base::front();
|
||||
if ( _size == 0 )
|
||||
w = u;
|
||||
else if (get(degree,u) < get(degree,w) )
|
||||
w = u;
|
||||
return u;
|
||||
}
|
||||
|
||||
inline value_type& top() { return front(); }
|
||||
inline const value_type& top() const { return front(); }
|
||||
|
||||
inline size_type size() const { return base::size(); }
|
||||
|
||||
inline size_type eccentricity() const { return eccen; }
|
||||
inline value_type spouse() const { return w; }
|
||||
|
||||
protected:
|
||||
size_type _size;
|
||||
size_type Qsize;
|
||||
int eccen;
|
||||
mutable value_type w;
|
||||
DegreeMap degree;
|
||||
};
|
||||
|
||||
|
||||
template <typename Tp, typename Sequence = std::deque<Tp> >
|
||||
class sparse_ordering_queue : public boost::queue<Tp, Sequence>{
|
||||
public:
|
||||
typedef typename Sequence::iterator iterator;
|
||||
typedef typename Sequence::reverse_iterator reverse_iterator;
|
||||
typedef queue<Tp,Sequence> base;
|
||||
typedef typename Sequence::size_type size_type;
|
||||
|
||||
inline iterator begin() { return this->c.begin(); }
|
||||
inline reverse_iterator rbegin() { return this->c.rbegin(); }
|
||||
inline iterator end() { return this->c.end(); }
|
||||
inline reverse_iterator rend() { return this->c.rend(); }
|
||||
inline Tp &operator[](int n) { return this->c[n]; }
|
||||
inline size_type size() {return this->c.size(); }
|
||||
protected:
|
||||
//nothing
|
||||
};
|
||||
|
||||
} // namespace sparse
|
||||
|
||||
// Compute Pseudo peripheral
|
||||
//
|
||||
// To compute an approximated peripheral for a given vertex.
|
||||
// Used in <tt>king_ordering</tt> algorithm.
|
||||
//
|
||||
template <class Graph, class Vertex, class ColorMap, class DegreeMap>
|
||||
Vertex
|
||||
pseudo_peripheral_pair(Graph const& G, const Vertex& u, int& ecc,
|
||||
ColorMap color, DegreeMap degree)
|
||||
{
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
sparse::rcm_queue<Vertex, DegreeMap> Q(degree);
|
||||
|
||||
typename boost::graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
|
||||
if (get(color, *ui) != Color::red()) put(color, *ui, Color::white());
|
||||
breadth_first_visit(G, u, buffer(Q).color_map(color));
|
||||
|
||||
ecc = Q.eccentricity();
|
||||
return Q.spouse();
|
||||
}
|
||||
|
||||
// Find a good starting node
|
||||
//
|
||||
// This is to find a good starting node for the
|
||||
// king_ordering algorithm. "good" is in the sense
|
||||
// of the ordering generated by RCM.
|
||||
//
|
||||
template <class Graph, class Vertex, class Color, class Degree>
|
||||
Vertex find_starting_node(Graph const& G, Vertex r, Color color, Degree degree)
|
||||
{
|
||||
Vertex x, y;
|
||||
int eccen_r, eccen_x;
|
||||
|
||||
x = pseudo_peripheral_pair(G, r, eccen_r, color, degree);
|
||||
y = pseudo_peripheral_pair(G, x, eccen_x, color, degree);
|
||||
|
||||
while (eccen_x > eccen_r) {
|
||||
r = x;
|
||||
eccen_r = eccen_x;
|
||||
x = y;
|
||||
y = pseudo_peripheral_pair(G, x, eccen_x, color, degree);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
class out_degree_property_map
|
||||
: public put_get_helper<typename graph_traits<Graph>::degree_size_type,
|
||||
out_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;
|
||||
out_degree_property_map(const Graph& g) : m_g(g) { }
|
||||
value_type operator[](const key_type& v) const {
|
||||
return out_degree(v, m_g);
|
||||
}
|
||||
private:
|
||||
const Graph& m_g;
|
||||
};
|
||||
template <typename Graph>
|
||||
inline out_degree_property_map<Graph>
|
||||
make_out_degree_map(const Graph& g) {
|
||||
return out_degree_property_map<Graph>(g);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_KING_HPP
|
||||
347
libraries/include/boost/graph/dijkstra_shortest_paths.hpp
Normal file
347
libraries/include/boost/graph/dijkstra_shortest_paths.hpp
Normal file
@@ -0,0 +1,347 @@
|
||||
//=======================================================================
|
||||
// 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_DIJKSTRA_HPP
|
||||
#define BOOST_GRAPH_DIJKSTRA_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include <boost/graph/relax.hpp>
|
||||
#include <boost/pending/indirect_cmp.hpp>
|
||||
#include <boost/graph/exception.hpp>
|
||||
#include <boost/pending/relaxed_heap.hpp>
|
||||
|
||||
#ifdef BOOST_GRAPH_DIJKSTRA_TESTING
|
||||
# include <boost/pending/mutable_queue.hpp>
|
||||
#endif // BOOST_GRAPH_DIJKSTRA_TESTING
|
||||
|
||||
namespace boost {
|
||||
|
||||
#ifdef BOOST_GRAPH_DIJKSTRA_TESTING
|
||||
static bool dijkstra_relaxed_heap = true;
|
||||
#endif
|
||||
|
||||
template <class Visitor, class Graph>
|
||||
struct DijkstraVisitorConcept {
|
||||
void constraints() {
|
||||
function_requires< CopyConstructibleConcept<Visitor> >();
|
||||
vis.initialize_vertex(u, g);
|
||||
vis.discover_vertex(u, g);
|
||||
vis.examine_vertex(u, g);
|
||||
vis.examine_edge(e, g);
|
||||
vis.edge_relaxed(e, g);
|
||||
vis.edge_not_relaxed(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;
|
||||
};
|
||||
|
||||
template <class Visitors = null_visitor>
|
||||
class dijkstra_visitor : public bfs_visitor<Visitors> {
|
||||
public:
|
||||
dijkstra_visitor() { }
|
||||
dijkstra_visitor(Visitors vis)
|
||||
: bfs_visitor<Visitors>(vis) { }
|
||||
|
||||
template <class Edge, class Graph>
|
||||
void edge_relaxed(Edge e, Graph& g) {
|
||||
invoke_visitors(this->m_vis, e, g, on_edge_relaxed());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void edge_not_relaxed(Edge e, Graph& g) {
|
||||
invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed());
|
||||
}
|
||||
private:
|
||||
template <class Edge, class Graph>
|
||||
void tree_edge(Edge u, Graph& g) { }
|
||||
};
|
||||
template <class Visitors>
|
||||
dijkstra_visitor<Visitors>
|
||||
make_dijkstra_visitor(Visitors vis) {
|
||||
return dijkstra_visitor<Visitors>(vis);
|
||||
}
|
||||
typedef dijkstra_visitor<> default_dijkstra_visitor;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class UniformCostVisitor, class UpdatableQueue,
|
||||
class WeightMap, class PredecessorMap, class DistanceMap,
|
||||
class BinaryFunction, class BinaryPredicate>
|
||||
struct dijkstra_bfs_visitor
|
||||
{
|
||||
typedef typename property_traits<DistanceMap>::value_type D;
|
||||
|
||||
dijkstra_bfs_visitor(UniformCostVisitor vis, UpdatableQueue& Q,
|
||||
WeightMap w, PredecessorMap p, DistanceMap d,
|
||||
BinaryFunction combine, BinaryPredicate compare,
|
||||
D zero)
|
||||
: m_vis(vis), m_Q(Q), m_weight(w), m_predecessor(p), m_distance(d),
|
||||
m_combine(combine), m_compare(compare), m_zero(zero) { }
|
||||
|
||||
template <class Edge, class Graph>
|
||||
void tree_edge(Edge e, Graph& g) {
|
||||
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
|
||||
m_combine, m_compare);
|
||||
if (m_decreased)
|
||||
m_vis.edge_relaxed(e, g);
|
||||
else
|
||||
m_vis.edge_not_relaxed(e, g);
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void gray_target(Edge e, Graph& g) {
|
||||
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
|
||||
m_combine, m_compare);
|
||||
if (m_decreased) {
|
||||
m_Q.update(target(e, g));
|
||||
m_vis.edge_relaxed(e, g);
|
||||
} else
|
||||
m_vis.edge_not_relaxed(e, g);
|
||||
}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void initialize_vertex(Vertex /*u*/, Graph& /*g*/) { }
|
||||
template <class Edge, class Graph>
|
||||
void non_tree_edge(Edge, Graph&) { }
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph& g) { m_vis.discover_vertex(u, g); }
|
||||
template <class Vertex, class Graph>
|
||||
void examine_vertex(Vertex u, Graph& g) { m_vis.examine_vertex(u, g); }
|
||||
template <class Edge, class Graph>
|
||||
void examine_edge(Edge e, Graph& g) {
|
||||
if (m_compare(get(m_weight, e), m_zero))
|
||||
throw negative_edge();
|
||||
m_vis.examine_edge(e, g);
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void black_target(Edge, Graph&) { }
|
||||
template <class Vertex, class Graph>
|
||||
void finish_vertex(Vertex u, Graph& g) { m_vis.finish_vertex(u, g); }
|
||||
|
||||
UniformCostVisitor m_vis;
|
||||
UpdatableQueue& m_Q;
|
||||
WeightMap m_weight;
|
||||
PredecessorMap m_predecessor;
|
||||
DistanceMap m_distance;
|
||||
BinaryFunction m_combine;
|
||||
BinaryPredicate m_compare;
|
||||
bool m_decreased;
|
||||
D m_zero;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Call breadth first search with default color map.
|
||||
template <class VertexListGraph, class DijkstraVisitor,
|
||||
class PredecessorMap, class DistanceMap,
|
||||
class WeightMap, class IndexMap, class Compare, class Combine,
|
||||
class DistZero>
|
||||
inline void
|
||||
dijkstra_shortest_paths_no_init
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
|
||||
IndexMap index_map,
|
||||
Compare compare, Combine combine, DistZero zero,
|
||||
DijkstraVisitor vis)
|
||||
{
|
||||
std::vector<default_color_type> color(num_vertices(g));
|
||||
default_color_type c = white_color;
|
||||
dijkstra_shortest_paths_no_init( g, s, predecessor, distance, weight,
|
||||
index_map, compare, combine, zero, vis,
|
||||
make_iterator_property_map(&color[0], index_map, c));
|
||||
}
|
||||
|
||||
// Call breadth first search
|
||||
template <class VertexListGraph, class DijkstraVisitor,
|
||||
class PredecessorMap, class DistanceMap,
|
||||
class WeightMap, class IndexMap, class Compare, class Combine,
|
||||
class DistZero, class ColorMap>
|
||||
inline void
|
||||
dijkstra_shortest_paths_no_init
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
|
||||
IndexMap index_map,
|
||||
Compare compare, Combine combine, DistZero zero,
|
||||
DijkstraVisitor vis, ColorMap color)
|
||||
{
|
||||
typedef indirect_cmp<DistanceMap, Compare> IndirectCmp;
|
||||
IndirectCmp icmp(distance, compare);
|
||||
|
||||
typedef typename graph_traits<VertexListGraph>::vertex_descriptor Vertex;
|
||||
|
||||
#ifdef BOOST_GRAPH_DIJKSTRA_TESTING
|
||||
if (!dijkstra_relaxed_heap) {
|
||||
typedef mutable_queue<Vertex, std::vector<Vertex>, IndirectCmp, IndexMap>
|
||||
MutableQueue;
|
||||
|
||||
MutableQueue Q(num_vertices(g), icmp, index_map);
|
||||
|
||||
detail::dijkstra_bfs_visitor<DijkstraVisitor, MutableQueue, WeightMap,
|
||||
PredecessorMap, DistanceMap, Combine, Compare>
|
||||
bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero);
|
||||
|
||||
breadth_first_visit(g, s, Q, bfs_vis, color);
|
||||
return;
|
||||
}
|
||||
#endif // BOOST_GRAPH_DIJKSTRA_TESTING
|
||||
|
||||
typedef relaxed_heap<Vertex, IndirectCmp, IndexMap> MutableQueue;
|
||||
|
||||
MutableQueue Q(num_vertices(g), icmp, index_map);
|
||||
|
||||
detail::dijkstra_bfs_visitor<DijkstraVisitor, MutableQueue, WeightMap,
|
||||
PredecessorMap, DistanceMap, Combine, Compare>
|
||||
bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero);
|
||||
|
||||
breadth_first_visit(g, s, Q, bfs_vis, color);
|
||||
}
|
||||
|
||||
// Initialize distances and call breadth first search with default color map
|
||||
template <class VertexListGraph, class DijkstraVisitor,
|
||||
class PredecessorMap, class DistanceMap,
|
||||
class WeightMap, class IndexMap, class Compare, class Combine,
|
||||
class DistInf, class DistZero>
|
||||
inline void
|
||||
dijkstra_shortest_paths
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
|
||||
IndexMap index_map,
|
||||
Compare compare, Combine combine, DistInf inf, DistZero zero,
|
||||
DijkstraVisitor vis)
|
||||
{
|
||||
std::vector<default_color_type> color(num_vertices(g));
|
||||
default_color_type c = white_color;
|
||||
dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map,
|
||||
compare, combine, inf, zero, vis,
|
||||
make_iterator_property_map(&color[0], index_map,
|
||||
c));
|
||||
}
|
||||
|
||||
// Initialize distances and call breadth first search
|
||||
template <class VertexListGraph, class DijkstraVisitor,
|
||||
class PredecessorMap, class DistanceMap,
|
||||
class WeightMap, class IndexMap, class Compare, class Combine,
|
||||
class DistInf, class DistZero, class ColorMap>
|
||||
inline void
|
||||
dijkstra_shortest_paths
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
|
||||
IndexMap index_map,
|
||||
Compare compare, Combine combine, DistInf inf, DistZero zero,
|
||||
DijkstraVisitor vis, ColorMap color)
|
||||
{
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
||||
vis.initialize_vertex(*ui, g);
|
||||
put(distance, *ui, inf);
|
||||
put(predecessor, *ui, *ui);
|
||||
put(color, *ui, Color::white());
|
||||
}
|
||||
put(distance, s, zero);
|
||||
|
||||
dijkstra_shortest_paths_no_init(g, s, predecessor, distance, weight,
|
||||
index_map, compare, combine, zero, vis, color);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Handle defaults for PredecessorMap and
|
||||
// Distance Compare, Combine, Inf and Zero
|
||||
template <class VertexListGraph, class DistanceMap, class WeightMap,
|
||||
class IndexMap, class Params, class ColorMap>
|
||||
inline void
|
||||
dijkstra_dispatch2
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
DistanceMap distance, WeightMap weight, IndexMap index_map,
|
||||
const Params& params, ColorMap color)
|
||||
{
|
||||
// Default for predecessor map
|
||||
dummy_property_map p_map;
|
||||
|
||||
typedef typename property_traits<DistanceMap>::value_type D;
|
||||
dijkstra_shortest_paths
|
||||
(g, s,
|
||||
choose_param(get_param(params, vertex_predecessor), p_map),
|
||||
distance, weight, index_map,
|
||||
choose_param(get_param(params, distance_compare_t()),
|
||||
std::less<D>()),
|
||||
choose_param(get_param(params, distance_combine_t()),
|
||||
closed_plus<D>()),
|
||||
choose_param(get_param(params, distance_inf_t()),
|
||||
(std::numeric_limits<D>::max)()),
|
||||
choose_param(get_param(params, distance_zero_t()),
|
||||
D()),
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_dijkstra_visitor(null_visitor())),
|
||||
color);
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class DistanceMap, class WeightMap,
|
||||
class IndexMap, class Params, class ColorMap>
|
||||
inline void
|
||||
dijkstra_dispatch1
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
DistanceMap distance, WeightMap weight, IndexMap index_map,
|
||||
const Params& params, ColorMap color)
|
||||
{
|
||||
// Default for distance map
|
||||
typedef typename property_traits<WeightMap>::value_type D;
|
||||
typename std::vector<D>::size_type
|
||||
n = is_default_param(distance) ? num_vertices(g) : 1;
|
||||
std::vector<D> distance_map(n);
|
||||
|
||||
// Default for color map
|
||||
typename std::vector<default_color_type>::size_type
|
||||
m = is_default_param(color) ? num_vertices(g) : 1;
|
||||
std::vector<default_color_type> color_map(m);
|
||||
|
||||
detail::dijkstra_dispatch2
|
||||
(g, s, choose_param(distance, make_iterator_property_map
|
||||
(distance_map.begin(), index_map,
|
||||
distance_map[0])),
|
||||
weight, index_map, params,
|
||||
choose_param(color, make_iterator_property_map
|
||||
(color_map.begin(), index_map,
|
||||
color_map[0])));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// Named Parameter Variant
|
||||
template <class VertexListGraph, class Param, class Tag, class Rest>
|
||||
inline void
|
||||
dijkstra_shortest_paths
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
const bgl_named_params<Param,Tag,Rest>& params)
|
||||
{
|
||||
// Default for edge weight and vertex index map is to ask for them
|
||||
// from the graph. Default for the visitor is null_visitor.
|
||||
detail::dijkstra_dispatch1
|
||||
(g, s,
|
||||
get_param(params, vertex_distance),
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
|
||||
params,
|
||||
get_param(params, vertex_color));
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_DIJKSTRA_HPP
|
||||
491
libraries/include/boost/graph/dominator_tree.hpp
Normal file
491
libraries/include/boost/graph/dominator_tree.hpp
Normal file
@@ -0,0 +1,491 @@
|
||||
//=======================================================================
|
||||
// Copyright (C) 2005-2009 Jongsoo Park <jongsoo.park -at- gmail.com>
|
||||
//
|
||||
// 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_DOMINATOR_HPP
|
||||
#define BOOST_GRAPH_DOMINATOR_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
|
||||
// Dominator tree computation
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
/**
|
||||
* An extended time_stamper which also records vertices for each dfs number
|
||||
*/
|
||||
template<class TimeMap, class VertexVector, class TimeT, class Tag>
|
||||
class time_stamper_with_vertex_vector
|
||||
: public base_visitor<
|
||||
time_stamper_with_vertex_vector<TimeMap, VertexVector, TimeT, Tag> >
|
||||
{
|
||||
public :
|
||||
typedef Tag event_filter;
|
||||
time_stamper_with_vertex_vector(TimeMap timeMap, VertexVector& v,
|
||||
TimeT& t)
|
||||
: timeStamper_(timeMap, t), v_(v) { }
|
||||
|
||||
template<class Graph>
|
||||
void
|
||||
operator()(const typename property_traits<TimeMap>::key_type& v,
|
||||
const Graph& g)
|
||||
{
|
||||
timeStamper_(v, g);
|
||||
v_[timeStamper_.m_time] = v;
|
||||
}
|
||||
|
||||
private :
|
||||
time_stamper<TimeMap, TimeT, Tag> timeStamper_;
|
||||
VertexVector& v_;
|
||||
};
|
||||
|
||||
/**
|
||||
* A convenient way to create a time_stamper_with_vertex_vector
|
||||
*/
|
||||
template<class TimeMap, class VertexVector, class TimeT, class Tag>
|
||||
time_stamper_with_vertex_vector<TimeMap, VertexVector, TimeT, Tag>
|
||||
stamp_times_with_vertex_vector(TimeMap timeMap, VertexVector& v, TimeT& t,
|
||||
Tag)
|
||||
{
|
||||
return time_stamper_with_vertex_vector<TimeMap, VertexVector, TimeT,
|
||||
Tag>(timeMap, v, t);
|
||||
}
|
||||
|
||||
template<class Graph, class IndexMap, class TimeMap, class PredMap,
|
||||
class DomTreePredMap>
|
||||
class dominator_visitor
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
|
||||
|
||||
public :
|
||||
/**
|
||||
* @param g [in] the target graph of the dominator tree
|
||||
* @param entry [in] the entry node of g
|
||||
* @param domTreePredMap [out] the immediate dominator map
|
||||
* (parent map in dominator tree)
|
||||
*/
|
||||
dominator_visitor(const Graph& g, const Vertex& entry,
|
||||
DomTreePredMap domTreePredMap)
|
||||
: semi_(num_vertices(g)),
|
||||
ancestor_(num_vertices(g), graph_traits<Graph>::null_vertex()),
|
||||
samedom_(ancestor_),
|
||||
best_(semi_),
|
||||
semiMap_(make_iterator_property_map(semi_.begin(),
|
||||
get(vertex_index, g))),
|
||||
ancestorMap_(make_iterator_property_map(ancestor_.begin(),
|
||||
get(vertex_index, g))),
|
||||
bestMap_(make_iterator_property_map(best_.begin(),
|
||||
get(vertex_index, g))),
|
||||
buckets_(num_vertices(g)),
|
||||
bucketMap_(make_iterator_property_map(buckets_.begin(),
|
||||
get(vertex_index, g))),
|
||||
entry_(entry),
|
||||
domTreePredMap_(domTreePredMap),
|
||||
numOfVertices_(num_vertices(g)),
|
||||
samedomMap(make_iterator_property_map(samedom_.begin(),
|
||||
get(vertex_index, g)))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()(const Vertex& n, const TimeMap& dfnumMap,
|
||||
const PredMap& parentMap, const Graph& g)
|
||||
{
|
||||
if (n == entry_) return;
|
||||
|
||||
const Vertex p(get(parentMap, n));
|
||||
Vertex s(p);
|
||||
|
||||
// 1. Calculate the semidominator of n,
|
||||
// based on the semidominator thm.
|
||||
// * Semidominator thm. : To find the semidominator of a node n,
|
||||
// consider all predecessors v of n in the CFG (Control Flow Graph).
|
||||
// - If v is a proper ancestor of n in the spanning tree
|
||||
// (so dfnum(v) < dfnum(n)), then v is a candidate for semi(n)
|
||||
// - If v is a non-ancestor of n (so dfnum(v) > dfnum(n))
|
||||
// then for each u that is an ancestor of v (or u = v),
|
||||
// Let semi(u) be a candidate for semi(n)
|
||||
// of all these candidates, the one with lowest dfnum is
|
||||
// the semidominator of n.
|
||||
|
||||
// For each predecessor of n
|
||||
typename graph_traits<Graph>::in_edge_iterator inItr, inEnd;
|
||||
for (tie(inItr, inEnd) = in_edges(n, g); inItr != inEnd; ++inItr)
|
||||
{
|
||||
const Vertex v = source(*inItr, g);
|
||||
// To deal with unreachable nodes
|
||||
if (get(dfnumMap, v) < 0 || get(dfnumMap, v) >= numOfVertices_)
|
||||
continue;
|
||||
|
||||
Vertex s2;
|
||||
if (get(dfnumMap, v) <= get(dfnumMap, n))
|
||||
s2 = v;
|
||||
else
|
||||
s2 = get(semiMap_, ancestor_with_lowest_semi_(v, dfnumMap));
|
||||
|
||||
if (get(dfnumMap, s2) < get(dfnumMap, s))
|
||||
s = s2;
|
||||
}
|
||||
put(semiMap_, n, s);
|
||||
|
||||
// 2. Calculation of n's dominator is deferred until
|
||||
// the path from s to n has been linked into the forest
|
||||
get(bucketMap_, s).push_back(n);
|
||||
get(ancestorMap_, n) = p;
|
||||
get(bestMap_, n) = n;
|
||||
|
||||
// 3. Now that the path from p to v has been linked into
|
||||
// the spanning forest, these lines calculate the dominator of v,
|
||||
// based on the dominator thm., or else defer the calculation
|
||||
// until y's dominator is known
|
||||
// * Dominator thm. : On the spanning-tree path below semi(n) and
|
||||
// above or including n, let y be the node
|
||||
// with the smallest-numbered semidominator. Then,
|
||||
//
|
||||
// idom(n) = semi(n) if semi(y)=semi(n) or
|
||||
// idom(y) if semi(y) != semi(n)
|
||||
typename std::deque<Vertex>::iterator buckItr;
|
||||
for (buckItr = get(bucketMap_, p).begin();
|
||||
buckItr != get(bucketMap_, p).end();
|
||||
++buckItr)
|
||||
{
|
||||
const Vertex v(*buckItr);
|
||||
const Vertex y(ancestor_with_lowest_semi_(v, dfnumMap));
|
||||
if (get(semiMap_, y) == get(semiMap_, v))
|
||||
put(domTreePredMap_, v, p);
|
||||
else
|
||||
put(samedomMap, v, y);
|
||||
}
|
||||
|
||||
get(bucketMap_, p).clear();
|
||||
}
|
||||
|
||||
protected :
|
||||
|
||||
/**
|
||||
* Evaluate function in Tarjan's path compression
|
||||
*/
|
||||
const Vertex
|
||||
ancestor_with_lowest_semi_(const Vertex& v, const TimeMap& dfnumMap)
|
||||
{
|
||||
const Vertex a(get(ancestorMap_, v));
|
||||
|
||||
if (get(ancestorMap_, a) != graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
const Vertex b(ancestor_with_lowest_semi_(a, dfnumMap));
|
||||
|
||||
put(ancestorMap_, v, get(ancestorMap_, a));
|
||||
|
||||
if (get(dfnumMap, get(semiMap_, b)) <
|
||||
get(dfnumMap, get(semiMap_, get(bestMap_, v))))
|
||||
put(bestMap_, v, b);
|
||||
}
|
||||
|
||||
return get(bestMap_, v);
|
||||
}
|
||||
|
||||
std::vector<Vertex> semi_, ancestor_, samedom_, best_;
|
||||
PredMap semiMap_, ancestorMap_, bestMap_;
|
||||
std::vector< std::deque<Vertex> > buckets_;
|
||||
|
||||
iterator_property_map<typename std::vector<std::deque<Vertex> >::iterator,
|
||||
IndexMap> bucketMap_;
|
||||
|
||||
const Vertex& entry_;
|
||||
DomTreePredMap domTreePredMap_;
|
||||
const VerticesSizeType numOfVertices_;
|
||||
|
||||
public :
|
||||
|
||||
PredMap samedomMap;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief Build dominator tree using Lengauer-Tarjan algorithm.
|
||||
* It takes O((V+E)log(V+E)) time.
|
||||
*
|
||||
* @pre dfnumMap, parentMap and verticesByDFNum have dfs results corresponding
|
||||
* indexMap.
|
||||
* If dfs has already run before,
|
||||
* this function would be good for saving computations.
|
||||
* @pre Unreachable nodes must be masked as
|
||||
* graph_traits<Graph>::null_vertex in parentMap.
|
||||
* @pre Unreachable nodes must be masked as
|
||||
* (std::numeric_limits<VerticesSizeType>::max)() in dfnumMap.
|
||||
*
|
||||
* @param domTreePredMap [out] : immediate dominator map (parent map
|
||||
* in dom. tree)
|
||||
*
|
||||
* @note reference Appel. p. 452~453. algorithm 19.9, 19.10.
|
||||
*
|
||||
* @todo : Optimization in Finding Dominators in Practice, Loukas Georgiadis
|
||||
*/
|
||||
template<class Graph, class IndexMap, class TimeMap, class PredMap,
|
||||
class VertexVector, class DomTreePredMap>
|
||||
void
|
||||
lengauer_tarjan_dominator_tree_without_dfs
|
||||
(const Graph& g,
|
||||
const typename graph_traits<Graph>::vertex_descriptor& entry,
|
||||
const IndexMap& indexMap,
|
||||
TimeMap dfnumMap, PredMap parentMap, VertexVector& verticesByDFNum,
|
||||
DomTreePredMap domTreePredMap)
|
||||
{
|
||||
// Typedefs and concept check
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
|
||||
|
||||
function_requires< BidirectionalGraphConcept<Graph> >();
|
||||
|
||||
const VerticesSizeType numOfVertices = num_vertices(g);
|
||||
if (numOfVertices == 0) return;
|
||||
|
||||
// 1. Visit each vertex in reverse post order and calculate sdom.
|
||||
detail::dominator_visitor<Graph, IndexMap, TimeMap, PredMap, DomTreePredMap>
|
||||
visitor(g, entry, domTreePredMap);
|
||||
|
||||
VerticesSizeType i;
|
||||
for (i = 0; i < numOfVertices; ++i)
|
||||
{
|
||||
const Vertex u(verticesByDFNum[numOfVertices - 1 - i]);
|
||||
if (u != graph_traits<Graph>::null_vertex())
|
||||
visitor(u, dfnumMap, parentMap, g);
|
||||
}
|
||||
|
||||
// 2. Now all the deferred dominator calculations,
|
||||
// based on the second clause of the dominator thm., are performed
|
||||
for (i = 0; i < numOfVertices; ++i)
|
||||
{
|
||||
const Vertex n(verticesByDFNum[i]);
|
||||
|
||||
if (n == entry || n == graph_traits<Graph>::null_vertex())
|
||||
continue;
|
||||
|
||||
Vertex u = get(visitor.samedomMap, n);
|
||||
if (u != graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
put(domTreePredMap, n, get(domTreePredMap, u));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike lengauer_tarjan_dominator_tree_without_dfs,
|
||||
* dfs is run in this function and
|
||||
* the result is written to dfnumMap, parentMap, vertices.
|
||||
*
|
||||
* If the result of dfs required after this algorithm,
|
||||
* this function can eliminate the need of rerunning dfs.
|
||||
*/
|
||||
template<class Graph, class IndexMap, class TimeMap, class PredMap,
|
||||
class VertexVector, class DomTreePredMap>
|
||||
void
|
||||
lengauer_tarjan_dominator_tree
|
||||
(const Graph& g,
|
||||
const typename graph_traits<Graph>::vertex_descriptor& entry,
|
||||
const IndexMap& indexMap,
|
||||
TimeMap dfnumMap, PredMap parentMap, VertexVector& verticesByDFNum,
|
||||
DomTreePredMap domTreePredMap)
|
||||
{
|
||||
// Typedefs and concept check
|
||||
typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
|
||||
|
||||
function_requires< BidirectionalGraphConcept<Graph> >();
|
||||
|
||||
// 1. Depth first visit
|
||||
const VerticesSizeType numOfVertices = num_vertices(g);
|
||||
if (numOfVertices == 0) return;
|
||||
|
||||
VerticesSizeType time =
|
||||
(std::numeric_limits<VerticesSizeType>::max)();
|
||||
std::vector<default_color_type>
|
||||
colors(numOfVertices, color_traits<default_color_type>::white());
|
||||
depth_first_visit
|
||||
(g, entry,
|
||||
make_dfs_visitor
|
||||
(make_pair(record_predecessors(parentMap, on_tree_edge()),
|
||||
detail::stamp_times_with_vertex_vector
|
||||
(dfnumMap, verticesByDFNum, time, on_discover_vertex()))),
|
||||
make_iterator_property_map(colors.begin(), indexMap));
|
||||
|
||||
// 2. Run main algorithm.
|
||||
lengauer_tarjan_dominator_tree_without_dfs(g, entry, indexMap, dfnumMap,
|
||||
parentMap, verticesByDFNum,
|
||||
domTreePredMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use vertex_index as IndexMap and make dfnumMap, parentMap, verticesByDFNum
|
||||
* internally.
|
||||
* If we don't need the result of dfs (dfnumMap, parentMap, verticesByDFNum),
|
||||
* this function would be more convenient one.
|
||||
*/
|
||||
template<class Graph, class DomTreePredMap>
|
||||
void
|
||||
lengauer_tarjan_dominator_tree
|
||||
(const Graph& g,
|
||||
const typename graph_traits<Graph>::vertex_descriptor& entry,
|
||||
DomTreePredMap domTreePredMap)
|
||||
{
|
||||
// typedefs
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
|
||||
typedef typename property_map<Graph, vertex_index_t>::const_type IndexMap;
|
||||
typedef
|
||||
iterator_property_map<typename std::vector<VerticesSizeType>::iterator,
|
||||
IndexMap> TimeMap;
|
||||
typedef
|
||||
iterator_property_map<typename std::vector<Vertex>::iterator, IndexMap>
|
||||
PredMap;
|
||||
|
||||
// Make property maps
|
||||
const VerticesSizeType numOfVertices = num_vertices(g);
|
||||
if (numOfVertices == 0) return;
|
||||
|
||||
const IndexMap indexMap = get(vertex_index, g);
|
||||
|
||||
std::vector<VerticesSizeType> dfnum(numOfVertices, 0);
|
||||
TimeMap dfnumMap(make_iterator_property_map(dfnum.begin(), indexMap));
|
||||
|
||||
std::vector<Vertex> parent(numOfVertices,
|
||||
graph_traits<Graph>::null_vertex());
|
||||
PredMap parentMap(make_iterator_property_map(parent.begin(), indexMap));
|
||||
|
||||
std::vector<Vertex> verticesByDFNum(parent);
|
||||
|
||||
// Run main algorithm
|
||||
lengauer_tarjan_dominator_tree(g, entry,
|
||||
indexMap, dfnumMap, parentMap,
|
||||
verticesByDFNum, domTreePredMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Muchnick. p. 182, 184
|
||||
*
|
||||
* using iterative bit vector analysis
|
||||
*/
|
||||
template<class Graph, class IndexMap, class DomTreePredMap>
|
||||
void
|
||||
iterative_bit_vector_dominator_tree
|
||||
(const Graph& g,
|
||||
const typename graph_traits<Graph>::vertex_descriptor& entry,
|
||||
const IndexMap& indexMap,
|
||||
DomTreePredMap domTreePredMap)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertexItr;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
|
||||
typedef
|
||||
iterator_property_map<typename std::vector< std::set<Vertex> >::iterator,
|
||||
IndexMap> vertexSetMap;
|
||||
|
||||
function_requires<BidirectionalGraphConcept<Graph> >();
|
||||
|
||||
// 1. Finding dominator
|
||||
// 1.1. Initialize
|
||||
const VerticesSizeType numOfVertices = num_vertices(g);
|
||||
if (numOfVertices == 0) return;
|
||||
|
||||
vertexItr vi, viend;
|
||||
tie(vi, viend) = vertices(g);
|
||||
const std::set<Vertex> N(vi, viend);
|
||||
|
||||
bool change = true;
|
||||
|
||||
std::vector< std::set<Vertex> > dom(numOfVertices, N);
|
||||
vertexSetMap domMap(make_iterator_property_map(dom.begin(), indexMap));
|
||||
get(domMap, entry).clear();
|
||||
get(domMap, entry).insert(entry);
|
||||
|
||||
while (change)
|
||||
{
|
||||
change = false;
|
||||
for (tie(vi, viend) = vertices(g); vi != viend; ++vi)
|
||||
{
|
||||
if (*vi == entry) continue;
|
||||
|
||||
std::set<Vertex> T(N);
|
||||
|
||||
typename graph_traits<Graph>::in_edge_iterator inItr, inEnd;
|
||||
for (tie(inItr, inEnd) = in_edges(*vi, g); inItr != inEnd; ++inItr)
|
||||
{
|
||||
const Vertex p = source(*inItr, g);
|
||||
|
||||
std::set<Vertex> tempSet;
|
||||
std::set_intersection(T.begin(), T.end(),
|
||||
get(domMap, p).begin(),
|
||||
get(domMap, p).end(),
|
||||
std::inserter(tempSet, tempSet.begin()));
|
||||
T.swap(tempSet);
|
||||
}
|
||||
|
||||
T.insert(*vi);
|
||||
if (T != get(domMap, *vi))
|
||||
{
|
||||
change = true;
|
||||
get(domMap, *vi).swap(T);
|
||||
}
|
||||
} // end of for (tie(vi, viend) = vertices(g)
|
||||
} // end of while(change)
|
||||
|
||||
// 2. Build dominator tree
|
||||
for (tie(vi, viend) = vertices(g); vi != viend; ++vi)
|
||||
get(domMap, *vi).erase(*vi);
|
||||
|
||||
Graph domTree(numOfVertices);
|
||||
|
||||
for (tie(vi, viend) = vertices(g); vi != viend; ++vi)
|
||||
{
|
||||
if (*vi == entry) continue;
|
||||
|
||||
// We have to iterate through copied dominator set
|
||||
const std::set<Vertex> tempSet(get(domMap, *vi));
|
||||
typename std::set<Vertex>::const_iterator s;
|
||||
for (s = tempSet.begin(); s != tempSet.end(); ++s)
|
||||
{
|
||||
typename std::set<Vertex>::iterator t;
|
||||
for (t = get(domMap, *vi).begin(); t != get(domMap, *vi).end(); )
|
||||
{
|
||||
typename std::set<Vertex>::iterator old_t = t;
|
||||
++t; // Done early because t may become invalid
|
||||
if (*old_t == *s) continue;
|
||||
if (get(domMap, *s).find(*old_t) != get(domMap, *s).end())
|
||||
get(domMap, *vi).erase(old_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (tie(vi, viend) = vertices(g); vi != viend; ++vi)
|
||||
{
|
||||
if (*vi != entry && get(domMap, *vi).size() == 1)
|
||||
{
|
||||
Vertex temp = *get(domMap, *vi).begin();
|
||||
put(domTreePredMap, *vi, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Graph, class DomTreePredMap>
|
||||
void
|
||||
iterative_bit_vector_dominator_tree
|
||||
(const Graph& g,
|
||||
const typename graph_traits<Graph>::vertex_descriptor& entry,
|
||||
DomTreePredMap domTreePredMap)
|
||||
{
|
||||
typename property_map<Graph, vertex_index_t>::const_type
|
||||
indexMap = get(vertex_index, g);
|
||||
|
||||
iterative_bit_vector_dominator_tree(g, entry, indexMap, domTreePredMap);
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_DOMINATOR_HPP
|
||||
181
libraries/include/boost/graph/edge_connectivity.hpp
Normal file
181
libraries/include/boost/graph/edge_connectivity.hpp
Normal file
@@ -0,0 +1,181 @@
|
||||
//=======================================================================
|
||||
// Copyright 2000 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
||||
//
|
||||
// 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_EDGE_CONNECTIVITY
|
||||
#define BOOST_EDGE_CONNECTIVITY
|
||||
|
||||
// WARNING: not-yet fully tested!
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <boost/graph/edmonds_karp_max_flow.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Graph>
|
||||
inline
|
||||
std::pair<typename graph_traits<Graph>::vertex_descriptor,
|
||||
typename graph_traits<Graph>::degree_size_type>
|
||||
min_degree_vertex(Graph& g)
|
||||
{
|
||||
typedef graph_traits<Graph> Traits;
|
||||
typename Traits::vertex_descriptor p;
|
||||
typedef typename Traits::degree_size_type size_type;
|
||||
size_type delta = (std::numeric_limits<size_type>::max)();
|
||||
|
||||
typename Traits::vertex_iterator i, iend;
|
||||
for (tie(i, iend) = vertices(g); i != iend; ++i)
|
||||
if (degree(*i, g) < delta) {
|
||||
delta = degree(*i, g);
|
||||
p = *i;
|
||||
}
|
||||
return std::make_pair(p, delta);
|
||||
}
|
||||
|
||||
template <class Graph, class OutputIterator>
|
||||
void neighbors(const Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor u,
|
||||
OutputIterator result)
|
||||
{
|
||||
typename graph_traits<Graph>::adjacency_iterator ai, aend;
|
||||
for (tie(ai, aend) = adjacent_vertices(u, g); ai != aend; ++ai)
|
||||
*result++ = *ai;
|
||||
}
|
||||
|
||||
template <class Graph, class VertexIterator, class OutputIterator>
|
||||
void neighbors(const Graph& g,
|
||||
VertexIterator first, VertexIterator last,
|
||||
OutputIterator result)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
neighbors(g, *first, result);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// O(m n)
|
||||
template <class VertexListGraph, class OutputIterator>
|
||||
typename graph_traits<VertexListGraph>::degree_size_type
|
||||
edge_connectivity(VertexListGraph& g, OutputIterator disconnecting_set)
|
||||
{
|
||||
//-------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
typedef graph_traits<VertexListGraph> Traits;
|
||||
typedef typename Traits::vertex_iterator vertex_iterator;
|
||||
typedef typename Traits::edge_iterator edge_iterator;
|
||||
typedef typename Traits::out_edge_iterator out_edge_iterator;
|
||||
typedef typename Traits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename Traits::degree_size_type degree_size_type;
|
||||
typedef color_traits<default_color_type> Color;
|
||||
|
||||
typedef adjacency_list_traits<vecS, vecS, directedS> Tr;
|
||||
typedef typename Tr::edge_descriptor Tr_edge_desc;
|
||||
typedef adjacency_list<vecS, vecS, directedS, no_property,
|
||||
property<edge_capacity_t, degree_size_type,
|
||||
property<edge_residual_capacity_t, degree_size_type,
|
||||
property<edge_reverse_t, Tr_edge_desc> > > >
|
||||
FlowGraph;
|
||||
typedef typename graph_traits<FlowGraph>::edge_descriptor edge_descriptor;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Variable Declarations
|
||||
vertex_descriptor u, v, p, k;
|
||||
edge_descriptor e1, e2;
|
||||
bool inserted;
|
||||
vertex_iterator vi, vi_end;
|
||||
edge_iterator ei, ei_end;
|
||||
degree_size_type delta, alpha_star, alpha_S_k;
|
||||
std::set<vertex_descriptor> S, neighbor_S;
|
||||
std::vector<vertex_descriptor> S_star, non_neighbor_S;
|
||||
std::vector<default_color_type> color(num_vertices(g));
|
||||
std::vector<edge_descriptor> pred(num_vertices(g));
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Create a network flow graph out of the undirected graph
|
||||
FlowGraph flow_g(num_vertices(g));
|
||||
|
||||
typename property_map<FlowGraph, edge_capacity_t>::type
|
||||
cap = get(edge_capacity, flow_g);
|
||||
typename property_map<FlowGraph, edge_residual_capacity_t>::type
|
||||
res_cap = get(edge_residual_capacity, flow_g);
|
||||
typename property_map<FlowGraph, edge_reverse_t>::type
|
||||
rev_edge = get(edge_reverse, flow_g);
|
||||
|
||||
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
|
||||
u = source(*ei, g), v = target(*ei, g);
|
||||
tie(e1, inserted) = add_edge(u, v, flow_g);
|
||||
cap[e1] = 1;
|
||||
tie(e2, inserted) = add_edge(v, u, flow_g);
|
||||
cap[e2] = 1; // not sure about this
|
||||
rev_edge[e1] = e2;
|
||||
rev_edge[e2] = e1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// The Algorithm
|
||||
|
||||
tie(p, delta) = detail::min_degree_vertex(g);
|
||||
S_star.push_back(p);
|
||||
alpha_star = delta;
|
||||
S.insert(p);
|
||||
neighbor_S.insert(p);
|
||||
detail::neighbors(g, S.begin(), S.end(),
|
||||
std::inserter(neighbor_S, neighbor_S.begin()));
|
||||
|
||||
std::set_difference(vertices(g).first, vertices(g).second,
|
||||
neighbor_S.begin(), neighbor_S.end(),
|
||||
std::back_inserter(non_neighbor_S));
|
||||
|
||||
while (!non_neighbor_S.empty()) { // at most n - 1 times
|
||||
k = non_neighbor_S.front();
|
||||
|
||||
alpha_S_k = edmonds_karp_max_flow
|
||||
(flow_g, p, k, cap, res_cap, rev_edge, &color[0], &pred[0]);
|
||||
|
||||
if (alpha_S_k < alpha_star) {
|
||||
alpha_star = alpha_S_k;
|
||||
S_star.clear();
|
||||
for (tie(vi, vi_end) = vertices(flow_g); vi != vi_end; ++vi)
|
||||
if (color[*vi] != Color::white())
|
||||
S_star.push_back(*vi);
|
||||
}
|
||||
S.insert(k);
|
||||
neighbor_S.insert(k);
|
||||
detail::neighbors(g, k, std::inserter(neighbor_S, neighbor_S.begin()));
|
||||
non_neighbor_S.clear();
|
||||
std::set_difference(vertices(g).first, vertices(g).second,
|
||||
neighbor_S.begin(), neighbor_S.end(),
|
||||
std::back_inserter(non_neighbor_S));
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// Compute edges of the cut [S*, ~S*]
|
||||
std::vector<bool> in_S_star(num_vertices(g), false);
|
||||
typename std::vector<vertex_descriptor>::iterator si;
|
||||
for (si = S_star.begin(); si != S_star.end(); ++si)
|
||||
in_S_star[*si] = true;
|
||||
|
||||
degree_size_type c = 0;
|
||||
for (si = S_star.begin(); si != S_star.end(); ++si) {
|
||||
out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(*si, g); ei != ei_end; ++ei)
|
||||
if (!in_S_star[target(*ei, g)]) {
|
||||
*disconnecting_set++ = *ei;
|
||||
++c;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_EDGE_CONNECTIVITY
|
||||
304
libraries/include/boost/graph/edge_list.hpp
Normal file
304
libraries/include/boost/graph/edge_list.hpp
Normal file
@@ -0,0 +1,304 @@
|
||||
//=======================================================================
|
||||
// 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_EDGE_LIST_HPP
|
||||
#define BOOST_GRAPH_EDGE_LIST_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//
|
||||
// The edge_list class is an EdgeListGraph module that is constructed
|
||||
// from a pair of iterators whose value type is a pair of vertex
|
||||
// descriptors.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// typedef std::pair<int,int> E;
|
||||
// list<E> elist;
|
||||
// ...
|
||||
// typedef edge_list<list<E>::iterator> Graph;
|
||||
// Graph g(elist.begin(), elist.end());
|
||||
//
|
||||
// If the iterators are random access, then Graph::edge_descriptor
|
||||
// is of Integral type, otherwise it is a struct, though it is
|
||||
// convertible to an Integral type.
|
||||
//
|
||||
|
||||
struct edge_list_tag { };
|
||||
|
||||
// The implementation class for edge_list.
|
||||
template <class G, class EdgeIter, class T, class D>
|
||||
class edge_list_impl
|
||||
{
|
||||
public:
|
||||
typedef D edge_id;
|
||||
typedef T Vpair;
|
||||
typedef typename Vpair::first_type V;
|
||||
typedef V vertex_descriptor;
|
||||
typedef edge_list_tag graph_tag;
|
||||
typedef void edge_property_type;
|
||||
|
||||
struct edge_descriptor
|
||||
{
|
||||
edge_descriptor() { }
|
||||
edge_descriptor(EdgeIter p, edge_id id) : _ptr(p), _id(id) { }
|
||||
operator edge_id() { return _id; }
|
||||
EdgeIter _ptr;
|
||||
edge_id _id;
|
||||
};
|
||||
typedef edge_descriptor E;
|
||||
|
||||
struct edge_iterator
|
||||
{
|
||||
typedef edge_iterator self;
|
||||
typedef E value_type;
|
||||
typedef E& reference;
|
||||
typedef E* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
edge_iterator() { }
|
||||
edge_iterator(EdgeIter iter) : _iter(iter), _i(0) { }
|
||||
E operator*() { return E(_iter, _i); }
|
||||
self& operator++() { ++_iter; ++_i; return *this; }
|
||||
self operator++(int) { self t = *this; ++(*this); return t; }
|
||||
bool operator==(const self& x) { return _iter == x._iter; }
|
||||
bool operator!=(const self& x) { return _iter != x._iter; }
|
||||
EdgeIter _iter;
|
||||
edge_id _i;
|
||||
};
|
||||
typedef void out_edge_iterator;
|
||||
typedef void in_edge_iterator;
|
||||
typedef void adjacency_iterator;
|
||||
typedef void vertex_iterator;
|
||||
};
|
||||
|
||||
template <class G, class EI, class T, class D>
|
||||
std::pair<typename edge_list_impl<G,EI,T,D>::edge_iterator,
|
||||
typename edge_list_impl<G,EI,T,D>::edge_iterator>
|
||||
edges(const edge_list_impl<G,EI,T,D>& g_) {
|
||||
const G& g = static_cast<const G&>(g_);
|
||||
typedef typename edge_list_impl<G,EI,T,D>::edge_iterator edge_iterator;
|
||||
return std::make_pair(edge_iterator(g._first), edge_iterator(g._last));
|
||||
}
|
||||
template <class G, class EI, class T, class D>
|
||||
typename edge_list_impl<G,EI,T,D>::vertex_descriptor
|
||||
source(typename edge_list_impl<G,EI,T,D>::edge_descriptor e,
|
||||
const edge_list_impl<G,EI,T,D>&) {
|
||||
return (*e._ptr).first;
|
||||
}
|
||||
template <class G, class EI, class T, class D>
|
||||
typename edge_list_impl<G,EI,T,D>::vertex_descriptor
|
||||
target(typename edge_list_impl<G,EI,T,D>::edge_descriptor e,
|
||||
const edge_list_impl<G,EI,T,D>&) {
|
||||
return (*e._ptr).second;
|
||||
}
|
||||
|
||||
template <class D, class E>
|
||||
class el_edge_property_map
|
||||
: public put_get_helper<D, el_edge_property_map<D,E> >{
|
||||
public:
|
||||
typedef E key_type;
|
||||
typedef D value_type;
|
||||
typedef D reference;
|
||||
typedef readable_property_map_tag category;
|
||||
|
||||
value_type operator[](key_type e) const {
|
||||
return e._i;
|
||||
}
|
||||
};
|
||||
struct edge_list_edge_property_selector {
|
||||
template <class Graph, class Property, class Tag>
|
||||
struct bind_ {
|
||||
typedef el_edge_property_map<typename Graph::edge_id,
|
||||
typename Graph::edge_descriptor> type;
|
||||
typedef type const_type;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct edge_property_selector<edge_list_tag> {
|
||||
typedef edge_list_edge_property_selector type;
|
||||
};
|
||||
|
||||
template <class G, class EI, class T, class D>
|
||||
typename property_map< edge_list_impl<G,EI,T,D>, edge_index_t>::type
|
||||
get(edge_index_t, const edge_list_impl<G,EI,T,D>&) {
|
||||
typedef typename property_map< edge_list_impl<G,EI,T,D>,
|
||||
edge_index_t>::type EdgeIndexMap;
|
||||
return EdgeIndexMap();
|
||||
}
|
||||
|
||||
template <class G, class EI, class T, class D>
|
||||
inline D
|
||||
get(edge_index_t, const edge_list_impl<G,EI,T,D>&,
|
||||
typename edge_list_impl<G,EI,T,D>::edge_descriptor e) {
|
||||
return e._i;
|
||||
}
|
||||
|
||||
// A specialized implementation for when the iterators are random access.
|
||||
|
||||
struct edge_list_ra_tag { };
|
||||
|
||||
template <class G, class EdgeIter, class T, class D>
|
||||
class edge_list_impl_ra
|
||||
{
|
||||
public:
|
||||
typedef D edge_id;
|
||||
typedef T Vpair;
|
||||
typedef typename Vpair::first_type V;
|
||||
typedef edge_list_ra_tag graph_tag;
|
||||
typedef void edge_property_type;
|
||||
|
||||
typedef edge_id edge_descriptor;
|
||||
typedef V vertex_descriptor;
|
||||
typedef typename boost::integer_range<edge_id>::iterator edge_iterator;
|
||||
typedef void out_edge_iterator;
|
||||
typedef void in_edge_iterator;
|
||||
typedef void adjacency_iterator;
|
||||
typedef void vertex_iterator;
|
||||
};
|
||||
|
||||
template <class G, class EI, class T, class D>
|
||||
std::pair<typename edge_list_impl_ra<G,EI,T,D>::edge_iterator,
|
||||
typename edge_list_impl_ra<G,EI,T,D>::edge_iterator>
|
||||
edges(const edge_list_impl_ra<G,EI,T,D>& g_)
|
||||
{
|
||||
const G& g = static_cast<const G&>(g_);
|
||||
typedef typename edge_list_impl_ra<G,EI,T,D>::edge_iterator edge_iterator;
|
||||
return std::make_pair(edge_iterator(0), edge_iterator(g._last - g._first));
|
||||
}
|
||||
template <class G, class EI, class T, class D>
|
||||
typename edge_list_impl_ra<G,EI,T,D>::vertex_descriptor
|
||||
source(typename edge_list_impl_ra<G,EI,T,D>::edge_descriptor e,
|
||||
const edge_list_impl_ra<G,EI,T,D>& g_)
|
||||
{
|
||||
const G& g = static_cast<const G&>(g_);
|
||||
return g._first[e].first;
|
||||
}
|
||||
template <class G, class EI, class T, class D>
|
||||
typename edge_list_impl_ra<G,EI,T,D>::vertex_descriptor
|
||||
target(typename edge_list_impl_ra<G,EI,T,D>::edge_descriptor e,
|
||||
const edge_list_impl_ra<G,EI,T,D>& g_)
|
||||
{
|
||||
const G& g = static_cast<const G&>(g_);
|
||||
return g._first[e].second;
|
||||
}
|
||||
template <class E>
|
||||
class el_ra_edge_property_map
|
||||
: public put_get_helper<E, el_ra_edge_property_map<E> >{
|
||||
public:
|
||||
typedef E key_type;
|
||||
typedef E value_type;
|
||||
typedef E reference;
|
||||
typedef readable_property_map_tag category;
|
||||
|
||||
value_type operator[](key_type e) const {
|
||||
return e;
|
||||
}
|
||||
};
|
||||
struct edge_list_ra_edge_property_selector {
|
||||
template <class Graph, class Property, class Tag>
|
||||
struct bind_ {
|
||||
typedef el_ra_edge_property_map<typename Graph::edge_descriptor> type;
|
||||
typedef type const_type;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct edge_property_selector<edge_list_ra_tag> {
|
||||
typedef edge_list_ra_edge_property_selector type;
|
||||
};
|
||||
template <class G, class EI, class T, class D>
|
||||
inline
|
||||
typename property_map< edge_list_impl_ra<G,EI,T,D>, edge_index_t>::type
|
||||
get(edge_index_t, const edge_list_impl_ra<G,EI,T,D>&) {
|
||||
typedef typename property_map< edge_list_impl_ra<G,EI,T,D>,
|
||||
edge_index_t>::type EdgeIndexMap;
|
||||
return EdgeIndexMap();
|
||||
}
|
||||
|
||||
template <class G, class EI, class T, class D>
|
||||
inline D
|
||||
get(edge_index_t, const edge_list_impl_ra<G,EI,T,D>&,
|
||||
typename edge_list_impl_ra<G,EI,T,D>::edge_descriptor e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
// Some helper classes for determining if the iterators are random access
|
||||
template <class Cat>
|
||||
struct is_random {
|
||||
enum { RET = false };
|
||||
typedef mpl::false_ type;
|
||||
};
|
||||
template <>
|
||||
struct is_random<std::random_access_iterator_tag> {
|
||||
enum { RET = true }; typedef mpl::true_ type;
|
||||
};
|
||||
|
||||
// The edge_list class conditionally inherits from one of the
|
||||
// above two classes.
|
||||
|
||||
template <class EdgeIter,
|
||||
#if !defined BOOST_NO_STD_ITERATOR_TRAITS
|
||||
class T = typename std::iterator_traits<EdgeIter>::value_type,
|
||||
class D = typename std::iterator_traits<EdgeIter>::difference_type,
|
||||
class Cat = typename std::iterator_traits<EdgeIter>::iterator_category>
|
||||
#else
|
||||
class T,
|
||||
class D,
|
||||
class Cat>
|
||||
#endif
|
||||
class edge_list
|
||||
: public mpl::if_< typename is_random<Cat>::type,
|
||||
edge_list_impl_ra< edge_list<EdgeIter,T,D,Cat>, EdgeIter,T,D>,
|
||||
edge_list_impl< edge_list<EdgeIter,T,D,Cat>, EdgeIter,T,D>
|
||||
>::type
|
||||
{
|
||||
public:
|
||||
typedef directed_tag directed_category;
|
||||
typedef allow_parallel_edge_tag edge_parallel_category;
|
||||
typedef edge_list_graph_tag traversal_category;
|
||||
typedef std::size_t edges_size_type;
|
||||
typedef std::size_t vertices_size_type;
|
||||
typedef std::size_t degree_size_type;
|
||||
edge_list(EdgeIter first, EdgeIter last) : _first(first), _last(last) {
|
||||
m_num_edges = std::distance(first, last);
|
||||
}
|
||||
edge_list(EdgeIter first, EdgeIter last, edges_size_type E)
|
||||
: _first(first), _last(last), m_num_edges(E) { }
|
||||
|
||||
EdgeIter _first, _last;
|
||||
edges_size_type m_num_edges;
|
||||
};
|
||||
|
||||
template <class EdgeIter, class T, class D, class Cat>
|
||||
std::size_t num_edges(const edge_list<EdgeIter, T, D, Cat>& el) {
|
||||
return el.m_num_edges;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
template <class EdgeIter>
|
||||
inline edge_list<EdgeIter>
|
||||
make_edge_list(EdgeIter first, EdgeIter last)
|
||||
{
|
||||
return edge_list<EdgeIter>(first, last);
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_GRAPH_EDGE_LIST_HPP */
|
||||
250
libraries/include/boost/graph/edmonds_karp_max_flow.hpp
Normal file
250
libraries/include/boost/graph/edmonds_karp_max_flow.hpp
Normal file
@@ -0,0 +1,250 @@
|
||||
//=======================================================================
|
||||
// Copyright 2000 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
||||
//
|
||||
// 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 EDMONDS_KARP_MAX_FLOW_HPP
|
||||
#define EDMONDS_KARP_MAX_FLOW_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm> // for std::min and std::max
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/pending/queue.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/filtered_graph.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// The "labeling" algorithm from "Network Flows" by Ahuja, Magnanti,
|
||||
// Orlin. I think this is the same as or very similar to the original
|
||||
// Edmonds-Karp algorithm. This solves the maximum flow problem.
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Graph, class ResCapMap>
|
||||
filtered_graph<Graph, is_residual_edge<ResCapMap> >
|
||||
residual_graph(Graph& g, ResCapMap residual_capacity) {
|
||||
return filtered_graph<Graph, is_residual_edge<ResCapMap> >
|
||||
(g, is_residual_edge<ResCapMap>(residual_capacity));
|
||||
}
|
||||
|
||||
template <class Graph, class PredEdgeMap, class ResCapMap,
|
||||
class RevEdgeMap>
|
||||
inline void
|
||||
augment(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
PredEdgeMap p,
|
||||
ResCapMap residual_capacity,
|
||||
RevEdgeMap reverse_edge)
|
||||
{
|
||||
typename graph_traits<Graph>::edge_descriptor e;
|
||||
typename graph_traits<Graph>::vertex_descriptor u;
|
||||
typedef typename property_traits<ResCapMap>::value_type FlowValue;
|
||||
|
||||
// find minimum residual capacity along the augmenting path
|
||||
FlowValue delta = (std::numeric_limits<FlowValue>::max)();
|
||||
e = p[sink];
|
||||
do {
|
||||
BOOST_USING_STD_MIN();
|
||||
delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, residual_capacity[e]);
|
||||
u = source(e, g);
|
||||
e = p[u];
|
||||
} while (u != src);
|
||||
|
||||
// push delta units of flow along the augmenting path
|
||||
e = p[sink];
|
||||
do {
|
||||
residual_capacity[e] -= delta;
|
||||
residual_capacity[reverse_edge[e]] += delta;
|
||||
u = source(e, g);
|
||||
e = p[u];
|
||||
} while (u != src);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Graph,
|
||||
class CapacityEdgeMap, class ResidualCapacityEdgeMap,
|
||||
class ReverseEdgeMap, class ColorMap, class PredEdgeMap>
|
||||
typename property_traits<CapacityEdgeMap>::value_type
|
||||
edmonds_karp_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
CapacityEdgeMap cap,
|
||||
ResidualCapacityEdgeMap res,
|
||||
ReverseEdgeMap rev,
|
||||
ColorMap color,
|
||||
PredEdgeMap pred)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator u_iter, u_end;
|
||||
typename graph_traits<Graph>::out_edge_iterator ei, e_end;
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
|
||||
for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
|
||||
res[*ei] = cap[*ei];
|
||||
|
||||
color[sink] = Color::gray();
|
||||
while (color[sink] != Color::white()) {
|
||||
boost::queue<vertex_t> Q;
|
||||
breadth_first_search
|
||||
(detail::residual_graph(g, res), src, Q,
|
||||
make_bfs_visitor(record_edge_predecessors(pred, on_tree_edge())),
|
||||
color);
|
||||
if (color[sink] != Color::white())
|
||||
detail::augment(g, src, sink, pred, res, rev);
|
||||
} // while
|
||||
|
||||
typename property_traits<CapacityEdgeMap>::value_type flow = 0;
|
||||
for (tie(ei, e_end) = out_edges(src, g); ei != e_end; ++ei)
|
||||
flow += (cap[*ei] - res[*ei]);
|
||||
return flow;
|
||||
} // edmonds_karp_max_flow()
|
||||
|
||||
namespace detail {
|
||||
//-------------------------------------------------------------------------
|
||||
// Handle default for color property map
|
||||
|
||||
// use of class here is a VC++ workaround
|
||||
template <class ColorMap>
|
||||
struct edmonds_karp_dispatch2 {
|
||||
template <class Graph, class PredMap, class P, class T, class R>
|
||||
static typename edge_capacity_value<Graph, P, T, R>::type
|
||||
apply
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
PredMap pred,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
ColorMap color)
|
||||
{
|
||||
return edmonds_karp_max_flow
|
||||
(g, src, sink,
|
||||
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
|
||||
choose_pmap(get_param(params, edge_residual_capacity),
|
||||
g, edge_residual_capacity),
|
||||
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
|
||||
color, pred);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct edmonds_karp_dispatch2<detail::error_property_not_found> {
|
||||
template <class Graph, class PredMap, class P, class T, class R>
|
||||
static typename edge_capacity_value<Graph, P, T, R>::type
|
||||
apply
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
PredMap pred,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
detail::error_property_not_found)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
size_type n = is_default_param(get_param(params, vertex_color)) ?
|
||||
num_vertices(g) : 1;
|
||||
std::vector<default_color_type> color_vec(n);
|
||||
return edmonds_karp_max_flow
|
||||
(g, src, sink,
|
||||
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
|
||||
choose_pmap(get_param(params, edge_residual_capacity),
|
||||
g, edge_residual_capacity),
|
||||
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
|
||||
make_iterator_property_map(color_vec.begin(), choose_const_pmap
|
||||
(get_param(params, vertex_index),
|
||||
g, vertex_index), color_vec[0]),
|
||||
pred);
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Handle default for predecessor property map
|
||||
|
||||
// use of class here is a VC++ workaround
|
||||
template <class PredMap>
|
||||
struct edmonds_karp_dispatch1 {
|
||||
template <class Graph, class P, class T, class R>
|
||||
static typename edge_capacity_value<Graph, P, T, R>::type
|
||||
apply(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
PredMap pred)
|
||||
{
|
||||
typedef typename property_value< bgl_named_params<P,T,R>, vertex_color_t>::type C;
|
||||
return edmonds_karp_dispatch2<C>::apply
|
||||
(g, src, sink, pred, params, get_param(params, vertex_color));
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct edmonds_karp_dispatch1<detail::error_property_not_found> {
|
||||
|
||||
template <class Graph, class P, class T, class R>
|
||||
static typename edge_capacity_value<Graph, P, T, R>::type
|
||||
apply
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
detail::error_property_not_found)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
size_type n = is_default_param(get_param(params, vertex_predecessor)) ?
|
||||
num_vertices(g) : 1;
|
||||
std::vector<edge_descriptor> pred_vec(n);
|
||||
|
||||
typedef typename property_value< bgl_named_params<P,T,R>, vertex_color_t>::type C;
|
||||
return edmonds_karp_dispatch2<C>::apply
|
||||
(g, src, sink,
|
||||
make_iterator_property_map(pred_vec.begin(), choose_const_pmap
|
||||
(get_param(params, vertex_index),
|
||||
g, vertex_index), pred_vec[0]),
|
||||
params,
|
||||
get_param(params, vertex_color));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Graph, class P, class T, class R>
|
||||
typename detail::edge_capacity_value<Graph, P, T, R>::type
|
||||
edmonds_karp_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename property_value< bgl_named_params<P,T,R>, vertex_predecessor_t>::type Pred;
|
||||
return detail::edmonds_karp_dispatch1<Pred>::apply
|
||||
(g, src, sink, params, get_param(params, vertex_predecessor));
|
||||
}
|
||||
|
||||
template <class Graph>
|
||||
typename property_traits<
|
||||
typename property_map<Graph, edge_capacity_t>::const_type
|
||||
>::value_type
|
||||
edmonds_karp_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink)
|
||||
{
|
||||
bgl_named_params<int, buffer_param_t> params(0);
|
||||
return edmonds_karp_max_flow(g, src, sink, params);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // EDMONDS_KARP_MAX_FLOW_HPP
|
||||
19
libraries/include/boost/graph/edmunds_karp_max_flow.hpp
Normal file
19
libraries/include/boost/graph/edmunds_karp_max_flow.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
//=======================================================================
|
||||
// (c) Copyright Juergen Hunold 2008
|
||||
// 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_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP
|
||||
#define BOOST_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
|
||||
# pragma message ("Warning: This header is deprecated. Please use: boost/graph/edmonds_karp_max_flow.hpp")
|
||||
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
# warning "This header is deprecated. Please use: boost/graph/edmonds_karp_max_flow.hpp"
|
||||
#endif
|
||||
|
||||
#include <boost/graph/edmonds_karp_max_flow.hpp>
|
||||
|
||||
#endif // BOOST_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP
|
||||
228
libraries/include/boost/graph/erdos_renyi_generator.hpp
Normal file
228
libraries/include/boost/graph/erdos_renyi_generator.hpp
Normal file
@@ -0,0 +1,228 @@
|
||||
// Copyright 2004, 2005 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
|
||||
#ifndef BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP
|
||||
#define BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/random/geometric_distribution.hpp>
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename RandomGenerator, typename Graph>
|
||||
class erdos_renyi_iterator
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category directed_category;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
|
||||
typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT
|
||||
(bool,
|
||||
is_undirected = (is_base_and_derived<undirected_tag,
|
||||
directed_category>::value
|
||||
|| is_same<undirected_tag, directed_category>::value));
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef std::pair<vertices_size_type, vertices_size_type> value_type;
|
||||
typedef const value_type& reference;
|
||||
typedef const value_type* pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
erdos_renyi_iterator() : gen(), n(0), edges(0), allow_self_loops(false) {}
|
||||
erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n,
|
||||
double fraction = 0.0, bool allow_self_loops = false)
|
||||
: gen(&gen), n(n), edges(edges_size_type(fraction * n * n)),
|
||||
allow_self_loops(allow_self_loops)
|
||||
{
|
||||
if (is_undirected) edges = edges / 2;
|
||||
next();
|
||||
}
|
||||
|
||||
erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n,
|
||||
edges_size_type m, bool allow_self_loops = false)
|
||||
: gen(&gen), n(n), edges(m),
|
||||
allow_self_loops(allow_self_loops)
|
||||
{
|
||||
next();
|
||||
}
|
||||
|
||||
reference operator*() const { return current; }
|
||||
pointer operator->() const { return ¤t; }
|
||||
|
||||
erdos_renyi_iterator& operator++()
|
||||
{
|
||||
--edges;
|
||||
next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
erdos_renyi_iterator operator++(int)
|
||||
{
|
||||
erdos_renyi_iterator temp(*this);
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool operator==(const erdos_renyi_iterator& other) const
|
||||
{ return edges == other.edges; }
|
||||
|
||||
bool operator!=(const erdos_renyi_iterator& other) const
|
||||
{ return !(*this == other); }
|
||||
|
||||
private:
|
||||
void next()
|
||||
{
|
||||
uniform_int<vertices_size_type> rand_vertex(0, n-1);
|
||||
current.first = rand_vertex(*gen);
|
||||
do {
|
||||
current.second = rand_vertex(*gen);
|
||||
} while (current.first == current.second && !allow_self_loops);
|
||||
}
|
||||
|
||||
RandomGenerator* gen;
|
||||
vertices_size_type n;
|
||||
edges_size_type edges;
|
||||
bool allow_self_loops;
|
||||
value_type current;
|
||||
};
|
||||
|
||||
template<typename RandomGenerator, typename Graph>
|
||||
class sorted_erdos_renyi_iterator
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category directed_category;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
|
||||
typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT
|
||||
(bool,
|
||||
is_undirected = (is_base_and_derived<undirected_tag,
|
||||
directed_category>::value
|
||||
|| is_same<undirected_tag, directed_category>::value));
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef std::pair<vertices_size_type, vertices_size_type> value_type;
|
||||
typedef const value_type& reference;
|
||||
typedef const value_type* pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
sorted_erdos_renyi_iterator()
|
||||
: gen(), rand_vertex(0.5), n(0), allow_self_loops(false),
|
||||
src((std::numeric_limits<vertices_size_type>::max)()), tgt(0), prob(0) {}
|
||||
sorted_erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n,
|
||||
double prob = 0.0,
|
||||
bool allow_self_loops = false)
|
||||
: gen(),
|
||||
// The "1.0 - prob" in the next line is to work around a Boost.Random
|
||||
// (and TR1) bug in the specification of geometric_distribution. It
|
||||
// should be replaced by "prob" when the issue is fixed.
|
||||
rand_vertex(1.0 - prob),
|
||||
n(n), allow_self_loops(allow_self_loops), src(0), tgt(0), prob(prob)
|
||||
{
|
||||
this->gen.reset(new uniform_01<RandomGenerator>(gen));
|
||||
|
||||
if (prob == 0.0) {src = (std::numeric_limits<vertices_size_type>::max)(); return;}
|
||||
next();
|
||||
}
|
||||
|
||||
reference operator*() const { return current; }
|
||||
pointer operator->() const { return ¤t; }
|
||||
|
||||
sorted_erdos_renyi_iterator& operator++()
|
||||
{
|
||||
next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
sorted_erdos_renyi_iterator operator++(int)
|
||||
{
|
||||
sorted_erdos_renyi_iterator temp(*this);
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool operator==(const sorted_erdos_renyi_iterator& other) const
|
||||
{ return src == other.src && tgt == other.tgt; }
|
||||
|
||||
bool operator!=(const sorted_erdos_renyi_iterator& other) const
|
||||
{ return !(*this == other); }
|
||||
|
||||
private:
|
||||
void next()
|
||||
{
|
||||
using std::sqrt;
|
||||
using std::floor;
|
||||
|
||||
// In order to get the edges from the generator in sorted order, one
|
||||
// effective (but slow) procedure would be to use a
|
||||
// bernoulli_distribution for each legal (src, tgt) pair. Because of the
|
||||
// O(n^2) cost of that, a geometric distribution is used. The geometric
|
||||
// distribution tells how many times the bernoulli_distribution would
|
||||
// need to be run until it returns true. Thus, this distribution can be
|
||||
// used to step through the edges which are actually present. Everything
|
||||
// beyond "tgt += increment" is done to effectively convert linear
|
||||
// indexing (the partial sums of the geometric distribution output) into
|
||||
// graph edges.
|
||||
assert (src != (std::numeric_limits<vertices_size_type>::max)());
|
||||
vertices_size_type increment = rand_vertex(*gen);
|
||||
tgt += increment;
|
||||
if (is_undirected) {
|
||||
// Update src and tgt based on position of tgt
|
||||
// Basically, we want the greatest src_increment such that (in \bbQ):
|
||||
// src_increment * (src + allow_self_loops + src_increment - 1/2) <= tgt
|
||||
// The result of the LHS of this, evaluated with the computed
|
||||
// src_increment, is then subtracted from tgt
|
||||
double src_minus_half = (src + allow_self_loops) - 0.5;
|
||||
double disc = src_minus_half * src_minus_half + 2 * tgt;
|
||||
double src_increment_fp = floor(sqrt(disc) - src_minus_half);
|
||||
vertices_size_type src_increment = vertices_size_type(src_increment_fp);
|
||||
if (src + src_increment >= n) {
|
||||
src = n;
|
||||
} else {
|
||||
tgt -= (src + allow_self_loops) * src_increment +
|
||||
src_increment * (src_increment - 1) / 2;
|
||||
src += src_increment;
|
||||
}
|
||||
} else {
|
||||
// Number of out edge positions possible from each vertex in this graph
|
||||
vertices_size_type possible_out_edges = n - (allow_self_loops ? 0 : 1);
|
||||
src += (std::min)(n - src, tgt / possible_out_edges);
|
||||
tgt %= possible_out_edges;
|
||||
}
|
||||
// Set end of graph code so (src, tgt) will be the same as for the end
|
||||
// sorted_erdos_renyi_iterator
|
||||
if (src >= n) {src = (std::numeric_limits<vertices_size_type>::max)(); tgt = 0;}
|
||||
// Copy (src, tgt) into current
|
||||
current.first = src;
|
||||
current.second = tgt;
|
||||
// Adjust for (src, src) edge being forbidden
|
||||
if (!allow_self_loops && tgt >= src) ++current.second;
|
||||
}
|
||||
|
||||
shared_ptr<uniform_01<RandomGenerator> > gen;
|
||||
geometric_distribution<vertices_size_type> rand_vertex;
|
||||
vertices_size_type n;
|
||||
bool allow_self_loops;
|
||||
vertices_size_type src, tgt;
|
||||
value_type current;
|
||||
double prob;
|
||||
};
|
||||
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP
|
||||
55
libraries/include/boost/graph/exception.hpp
Normal file
55
libraries/include/boost/graph/exception.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//=======================================================================
|
||||
// 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_EXCEPTION_HPP
|
||||
#define BOOST_GRAPH_EXCEPTION_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct bad_graph : public std::invalid_argument {
|
||||
bad_graph(const std::string& what_arg)
|
||||
: std::invalid_argument(what_arg) { }
|
||||
};
|
||||
|
||||
struct not_a_dag : public bad_graph {
|
||||
not_a_dag()
|
||||
: bad_graph("The graph must be a DAG.")
|
||||
{ }
|
||||
};
|
||||
|
||||
struct negative_edge : public bad_graph {
|
||||
negative_edge()
|
||||
: bad_graph("The graph may not contain an edge with negative weight.")
|
||||
{ }
|
||||
};
|
||||
|
||||
struct negative_cycle : public bad_graph {
|
||||
negative_cycle()
|
||||
: bad_graph("The graph may not contain negative cycles.")
|
||||
{ }
|
||||
};
|
||||
|
||||
struct not_connected : public bad_graph {
|
||||
not_connected()
|
||||
: bad_graph("The graph must be connected.")
|
||||
{ }
|
||||
};
|
||||
|
||||
struct not_complete : public bad_graph {
|
||||
not_complete()
|
||||
: bad_graph("The graph must be complete.")
|
||||
{ }
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_EXCEPTION_HPP
|
||||
507
libraries/include/boost/graph/filtered_graph.hpp
Normal file
507
libraries/include/boost/graph/filtered_graph.hpp
Normal file
@@ -0,0 +1,507 @@
|
||||
//=======================================================================
|
||||
// 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_FILTERED_GRAPH_HPP
|
||||
#define BOOST_FILTERED_GRAPH_HPP
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/adjacency_iterator.hpp>
|
||||
#include <boost/iterator/filter_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//=========================================================================
|
||||
// Some predicate classes.
|
||||
|
||||
struct keep_all {
|
||||
template <typename T>
|
||||
bool operator()(const T&) const { return true; }
|
||||
};
|
||||
|
||||
// Keep residual edges (used in maximum-flow algorithms).
|
||||
template <typename ResidualCapacityEdgeMap>
|
||||
struct is_residual_edge {
|
||||
is_residual_edge() { }
|
||||
is_residual_edge(ResidualCapacityEdgeMap rcap) : m_rcap(rcap) { }
|
||||
template <typename Edge>
|
||||
bool operator()(const Edge& e) const {
|
||||
return 0 < get(m_rcap, e);
|
||||
}
|
||||
ResidualCapacityEdgeMap m_rcap;
|
||||
};
|
||||
|
||||
template <typename Set>
|
||||
struct is_in_subset {
|
||||
is_in_subset() : m_s(0) { }
|
||||
is_in_subset(const Set& s) : m_s(&s) { }
|
||||
|
||||
template <typename Elt>
|
||||
bool operator()(const Elt& x) const {
|
||||
return set_contains(*m_s, x);
|
||||
}
|
||||
const Set* m_s;
|
||||
};
|
||||
|
||||
template <typename Set>
|
||||
struct is_not_in_subset {
|
||||
is_not_in_subset() : m_s(0) { }
|
||||
is_not_in_subset(const Set& s) : m_s(&s) { }
|
||||
|
||||
template <typename Elt>
|
||||
bool operator()(const Elt& x) const {
|
||||
return !set_contains(*m_s, x);
|
||||
}
|
||||
const Set* m_s;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename EdgePredicate, typename VertexPredicate, typename Graph>
|
||||
struct out_edge_predicate {
|
||||
out_edge_predicate() { }
|
||||
out_edge_predicate(EdgePredicate ep, VertexPredicate vp,
|
||||
const Graph& g)
|
||||
: m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { }
|
||||
|
||||
template <typename Edge>
|
||||
bool operator()(const Edge& e) const {
|
||||
return m_edge_pred(e) && m_vertex_pred(target(e, *m_g));
|
||||
}
|
||||
EdgePredicate m_edge_pred;
|
||||
VertexPredicate m_vertex_pred;
|
||||
const Graph* m_g;
|
||||
};
|
||||
|
||||
template <typename EdgePredicate, typename VertexPredicate, typename Graph>
|
||||
struct in_edge_predicate {
|
||||
in_edge_predicate() { }
|
||||
in_edge_predicate(EdgePredicate ep, VertexPredicate vp,
|
||||
const Graph& g)
|
||||
: m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { }
|
||||
|
||||
template <typename Edge>
|
||||
bool operator()(const Edge& e) const {
|
||||
return m_edge_pred(e) && m_vertex_pred(source(e, *m_g));
|
||||
}
|
||||
EdgePredicate m_edge_pred;
|
||||
VertexPredicate m_vertex_pred;
|
||||
const Graph* m_g;
|
||||
};
|
||||
|
||||
template <typename EdgePredicate, typename VertexPredicate, typename Graph>
|
||||
struct edge_predicate {
|
||||
edge_predicate() { }
|
||||
edge_predicate(EdgePredicate ep, VertexPredicate vp,
|
||||
const Graph& g)
|
||||
: m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { }
|
||||
|
||||
template <typename Edge>
|
||||
bool operator()(const Edge& e) const {
|
||||
return m_edge_pred(e)
|
||||
&& m_vertex_pred(source(e, *m_g)) && m_vertex_pred(target(e, *m_g));
|
||||
}
|
||||
EdgePredicate m_edge_pred;
|
||||
VertexPredicate m_vertex_pred;
|
||||
const Graph* m_g;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// Filtered Graph
|
||||
|
||||
struct filtered_graph_tag { };
|
||||
|
||||
// This base class is a stupid hack to change overload resolution
|
||||
// rules for the source and target functions so that they are a
|
||||
// worse match than the source and target functions defined for
|
||||
// pairs in graph_traits.hpp. I feel dirty. -JGS
|
||||
template <class G>
|
||||
struct filtered_graph_base {
|
||||
typedef graph_traits<G> Traits;
|
||||
typedef typename Traits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename Traits::edge_descriptor edge_descriptor;
|
||||
filtered_graph_base(const G& g) : m_g(g) { }
|
||||
//protected:
|
||||
const G& m_g;
|
||||
};
|
||||
|
||||
template <typename Graph,
|
||||
typename EdgePredicate,
|
||||
typename VertexPredicate = keep_all>
|
||||
class filtered_graph : public filtered_graph_base<Graph> {
|
||||
typedef filtered_graph_base<Graph> Base;
|
||||
typedef graph_traits<Graph> Traits;
|
||||
typedef filtered_graph self;
|
||||
public:
|
||||
typedef Graph graph_type;
|
||||
typedef detail::out_edge_predicate<EdgePredicate,
|
||||
VertexPredicate, self> OutEdgePred;
|
||||
typedef detail::in_edge_predicate<EdgePredicate,
|
||||
VertexPredicate, self> InEdgePred;
|
||||
typedef detail::edge_predicate<EdgePredicate,
|
||||
VertexPredicate, self> EdgePred;
|
||||
|
||||
// Constructors
|
||||
filtered_graph(const Graph& g, EdgePredicate ep)
|
||||
: Base(g), m_edge_pred(ep) { }
|
||||
|
||||
filtered_graph(const Graph& g, EdgePredicate ep, VertexPredicate vp)
|
||||
: Base(g), m_edge_pred(ep), m_vertex_pred(vp) { }
|
||||
|
||||
// Graph requirements
|
||||
typedef typename Traits::vertex_descriptor vertex_descriptor;
|
||||
typedef 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 filter_iterator<
|
||||
OutEdgePred, typename Traits::out_edge_iterator
|
||||
> out_edge_iterator;
|
||||
|
||||
typedef typename Traits::degree_size_type degree_size_type;
|
||||
|
||||
// AdjacencyGraph requirements
|
||||
typedef typename adjacency_iterator_generator<self,
|
||||
vertex_descriptor, out_edge_iterator>::type adjacency_iterator;
|
||||
|
||||
// BidirectionalGraph requirements
|
||||
typedef filter_iterator<
|
||||
InEdgePred, typename Traits::in_edge_iterator
|
||||
> in_edge_iterator;
|
||||
|
||||
// VertexListGraph requirements
|
||||
typedef filter_iterator<
|
||||
VertexPredicate, typename Traits::vertex_iterator
|
||||
> vertex_iterator;
|
||||
typedef typename Traits::vertices_size_type vertices_size_type;
|
||||
|
||||
// EdgeListGraph requirements
|
||||
typedef filter_iterator<
|
||||
EdgePred, typename Traits::edge_iterator
|
||||
> edge_iterator;
|
||||
typedef typename Traits::edges_size_type edges_size_type;
|
||||
|
||||
typedef typename ::boost::edge_property_type<Graph>::type edge_property_type;
|
||||
typedef typename ::boost::vertex_property_type<Graph>::type vertex_property_type;
|
||||
typedef filtered_graph_tag graph_tag;
|
||||
|
||||
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
||||
// Bundled properties support
|
||||
template<typename Descriptor>
|
||||
typename graph::detail::bundled_result<Graph, Descriptor>::type&
|
||||
operator[](Descriptor x)
|
||||
{ return const_cast<Graph&>(this->m_g)[x]; }
|
||||
|
||||
template<typename Descriptor>
|
||||
typename graph::detail::bundled_result<Graph, Descriptor>::type const&
|
||||
operator[](Descriptor x) const
|
||||
{ return this->m_g[x]; }
|
||||
#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
||||
|
||||
static vertex_descriptor null_vertex()
|
||||
{
|
||||
return Graph::null_vertex();
|
||||
}
|
||||
|
||||
//private:
|
||||
EdgePredicate m_edge_pred;
|
||||
VertexPredicate m_vertex_pred;
|
||||
};
|
||||
|
||||
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
||||
template<typename Graph, typename EdgePredicate, typename VertexPredicate>
|
||||
struct vertex_bundle_type<filtered_graph<Graph, EdgePredicate,
|
||||
VertexPredicate> >
|
||||
: vertex_bundle_type<Graph> { };
|
||||
|
||||
template<typename Graph, typename EdgePredicate, typename VertexPredicate>
|
||||
struct edge_bundle_type<filtered_graph<Graph, EdgePredicate,
|
||||
VertexPredicate> >
|
||||
: edge_bundle_type<Graph> { };
|
||||
#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
||||
|
||||
//===========================================================================
|
||||
// Non-member functions for the Filtered Edge Graph
|
||||
|
||||
// Helper functions
|
||||
template <typename Graph, typename EdgePredicate>
|
||||
inline filtered_graph<Graph, EdgePredicate>
|
||||
make_filtered_graph(Graph& g, EdgePredicate ep) {
|
||||
return filtered_graph<Graph, EdgePredicate>(g, ep);
|
||||
}
|
||||
template <typename Graph, typename EdgePredicate, typename VertexPredicate>
|
||||
inline filtered_graph<Graph, EdgePredicate, VertexPredicate>
|
||||
make_filtered_graph(Graph& g, EdgePredicate ep, VertexPredicate vp) {
|
||||
return filtered_graph<Graph, EdgePredicate, VertexPredicate>(g, ep, vp);
|
||||
}
|
||||
|
||||
template <typename Graph, typename EdgePredicate>
|
||||
inline filtered_graph<const Graph, EdgePredicate>
|
||||
make_filtered_graph(const Graph& g, EdgePredicate ep) {
|
||||
return filtered_graph<const Graph, EdgePredicate>(g, ep);
|
||||
}
|
||||
template <typename Graph, typename EdgePredicate, typename VertexPredicate>
|
||||
inline filtered_graph<const Graph, EdgePredicate, VertexPredicate>
|
||||
make_filtered_graph(const Graph& g, EdgePredicate ep, VertexPredicate vp) {
|
||||
return filtered_graph<const Graph, EdgePredicate, VertexPredicate>(g, ep, vp);
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
std::pair<typename filtered_graph<G, EP, VP>::vertex_iterator,
|
||||
typename filtered_graph<G, EP, VP>::vertex_iterator>
|
||||
vertices(const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typedef filtered_graph<G, EP, VP> Graph;
|
||||
typename graph_traits<G>::vertex_iterator f, l;
|
||||
tie(f, l) = vertices(g.m_g);
|
||||
typedef typename Graph::vertex_iterator iter;
|
||||
return std::make_pair(iter(g.m_vertex_pred, f, l),
|
||||
iter(g.m_vertex_pred, l, l));
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
std::pair<typename filtered_graph<G, EP, VP>::edge_iterator,
|
||||
typename filtered_graph<G, EP, VP>::edge_iterator>
|
||||
edges(const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typedef filtered_graph<G, EP, VP> Graph;
|
||||
typename Graph::EdgePred pred(g.m_edge_pred, g.m_vertex_pred, g);
|
||||
typename graph_traits<G>::edge_iterator f, l;
|
||||
tie(f, l) = edges(g.m_g);
|
||||
typedef typename Graph::edge_iterator iter;
|
||||
return std::make_pair(iter(pred, f, l), iter(pred, l, l));
|
||||
}
|
||||
|
||||
// An alternative for num_vertices() and num_edges() would be to
|
||||
// count the number in the filtered graph. This is problematic
|
||||
// because of the interaction with the vertex indices... they would
|
||||
// no longer go from 0 to num_vertices(), which would cause trouble
|
||||
// for algorithms allocating property storage in an array. We could
|
||||
// try to create a mapping to new recalibrated indices, but I don't
|
||||
// see an efficient way to do this.
|
||||
//
|
||||
// However, the current solution is still unsatisfactory because
|
||||
// the following semantic constraints no longer hold:
|
||||
// tie(vi, viend) = vertices(g);
|
||||
// assert(std::distance(vi, viend) == num_vertices(g));
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
typename filtered_graph<G, EP, VP>::vertices_size_type
|
||||
num_vertices(const filtered_graph<G, EP, VP>& g) {
|
||||
return num_vertices(g.m_g);
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
typename filtered_graph<G, EP, VP>::edges_size_type
|
||||
num_edges(const filtered_graph<G, EP, VP>& g) {
|
||||
return num_edges(g.m_g);
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
typename filtered_graph_base<G>::vertex_descriptor
|
||||
source(typename filtered_graph_base<G>::edge_descriptor e,
|
||||
const filtered_graph_base<G>& g)
|
||||
{
|
||||
return source(e, g.m_g);
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
typename filtered_graph_base<G>::vertex_descriptor
|
||||
target(typename filtered_graph_base<G>::edge_descriptor e,
|
||||
const filtered_graph_base<G>& g)
|
||||
{
|
||||
return target(e, g.m_g);
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
std::pair<typename filtered_graph<G, EP, VP>::out_edge_iterator,
|
||||
typename filtered_graph<G, EP, VP>::out_edge_iterator>
|
||||
out_edges(typename filtered_graph<G, EP, VP>::vertex_descriptor u,
|
||||
const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typedef filtered_graph<G, EP, VP> Graph;
|
||||
typename Graph::OutEdgePred pred(g.m_edge_pred, g.m_vertex_pred, g);
|
||||
typedef typename Graph::out_edge_iterator iter;
|
||||
typename graph_traits<G>::out_edge_iterator f, l;
|
||||
tie(f, l) = out_edges(u, g.m_g);
|
||||
return std::make_pair(iter(pred, f, l), iter(pred, l, l));
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
typename filtered_graph<G, EP, VP>::degree_size_type
|
||||
out_degree(typename filtered_graph<G, EP, VP>::vertex_descriptor u,
|
||||
const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typename filtered_graph<G, EP, VP>::degree_size_type n = 0;
|
||||
typename filtered_graph<G, EP, VP>::out_edge_iterator f, l;
|
||||
for (tie(f, l) = out_edges(u, g); f != l; ++f)
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
std::pair<typename filtered_graph<G, EP, VP>::adjacency_iterator,
|
||||
typename filtered_graph<G, EP, VP>::adjacency_iterator>
|
||||
adjacent_vertices(typename filtered_graph<G, EP, VP>::vertex_descriptor u,
|
||||
const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typedef filtered_graph<G, EP, VP> Graph;
|
||||
typedef typename Graph::adjacency_iterator adjacency_iterator;
|
||||
typename Graph::out_edge_iterator f, l;
|
||||
tie(f, l) = out_edges(u, g);
|
||||
return std::make_pair(adjacency_iterator(f, const_cast<Graph*>(&g)),
|
||||
adjacency_iterator(l, const_cast<Graph*>(&g)));
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
std::pair<typename filtered_graph<G, EP, VP>::in_edge_iterator,
|
||||
typename filtered_graph<G, EP, VP>::in_edge_iterator>
|
||||
in_edges(typename filtered_graph<G, EP, VP>::vertex_descriptor u,
|
||||
const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typedef filtered_graph<G, EP, VP> Graph;
|
||||
typename Graph::InEdgePred pred(g.m_edge_pred, g.m_vertex_pred, g);
|
||||
typedef typename Graph::in_edge_iterator iter;
|
||||
typename graph_traits<G>::in_edge_iterator f, l;
|
||||
tie(f, l) = in_edges(u, g.m_g);
|
||||
return std::make_pair(iter(pred, f, l), iter(pred, l, l));
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
typename filtered_graph<G, EP, VP>::degree_size_type
|
||||
in_degree(typename filtered_graph<G, EP, VP>::vertex_descriptor u,
|
||||
const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typename filtered_graph<G, EP, VP>::degree_size_type n = 0;
|
||||
typename filtered_graph<G, EP, VP>::in_edge_iterator f, l;
|
||||
for (tie(f, l) = in_edges(u, g); f != l; ++f)
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
std::pair<typename filtered_graph<G, EP, VP>::edge_descriptor, bool>
|
||||
edge(typename filtered_graph<G, EP, VP>::vertex_descriptor u,
|
||||
typename filtered_graph<G, EP, VP>::vertex_descriptor v,
|
||||
const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typename graph_traits<G>::edge_descriptor e;
|
||||
bool exists;
|
||||
tie(e, exists) = edge(u, v, g.m_g);
|
||||
return std::make_pair(e, exists && g.m_edge_pred(e));
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP>
|
||||
std::pair<typename filtered_graph<G, EP, VP>::out_edge_iterator,
|
||||
typename filtered_graph<G, EP, VP>::out_edge_iterator>
|
||||
edge_range(typename filtered_graph<G, EP, VP>::vertex_descriptor u,
|
||||
typename filtered_graph<G, EP, VP>::vertex_descriptor v,
|
||||
const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
typedef filtered_graph<G, EP, VP> Graph;
|
||||
typename Graph::OutEdgePred pred(g.m_edge_pred, g.m_vertex_pred, g);
|
||||
typedef typename Graph::out_edge_iterator iter;
|
||||
typename graph_traits<G>::out_edge_iterator f, l;
|
||||
tie(f, l) = edge_range(u, v, g.m_g);
|
||||
return std::make_pair(iter(pred, f, l), iter(pred, l, l));
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// Property map
|
||||
|
||||
namespace detail {
|
||||
struct filtered_graph_property_selector {
|
||||
template <class FilteredGraph, class Property, class Tag>
|
||||
struct bind_ {
|
||||
typedef typename FilteredGraph::graph_type Graph;
|
||||
typedef property_map<Graph, Tag> Map;
|
||||
typedef typename Map::type type;
|
||||
typedef typename Map::const_type const_type;
|
||||
};
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <>
|
||||
struct vertex_property_selector<filtered_graph_tag> {
|
||||
typedef detail::filtered_graph_property_selector type;
|
||||
};
|
||||
template <>
|
||||
struct edge_property_selector<filtered_graph_tag> {
|
||||
typedef detail::filtered_graph_property_selector type;
|
||||
};
|
||||
|
||||
template <typename G, typename EP, typename VP, typename Property>
|
||||
typename property_map<G, Property>::type
|
||||
get(Property p, filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
return get(p, const_cast<G&>(g.m_g));
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP,typename Property>
|
||||
typename property_map<G, Property>::const_type
|
||||
get(Property p, const filtered_graph<G, EP, VP>& g)
|
||||
{
|
||||
return get(p, (const G&)g.m_g);
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP, typename Property,
|
||||
typename Key>
|
||||
typename property_map_value<G, Property>::type
|
||||
get(Property p, const filtered_graph<G, EP, VP>& g, const Key& k)
|
||||
{
|
||||
return get(p, (const G&)g.m_g, k);
|
||||
}
|
||||
|
||||
template <typename G, typename EP, typename VP, typename Property,
|
||||
typename Key, typename Value>
|
||||
void
|
||||
put(Property p, const filtered_graph<G, EP, VP>& g, const Key& k,
|
||||
const Value& val)
|
||||
{
|
||||
put(p, const_cast<G&>(g.m_g), k, val);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Some filtered subgraph specializations
|
||||
|
||||
template <typename Graph, typename Set>
|
||||
struct vertex_subset_filter {
|
||||
typedef filtered_graph<Graph, keep_all, is_in_subset<Set> > type;
|
||||
};
|
||||
template <typename Graph, typename Set>
|
||||
inline typename vertex_subset_filter<Graph, Set>::type
|
||||
make_vertex_subset_filter(Graph& g, const Set& s) {
|
||||
typedef typename vertex_subset_filter<Graph, Set>::type Filter;
|
||||
is_in_subset<Set> p(s);
|
||||
return Filter(g, keep_all(), p);
|
||||
}
|
||||
|
||||
template <typename Graph, typename Set>
|
||||
struct vertex_subset_compliment_filter {
|
||||
typedef filtered_graph<Graph, keep_all, is_not_in_subset<Set> > type;
|
||||
};
|
||||
template <typename Graph, typename Set>
|
||||
inline typename vertex_subset_compliment_filter<Graph, Set>::type
|
||||
make_vertex_subset_compliment_filter(Graph& g, const Set& s) {
|
||||
typedef typename vertex_subset_compliment_filter<Graph, Set>::type Filter;
|
||||
is_not_in_subset<Set> p(s);
|
||||
return Filter(g, keep_all(), p);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FILTERED_GRAPH_HPP
|
||||
251
libraries/include/boost/graph/floyd_warshall_shortest.hpp
Normal file
251
libraries/include/boost/graph/floyd_warshall_shortest.hpp
Normal file
@@ -0,0 +1,251 @@
|
||||
// Copyright 2002 Rensselaer Polytechnic Institute
|
||||
|
||||
// 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: Lauren Foutz
|
||||
// Scott Hill
|
||||
|
||||
/*
|
||||
This file implements the functions
|
||||
|
||||
template <class VertexListGraph, class DistanceMatrix,
|
||||
class P, class T, class R>
|
||||
bool floyd_warshall_initialized_all_pairs_shortest_paths(
|
||||
const VertexListGraph& g, DistanceMatrix& d,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
|
||||
AND
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix,
|
||||
class P, class T, class R>
|
||||
bool floyd_warshall_all_pairs_shortest_paths(
|
||||
const VertexAndEdgeListGraph& g, DistanceMatrix& d,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_GRAPH_FLOYD_WARSHALL_HPP
|
||||
#define BOOST_GRAPH_FLOYD_WARSHALL_HPP
|
||||
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/relax.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail {
|
||||
template<typename T, typename BinaryPredicate>
|
||||
T min_with_compare(const T& x, const T& y, const BinaryPredicate& compare)
|
||||
{
|
||||
if (compare(x, y)) return x;
|
||||
else return y;
|
||||
}
|
||||
|
||||
template<typename VertexListGraph, typename DistanceMatrix,
|
||||
typename BinaryPredicate, typename BinaryFunction,
|
||||
typename Infinity, typename Zero>
|
||||
bool floyd_warshall_dispatch(const VertexListGraph& g,
|
||||
DistanceMatrix& d, const BinaryPredicate &compare,
|
||||
const BinaryFunction &combine, const Infinity& inf,
|
||||
const Zero& zero)
|
||||
{
|
||||
typename graph_traits<VertexListGraph>::vertex_iterator
|
||||
i, lasti, j, lastj, k, lastk;
|
||||
|
||||
|
||||
for (tie(k, lastk) = vertices(g); k != lastk; k++)
|
||||
for (tie(i, lasti) = vertices(g); i != lasti; i++)
|
||||
if(d[*i][*k] != inf)
|
||||
for (tie(j, lastj) = vertices(g); j != lastj; j++)
|
||||
if(d[*k][*j] != inf)
|
||||
d[*i][*j] =
|
||||
detail::min_with_compare(d[*i][*j],
|
||||
combine(d[*i][*k], d[*k][*j]),
|
||||
compare);
|
||||
|
||||
|
||||
for (tie(i, lasti) = vertices(g); i != lasti; i++)
|
||||
if (compare(d[*i][*i], zero))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexListGraph, typename DistanceMatrix,
|
||||
typename BinaryPredicate, typename BinaryFunction,
|
||||
typename Infinity, typename Zero>
|
||||
bool floyd_warshall_initialized_all_pairs_shortest_paths(
|
||||
const VertexListGraph& g, DistanceMatrix& d,
|
||||
const BinaryPredicate& compare,
|
||||
const BinaryFunction& combine, const Infinity& inf,
|
||||
const Zero& zero)
|
||||
{
|
||||
function_requires<VertexListGraphConcept<VertexListGraph> >();
|
||||
|
||||
return detail::floyd_warshall_dispatch(g, d, compare, combine,
|
||||
inf, zero);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename VertexAndEdgeListGraph, typename DistanceMatrix,
|
||||
typename WeightMap, typename BinaryPredicate,
|
||||
typename BinaryFunction, typename Infinity, typename Zero>
|
||||
bool floyd_warshall_all_pairs_shortest_paths(
|
||||
const VertexAndEdgeListGraph& g,
|
||||
DistanceMatrix& d, const WeightMap& w,
|
||||
const BinaryPredicate& compare, const BinaryFunction& combine,
|
||||
const Infinity& inf, const Zero& zero)
|
||||
{
|
||||
function_requires<VertexListGraphConcept<VertexAndEdgeListGraph> >();
|
||||
function_requires<EdgeListGraphConcept<VertexAndEdgeListGraph> >();
|
||||
function_requires<IncidenceGraphConcept<VertexAndEdgeListGraph> >();
|
||||
|
||||
typename graph_traits<VertexAndEdgeListGraph>::vertex_iterator
|
||||
firstv, lastv, firstv2, lastv2;
|
||||
typename graph_traits<VertexAndEdgeListGraph>::edge_iterator first, last;
|
||||
|
||||
|
||||
for(tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++)
|
||||
for(tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2; firstv2++)
|
||||
d[*firstv][*firstv2] = inf;
|
||||
|
||||
|
||||
for(tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++)
|
||||
d[*firstv][*firstv] = zero;
|
||||
|
||||
|
||||
for(tie(first, last) = edges(g); first != last; first++)
|
||||
{
|
||||
if (d[source(*first, g)][target(*first, g)] != inf) {
|
||||
d[source(*first, g)][target(*first, g)] =
|
||||
detail::min_with_compare(
|
||||
get(w, *first),
|
||||
d[source(*first, g)][target(*first, g)],
|
||||
compare);
|
||||
} else
|
||||
d[source(*first, g)][target(*first, g)] = get(w, *first);
|
||||
}
|
||||
|
||||
bool is_undirected = is_same<typename
|
||||
graph_traits<VertexAndEdgeListGraph>::directed_category,
|
||||
undirected_tag>::value;
|
||||
if (is_undirected)
|
||||
{
|
||||
for(tie(first, last) = edges(g); first != last; first++)
|
||||
{
|
||||
if (d[target(*first, g)][source(*first, g)] != inf)
|
||||
d[target(*first, g)][source(*first, g)] =
|
||||
detail::min_with_compare(
|
||||
get(w, *first),
|
||||
d[target(*first, g)][source(*first, g)],
|
||||
compare);
|
||||
else
|
||||
d[target(*first, g)][source(*first, g)] = get(w, *first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return detail::floyd_warshall_dispatch(g, d, compare, combine,
|
||||
inf, zero);
|
||||
}
|
||||
|
||||
|
||||
namespace detail {
|
||||
template <class VertexListGraph, class DistanceMatrix,
|
||||
class WeightMap, class P, class T, class R>
|
||||
bool floyd_warshall_init_dispatch(const VertexListGraph& g,
|
||||
DistanceMatrix& d, WeightMap w,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type WM;
|
||||
|
||||
return floyd_warshall_initialized_all_pairs_shortest_paths(g, d,
|
||||
choose_param(get_param(params, distance_compare_t()),
|
||||
std::less<WM>()),
|
||||
choose_param(get_param(params, distance_combine_t()),
|
||||
closed_plus<WM>()),
|
||||
choose_param(get_param(params, distance_inf_t()),
|
||||
std::numeric_limits<WM>::max BOOST_PREVENT_MACRO_SUBSTITUTION()),
|
||||
choose_param(get_param(params, distance_zero_t()),
|
||||
WM()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix,
|
||||
class WeightMap, class P, class T, class R>
|
||||
bool floyd_warshall_noninit_dispatch(const VertexAndEdgeListGraph& g,
|
||||
DistanceMatrix& d, WeightMap w,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type WM;
|
||||
|
||||
return floyd_warshall_all_pairs_shortest_paths(g, d, w,
|
||||
choose_param(get_param(params, distance_compare_t()),
|
||||
std::less<WM>()),
|
||||
choose_param(get_param(params, distance_combine_t()),
|
||||
closed_plus<WM>()),
|
||||
choose_param(get_param(params, distance_inf_t()),
|
||||
std::numeric_limits<WM>::max BOOST_PREVENT_MACRO_SUBSTITUTION()),
|
||||
choose_param(get_param(params, distance_zero_t()),
|
||||
WM()));
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
|
||||
template <class VertexListGraph, class DistanceMatrix, class P,
|
||||
class T, class R>
|
||||
bool floyd_warshall_initialized_all_pairs_shortest_paths(
|
||||
const VertexListGraph& g, DistanceMatrix& d,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return detail::floyd_warshall_init_dispatch(g, d,
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
|
||||
params);
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class DistanceMatrix>
|
||||
bool floyd_warshall_initialized_all_pairs_shortest_paths(
|
||||
const VertexListGraph& g, DistanceMatrix& d)
|
||||
{
|
||||
bgl_named_params<int,int> params(0);
|
||||
return detail::floyd_warshall_init_dispatch(g, d,
|
||||
get(edge_weight, g), params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix,
|
||||
class P, class T, class R>
|
||||
bool floyd_warshall_all_pairs_shortest_paths(
|
||||
const VertexAndEdgeListGraph& g, DistanceMatrix& d,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return detail::floyd_warshall_noninit_dispatch(g, d,
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
|
||||
params);
|
||||
}
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix>
|
||||
bool floyd_warshall_all_pairs_shortest_paths(
|
||||
const VertexAndEdgeListGraph& g, DistanceMatrix& d)
|
||||
{
|
||||
bgl_named_params<int,int> params(0);
|
||||
return detail::floyd_warshall_noninit_dispatch(g, d,
|
||||
get(edge_weight, g), params);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
420
libraries/include/boost/graph/fruchterman_reingold.hpp
Normal file
420
libraries/include/boost/graph/fruchterman_reingold.hpp
Normal file
@@ -0,0 +1,420 @@
|
||||
// Copyright 2004 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: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
|
||||
#define BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
#include <boost/graph/simple_point.hpp>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <algorithm> // for std::min and std::max
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct square_distance_attractive_force {
|
||||
template<typename Graph, typename T>
|
||||
T
|
||||
operator()(typename graph_traits<Graph>::edge_descriptor,
|
||||
T k,
|
||||
T d,
|
||||
const Graph&) const
|
||||
{
|
||||
return d * d / k;
|
||||
}
|
||||
};
|
||||
|
||||
struct square_distance_repulsive_force {
|
||||
template<typename Graph, typename T>
|
||||
T
|
||||
operator()(typename graph_traits<Graph>::vertex_descriptor,
|
||||
typename graph_traits<Graph>::vertex_descriptor,
|
||||
T k,
|
||||
T d,
|
||||
const Graph&) const
|
||||
{
|
||||
return k * k / d;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct linear_cooling {
|
||||
typedef T result_type;
|
||||
|
||||
linear_cooling(std::size_t iterations)
|
||||
: temp(T(iterations) / T(10)), step(0.1) { }
|
||||
|
||||
linear_cooling(std::size_t iterations, T temp)
|
||||
: temp(temp), step(temp / T(iterations)) { }
|
||||
|
||||
T operator()()
|
||||
{
|
||||
T old_temp = temp;
|
||||
temp -= step;
|
||||
if (temp < T(0)) temp = T(0);
|
||||
return old_temp;
|
||||
}
|
||||
|
||||
private:
|
||||
T temp;
|
||||
T step;
|
||||
};
|
||||
|
||||
struct all_force_pairs
|
||||
{
|
||||
template<typename Graph, typename ApplyForce >
|
||||
void operator()(const Graph& g, ApplyForce apply_force)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
vertex_iterator v, end;
|
||||
for (tie(v, end) = vertices(g); v != end; ++v) {
|
||||
vertex_iterator u = v;
|
||||
for (++u; u != end; ++u) {
|
||||
apply_force(*u, *v);
|
||||
apply_force(*v, *u);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Dim, typename PositionMap>
|
||||
struct grid_force_pairs
|
||||
{
|
||||
template<typename Graph>
|
||||
explicit
|
||||
grid_force_pairs(Dim width, Dim height, PositionMap position, const Graph& g)
|
||||
: width(width), height(height), position(position)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif // BOOST_NO_STDC_NAMESPACE
|
||||
two_k = Dim(2) * sqrt(width*height / num_vertices(g));
|
||||
}
|
||||
|
||||
template<typename Graph, typename ApplyForce >
|
||||
void operator()(const Graph& g, ApplyForce apply_force)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef std::list<vertex_descriptor> bucket_t;
|
||||
typedef std::vector<bucket_t> buckets_t;
|
||||
|
||||
std::size_t columns = std::size_t(width / two_k + Dim(1));
|
||||
std::size_t rows = std::size_t(height / two_k + Dim(1));
|
||||
buckets_t buckets(rows * columns);
|
||||
vertex_iterator v, v_end;
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
|
||||
std::size_t column = std::size_t((position[*v].x + width / 2) / two_k);
|
||||
std::size_t row = std::size_t((position[*v].y + height / 2) / two_k);
|
||||
|
||||
if (column >= columns) column = columns - 1;
|
||||
if (row >= rows) row = rows - 1;
|
||||
buckets[row * columns + column].push_back(*v);
|
||||
}
|
||||
|
||||
for (std::size_t row = 0; row < rows; ++row)
|
||||
for (std::size_t column = 0; column < columns; ++column) {
|
||||
bucket_t& bucket = buckets[row * columns + column];
|
||||
typedef typename bucket_t::iterator bucket_iterator;
|
||||
for (bucket_iterator u = bucket.begin(); u != bucket.end(); ++u) {
|
||||
// Repulse vertices in this bucket
|
||||
bucket_iterator v = u;
|
||||
for (++v; v != bucket.end(); ++v) {
|
||||
apply_force(*u, *v);
|
||||
apply_force(*v, *u);
|
||||
}
|
||||
|
||||
std::size_t adj_start_row = row == 0? 0 : row - 1;
|
||||
std::size_t adj_end_row = row == rows - 1? row : row + 1;
|
||||
std::size_t adj_start_column = column == 0? 0 : column - 1;
|
||||
std::size_t adj_end_column = column == columns - 1? column : column + 1;
|
||||
for (std::size_t other_row = adj_start_row; other_row <= adj_end_row;
|
||||
++other_row)
|
||||
for (std::size_t other_column = adj_start_column;
|
||||
other_column <= adj_end_column; ++other_column)
|
||||
if (other_row != row || other_column != column) {
|
||||
// Repulse vertices in this bucket
|
||||
bucket_t& other_bucket
|
||||
= buckets[other_row * columns + other_column];
|
||||
for (v = other_bucket.begin(); v != other_bucket.end(); ++v)
|
||||
apply_force(*u, *v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Dim width;
|
||||
Dim height;
|
||||
PositionMap position;
|
||||
Dim two_k;
|
||||
};
|
||||
|
||||
template<typename Dim, typename PositionMap, typename Graph>
|
||||
inline grid_force_pairs<Dim, PositionMap>
|
||||
make_grid_force_pairs(Dim width, Dim height, const PositionMap& position,
|
||||
const Graph& g)
|
||||
{ return grid_force_pairs<Dim, PositionMap>(width, height, position, g); }
|
||||
|
||||
template<typename Graph, typename PositionMap, typename Dim>
|
||||
void
|
||||
scale_graph(const Graph& g, PositionMap position,
|
||||
Dim left, Dim top, Dim right, Dim bottom)
|
||||
{
|
||||
if (num_vertices(g) == 0) return;
|
||||
|
||||
if (bottom > top) {
|
||||
using std::swap;
|
||||
swap(bottom, top);
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
|
||||
// Find min/max ranges
|
||||
Dim minX = position[*vertices(g).first].x, maxX = minX;
|
||||
Dim minY = position[*vertices(g).first].y, maxY = minY;
|
||||
vertex_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
|
||||
BOOST_USING_STD_MIN();
|
||||
BOOST_USING_STD_MAX();
|
||||
minX = min BOOST_PREVENT_MACRO_SUBSTITUTION (minX, position[*vi].x);
|
||||
maxX = max BOOST_PREVENT_MACRO_SUBSTITUTION (maxX, position[*vi].x);
|
||||
minY = min BOOST_PREVENT_MACRO_SUBSTITUTION (minY, position[*vi].y);
|
||||
maxY = max BOOST_PREVENT_MACRO_SUBSTITUTION (maxY, position[*vi].y);
|
||||
}
|
||||
|
||||
// Scale to bounding box provided
|
||||
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
|
||||
position[*vi].x = ((position[*vi].x - minX) / (maxX - minX))
|
||||
* (right - left) + left;
|
||||
position[*vi].y = ((position[*vi].y - minY) / (maxY - minY))
|
||||
* (top - bottom) + bottom;
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename PositionMap, typename DisplacementMap,
|
||||
typename RepulsiveForce, typename Dim, typename Graph>
|
||||
struct fr_apply_force
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
fr_apply_force(const PositionMap& position,
|
||||
const DisplacementMap& displacement,
|
||||
RepulsiveForce repulsive_force, Dim k, const Graph& g)
|
||||
: position(position), displacement(displacement),
|
||||
repulsive_force(repulsive_force), k(k), g(g)
|
||||
{ }
|
||||
|
||||
void operator()(vertex_descriptor u, vertex_descriptor v)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif // BOOST_NO_STDC_NAMESPACE
|
||||
if (u != v) {
|
||||
Dim delta_x = position[v].x - position[u].x;
|
||||
Dim delta_y = position[v].y - position[u].y;
|
||||
Dim dist = sqrt(delta_x * delta_x + delta_y * delta_y);
|
||||
Dim fr = repulsive_force(u, v, k, dist, g);
|
||||
displacement[v].x += delta_x / dist * fr;
|
||||
displacement[v].y += delta_y / dist * fr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PositionMap position;
|
||||
DisplacementMap displacement;
|
||||
RepulsiveForce repulsive_force;
|
||||
Dim k;
|
||||
const Graph& g;
|
||||
};
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
template<typename Graph, typename PositionMap, typename Dim,
|
||||
typename AttractiveForce, typename RepulsiveForce,
|
||||
typename ForcePairs, typename Cooling, typename DisplacementMap>
|
||||
void
|
||||
fruchterman_reingold_force_directed_layout
|
||||
(const Graph& g,
|
||||
PositionMap position,
|
||||
Dim width,
|
||||
Dim height,
|
||||
AttractiveForce attractive_force,
|
||||
RepulsiveForce repulsive_force,
|
||||
ForcePairs force_pairs,
|
||||
Cooling cool,
|
||||
DisplacementMap displacement)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
|
||||
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif // BOOST_NO_STDC_NAMESPACE
|
||||
|
||||
Dim area = width * height;
|
||||
// assume positions are initialized randomly
|
||||
Dim k = sqrt(area / num_vertices(g));
|
||||
|
||||
detail::fr_apply_force<PositionMap, DisplacementMap,
|
||||
RepulsiveForce, Dim, Graph>
|
||||
apply_force(position, displacement, repulsive_force, k, g);
|
||||
|
||||
Dim temp = cool();
|
||||
if (temp) do {
|
||||
// Calculate repulsive forces
|
||||
vertex_iterator v, v_end;
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
|
||||
displacement[*v].x = 0;
|
||||
displacement[*v].y = 0;
|
||||
}
|
||||
force_pairs(g, apply_force);
|
||||
|
||||
// Calculate attractive forces
|
||||
edge_iterator e, e_end;
|
||||
for (tie(e, e_end) = edges(g); e != e_end; ++e) {
|
||||
vertex_descriptor v = source(*e, g);
|
||||
vertex_descriptor u = target(*e, g);
|
||||
Dim delta_x = position[v].x - position[u].x;
|
||||
Dim delta_y = position[v].y - position[u].y;
|
||||
Dim dist = sqrt(delta_x * delta_x + delta_y * delta_y);
|
||||
Dim fa = attractive_force(*e, k, dist, g);
|
||||
|
||||
displacement[v].x -= delta_x / dist * fa;
|
||||
displacement[v].y -= delta_y / dist * fa;
|
||||
displacement[u].x += delta_x / dist * fa;
|
||||
displacement[u].y += delta_y / dist * fa;
|
||||
}
|
||||
|
||||
// Update positions
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
|
||||
BOOST_USING_STD_MIN();
|
||||
BOOST_USING_STD_MAX();
|
||||
Dim disp_size = sqrt(displacement[*v].x * displacement[*v].x
|
||||
+ displacement[*v].y * displacement[*v].y);
|
||||
position[*v].x += displacement[*v].x / disp_size
|
||||
* min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp);
|
||||
position[*v].y += displacement[*v].y / disp_size
|
||||
* min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp);
|
||||
position[*v].x = min BOOST_PREVENT_MACRO_SUBSTITUTION
|
||||
(width / 2,
|
||||
max BOOST_PREVENT_MACRO_SUBSTITUTION(-width / 2,
|
||||
position[*v].x));
|
||||
position[*v].y = min BOOST_PREVENT_MACRO_SUBSTITUTION
|
||||
(height / 2,
|
||||
max BOOST_PREVENT_MACRO_SUBSTITUTION(-height / 2,
|
||||
position[*v].y));
|
||||
}
|
||||
} while ((temp = cool()));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename DisplacementMap>
|
||||
struct fr_force_directed_layout
|
||||
{
|
||||
template<typename Graph, typename PositionMap, typename Dim,
|
||||
typename AttractiveForce, typename RepulsiveForce,
|
||||
typename ForcePairs, typename Cooling,
|
||||
typename Param, typename Tag, typename Rest>
|
||||
static void
|
||||
run(const Graph& g,
|
||||
PositionMap position,
|
||||
Dim width,
|
||||
Dim height,
|
||||
AttractiveForce attractive_force,
|
||||
RepulsiveForce repulsive_force,
|
||||
ForcePairs force_pairs,
|
||||
Cooling cool,
|
||||
DisplacementMap displacement,
|
||||
const bgl_named_params<Param, Tag, Rest>&)
|
||||
{
|
||||
fruchterman_reingold_force_directed_layout
|
||||
(g, position, width, height, attractive_force, repulsive_force,
|
||||
force_pairs, cool, displacement);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct fr_force_directed_layout<error_property_not_found>
|
||||
{
|
||||
template<typename Graph, typename PositionMap, typename Dim,
|
||||
typename AttractiveForce, typename RepulsiveForce,
|
||||
typename ForcePairs, typename Cooling,
|
||||
typename Param, typename Tag, typename Rest>
|
||||
static void
|
||||
run(const Graph& g,
|
||||
PositionMap position,
|
||||
Dim width,
|
||||
Dim height,
|
||||
AttractiveForce attractive_force,
|
||||
RepulsiveForce repulsive_force,
|
||||
ForcePairs force_pairs,
|
||||
Cooling cool,
|
||||
error_property_not_found,
|
||||
const bgl_named_params<Param, Tag, Rest>& params)
|
||||
{
|
||||
std::vector<simple_point<Dim> > displacements(num_vertices(g));
|
||||
fruchterman_reingold_force_directed_layout
|
||||
(g, position, width, height, attractive_force, repulsive_force,
|
||||
force_pairs, cool,
|
||||
make_iterator_property_map
|
||||
(displacements.begin(),
|
||||
choose_const_pmap(get_param(params, vertex_index), g,
|
||||
vertex_index),
|
||||
simple_point<Dim>()));
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
template<typename Graph, typename PositionMap, typename Dim, typename Param,
|
||||
typename Tag, typename Rest>
|
||||
void
|
||||
fruchterman_reingold_force_directed_layout
|
||||
(const Graph& g,
|
||||
PositionMap position,
|
||||
Dim width,
|
||||
Dim height,
|
||||
const bgl_named_params<Param, Tag, Rest>& params)
|
||||
{
|
||||
typedef typename property_value<bgl_named_params<Param,Tag,Rest>,
|
||||
vertex_displacement_t>::type D;
|
||||
|
||||
detail::fr_force_directed_layout<D>::run
|
||||
(g, position, width, height,
|
||||
choose_param(get_param(params, attractive_force_t()),
|
||||
square_distance_attractive_force()),
|
||||
choose_param(get_param(params, repulsive_force_t()),
|
||||
square_distance_repulsive_force()),
|
||||
choose_param(get_param(params, force_pairs_t()),
|
||||
make_grid_force_pairs(width, height, position, g)),
|
||||
choose_param(get_param(params, cooling_t()),
|
||||
linear_cooling<Dim>(100)),
|
||||
get_param(params, vertex_displacement_t()),
|
||||
params);
|
||||
}
|
||||
|
||||
template<typename Graph, typename PositionMap, typename Dim>
|
||||
void
|
||||
fruchterman_reingold_force_directed_layout(const Graph& g,
|
||||
PositionMap position,
|
||||
Dim width,
|
||||
Dim height)
|
||||
{
|
||||
fruchterman_reingold_force_directed_layout
|
||||
(g, position, width, height,
|
||||
attractive_force(square_distance_attractive_force()));
|
||||
}
|
||||
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
|
||||
290
libraries/include/boost/graph/graph_archetypes.hpp
Normal file
290
libraries/include/boost/graph/graph_archetypes.hpp
Normal file
@@ -0,0 +1,290 @@
|
||||
//=======================================================================
|
||||
// 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_ARCHETYPES_HPP
|
||||
#define BOOST_GRAPH_ARCHETYPES_HPP
|
||||
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
|
||||
namespace boost { // should use a different namespace for this
|
||||
|
||||
namespace detail {
|
||||
struct null_graph_archetype : public null_archetype<> {
|
||||
struct traversal_category { };
|
||||
};
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
template <typename Vertex, typename Directed, typename ParallelCategory,
|
||||
typename Base = detail::null_graph_archetype >
|
||||
struct incidence_graph_archetype : public Base
|
||||
{
|
||||
typedef typename Base::traversal_category base_trav_cat;
|
||||
struct traversal_category
|
||||
: public incidence_graph_tag, public base_trav_cat { };
|
||||
#if 0
|
||||
typedef immutable_graph_tag mutability_category;
|
||||
#endif
|
||||
typedef Vertex vertex_descriptor;
|
||||
typedef unsigned int degree_size_type;
|
||||
typedef unsigned int vertices_size_type;
|
||||
typedef unsigned int edges_size_type;
|
||||
struct edge_descriptor {
|
||||
edge_descriptor() { }
|
||||
edge_descriptor(const detail::dummy_constructor&) { }
|
||||
bool operator==(const edge_descriptor&) const { return false; }
|
||||
bool operator!=(const edge_descriptor&) const { return false; }
|
||||
};
|
||||
typedef input_iterator_archetype<edge_descriptor> out_edge_iterator;
|
||||
|
||||
typedef Directed directed_category;
|
||||
typedef ParallelCategory edge_parallel_category;
|
||||
|
||||
typedef void adjacency_iterator;
|
||||
typedef void in_edge_iterator;
|
||||
typedef void vertex_iterator;
|
||||
typedef void edge_iterator;
|
||||
};
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
V source(const typename incidence_graph_archetype<V,D,P,B>::edge_descriptor&,
|
||||
const incidence_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
return V(static_object<detail::dummy_constructor>::get());
|
||||
}
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
V target(const typename incidence_graph_archetype<V,D,P,B>::edge_descriptor&,
|
||||
const incidence_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
return V(static_object<detail::dummy_constructor>::get());
|
||||
}
|
||||
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
std::pair<typename incidence_graph_archetype<V,D,P,B>::out_edge_iterator,
|
||||
typename incidence_graph_archetype<V,D,P,B>::out_edge_iterator>
|
||||
out_edges(const V&, const incidence_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
typedef typename incidence_graph_archetype<V,D,P,B>::out_edge_iterator Iter;
|
||||
return std::make_pair(Iter(), Iter());
|
||||
}
|
||||
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
typename incidence_graph_archetype<V,D,P,B>::degree_size_type
|
||||
out_degree(const V&, const incidence_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
template <typename Vertex, typename Directed, typename ParallelCategory,
|
||||
typename Base = detail::null_graph_archetype >
|
||||
struct adjacency_graph_archetype : public Base
|
||||
{
|
||||
typedef typename Base::traversal_category base_trav_cat;
|
||||
struct traversal_category
|
||||
: public adjacency_graph_tag, public base_trav_cat { };
|
||||
typedef Vertex vertex_descriptor;
|
||||
typedef unsigned int degree_size_type;
|
||||
typedef unsigned int vertices_size_type;
|
||||
typedef unsigned int edges_size_type;
|
||||
typedef void edge_descriptor;
|
||||
typedef input_iterator_archetype<Vertex> adjacency_iterator;
|
||||
|
||||
typedef Directed directed_category;
|
||||
typedef ParallelCategory edge_parallel_category;
|
||||
|
||||
typedef void in_edge_iterator;
|
||||
typedef void out_edge_iterator;
|
||||
typedef void vertex_iterator;
|
||||
typedef void edge_iterator;
|
||||
};
|
||||
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
std::pair<typename adjacency_graph_archetype<V,D,P,B>::adjacency_iterator,
|
||||
typename adjacency_graph_archetype<V,D,P,B>::adjacency_iterator>
|
||||
adjacent_vertices(const V&, const adjacency_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
typedef typename adjacency_graph_archetype<V,D,P,B>::adjacency_iterator Iter;
|
||||
return std::make_pair(Iter(), Iter());
|
||||
}
|
||||
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
typename adjacency_graph_archetype<V,D,P,B>::degree_size_type
|
||||
out_degree(const V&, const adjacency_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
template <typename Vertex, typename Directed, typename ParallelCategory,
|
||||
typename Base = detail::null_graph_archetype >
|
||||
struct vertex_list_graph_archetype : public Base
|
||||
{
|
||||
typedef incidence_graph_archetype<Vertex, Directed, ParallelCategory>
|
||||
Incidence;
|
||||
typedef adjacency_graph_archetype<Vertex, Directed, ParallelCategory>
|
||||
Adjacency;
|
||||
|
||||
typedef typename Base::traversal_category base_trav_cat;
|
||||
struct traversal_category
|
||||
: public vertex_list_graph_tag, public base_trav_cat { };
|
||||
#if 0
|
||||
typedef immutable_graph_tag mutability_category;
|
||||
#endif
|
||||
typedef Vertex vertex_descriptor;
|
||||
typedef unsigned int degree_size_type;
|
||||
typedef typename Incidence::edge_descriptor edge_descriptor;
|
||||
typedef typename Incidence::out_edge_iterator out_edge_iterator;
|
||||
typedef typename Adjacency::adjacency_iterator adjacency_iterator;
|
||||
|
||||
typedef input_iterator_archetype<Vertex> vertex_iterator;
|
||||
typedef unsigned int vertices_size_type;
|
||||
typedef unsigned int edges_size_type;
|
||||
|
||||
typedef Directed directed_category;
|
||||
typedef ParallelCategory edge_parallel_category;
|
||||
|
||||
typedef void in_edge_iterator;
|
||||
typedef void edge_iterator;
|
||||
};
|
||||
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
std::pair<typename vertex_list_graph_archetype<V,D,P,B>::vertex_iterator,
|
||||
typename vertex_list_graph_archetype<V,D,P,B>::vertex_iterator>
|
||||
vertices(const vertex_list_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
typedef typename vertex_list_graph_archetype<V,D,P,B>::vertex_iterator Iter;
|
||||
return std::make_pair(Iter(), Iter());
|
||||
}
|
||||
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
typename vertex_list_graph_archetype<V,D,P,B>::vertices_size_type
|
||||
num_vertices(const vertex_list_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ambiguously inherited from incidence graph and adjacency graph
|
||||
template <typename V, typename D, typename P, typename B>
|
||||
typename vertex_list_graph_archetype<V,D,P,B>::degree_size_type
|
||||
out_degree(const V&, const vertex_list_graph_archetype<V,D,P,B>& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
struct property_graph_archetype_tag { };
|
||||
|
||||
template <typename GraphArchetype, typename Property, typename ValueArch>
|
||||
struct property_graph_archetype : public GraphArchetype
|
||||
{
|
||||
typedef property_graph_archetype_tag graph_tag;
|
||||
typedef ValueArch vertex_property_type;
|
||||
typedef ValueArch edge_property_type;
|
||||
};
|
||||
|
||||
struct choose_edge_property_map_archetype {
|
||||
template <typename Graph, typename Property, typename Tag>
|
||||
struct bind_ {
|
||||
typedef mutable_lvalue_property_map_archetype
|
||||
<typename Graph::edge_descriptor, Property> type;
|
||||
typedef lvalue_property_map_archetype
|
||||
<typename Graph::edge_descriptor, Property> const_type;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct edge_property_selector<property_graph_archetype_tag> {
|
||||
typedef choose_edge_property_map_archetype type;
|
||||
};
|
||||
|
||||
struct choose_vertex_property_map_archetype {
|
||||
template <typename Graph, typename Property, typename Tag>
|
||||
struct bind_ {
|
||||
typedef mutable_lvalue_property_map_archetype
|
||||
<typename Graph::vertex_descriptor, Property> type;
|
||||
typedef lvalue_property_map_archetype
|
||||
<typename Graph::vertex_descriptor, Property> const_type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct vertex_property_selector<property_graph_archetype_tag> {
|
||||
typedef choose_vertex_property_map_archetype type;
|
||||
};
|
||||
|
||||
template <typename G, typename P, typename V>
|
||||
typename property_map<property_graph_archetype<G, P, V>, P>::type
|
||||
get(P, property_graph_archetype<G, P, V>&) {
|
||||
typename property_map<property_graph_archetype<G, P, V>, P>::type pmap;
|
||||
return pmap;
|
||||
}
|
||||
|
||||
template <typename G, typename P, typename V>
|
||||
typename property_map<property_graph_archetype<G, P, V>, P>::const_type
|
||||
get(P, const property_graph_archetype<G, P, V>&) {
|
||||
typename property_map<property_graph_archetype<G, P, V>, P>::const_type pmap;
|
||||
return pmap;
|
||||
}
|
||||
|
||||
template <typename G, typename P, typename K, typename V>
|
||||
typename property_traits<typename property_map<property_graph_archetype<G, P, V>, P>::const_type>::value_type
|
||||
get(P p, const property_graph_archetype<G, P, V>& g, K k) {
|
||||
return get( get(p, g), k);
|
||||
}
|
||||
|
||||
template <typename G, typename P, typename V, typename Key>
|
||||
void
|
||||
put(P p, property_graph_archetype<G, P, V>& g,
|
||||
const Key& key, const V& value)
|
||||
{
|
||||
typedef typename boost::property_map<property_graph_archetype<G, P, V>, P>::type Map;
|
||||
Map pmap = get(p, g);
|
||||
put(pmap, key, value);
|
||||
}
|
||||
|
||||
struct color_value_archetype {
|
||||
color_value_archetype() { }
|
||||
color_value_archetype(detail::dummy_constructor) { }
|
||||
bool operator==(const color_value_archetype& ) const { return true; }
|
||||
bool operator!=(const color_value_archetype& ) const { return true; }
|
||||
};
|
||||
template <>
|
||||
struct color_traits<color_value_archetype> {
|
||||
static color_value_archetype white()
|
||||
{
|
||||
return color_value_archetype
|
||||
(static_object<detail::dummy_constructor>::get());
|
||||
}
|
||||
static color_value_archetype gray()
|
||||
{
|
||||
return color_value_archetype
|
||||
(static_object<detail::dummy_constructor>::get());
|
||||
}
|
||||
static color_value_archetype black()
|
||||
{
|
||||
return color_value_archetype
|
||||
(static_object<detail::dummy_constructor>::get());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class buffer_archetype {
|
||||
public:
|
||||
void push(const T&) {}
|
||||
void pop() {}
|
||||
T& top() { return static_object<T>::get(); }
|
||||
const T& top() const { return static_object<T>::get(); }
|
||||
bool empty() const { return true; }
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_ARCHETYPES_HPP
|
||||
154
libraries/include/boost/graph/graph_as_tree.hpp
Normal file
154
libraries/include/boost/graph/graph_as_tree.hpp
Normal file
@@ -0,0 +1,154 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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_GRAPH_AS_TREE_HPP
|
||||
#define BOOST_GRAPH_GRAPH_AS_TREE_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/tree_traits.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include <boost/graph/visitors.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Graph, class Node, class ChIt, class Derived>
|
||||
class graph_as_tree_base
|
||||
{
|
||||
typedef Derived Tree;
|
||||
public:
|
||||
typedef Node node_descriptor;
|
||||
typedef ChIt children_iterator;
|
||||
|
||||
graph_as_tree_base(Graph& g, Node root) : _g(g), _root(root) { }
|
||||
|
||||
friend Node root(const Tree& t) { return t._root; }
|
||||
|
||||
template <class N>
|
||||
friend std::pair<ChIt,ChIt>
|
||||
children(N n, const Tree& t) { return adjacent_vertices(n, t._g); }
|
||||
|
||||
template<class N>
|
||||
friend Node parent(N n, const Tree& t) {
|
||||
return boost::get(t.parent_pa(), n);
|
||||
}
|
||||
|
||||
Graph& _g;
|
||||
Node _root;
|
||||
};
|
||||
|
||||
struct graph_as_tree_tag { };
|
||||
|
||||
template <class Graph, class ParentMap
|
||||
, class Node
|
||||
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
= typename graph_traits<Graph>::vertex_descriptor
|
||||
#endif
|
||||
, class ChIt
|
||||
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
= typename graph_traits<Graph>::adjacency_iterator
|
||||
#endif
|
||||
>
|
||||
class graph_as_tree
|
||||
: public graph_as_tree_base<Graph, Node, ChIt,
|
||||
graph_as_tree<Graph,ParentMap,Node,ChIt> >
|
||||
{
|
||||
typedef graph_as_tree self;
|
||||
typedef graph_as_tree_base<Graph, Node, ChIt, self> super;
|
||||
public:
|
||||
graph_as_tree(Graph& g, Node root) : super(g, root) { }
|
||||
|
||||
graph_as_tree(Graph& g, Node root, ParentMap p) : super(g, root), _p(p) {
|
||||
breadth_first_search(g, root,
|
||||
visitor(make_bfs_visitor
|
||||
(record_predecessors(p, boost::on_tree_edge()))));
|
||||
}
|
||||
ParentMap parent_pa() const { return _p; }
|
||||
typedef graph_as_tree_tag graph_tag; // for property_map
|
||||
protected:
|
||||
ParentMap _p;
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct graph_as_tree_vertex_property_selector {
|
||||
template <typename GraphAsTree, typename Property, typename Tag>
|
||||
struct bind_ {
|
||||
typedef typename GraphAsTree::base_type Graph;
|
||||
typedef property_map<Graph, Tag> PMap;
|
||||
typedef typename PMap::type type;
|
||||
typedef typename PMap::const_type const_type;
|
||||
};
|
||||
};
|
||||
|
||||
struct graph_as_tree_edge_property_selector {
|
||||
template <typename GraphAsTree, typename Property, typename Tag>
|
||||
struct bind_ {
|
||||
typedef typename GraphAsTree::base_type Graph;
|
||||
typedef property_map<Graph, Tag> PMap;
|
||||
typedef typename PMap::type type;
|
||||
typedef typename PMap::const_type const_type;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <>
|
||||
struct vertex_property_selector<graph_as_tree_tag> {
|
||||
typedef detail::graph_as_tree_vertex_property_selector type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct edge_property_selector<graph_as_tree_tag> {
|
||||
typedef detail::graph_as_tree_edge_property_selector type;
|
||||
};
|
||||
|
||||
template <typename Graph, typename P, typename N, typename C,
|
||||
typename Property>
|
||||
typename property_map<Graph, Property>::type
|
||||
get(Property p, graph_as_tree<Graph,P,N,C>& g)
|
||||
{
|
||||
return get(p, g._g);
|
||||
}
|
||||
|
||||
template <typename Graph, typename P, typename N, typename C,
|
||||
typename Property>
|
||||
typename property_map<Graph, Property>::const_type
|
||||
get(Property p, const graph_as_tree<Graph,P,N,C>& g)
|
||||
{
|
||||
const Graph& gref = g._g; // in case GRef is non-const
|
||||
return get(p, gref);
|
||||
}
|
||||
|
||||
template <typename Graph, typename P, typename N, typename C,
|
||||
typename Property, typename Key>
|
||||
typename property_traits<
|
||||
typename property_map<Graph, Property>::const_type
|
||||
>::value_type
|
||||
get(Property p, const graph_as_tree<Graph,P,N,C>& g, const Key& k)
|
||||
{
|
||||
return get(p, g._g, k);
|
||||
}
|
||||
|
||||
template <typename Graph, typename P, typename N, typename C,
|
||||
typename Property, typename Key, typename Value>
|
||||
void
|
||||
put(Property p, const graph_as_tree<Graph,P,N,C>& g, const Key& k,
|
||||
const Value& val)
|
||||
{
|
||||
put(p, g._g, k, val);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_GRAPH_AS_TREE_HPP
|
||||
510
libraries/include/boost/graph/graph_concepts.hpp
Normal file
510
libraries/include/boost/graph/graph_concepts.hpp
Normal file
@@ -0,0 +1,510 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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_CONCEPTS_HPP
|
||||
#define BOOST_GRAPH_CONCEPTS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/detail/workaround.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(__GNUC__, <= 2) \
|
||||
&& !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>::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>::traversal_category
|
||||
traversal_category;
|
||||
|
||||
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>));
|
||||
|
||||
p = in_edges(v, g);
|
||||
n = in_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);
|
||||
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>));
|
||||
|
||||
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>));
|
||||
|
||||
#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>));
|
||||
|
||||
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<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<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;
|
||||
};
|
||||
|
||||
// This needs to move out of the graph library
|
||||
BOOST_concept(Buffer,(B))
|
||||
{
|
||||
BOOST_CONCEPT_USAGE(Buffer) {
|
||||
b.push(t);
|
||||
b.pop();
|
||||
typename B::value_type& v = b.top();
|
||||
const_constraints(b);
|
||||
ignore_unused_variable_warning(v);
|
||||
}
|
||||
void const_constraints(const B& cb) {
|
||||
const typename B::value_type& v = cb.top();
|
||||
n = cb.size();
|
||||
bool e = cb.empty();
|
||||
ignore_unused_variable_warning(v);
|
||||
ignore_unused_variable_warning(e);
|
||||
}
|
||||
typename B::size_type n;
|
||||
typename B::value_type t;
|
||||
B b;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // end namespace concepts
|
||||
|
||||
using boost::concepts::MultiPassInputIteratorConcept;
|
||||
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::BufferConcept;
|
||||
using boost::concepts::ColorValueConcept;
|
||||
using boost::concepts::BasicMatrixConcept;
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/concept/detail/concept_undef.hpp>
|
||||
|
||||
#endif /* BOOST_GRAPH_CONCEPTS_H */
|
||||
38
libraries/include/boost/graph/graph_selectors.hpp
Normal file
38
libraries/include/boost/graph/graph_selectors.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_GRAPH_SELECTORS_HPP
|
||||
#define BOOST_GRAPH_SELECTORS_HPP
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//===========================================================================
|
||||
// Selectors for the Directed template parameter of adjacency_list
|
||||
// and adjacency_matrix.
|
||||
|
||||
struct directedS { enum { is_directed = true, is_bidir = false };
|
||||
typedef mpl::true_ is_directed_t;
|
||||
typedef mpl::false_ is_bidir_t;
|
||||
};
|
||||
struct undirectedS {
|
||||
enum { is_directed = false, is_bidir = false };
|
||||
typedef mpl::false_ is_directed_t;
|
||||
typedef mpl::false_ is_bidir_t;
|
||||
};
|
||||
struct bidirectionalS {
|
||||
enum { is_directed = true, is_bidir = true };
|
||||
typedef mpl::true_ is_directed_t;
|
||||
typedef mpl::true_ is_bidir_t;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_SELECTORS_HPP
|
||||
382
libraries/include/boost/graph/graph_test.hpp
Normal file
382
libraries/include/boost/graph/graph_test.hpp
Normal file
@@ -0,0 +1,382 @@
|
||||
//=======================================================================
|
||||
// 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_TEST_HPP
|
||||
#define BOOST_GRAPH_TEST_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/graph/filtered_graph.hpp>
|
||||
#include <boost/graph/iteration_macros.hpp>
|
||||
#include <boost/graph/isomorphism.hpp>
|
||||
#include <boost/graph/copy.hpp>
|
||||
#include <boost/graph/graph_utility.hpp> // for connects
|
||||
|
||||
|
||||
// UNDER CONSTRUCTION
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename Graph>
|
||||
struct graph_test
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef typename graph_traits<Graph>::degree_size_type deg_size_t;
|
||||
typedef typename graph_traits<Graph>::edges_size_type e_size_t;
|
||||
typedef typename graph_traits<Graph>::out_edge_iterator out_edge_iter;
|
||||
typedef typename property_map<Graph, vertex_index_t>::type index_map_t;
|
||||
typedef iterator_property_map<typename std::vector<vertex_t>::iterator,
|
||||
index_map_t,vertex_t,vertex_t&> IsoMap;
|
||||
|
||||
struct ignore_vertex {
|
||||
ignore_vertex() { }
|
||||
ignore_vertex(vertex_t v) : v(v) { }
|
||||
bool operator()(vertex_t x) const { return x != v; }
|
||||
vertex_t v;
|
||||
};
|
||||
struct ignore_edge {
|
||||
ignore_edge() { }
|
||||
ignore_edge(edge_t e) : e(e) { }
|
||||
bool operator()(edge_t x) const { return x != e; }
|
||||
edge_t e;
|
||||
};
|
||||
struct ignore_edges {
|
||||
ignore_edges(vertex_t s, vertex_t t, const Graph& g)
|
||||
: s(s), t(t), g(g) { }
|
||||
bool operator()(edge_t x) const {
|
||||
return !(source(x, g) == s && target(x, g) == t);
|
||||
}
|
||||
vertex_t s; vertex_t t; const Graph& g;
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
// Traversal Operations
|
||||
|
||||
void test_incidence_graph
|
||||
(const std::vector<vertex_t>& vertex_set,
|
||||
const std::vector< std::pair<vertex_t, vertex_t> >& edge_set,
|
||||
const Graph& g)
|
||||
{
|
||||
typedef typename std::vector<vertex_t>::const_iterator vertex_iter;
|
||||
typedef typename std::vector< std::pair<vertex_t, vertex_t> >
|
||||
::const_iterator edge_iter;
|
||||
typedef typename graph_traits<Graph>::out_edge_iterator out_edge_iter;
|
||||
|
||||
for (vertex_iter ui = vertex_set.begin(); ui != vertex_set.end(); ++ui) {
|
||||
vertex_t u = *ui;
|
||||
std::vector<vertex_t> adj;
|
||||
for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e)
|
||||
if (e->first == u)
|
||||
adj.push_back(e->second);
|
||||
|
||||
std::pair<out_edge_iter, out_edge_iter> p = out_edges(u, g);
|
||||
BOOST_CHECK(out_degree(u, g) == adj.size());
|
||||
BOOST_CHECK(deg_size_t(std::distance(p.first, p.second))
|
||||
== out_degree(u, g));
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
edge_t e = *p.first;
|
||||
BOOST_CHECK(source(e, g) == u);
|
||||
BOOST_CHECK(container_contains(adj, target(e, g)) == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_bidirectional_graph
|
||||
(const std::vector<vertex_t>& vertex_set,
|
||||
const std::vector< std::pair<vertex_t, vertex_t> >& edge_set,
|
||||
const Graph& g)
|
||||
{
|
||||
typedef typename std::vector<vertex_t>::const_iterator vertex_iter;
|
||||
typedef typename std::vector< std::pair<vertex_t, vertex_t> >
|
||||
::const_iterator edge_iter;
|
||||
typedef typename graph_traits<Graph>::in_edge_iterator in_edge_iter;
|
||||
|
||||
for (vertex_iter vi = vertex_set.begin(); vi != vertex_set.end(); ++vi) {
|
||||
vertex_t v = *vi;
|
||||
std::vector<vertex_t> inv_adj;
|
||||
for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e)
|
||||
if (e->second == v)
|
||||
inv_adj.push_back(e->first);
|
||||
|
||||
std::pair<in_edge_iter, in_edge_iter> p = in_edges(v, g);
|
||||
BOOST_CHECK(in_degree(v, g) == inv_adj.size());
|
||||
BOOST_CHECK(deg_size_t(std::distance(p.first, p.second))
|
||||
== in_degree(v, g));
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
edge_t e = *p.first;
|
||||
BOOST_CHECK(target(e, g) == v);
|
||||
BOOST_CHECK(container_contains(inv_adj, source(e, g)) == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_adjacency_graph
|
||||
(const std::vector<vertex_t>& vertex_set,
|
||||
const std::vector< std::pair<vertex_t,vertex_t> >& edge_set,
|
||||
const Graph& g)
|
||||
{
|
||||
typedef typename std::vector<vertex_t>::const_iterator vertex_iter;
|
||||
typedef typename std::vector<std::pair<vertex_t,vertex_t> >
|
||||
::const_iterator edge_iter;
|
||||
typedef typename graph_traits<Graph>::adjacency_iterator adj_iter;
|
||||
|
||||
for (vertex_iter ui = vertex_set.begin(); ui != vertex_set.end(); ++ui) {
|
||||
vertex_t u = *ui;
|
||||
std::vector<vertex_t> adj;
|
||||
for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e)
|
||||
if (e->first == u)
|
||||
adj.push_back(e->second);
|
||||
|
||||
std::pair<adj_iter, adj_iter> p = adjacent_vertices(u, g);
|
||||
BOOST_CHECK(deg_size_t(std::distance(p.first, p.second)) == adj.size());
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
vertex_t v = *p.first;
|
||||
BOOST_CHECK(container_contains(adj, v) == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_vertex_list_graph
|
||||
(const std::vector<vertex_t>& vertex_set, const Graph& g)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator v_iter;
|
||||
std::pair<v_iter, v_iter> p = vertices(g);
|
||||
BOOST_CHECK(num_vertices(g) == vertex_set.size());
|
||||
v_size_t n = std::distance(p.first, p.second);
|
||||
BOOST_CHECK(n == num_vertices(g));
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
vertex_t v = *p.first;
|
||||
BOOST_CHECK(container_contains(vertex_set, v) == true);
|
||||
}
|
||||
}
|
||||
|
||||
void test_edge_list_graph
|
||||
(const std::vector<vertex_t>& vertex_set,
|
||||
const std::vector< std::pair<vertex_t, vertex_t> >& edge_set,
|
||||
const Graph& g)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_iterator e_iter;
|
||||
std::pair<e_iter, e_iter> p = edges(g);
|
||||
BOOST_CHECK(num_edges(g) == edge_set.size());
|
||||
e_size_t m = std::distance(p.first, p.second);
|
||||
BOOST_CHECK(m == num_edges(g));
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
edge_t e = *p.first;
|
||||
BOOST_CHECK(any_if(edge_set, connects(source(e, g), target(e, g), g)));
|
||||
BOOST_CHECK(container_contains(vertex_set, source(e, g)) == true);
|
||||
BOOST_CHECK(container_contains(vertex_set, target(e, g)) == true);
|
||||
}
|
||||
}
|
||||
|
||||
void test_adjacency_matrix
|
||||
(const std::vector<vertex_t>& vertex_set,
|
||||
const std::vector< std::pair<vertex_t, vertex_t> >& edge_set,
|
||||
const Graph& g)
|
||||
{
|
||||
std::pair<edge_t, bool> p;
|
||||
for (typename std::vector<std::pair<vertex_t, vertex_t> >
|
||||
::const_iterator i = edge_set.begin();
|
||||
i != edge_set.end(); ++i) {
|
||||
p = edge(i->first, i->second, g);
|
||||
BOOST_CHECK(p.second == true);
|
||||
BOOST_CHECK(source(p.first, g) == i->first);
|
||||
BOOST_CHECK(target(p.first, g) == i->second);
|
||||
}
|
||||
typename std::vector<vertex_t>::const_iterator j, k;
|
||||
for (j = vertex_set.begin(); j != vertex_set.end(); ++j)
|
||||
for (k = vertex_set.begin(); k != vertex_set.end(); ++k) {
|
||||
p = edge(*j, *k, g);
|
||||
if (p.second == true)
|
||||
BOOST_CHECK(any_if(edge_set,
|
||||
connects(source(p.first, g), target(p.first, g), g)) == true);
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Mutating Operations
|
||||
|
||||
void test_add_vertex(Graph& g)
|
||||
{
|
||||
Graph cpy;
|
||||
std::vector<vertex_t> iso_vec(num_vertices(g));
|
||||
IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
|
||||
copy_graph(g, cpy, orig_to_copy(iso_map));
|
||||
|
||||
assert((verify_isomorphism(g, cpy, iso_map)));
|
||||
|
||||
vertex_t v = add_vertex(g);
|
||||
|
||||
BOOST_CHECK(num_vertices(g) == num_vertices(cpy) + 1);
|
||||
|
||||
BOOST_CHECK(out_degree(v, g) == 0);
|
||||
|
||||
// Make sure the rest of the graph stayed the same
|
||||
BOOST_CHECK((verify_isomorphism
|
||||
(make_filtered_graph(g, keep_all(), ignore_vertex(v)), cpy,
|
||||
iso_map)));
|
||||
}
|
||||
|
||||
void test_add_edge(vertex_t u, vertex_t v, Graph& g)
|
||||
{
|
||||
Graph cpy;
|
||||
std::vector<vertex_t> iso_vec(num_vertices(g));
|
||||
IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
|
||||
copy_graph(g, cpy, orig_to_copy(iso_map));
|
||||
|
||||
bool parallel_edge_exists = container_contains(adjacent_vertices(u, g), v);
|
||||
|
||||
std::pair<edge_t, bool> p = add_edge(u, v, g);
|
||||
edge_t e = p.first;
|
||||
bool added = p.second;
|
||||
|
||||
if (is_undirected(g) && u == v) // self edge
|
||||
BOOST_CHECK(added == false);
|
||||
else if (parallel_edge_exists)
|
||||
BOOST_CHECK(allows_parallel_edges(g) && added == true
|
||||
|| !allows_parallel_edges(g) && added == false);
|
||||
else
|
||||
BOOST_CHECK(added == true);
|
||||
|
||||
if (p.second == true) { // edge added
|
||||
BOOST_CHECK(num_edges(g) == num_edges(cpy) + 1);
|
||||
|
||||
BOOST_CHECK(container_contains(out_edges(u, g), e) == true);
|
||||
|
||||
BOOST_CHECK((verify_isomorphism
|
||||
(make_filtered_graph(g, ignore_edge(e)), cpy, iso_map)));
|
||||
}
|
||||
else { // edge not added
|
||||
if (! (is_undirected(g) && u == v)) {
|
||||
// e should be a parallel edge
|
||||
BOOST_CHECK(source(e, g) == u);
|
||||
BOOST_CHECK(target(e, g) == v);
|
||||
}
|
||||
// The graph should not be changed.
|
||||
BOOST_CHECK((verify_isomorphism(g, cpy, iso_map)));
|
||||
}
|
||||
} // test_add_edge()
|
||||
|
||||
|
||||
void test_remove_edge(vertex_t u, vertex_t v, Graph& g)
|
||||
{
|
||||
Graph cpy;
|
||||
std::vector<vertex_t> iso_vec(num_vertices(g));
|
||||
IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
|
||||
copy_graph(g, cpy, orig_to_copy(iso_map));
|
||||
|
||||
deg_size_t occurances = count(adjacent_vertices(u, g), v);
|
||||
|
||||
remove_edge(u, v, g);
|
||||
|
||||
BOOST_CHECK(num_edges(g) + occurances == num_edges(cpy));
|
||||
BOOST_CHECK((verify_isomorphism
|
||||
(g, make_filtered_graph(cpy, ignore_edges(u,v,cpy)),
|
||||
iso_map)));
|
||||
}
|
||||
|
||||
void test_remove_edge(edge_t e, Graph& g)
|
||||
{
|
||||
Graph cpy;
|
||||
std::vector<vertex_t> iso_vec(num_vertices(g));
|
||||
IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
|
||||
copy_graph(g, cpy, orig_to_copy(iso_map));
|
||||
|
||||
vertex_t u = source(e, g), v = target(e, g);
|
||||
deg_size_t occurances = count(adjacent_vertices(u, g), v);
|
||||
|
||||
remove_edge(e, g);
|
||||
|
||||
BOOST_CHECK(num_edges(g) + 1 == num_edges(cpy));
|
||||
BOOST_CHECK(count(adjacent_vertices(u, g), v) + 1 == occurances);
|
||||
BOOST_CHECK((verify_isomorphism
|
||||
(g, make_filtered_graph(cpy, ignore_edge(e)),
|
||||
iso_map)));
|
||||
}
|
||||
|
||||
void test_clear_vertex(vertex_t v, Graph& g)
|
||||
{
|
||||
Graph cpy;
|
||||
std::vector<vertex_t> iso_vec(num_vertices(g));
|
||||
IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
|
||||
copy_graph(g, cpy, orig_to_copy(iso_map));
|
||||
|
||||
clear_vertex(v, g);
|
||||
|
||||
BOOST_CHECK(out_degree(v, g) == 0);
|
||||
BOOST_CHECK(num_vertices(g) == num_vertices(cpy));
|
||||
BOOST_CHECK((verify_isomorphism
|
||||
(g, make_filtered_graph(cpy, keep_all(), ignore_vertex(v)),
|
||||
iso_map)));
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Property Map
|
||||
|
||||
template <typename PropVal, typename PropertyTag>
|
||||
void test_readable_vertex_property_graph
|
||||
(const std::vector<PropVal>& vertex_prop, PropertyTag, const Graph& g)
|
||||
{
|
||||
typedef typename property_map<Graph, PropertyTag>::const_type const_Map;
|
||||
const_Map pmap = get(PropertyTag(), g);
|
||||
typename std::vector<PropVal>::const_iterator i = vertex_prop.begin();
|
||||
|
||||
for (typename boost::graph_traits<Graph>::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>::vertex_descriptor v;
|
||||
bgl_first_9 != bgl_last_9 ? (v = *bgl_first_9, true) : false;
|
||||
++bgl_first_9) {
|
||||
//BGL_FORALL_VERTICES_T(v, g, Graph) {
|
||||
typename property_traits<const_Map>::value_type
|
||||
pval1 = get(pmap, v), pval2 = get(PropertyTag(), g, v);
|
||||
BOOST_CHECK(pval1 == pval2);
|
||||
BOOST_CHECK(pval1 == *i++);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PropVal, typename PropertyTag>
|
||||
void test_vertex_property_graph
|
||||
(const std::vector<PropVal>& vertex_prop, PropertyTag tag, Graph& g)
|
||||
{
|
||||
typedef typename property_map<Graph, PropertyTag>::type PMap;
|
||||
PMap pmap = get(PropertyTag(), g);
|
||||
typename std::vector<PropVal>::const_iterator i = vertex_prop.begin();
|
||||
for (typename boost::graph_traits<Graph>::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>::vertex_descriptor v;
|
||||
bgl_first_9 != bgl_last_9 ? (v = *bgl_first_9, true) : false;
|
||||
++bgl_first_9)
|
||||
// BGL_FORALL_VERTICES_T(v, g, Graph)
|
||||
put(pmap, v, *i++);
|
||||
|
||||
test_readable_vertex_property_graph(vertex_prop, tag, g);
|
||||
|
||||
BGL_FORALL_VERTICES_T(v, g, Graph)
|
||||
put(pmap, v, vertex_prop[0]);
|
||||
|
||||
typename std::vector<PropVal>::const_iterator j = vertex_prop.begin();
|
||||
BGL_FORALL_VERTICES_T(v, g, Graph)
|
||||
put(PropertyTag(), g, v, *j++);
|
||||
|
||||
test_readable_vertex_property_graph(vertex_prop, tag, g);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/graph/iteration_macros_undef.hpp>
|
||||
|
||||
#endif // BOOST_GRAPH_TEST_HPP
|
||||
168
libraries/include/boost/graph/graph_traits.hpp
Normal file
168
libraries/include/boost/graph/graph_traits.hpp
Normal file
@@ -0,0 +1,168 @@
|
||||
//=======================================================================
|
||||
// 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 <boost/tuple/tuple.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename G>
|
||||
struct graph_traits {
|
||||
typedef typename G::vertex_descriptor vertex_descriptor;
|
||||
typedef typename G::edge_descriptor edge_descriptor;
|
||||
typedef typename G::adjacency_iterator adjacency_iterator;
|
||||
typedef typename G::out_edge_iterator out_edge_iterator;
|
||||
typedef typename G::in_edge_iterator in_edge_iterator;
|
||||
typedef typename G::vertex_iterator vertex_iterator;
|
||||
typedef typename G::edge_iterator 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;
|
||||
|
||||
typedef typename G::vertices_size_type vertices_size_type;
|
||||
typedef typename G::edges_size_type edges_size_type;
|
||||
typedef typename G::degree_size_type degree_size_type;
|
||||
|
||||
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; }
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
bool is_directed(const Graph&) {
|
||||
typedef typename graph_traits<Graph>::directed_category Cat;
|
||||
return detail::is_directed(Cat());
|
||||
}
|
||||
template <typename Graph>
|
||||
bool is_undirected(const Graph& g) {
|
||||
return ! is_directed(g);
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
// traversal_category tags
|
||||
struct incidence_graph_tag { };
|
||||
struct adjacency_graph_tag { };
|
||||
struct bidirectional_graph_tag :
|
||||
public virtual incidence_graph_tag { };
|
||||
struct vertex_list_graph_tag { };
|
||||
struct edge_list_graph_tag { };
|
||||
struct adjacency_matrix_tag { };
|
||||
|
||||
//?? not the right place ?? Lee
|
||||
typedef boost::forward_traversal_tag multi_pass_input_iterator_tag;
|
||||
|
||||
template <typename G>
|
||||
struct edge_property_type {
|
||||
typedef typename G::edge_property_type type;
|
||||
};
|
||||
template <typename G>
|
||||
struct vertex_property_type {
|
||||
typedef typename G::vertex_property_type type;
|
||||
};
|
||||
template <typename G>
|
||||
struct graph_property_type {
|
||||
typedef typename G::graph_property_type type;
|
||||
};
|
||||
|
||||
struct no_vertex_bundle {};
|
||||
struct no_edge_bundle {};
|
||||
|
||||
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;
|
||||
};
|
||||
} } // end namespace graph::detail
|
||||
} // 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
|
||||
425
libraries/include/boost/graph/graph_utility.hpp
Normal file
425
libraries/include/boost/graph/graph_utility.hpp
Normal file
@@ -0,0 +1,425 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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_UTILITY_HPP
|
||||
#define BOOST_GRAPH_UTILITY_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#if !defined BOOST_NO_SLIST
|
||||
# ifdef BOOST_SLIST_HEADER
|
||||
# include BOOST_SLIST_HEADER
|
||||
# else
|
||||
# include <slist>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/pending/container_traits.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
// iota moved to detail/algorithm.hpp
|
||||
#include <boost/detail/algorithm.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Provide an undirected graph interface alternative to the
|
||||
// the source() and target() edge functions.
|
||||
template <class UndirectedGraph>
|
||||
inline
|
||||
std::pair<typename graph_traits<UndirectedGraph>::vertex_descriptor,
|
||||
typename graph_traits<UndirectedGraph>::vertex_descriptor>
|
||||
incident(typename graph_traits<UndirectedGraph>::edge_descriptor e,
|
||||
UndirectedGraph& g)
|
||||
{
|
||||
return std::make_pair(source(e,g), target(e,g));
|
||||
}
|
||||
|
||||
// Provide an undirected graph interface alternative
|
||||
// to the out_edges() function.
|
||||
template <class Graph>
|
||||
inline
|
||||
std::pair<typename graph_traits<Graph>::out_edge_iterator,
|
||||
typename graph_traits<Graph>::out_edge_iterator>
|
||||
incident_edges(typename graph_traits<Graph>::vertex_descriptor u,
|
||||
Graph& g)
|
||||
{
|
||||
return out_edges(u, g);
|
||||
}
|
||||
|
||||
template <class Graph>
|
||||
inline typename graph_traits<Graph>::vertex_descriptor
|
||||
opposite(typename graph_traits<Graph>::edge_descriptor e,
|
||||
typename graph_traits<Graph>::vertex_descriptor v,
|
||||
const Graph& g)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
if (v == source(e, g))
|
||||
return target(e, g);
|
||||
else if (v == target(e, g))
|
||||
return source(e, g);
|
||||
else
|
||||
return vertex_descriptor();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Some handy predicates
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
struct incident_from_predicate {
|
||||
incident_from_predicate(Vertex u, const Graph& g)
|
||||
: m_u(u), m_g(g) { }
|
||||
template <class Edge>
|
||||
bool operator()(const Edge& e) const {
|
||||
return source(e, m_g) == m_u;
|
||||
}
|
||||
Vertex m_u;
|
||||
const Graph& m_g;
|
||||
};
|
||||
template <typename Vertex, typename Graph>
|
||||
inline incident_from_predicate<Vertex, Graph>
|
||||
incident_from(Vertex u, const Graph& g) {
|
||||
return incident_from_predicate<Vertex, Graph>(u, g);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
struct incident_to_predicate {
|
||||
incident_to_predicate(Vertex u, const Graph& g)
|
||||
: m_u(u), m_g(g) { }
|
||||
template <class Edge>
|
||||
bool operator()(const Edge& e) const {
|
||||
return target(e, m_g) == m_u;
|
||||
}
|
||||
Vertex m_u;
|
||||
const Graph& m_g;
|
||||
};
|
||||
template <typename Vertex, typename Graph>
|
||||
inline incident_to_predicate<Vertex, Graph>
|
||||
incident_to(Vertex u, const Graph& g) {
|
||||
return incident_to_predicate<Vertex, Graph>(u, g);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
struct incident_on_predicate {
|
||||
incident_on_predicate(Vertex u, const Graph& g)
|
||||
: m_u(u), m_g(g) { }
|
||||
template <class Edge>
|
||||
bool operator()(const Edge& e) const {
|
||||
return source(e, m_g) == m_u || target(e, m_g) == m_u;
|
||||
}
|
||||
Vertex m_u;
|
||||
const Graph& m_g;
|
||||
};
|
||||
template <typename Vertex, typename Graph>
|
||||
inline incident_on_predicate<Vertex, Graph>
|
||||
incident_on(Vertex u, const Graph& g) {
|
||||
return incident_on_predicate<Vertex, Graph>(u, g);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
struct connects_predicate {
|
||||
connects_predicate(Vertex u, Vertex v, const Graph& g)
|
||||
: m_u(u), m_v(v), m_g(g) { }
|
||||
template <class Edge>
|
||||
bool operator()(const Edge& e) const {
|
||||
if (is_directed(m_g))
|
||||
return source(e, m_g) == m_u && target(e, m_g) == m_v;
|
||||
else
|
||||
return (source(e, m_g) == m_u && target(e, m_g) == m_v)
|
||||
|| (source(e, m_g) == m_v && target(e, m_g) == m_u);
|
||||
}
|
||||
Vertex m_u, m_v;
|
||||
const Graph& m_g;
|
||||
};
|
||||
template <typename Vertex, typename Graph>
|
||||
inline connects_predicate<Vertex, Graph>
|
||||
connects(Vertex u, Vertex v, const Graph& g) {
|
||||
return connects_predicate<Vertex, Graph>(u, v, g);
|
||||
}
|
||||
|
||||
|
||||
// Need to convert all of these printing functions to take an ostream object
|
||||
// -JGS
|
||||
|
||||
template <class IncidenceGraph, class Name>
|
||||
void print_in_edges(const IncidenceGraph& G, Name name)
|
||||
{
|
||||
typename graph_traits<IncidenceGraph>::vertex_iterator ui,ui_end;
|
||||
for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) {
|
||||
std::cout << get(name,*ui) << " <-- ";
|
||||
typename graph_traits<IncidenceGraph>
|
||||
::in_edge_iterator ei, ei_end;
|
||||
for(tie(ei,ei_end) = in_edges(*ui,G); ei != ei_end; ++ei)
|
||||
std::cout << get(name,source(*ei,G)) << " ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <class IncidenceGraph, class Name>
|
||||
void print_graph_dispatch(const IncidenceGraph& G, Name name, directed_tag)
|
||||
{
|
||||
typename graph_traits<IncidenceGraph>::vertex_iterator ui,ui_end;
|
||||
for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) {
|
||||
std::cout << get(name,*ui) << " --> ";
|
||||
typename graph_traits<IncidenceGraph>
|
||||
::out_edge_iterator ei, ei_end;
|
||||
for(tie(ei,ei_end) = out_edges(*ui,G); ei != ei_end; ++ei)
|
||||
std::cout << get(name,target(*ei,G)) << " ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
template <class IncidenceGraph, class Name>
|
||||
void print_graph_dispatch(const IncidenceGraph& G, Name name, undirected_tag)
|
||||
{
|
||||
typename graph_traits<IncidenceGraph>::vertex_iterator ui,ui_end;
|
||||
for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) {
|
||||
std::cout << get(name,*ui) << " <--> ";
|
||||
typename graph_traits<IncidenceGraph>
|
||||
::out_edge_iterator ei, ei_end;
|
||||
for(tie(ei,ei_end) = out_edges(*ui,G); ei != ei_end; ++ei)
|
||||
std::cout << get(name,target(*ei,G)) << " ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
template <class IncidenceGraph, class Name>
|
||||
void print_graph(const IncidenceGraph& G, Name name)
|
||||
{
|
||||
typedef typename graph_traits<IncidenceGraph>
|
||||
::directed_category Cat;
|
||||
print_graph_dispatch(G, name, Cat());
|
||||
}
|
||||
template <class IncidenceGraph>
|
||||
void print_graph(const IncidenceGraph& G) {
|
||||
print_graph(G, get(vertex_index, G));
|
||||
}
|
||||
|
||||
template <class EdgeListGraph, class Name>
|
||||
void print_edges(const EdgeListGraph& G, Name name)
|
||||
{
|
||||
typename graph_traits<EdgeListGraph>::edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei)
|
||||
std::cout << "(" << get(name, source(*ei, G))
|
||||
<< "," << get(name, target(*ei, G)) << ") ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template <class EdgeListGraph, class VertexName, class EdgeName>
|
||||
void print_edges2(const EdgeListGraph& G, VertexName vname, EdgeName ename)
|
||||
{
|
||||
typename graph_traits<EdgeListGraph>::edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei)
|
||||
std::cout << get(ename, *ei) << "(" << get(vname, source(*ei, G))
|
||||
<< "," << get(vname, target(*ei, G)) << ") ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class Name>
|
||||
void print_vertices(const VertexListGraph& G, Name name)
|
||||
{
|
||||
typename graph_traits<VertexListGraph>::vertex_iterator vi,vi_end;
|
||||
for (tie(vi,vi_end) = vertices(G); vi != vi_end; ++vi)
|
||||
std::cout << get(name,*vi) << " ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template <class Graph, class Vertex>
|
||||
bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, bidirectional_tag)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_descriptor
|
||||
edge_descriptor;
|
||||
typename graph_traits<Graph>::adjacency_iterator vi, viend,
|
||||
adj_found;
|
||||
tie(vi, viend) = adjacent_vertices(a, g);
|
||||
adj_found = std::find(vi, viend, b);
|
||||
if (adj_found == viend)
|
||||
return false;
|
||||
|
||||
typename graph_traits<Graph>::out_edge_iterator oi, oiend,
|
||||
out_found;
|
||||
tie(oi, oiend) = out_edges(a, g);
|
||||
out_found = std::find_if(oi, oiend, incident_to(b, g));
|
||||
if (out_found == oiend)
|
||||
return false;
|
||||
|
||||
typename graph_traits<Graph>::in_edge_iterator ii, iiend,
|
||||
in_found;
|
||||
tie(ii, iiend) = in_edges(b, g);
|
||||
in_found = std::find_if(ii, iiend, incident_from(a, g));
|
||||
if (in_found == iiend)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
template <class Graph, class Vertex>
|
||||
bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, directed_tag)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_descriptor
|
||||
edge_descriptor;
|
||||
typename graph_traits<Graph>::adjacency_iterator vi, viend, found;
|
||||
tie(vi, viend) = adjacent_vertices(a, g);
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT)
|
||||
// Getting internal compiler error with std::find()
|
||||
found = viend;
|
||||
for (; vi != viend; ++vi)
|
||||
if (*vi == b) {
|
||||
found = vi;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
found = std::find(vi, viend, b);
|
||||
#endif
|
||||
if ( found == viend )
|
||||
return false;
|
||||
|
||||
typename graph_traits<Graph>::out_edge_iterator oi, oiend,
|
||||
out_found;
|
||||
tie(oi, oiend) = out_edges(a, g);
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT)
|
||||
// Getting internal compiler error with std::find()
|
||||
out_found = oiend;
|
||||
for (; oi != oiend; ++oi)
|
||||
if (target(*oi, g) == b) {
|
||||
out_found = oi;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
out_found = std::find_if(oi, oiend, incident_to(b, g));
|
||||
#endif
|
||||
if (out_found == oiend)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
template <class Graph, class Vertex>
|
||||
bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, undirected_tag)
|
||||
{
|
||||
return is_adj_dispatch(g, a, b, directed_tag());
|
||||
}
|
||||
|
||||
template <class Graph, class Vertex>
|
||||
bool is_adjacent(Graph& g, Vertex a, Vertex b) {
|
||||
typedef typename graph_traits<Graph>::directed_category Cat;
|
||||
return is_adj_dispatch(g, a, b, Cat());
|
||||
}
|
||||
|
||||
template <class Graph, class Edge>
|
||||
bool in_edge_set(Graph& g, Edge e)
|
||||
{
|
||||
typename Graph::edge_iterator ei, ei_end, found;
|
||||
tie(ei, ei_end) = edges(g);
|
||||
found = std::find(ei, ei_end, e);
|
||||
return found != ei_end;
|
||||
}
|
||||
|
||||
template <class Graph, class Vertex>
|
||||
bool in_vertex_set(Graph& g, Vertex v)
|
||||
{
|
||||
typename Graph::vertex_iterator vi, vi_end, found;
|
||||
tie(vi, vi_end) = vertices(g);
|
||||
found = std::find(vi, vi_end, v);
|
||||
return found != vi_end;
|
||||
}
|
||||
|
||||
template <class Graph, class Vertex>
|
||||
bool in_edge_set(Graph& g, Vertex u, Vertex v)
|
||||
{
|
||||
typename Graph::edge_iterator ei, ei_end;
|
||||
for (tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
if (source(*ei,g) == u && target(*ei,g) == v)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// is x a descendant of y?
|
||||
template <typename ParentMap>
|
||||
inline bool is_descendant
|
||||
(typename property_traits<ParentMap>::value_type x,
|
||||
typename property_traits<ParentMap>::value_type y,
|
||||
ParentMap parent)
|
||||
{
|
||||
if (get(parent, x) == x) // x is the root of the tree
|
||||
return false;
|
||||
else if (get(parent, x) == y)
|
||||
return true;
|
||||
else
|
||||
return is_descendant(get(parent, x), y, parent);
|
||||
}
|
||||
|
||||
// is y reachable from x?
|
||||
template <typename IncidenceGraph, typename VertexColorMap>
|
||||
inline bool is_reachable
|
||||
(typename graph_traits<IncidenceGraph>::vertex_descriptor x,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor y,
|
||||
const IncidenceGraph& g,
|
||||
VertexColorMap color) // should start out white for every vertex
|
||||
{
|
||||
typedef typename property_traits<VertexColorMap>::value_type ColorValue;
|
||||
dfs_visitor<> vis;
|
||||
depth_first_visit(g, x, vis, color);
|
||||
return get(color, y) != color_traits<ColorValue>::white();
|
||||
}
|
||||
|
||||
// Is the undirected graph connected?
|
||||
// Is the directed graph strongly connected?
|
||||
template <typename VertexListGraph, typename VertexColorMap>
|
||||
inline bool is_connected(const VertexListGraph& g, VertexColorMap color)
|
||||
{
|
||||
typedef typename property_traits<VertexColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typename graph_traits<VertexListGraph>::vertex_iterator
|
||||
ui, ui_end, vi, vi_end, ci, ci_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
|
||||
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
if (*ui != *vi) {
|
||||
for (tie(ci, ci_end) = vertices(g); ci != ci_end; ++ci)
|
||||
put(color, *ci, Color::white());
|
||||
if (! is_reachable(*ui, *vi, g, color))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
bool is_self_loop
|
||||
(typename graph_traits<Graph>::edge_descriptor e,
|
||||
const Graph& g)
|
||||
{
|
||||
return source(e, g) == target(e, g);
|
||||
}
|
||||
|
||||
|
||||
template <class T1, class T2>
|
||||
std::pair<T1,T2>
|
||||
make_list(const T1& t1, const T2& t2)
|
||||
{ return std::make_pair(t1, t2); }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
std::pair<T1,std::pair<T2,T3> >
|
||||
make_list(const T1& t1, const T2& t2, const T3& t3)
|
||||
{ return std::make_pair(t1, std::make_pair(t2, t3)); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
std::pair<T1,std::pair<T2,std::pair<T3,T4> > >
|
||||
make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
{ return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, t4))); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
std::pair<T1,std::pair<T2,std::pair<T3,std::pair<T4,T5> > > >
|
||||
make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5)
|
||||
{ return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, std::make_pair(t4, t5)))); }
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_GRAPH_UTILITY_HPP*/
|
||||
332
libraries/include/boost/graph/graphml.hpp
Normal file
332
libraries/include/boost/graph/graphml.hpp
Normal file
@@ -0,0 +1,332 @@
|
||||
// Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de>
|
||||
// Copyright (C) 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
|
||||
// Tiago de Paula Peixoto
|
||||
|
||||
#ifndef BOOST_GRAPH_GRAPHML_HPP
|
||||
#define BOOST_GRAPH_GRAPHML_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/graph/graphviz.hpp> // for exceptions
|
||||
#include <typeinfo>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Graph reader exceptions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
struct parse_error: public graph_exception
|
||||
{
|
||||
parse_error(const std::string& error) {statement = "parse error: " + error;}
|
||||
virtual ~parse_error() throw() {}
|
||||
virtual const char* what() const throw() {return statement.c_str();}
|
||||
std::string statement;
|
||||
};
|
||||
|
||||
|
||||
class mutate_graph
|
||||
{
|
||||
public:
|
||||
virtual ~mutate_graph() {}
|
||||
virtual bool is_directed() const = 0;
|
||||
|
||||
virtual boost::any do_add_vertex() = 0;
|
||||
virtual std::pair<boost::any,bool> do_add_edge(boost::any source, boost::any target) = 0;
|
||||
|
||||
virtual void
|
||||
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0;
|
||||
|
||||
virtual void
|
||||
set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0;
|
||||
|
||||
virtual void
|
||||
set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0;
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
class mutate_graph_impl : public mutate_graph
|
||||
{
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<MutableGraph>::edge_descriptor edge_descriptor;
|
||||
|
||||
public:
|
||||
mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
|
||||
: m_g(g), m_dp(dp) { }
|
||||
|
||||
bool is_directed() const
|
||||
{
|
||||
return is_convertible<typename graph_traits<MutableGraph>::directed_category,
|
||||
directed_tag>::value;
|
||||
}
|
||||
|
||||
virtual any do_add_vertex()
|
||||
{
|
||||
return any(add_vertex(m_g));
|
||||
}
|
||||
|
||||
virtual std::pair<any,bool> do_add_edge(any source, any target)
|
||||
{
|
||||
std::pair<edge_descriptor,bool> retval = add_edge(any_cast<vertex_descriptor>(source),
|
||||
any_cast<vertex_descriptor>(target), m_g);
|
||||
return std::make_pair(any(retval.first), retval.second);
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<MutableGraph,value_types>
|
||||
(name, m_dp, m_g, value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
throw parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type);
|
||||
}
|
||||
if (!type_found)
|
||||
throw parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name);
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<vertex_descriptor,value_types>
|
||||
(name, m_dp, any_cast<vertex_descriptor>(vertex),
|
||||
value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
throw parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type);
|
||||
}
|
||||
if (!type_found)
|
||||
throw parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name);
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<edge_descriptor,value_types>
|
||||
(name, m_dp, any_cast<edge_descriptor>(edge),
|
||||
value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
throw parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type);
|
||||
}
|
||||
if (!type_found)
|
||||
throw parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name);
|
||||
}
|
||||
|
||||
template <typename Key, typename ValueVector>
|
||||
class put_property
|
||||
{
|
||||
public:
|
||||
put_property(const std::string& name, dynamic_properties& dp, const Key& key,
|
||||
const std::string& value, const std::string& value_type,
|
||||
const char** type_names, bool& type_found)
|
||||
: m_name(name), m_dp(dp), m_key(key), m_value(value),
|
||||
m_value_type(value_type), m_type_names(type_names),
|
||||
m_type_found(type_found) {}
|
||||
template <class Value>
|
||||
void operator()(Value)
|
||||
{
|
||||
if (m_value_type == m_type_names[mpl::find<ValueVector,Value>::type::pos::value])
|
||||
{
|
||||
put(m_name, m_dp, m_key, lexical_cast<Value>(m_value));
|
||||
m_type_found = true;
|
||||
}
|
||||
}
|
||||
private:
|
||||
const std::string& m_name;
|
||||
dynamic_properties& m_dp;
|
||||
const Key& m_key;
|
||||
const std::string& m_value;
|
||||
const std::string& m_value_type;
|
||||
const char** m_type_names;
|
||||
bool& m_type_found;
|
||||
};
|
||||
|
||||
protected:
|
||||
MutableGraph& m_g;
|
||||
dynamic_properties& m_dp;
|
||||
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
|
||||
static const char* m_type_names[];
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
const char* mutate_graph_impl<MutableGraph>::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"};
|
||||
|
||||
void BOOST_GRAPH_DECL
|
||||
read_graphml(std::istream& in, mutate_graph& g);
|
||||
|
||||
template<typename MutableGraph>
|
||||
void
|
||||
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp)
|
||||
{
|
||||
mutate_graph_impl<MutableGraph> mg(g,dp);
|
||||
read_graphml(in, mg);
|
||||
}
|
||||
|
||||
template <typename Types>
|
||||
class get_type_name
|
||||
{
|
||||
public:
|
||||
get_type_name(const std::type_info& type, const char** type_names, std::string& type_name)
|
||||
: m_type(type), m_type_names(type_names), m_type_name(type_name) {}
|
||||
template <typename Type>
|
||||
void operator()(Type)
|
||||
{
|
||||
if (typeid(Type) == m_type)
|
||||
m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
|
||||
}
|
||||
private:
|
||||
const std::type_info &m_type;
|
||||
const char** m_type_names;
|
||||
std::string &m_type_name;
|
||||
};
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
void
|
||||
write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
|
||||
const dynamic_properties& dp, bool ordered_vertices=false)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category directed_category;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool,
|
||||
graph_is_directed =
|
||||
(is_convertible<directed_category*, directed_tag*>::value));
|
||||
|
||||
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
<< "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
|
||||
|
||||
typedef mpl::vector<bool, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, std::string> value_types;
|
||||
const char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"};
|
||||
std::map<std::string, std::string> graph_key_ids;
|
||||
std::map<std::string, std::string> vertex_key_ids;
|
||||
std::map<std::string, std::string> edge_key_ids;
|
||||
int key_count = 0;
|
||||
|
||||
// Output keys
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
std::string key_id = "key" + lexical_cast<std::string>(key_count++);
|
||||
if (i->second->key() == typeid(Graph))
|
||||
vertex_key_ids[i->first] = key_id;
|
||||
else if (i->second->key() == typeid(vertex_descriptor))
|
||||
vertex_key_ids[i->first] = key_id;
|
||||
else if (i->second->key() == typeid(edge_descriptor))
|
||||
edge_key_ids[i->first] = key_id;
|
||||
else
|
||||
continue;
|
||||
std::string type_name = "string";
|
||||
mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
|
||||
out << " <key id=\"" << key_id << "\" for=\""
|
||||
<< (i->second->key() == typeid(Graph) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\""
|
||||
<< " attr.name=\"" << i->first << "\""
|
||||
<< " attr.type=\"" << type_name << "\""
|
||||
<< " />\n";
|
||||
}
|
||||
|
||||
out << " <graph id=\"G\" edgedefault=\""
|
||||
<< (graph_is_directed ? "directed" : "undirected") << "\""
|
||||
<< " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free") << "\""
|
||||
<< " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
|
||||
|
||||
// Output graph data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == typeid(Graph))
|
||||
{
|
||||
out << " <data key=\"" << graph_key_ids[i->first] << "\">"
|
||||
<< i->second->get_string(g) << "</data>\n";
|
||||
}
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
vertex_iterator v, v_end;
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v)
|
||||
{
|
||||
out << " <node id=\"n" << get(vertex_index, *v) << "\">\n";
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == typeid(vertex_descriptor))
|
||||
{
|
||||
out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
|
||||
<< i->second->get_string(*v) << "</data>\n";
|
||||
}
|
||||
}
|
||||
out << " </node>\n";
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
|
||||
edge_iterator e, e_end;
|
||||
typename graph_traits<Graph>::edges_size_type edge_count = 0;
|
||||
for (tie(e, e_end) = edges(g); e != e_end; ++e)
|
||||
{
|
||||
out << " <edge id=\"e" << edge_count++ << "\" source=\"n"
|
||||
<< get(vertex_index, source(*e, g)) << "\" target=\"n"
|
||||
<< get(vertex_index, target(*e, g)) << "\">\n";
|
||||
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == typeid(edge_descriptor))
|
||||
{
|
||||
out << " <data key=\"" << edge_key_ids[i->first] << "\">"
|
||||
<< i->second->get_string(*e) << "</data>\n";
|
||||
}
|
||||
}
|
||||
out << " </edge>\n";
|
||||
}
|
||||
|
||||
out << " </graph>\n"
|
||||
<< "</graphml>\n";
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
void
|
||||
write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp,
|
||||
bool ordered_vertices=false)
|
||||
{
|
||||
write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
|
||||
}
|
||||
|
||||
} // boost namespace
|
||||
|
||||
#endif // BOOST_GRAPH_GRAPHML_HPP
|
||||
783
libraries/include/boost/graph/graphviz.hpp
Normal file
783
libraries/include/boost/graph/graphviz.hpp
Normal file
@@ -0,0 +1,783 @@
|
||||
//=======================================================================
|
||||
// Copyright 2001 University of Notre Dame.
|
||||
// Copyright 2003 Jeremy Siek
|
||||
// Authors: Lie-Quan Lee and Jeremy 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_GRAPHVIZ_HPP
|
||||
#define BOOST_GRAPHVIZ_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdio.h> // for FILE
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/subgraph.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/dynamic_property_map.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_DECLSPEC
|
||||
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK)
|
||||
# ifdef BOOST_GRAPH_SOURCE
|
||||
# define BOOST_GRAPH_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define BOOST_GRAPH_DECL __declspec(dllimport)
|
||||
# endif // BOOST_GRAPH_SOURCE
|
||||
# endif // DYN_LINK
|
||||
#endif // BOOST_HAS_DECLSPEC
|
||||
|
||||
#ifndef BOOST_GRAPH_DECL
|
||||
# define BOOST_GRAPH_DECL
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename directed_category>
|
||||
struct graphviz_io_traits {
|
||||
static std::string name() {
|
||||
return "digraph";
|
||||
}
|
||||
static std::string delimiter() {
|
||||
return "->";
|
||||
} };
|
||||
|
||||
template <>
|
||||
struct graphviz_io_traits <undirected_tag> {
|
||||
static std::string name() {
|
||||
return "graph";
|
||||
}
|
||||
static std::string delimiter() {
|
||||
return "--";
|
||||
}
|
||||
};
|
||||
|
||||
struct default_writer {
|
||||
void operator()(std::ostream&) const {
|
||||
}
|
||||
template <class VorE>
|
||||
void operator()(std::ostream&, const VorE&) const {
|
||||
}
|
||||
};
|
||||
|
||||
template <class Name>
|
||||
class label_writer {
|
||||
public:
|
||||
label_writer(Name _name) : name(_name) {}
|
||||
template <class VertexOrEdge>
|
||||
void operator()(std::ostream& out, const VertexOrEdge& v) const {
|
||||
out << "[label=\"" << get(name, v) << "\"]";
|
||||
}
|
||||
private:
|
||||
Name name;
|
||||
};
|
||||
template <class Name>
|
||||
inline label_writer<Name>
|
||||
make_label_writer(Name n) {
|
||||
return label_writer<Name>(n);
|
||||
}
|
||||
|
||||
enum edge_attribute_t { edge_attribute = 1111 };
|
||||
enum vertex_attribute_t { vertex_attribute = 2222 };
|
||||
enum graph_graph_attribute_t { graph_graph_attribute = 3333 };
|
||||
enum graph_vertex_attribute_t { graph_vertex_attribute = 4444 };
|
||||
enum graph_edge_attribute_t { graph_edge_attribute = 5555 };
|
||||
|
||||
BOOST_INSTALL_PROPERTY(edge, attribute);
|
||||
BOOST_INSTALL_PROPERTY(vertex, attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, graph_attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, vertex_attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, edge_attribute);
|
||||
|
||||
|
||||
template <class Attribute>
|
||||
inline void write_attributes(const Attribute& attr, std::ostream& out) {
|
||||
typename Attribute::const_iterator i, iend;
|
||||
i = attr.begin();
|
||||
iend = attr.end();
|
||||
|
||||
while ( i != iend ) {
|
||||
out << i->first << "=\"" << i->second << "\"";
|
||||
++i;
|
||||
if ( i != iend )
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Attributes>
|
||||
inline void write_all_attributes(Attributes attributes,
|
||||
const std::string& name,
|
||||
std::ostream& out)
|
||||
{
|
||||
typename Attributes::const_iterator i = attributes.begin(),
|
||||
end = attributes.end();
|
||||
if (i != end) {
|
||||
out << name << " [\n";
|
||||
write_attributes(attributes, out);
|
||||
out << "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
inline void write_all_attributes(detail::error_property_not_found,
|
||||
const std::string&,
|
||||
std::ostream&)
|
||||
{
|
||||
// Do nothing - no attributes exist
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename GraphGraphAttributes,
|
||||
typename GraphNodeAttributes,
|
||||
typename GraphEdgeAttributes>
|
||||
struct graph_attributes_writer
|
||||
{
|
||||
graph_attributes_writer(GraphGraphAttributes gg,
|
||||
GraphNodeAttributes gn,
|
||||
GraphEdgeAttributes ge)
|
||||
: g_attributes(gg), n_attributes(gn), e_attributes(ge) { }
|
||||
|
||||
void operator()(std::ostream& out) const {
|
||||
write_all_attributes(g_attributes, "graph", out);
|
||||
write_all_attributes(n_attributes, "node", out);
|
||||
write_all_attributes(e_attributes, "edge", out);
|
||||
}
|
||||
GraphGraphAttributes g_attributes;
|
||||
GraphNodeAttributes n_attributes;
|
||||
GraphEdgeAttributes e_attributes;
|
||||
};
|
||||
|
||||
template <typename GAttrMap, typename NAttrMap, typename EAttrMap>
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
|
||||
make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr,
|
||||
const EAttrMap& e_attr) {
|
||||
return graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
|
||||
(g_attr, n_attr, e_attr);
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
graph_attributes_writer
|
||||
<typename graph_property<Graph, graph_graph_attribute_t>::type,
|
||||
typename graph_property<Graph, graph_vertex_attribute_t>::type,
|
||||
typename graph_property<Graph, graph_edge_attribute_t>::type>
|
||||
make_graph_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename graph_property<Graph, graph_graph_attribute_t>::type
|
||||
GAttrMap;
|
||||
typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
|
||||
NAttrMap;
|
||||
typedef typename graph_property<Graph, graph_edge_attribute_t>::type
|
||||
EAttrMap;
|
||||
GAttrMap gam = get_property(g, graph_graph_attribute);
|
||||
NAttrMap nam = get_property(g, graph_vertex_attribute);
|
||||
EAttrMap eam = get_property(g, graph_edge_attribute);
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
|
||||
return writer;
|
||||
}
|
||||
|
||||
template <typename AttributeMap>
|
||||
struct attributes_writer {
|
||||
attributes_writer(AttributeMap attr)
|
||||
: attributes(attr) { }
|
||||
|
||||
template <class VorE>
|
||||
void operator()(std::ostream& out, const VorE& e) const {
|
||||
this->write_attribute(out, attributes[e]);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename AttributeSequence>
|
||||
void write_attribute(std::ostream& out,
|
||||
const AttributeSequence& seq) const
|
||||
{
|
||||
if (!seq.empty()) {
|
||||
out << "[";
|
||||
write_attributes(seq, out);
|
||||
out << "]";
|
||||
}
|
||||
}
|
||||
|
||||
void write_attribute(std::ostream&,
|
||||
detail::error_property_not_found) const
|
||||
{
|
||||
}
|
||||
AttributeMap attributes;
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
attributes_writer
|
||||
<typename property_map<Graph, edge_attribute_t>::const_type>
|
||||
make_edge_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename property_map<Graph, edge_attribute_t>::const_type
|
||||
EdgeAttributeMap;
|
||||
return attributes_writer<EdgeAttributeMap>(get(edge_attribute, g));
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
attributes_writer
|
||||
<typename property_map<Graph, vertex_attribute_t>::const_type>
|
||||
make_vertex_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename property_map<Graph, vertex_attribute_t>::const_type
|
||||
VertexAttributeMap;
|
||||
return attributes_writer<VertexAttributeMap>(get(vertex_attribute, g));
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexPropertiesWriter,
|
||||
typename EdgePropertiesWriter, typename GraphPropertiesWriter,
|
||||
typename VertexID>
|
||||
inline void write_graphviz(std::ostream& out, const Graph& g,
|
||||
VertexPropertiesWriter vpw,
|
||||
EdgePropertiesWriter epw,
|
||||
GraphPropertiesWriter gpw,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category cat_type;
|
||||
typedef graphviz_io_traits<cat_type> Traits;
|
||||
std::string name = "G";
|
||||
out << Traits::name() << " " << name << " {" << std::endl;
|
||||
|
||||
gpw(out); //print graph properties
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
|
||||
for(tie(i,end) = vertices(g); i != end; ++i) {
|
||||
out << get(vertex_id, *i);
|
||||
vpw(out, *i); //print vertex attributes
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
typename graph_traits<Graph>::edge_iterator ei, edge_end;
|
||||
for(tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
|
||||
out << get(vertex_id, source(*ei, g)) << Traits::delimiter() << get(vertex_id, target(*ei, g)) << " ";
|
||||
epw(out, *ei); //print edge attributes
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexPropertiesWriter,
|
||||
typename EdgePropertiesWriter, typename GraphPropertiesWriter>
|
||||
inline void write_graphviz(std::ostream& out, const Graph& g,
|
||||
VertexPropertiesWriter vpw,
|
||||
EdgePropertiesWriter epw,
|
||||
GraphPropertiesWriter gpw)
|
||||
{ write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); }
|
||||
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
// ambiguous overload problem with VC++
|
||||
template <typename Graph>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g) {
|
||||
default_writer dw;
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, dw, dw, gw);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Graph, typename VertexWriter>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw) {
|
||||
default_writer dw;
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, vw, dw, gw);
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexWriter, typename EdgeWriter>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g,
|
||||
VertexWriter vw, EdgeWriter ew) {
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, vw, ew, gw);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Graph_, class RandomAccessIterator, class VertexID>
|
||||
void write_graphviz_subgraph (std::ostream& out,
|
||||
const subgraph<Graph_>& g,
|
||||
RandomAccessIterator vertex_marker,
|
||||
RandomAccessIterator edge_marker,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
typedef subgraph<Graph_> Graph;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::directed_category cat_type;
|
||||
typedef graphviz_io_traits<cat_type> Traits;
|
||||
|
||||
typedef typename graph_property<Graph, graph_name_t>::type NameType;
|
||||
const NameType& g_name = get_property(g, graph_name);
|
||||
|
||||
if ( g.is_root() )
|
||||
out << Traits::name() ;
|
||||
else
|
||||
out << "subgraph";
|
||||
|
||||
out << " " << g_name << " {" << std::endl;
|
||||
|
||||
typename Graph::const_children_iterator i_child, j_child;
|
||||
|
||||
//print graph/node/edge attributes
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename graph_property<Graph, graph_graph_attribute_t>::type
|
||||
GAttrMap;
|
||||
typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
|
||||
NAttrMap;
|
||||
typedef typename graph_property<Graph, graph_edge_attribute_t>::type
|
||||
EAttrMap;
|
||||
GAttrMap gam = get_property(g, graph_graph_attribute);
|
||||
NAttrMap nam = get_property(g, graph_vertex_attribute);
|
||||
EAttrMap eam = get_property(g, graph_edge_attribute);
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
|
||||
writer(out);
|
||||
#else
|
||||
make_graph_attributes_writer(g)(out);
|
||||
#endif
|
||||
|
||||
//print subgraph
|
||||
for ( tie(i_child,j_child) = g.children();
|
||||
i_child != j_child; ++i_child )
|
||||
write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker,
|
||||
vertex_id);
|
||||
|
||||
// Print out vertices and edges not in the subgraphs.
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
typename graph_traits<Graph>::edge_iterator ei, edge_end;
|
||||
|
||||
for(tie(i,end) = vertices(g); i != end; ++i) {
|
||||
Vertex v = g.local_to_global(*i);
|
||||
int pos = get(vertex_id, v);
|
||||
if ( vertex_marker[pos] ) {
|
||||
vertex_marker[pos] = false;
|
||||
out << pos;
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename property_map<Graph, vertex_attribute_t>::const_type
|
||||
VertexAttributeMap;
|
||||
attributes_writer<VertexAttributeMap> vawriter(get(vertex_attribute,
|
||||
g.root()));
|
||||
vawriter(out, v);
|
||||
#else
|
||||
make_vertex_attributes_writer(g.root())(out, v);
|
||||
#endif
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
|
||||
Vertex u = g.local_to_global(source(*ei,g)),
|
||||
v = g.local_to_global(target(*ei, g));
|
||||
int pos = get(get(edge_index, g.root()), g.local_to_global(*ei));
|
||||
if ( edge_marker[pos] ) {
|
||||
edge_marker[pos] = false;
|
||||
out << get(vertex_id, u) << " " << Traits::delimiter()
|
||||
<< " " << get(vertex_id, v);
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename property_map<Graph, edge_attribute_t>::const_type
|
||||
EdgeAttributeMap;
|
||||
attributes_writer<EdgeAttributeMap> eawriter(get(edge_attribute, g));
|
||||
eawriter(out, *ei);
|
||||
#else
|
||||
make_edge_attributes_writer(g)(out, *ei); //print edge properties
|
||||
#endif
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// requires graph_name graph property
|
||||
template <typename Graph>
|
||||
void write_graphviz(std::ostream& out, const subgraph<Graph>& g) {
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
void write_graphviz(const std::string& filename, const subgraph<Graph>& g) {
|
||||
std::ofstream out(filename.c_str());
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexID>
|
||||
void write_graphviz(std::ostream& out, const subgraph<Graph>& g,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
vertex_id);
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexID>
|
||||
void write_graphviz(const std::string& filename, const subgraph<Graph>& g,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
std::ofstream out(filename.c_str());
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
vertex_id);
|
||||
}
|
||||
|
||||
typedef std::map<std::string, std::string> GraphvizAttrList;
|
||||
|
||||
typedef property<vertex_attribute_t, GraphvizAttrList>
|
||||
GraphvizVertexProperty;
|
||||
|
||||
typedef property<edge_attribute_t, GraphvizAttrList,
|
||||
property<edge_index_t, int> >
|
||||
GraphvizEdgeProperty;
|
||||
|
||||
typedef property<graph_graph_attribute_t, GraphvizAttrList,
|
||||
property<graph_vertex_attribute_t, GraphvizAttrList,
|
||||
property<graph_edge_attribute_t, GraphvizAttrList,
|
||||
property<graph_name_t, std::string> > > >
|
||||
GraphvizGraphProperty;
|
||||
|
||||
typedef subgraph<adjacency_list<vecS,
|
||||
vecS, directedS,
|
||||
GraphvizVertexProperty,
|
||||
GraphvizEdgeProperty,
|
||||
GraphvizGraphProperty> >
|
||||
GraphvizDigraph;
|
||||
|
||||
typedef subgraph<adjacency_list<vecS,
|
||||
vecS, undirectedS,
|
||||
GraphvizVertexProperty,
|
||||
GraphvizEdgeProperty,
|
||||
GraphvizGraphProperty> >
|
||||
GraphvizGraph;
|
||||
|
||||
|
||||
// These four require linking the BGL-Graphviz library: libbgl-viz.a
|
||||
// from the /src directory.
|
||||
extern void read_graphviz(const std::string& file, GraphvizDigraph& g);
|
||||
extern void read_graphviz(FILE* file, GraphvizDigraph& g);
|
||||
|
||||
extern void read_graphviz(const std::string& file, GraphvizGraph& g);
|
||||
extern void read_graphviz(FILE* file, GraphvizGraph& g);
|
||||
|
||||
class dynamic_properties_writer
|
||||
{
|
||||
public:
|
||||
dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { }
|
||||
|
||||
template<typename Descriptor>
|
||||
void operator()(std::ostream& out, Descriptor key) const
|
||||
{
|
||||
bool first = true;
|
||||
for (dynamic_properties::const_iterator i = dp->begin();
|
||||
i != dp->end(); ++i) {
|
||||
if (typeid(key) == i->second->key()) {
|
||||
if (first) out << " [";
|
||||
else out << ", ";
|
||||
first = false;
|
||||
|
||||
out << i->first << "=\"" << i->second->get_string(key) << "\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (!first) out << "]";
|
||||
}
|
||||
|
||||
private:
|
||||
const dynamic_properties* dp;
|
||||
};
|
||||
|
||||
class dynamic_vertex_properties_writer
|
||||
{
|
||||
public:
|
||||
dynamic_vertex_properties_writer(const dynamic_properties& dp,
|
||||
const std::string& node_id)
|
||||
: dp(&dp), node_id(&node_id) { }
|
||||
|
||||
template<typename Descriptor>
|
||||
void operator()(std::ostream& out, Descriptor key) const
|
||||
{
|
||||
bool first = true;
|
||||
for (dynamic_properties::const_iterator i = dp->begin();
|
||||
i != dp->end(); ++i) {
|
||||
if (typeid(key) == i->second->key()
|
||||
&& i->first != *node_id) {
|
||||
if (first) out << " [";
|
||||
else out << ", ";
|
||||
first = false;
|
||||
|
||||
out << i->first << "=\"" << i->second->get_string(key) << "\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (!first) out << "]";
|
||||
}
|
||||
|
||||
private:
|
||||
const dynamic_properties* dp;
|
||||
const std::string* node_id;
|
||||
};
|
||||
|
||||
namespace graph { namespace detail {
|
||||
|
||||
template<typename Vertex>
|
||||
struct node_id_property_map
|
||||
{
|
||||
typedef std::string value_type;
|
||||
typedef value_type reference;
|
||||
typedef Vertex key_type;
|
||||
typedef readable_property_map_tag category;
|
||||
|
||||
node_id_property_map() {}
|
||||
|
||||
node_id_property_map(const dynamic_properties& dp,
|
||||
const std::string& node_id)
|
||||
: dp(&dp), node_id(&node_id) { }
|
||||
|
||||
const dynamic_properties* dp;
|
||||
const std::string* node_id;
|
||||
};
|
||||
|
||||
template<typename Vertex>
|
||||
inline std::string
|
||||
get(node_id_property_map<Vertex> pm,
|
||||
typename node_id_property_map<Vertex>::key_type v)
|
||||
{ return get(*pm.node_id, *pm.dp, v); }
|
||||
|
||||
} } // end namespace graph::detail
|
||||
|
||||
template<typename Graph>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g,
|
||||
const dynamic_properties& dp,
|
||||
const std::string& node_id = "node_id")
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
write_graphviz(out, g, dp, node_id,
|
||||
graph::detail::node_id_property_map<Vertex>(dp, node_id));
|
||||
}
|
||||
|
||||
template<typename Graph, typename VertexID>
|
||||
void
|
||||
write_graphviz(std::ostream& out, const Graph& g,
|
||||
const dynamic_properties& dp, const std::string& node_id,
|
||||
VertexID id)
|
||||
{
|
||||
write_graphviz
|
||||
(out, g,
|
||||
/*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id),
|
||||
/*edge_writer=*/dynamic_properties_writer(dp),
|
||||
/*graph_writer=*/default_writer(),
|
||||
id);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Graph reader exceptions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
struct graph_exception : public std::exception {
|
||||
virtual ~graph_exception() throw() {}
|
||||
virtual const char* what() const throw() = 0;
|
||||
};
|
||||
|
||||
struct bad_parallel_edge : public graph_exception {
|
||||
std::string from;
|
||||
std::string to;
|
||||
mutable std::string statement;
|
||||
bad_parallel_edge(const std::string& i, const std::string& j) :
|
||||
from(i), to(j) {}
|
||||
|
||||
virtual ~bad_parallel_edge() throw() {}
|
||||
const char* what() const throw() {
|
||||
if(statement.empty())
|
||||
statement =
|
||||
std::string("Failed to add parallel edge: (")
|
||||
+ from + "," + to + ")\n";
|
||||
|
||||
return statement.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
struct directed_graph_error : public graph_exception {
|
||||
virtual ~directed_graph_error() throw() {}
|
||||
virtual const char* what() const throw() {
|
||||
return
|
||||
"read_graphviz: "
|
||||
"Tried to read a directed graph into an undirected graph.";
|
||||
}
|
||||
};
|
||||
|
||||
struct undirected_graph_error : public graph_exception {
|
||||
virtual ~undirected_graph_error() throw() {}
|
||||
virtual const char* what() const throw() {
|
||||
return
|
||||
"read_graphviz: "
|
||||
"Tried to read an undirected graph into a directed graph.";
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail { namespace graph {
|
||||
|
||||
typedef std::string id_t;
|
||||
typedef id_t node_t;
|
||||
|
||||
// edges are not uniquely determined by adjacent nodes
|
||||
class edge_t {
|
||||
int idx_;
|
||||
explicit edge_t(int i) : idx_(i) {}
|
||||
public:
|
||||
static edge_t new_edge() {
|
||||
static int idx = 0;
|
||||
return edge_t(idx++);
|
||||
};
|
||||
|
||||
bool operator==(const edge_t& rhs) const {
|
||||
return idx_ == rhs.idx_;
|
||||
}
|
||||
bool operator<(const edge_t& rhs) const {
|
||||
return idx_ < rhs.idx_;
|
||||
}
|
||||
};
|
||||
|
||||
class mutate_graph
|
||||
{
|
||||
public:
|
||||
virtual ~mutate_graph() {}
|
||||
virtual bool is_directed() const = 0;
|
||||
virtual void do_add_vertex(const node_t& node) = 0;
|
||||
|
||||
virtual void
|
||||
do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
|
||||
= 0;
|
||||
|
||||
virtual void
|
||||
set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0;
|
||||
|
||||
virtual void
|
||||
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0;
|
||||
|
||||
virtual void // RG: need new second parameter to support BGL subgraphs
|
||||
set_graph_property(const id_t& key, const id_t& value) = 0;
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
class mutate_graph_impl : public mutate_graph
|
||||
{
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor bgl_vertex_t;
|
||||
typedef typename graph_traits<MutableGraph>::edge_descriptor bgl_edge_t;
|
||||
|
||||
public:
|
||||
mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp,
|
||||
std::string node_id_prop)
|
||||
: graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { }
|
||||
|
||||
~mutate_graph_impl() {}
|
||||
|
||||
bool is_directed() const
|
||||
{
|
||||
return
|
||||
boost::is_convertible<
|
||||
typename boost::graph_traits<MutableGraph>::directed_category,
|
||||
boost::directed_tag>::value;
|
||||
}
|
||||
|
||||
virtual void do_add_vertex(const node_t& node)
|
||||
{
|
||||
// Add the node to the graph.
|
||||
bgl_vertex_t v = add_vertex(graph_);
|
||||
|
||||
// Set up a mapping from name to BGL vertex.
|
||||
bgl_nodes.insert(std::make_pair(node, v));
|
||||
|
||||
// node_id_prop_ allows the caller to see the real id names for nodes.
|
||||
put(node_id_prop_, dp_, v, node);
|
||||
}
|
||||
|
||||
void
|
||||
do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
|
||||
{
|
||||
std::pair<bgl_edge_t, bool> result =
|
||||
add_edge(bgl_nodes[source], bgl_nodes[target], graph_);
|
||||
|
||||
if(!result.second) {
|
||||
// In the case of no parallel edges allowed
|
||||
throw bad_parallel_edge(source, target);
|
||||
} else {
|
||||
bgl_edges.insert(std::make_pair(edge, result.first));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_node_property(const id_t& key, const node_t& node, const id_t& value)
|
||||
{
|
||||
put(key, dp_, bgl_nodes[node], value);
|
||||
}
|
||||
|
||||
void
|
||||
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value)
|
||||
{
|
||||
put(key, dp_, bgl_edges[edge], value);
|
||||
}
|
||||
|
||||
void
|
||||
set_graph_property(const id_t& key, const id_t& value)
|
||||
{
|
||||
/* RG: pointer to graph prevents copying */
|
||||
put(key, dp_, &graph_, value);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
MutableGraph& graph_;
|
||||
dynamic_properties& dp_;
|
||||
std::string node_id_prop_;
|
||||
std::map<node_t, bgl_vertex_t> bgl_nodes;
|
||||
std::map<edge_t, bgl_edge_t> bgl_edges;
|
||||
};
|
||||
|
||||
BOOST_GRAPH_DECL
|
||||
bool read_graphviz(std::istream& in, mutate_graph& graph);
|
||||
|
||||
} } // end namespace detail::graph
|
||||
|
||||
// Parse the passed stream as a GraphViz dot file.
|
||||
template <typename MutableGraph>
|
||||
bool read_graphviz(std::istream& in, MutableGraph& graph,
|
||||
dynamic_properties& dp,
|
||||
std::string const& node_id = "node_id")
|
||||
{
|
||||
detail::graph::mutate_graph_impl<MutableGraph> m_graph(graph, dp, node_id);
|
||||
return detail::graph::read_graphviz(in, m_graph);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
|
||||
# include <boost/graph/detail/read_graphviz_spirit.hpp>
|
||||
#endif // BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
|
||||
|
||||
#endif // BOOST_GRAPHVIZ_HPP
|
||||
631
libraries/include/boost/graph/gursoy_atun_layout.hpp
Normal file
631
libraries/include/boost/graph/gursoy_atun_layout.hpp
Normal file
@@ -0,0 +1,631 @@
|
||||
// Copyright 2004 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
|
||||
#ifndef BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
|
||||
#define BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
|
||||
|
||||
// Gursoy-Atun graph layout, based on:
|
||||
// "Neighbourhood Preserving Load Balancing: A Self-Organizing Approach"
|
||||
// in EuroPar 2000, p. 234 of LNCS 1900
|
||||
// http://springerlink.metapress.com/link.asp?id=pcu07ew5rhexp9yt
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/graph/visitors.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/random/uniform_01.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include <boost/graph/dijkstra_shortest_paths.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct over_distance_limit : public std::exception {};
|
||||
|
||||
template <typename PositionMap, typename NodeDistanceMap, typename Topology,
|
||||
typename Graph>
|
||||
struct update_position_visitor {
|
||||
typedef typename Topology::point_type Point;
|
||||
PositionMap position_map;
|
||||
NodeDistanceMap node_distance;
|
||||
const Topology& space;
|
||||
Point input_vector;
|
||||
double distance_limit;
|
||||
double learning_constant;
|
||||
double falloff_ratio;
|
||||
|
||||
typedef boost::on_examine_vertex event_filter;
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor
|
||||
vertex_descriptor;
|
||||
|
||||
update_position_visitor(PositionMap position_map,
|
||||
NodeDistanceMap node_distance,
|
||||
const Topology& space,
|
||||
const Point& input_vector,
|
||||
double distance_limit,
|
||||
double learning_constant,
|
||||
double falloff_ratio):
|
||||
position_map(position_map), node_distance(node_distance),
|
||||
space(space),
|
||||
input_vector(input_vector), distance_limit(distance_limit),
|
||||
learning_constant(learning_constant), falloff_ratio(falloff_ratio) {}
|
||||
|
||||
void operator()(vertex_descriptor v, const Graph&) const
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::pow;
|
||||
#endif
|
||||
|
||||
if (get(node_distance, v) > distance_limit)
|
||||
throw over_distance_limit();
|
||||
Point old_position = get(position_map, v);
|
||||
double distance = get(node_distance, v);
|
||||
double fraction =
|
||||
learning_constant * pow(falloff_ratio, distance * distance);
|
||||
put(position_map, v,
|
||||
space.move_position_toward(old_position, fraction, input_vector));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename EdgeWeightMap>
|
||||
struct gursoy_shortest
|
||||
{
|
||||
template<typename Graph, typename NodeDistanceMap, typename UpdatePosition>
|
||||
static inline void
|
||||
run(const Graph& g, typename graph_traits<Graph>::vertex_descriptor s,
|
||||
NodeDistanceMap node_distance, UpdatePosition& update_position,
|
||||
EdgeWeightMap weight)
|
||||
{
|
||||
boost::dijkstra_shortest_paths(g, s, weight_map(weight).
|
||||
visitor(boost::make_dijkstra_visitor(std::make_pair(
|
||||
boost::record_distances(node_distance, boost::on_edge_relaxed()),
|
||||
update_position))));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct gursoy_shortest<dummy_property_map>
|
||||
{
|
||||
template<typename Graph, typename NodeDistanceMap, typename UpdatePosition>
|
||||
static inline void
|
||||
run(const Graph& g, typename graph_traits<Graph>::vertex_descriptor s,
|
||||
NodeDistanceMap node_distance, UpdatePosition& update_position,
|
||||
dummy_property_map)
|
||||
{
|
||||
boost::breadth_first_search(g, s,
|
||||
visitor(boost::make_bfs_visitor(std::make_pair(
|
||||
boost::record_distances(node_distance, boost::on_tree_edge()),
|
||||
update_position))));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename VertexListAndIncidenceGraph, typename Topology,
|
||||
typename PositionMap, typename Diameter, typename VertexIndexMap,
|
||||
typename EdgeWeightMap>
|
||||
void
|
||||
gursoy_atun_step
|
||||
(const VertexListAndIncidenceGraph& graph,
|
||||
const Topology& space,
|
||||
PositionMap position,
|
||||
Diameter diameter,
|
||||
double learning_constant,
|
||||
VertexIndexMap vertex_index_map,
|
||||
EdgeWeightMap weight)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::pow;
|
||||
using std::exp;
|
||||
#endif
|
||||
|
||||
typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
|
||||
vertex_iterator;
|
||||
typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_descriptor
|
||||
vertex_descriptor;
|
||||
typedef typename Topology::point_type point_type;
|
||||
vertex_iterator i, iend;
|
||||
std::vector<double> distance_from_input_vector(num_vertices(graph));
|
||||
typedef boost::iterator_property_map<std::vector<double>::iterator,
|
||||
VertexIndexMap,
|
||||
double, double&>
|
||||
DistanceFromInputMap;
|
||||
DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(),
|
||||
vertex_index_map);
|
||||
std::vector<double> node_distance_map_vector(num_vertices(graph));
|
||||
typedef boost::iterator_property_map<std::vector<double>::iterator,
|
||||
VertexIndexMap,
|
||||
double, double&>
|
||||
NodeDistanceMap;
|
||||
NodeDistanceMap node_distance(node_distance_map_vector.begin(),
|
||||
vertex_index_map);
|
||||
point_type input_vector = space.random_point();
|
||||
vertex_descriptor min_distance_loc
|
||||
= graph_traits<VertexListAndIncidenceGraph>::null_vertex();
|
||||
double min_distance = 0.0;
|
||||
bool min_distance_unset = true;
|
||||
for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) {
|
||||
double this_distance = space.distance(get(position, *i), input_vector);
|
||||
put(distance_from_input, *i, this_distance);
|
||||
if (min_distance_unset || this_distance < min_distance) {
|
||||
min_distance = this_distance;
|
||||
min_distance_loc = *i;
|
||||
}
|
||||
min_distance_unset = false;
|
||||
}
|
||||
assert (!min_distance_unset); // Graph must have at least one vertex
|
||||
boost::detail::update_position_visitor<
|
||||
PositionMap, NodeDistanceMap, Topology,
|
||||
VertexListAndIncidenceGraph>
|
||||
update_position(position, node_distance, space,
|
||||
input_vector, diameter, learning_constant,
|
||||
exp(-1. / (2 * diameter * diameter)));
|
||||
std::fill(node_distance_map_vector.begin(), node_distance_map_vector.end(), 0);
|
||||
try {
|
||||
typedef detail::gursoy_shortest<EdgeWeightMap> shortest;
|
||||
shortest::run(graph, min_distance_loc, node_distance, update_position,
|
||||
weight);
|
||||
} catch (detail::over_distance_limit) {
|
||||
/* Thrown to break out of BFS or Dijkstra early */
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexListAndIncidenceGraph, typename Topology,
|
||||
typename PositionMap, typename VertexIndexMap,
|
||||
typename EdgeWeightMap>
|
||||
void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph,
|
||||
const Topology& space,
|
||||
PositionMap position,
|
||||
int nsteps,
|
||||
double diameter_initial,
|
||||
double diameter_final,
|
||||
double learning_constant_initial,
|
||||
double learning_constant_final,
|
||||
VertexIndexMap vertex_index_map,
|
||||
EdgeWeightMap weight)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::pow;
|
||||
using std::exp;
|
||||
#endif
|
||||
|
||||
typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
|
||||
vertex_iterator;
|
||||
typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_descriptor
|
||||
vertex_descriptor;
|
||||
typedef typename Topology::point_type point_type;
|
||||
vertex_iterator i, iend;
|
||||
double diameter_ratio = (double)diameter_final / diameter_initial;
|
||||
double learning_constant_ratio =
|
||||
learning_constant_final / learning_constant_initial;
|
||||
std::vector<double> distance_from_input_vector(num_vertices(graph));
|
||||
typedef boost::iterator_property_map<std::vector<double>::iterator,
|
||||
VertexIndexMap,
|
||||
double, double&>
|
||||
DistanceFromInputMap;
|
||||
DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(),
|
||||
vertex_index_map);
|
||||
std::vector<int> node_distance_map_vector(num_vertices(graph));
|
||||
typedef boost::iterator_property_map<std::vector<int>::iterator,
|
||||
VertexIndexMap, double, double&>
|
||||
NodeDistanceMap;
|
||||
NodeDistanceMap node_distance(node_distance_map_vector.begin(),
|
||||
vertex_index_map);
|
||||
for (int round = 0; round < nsteps; ++round) {
|
||||
double part_done = (double)round / (nsteps - 1);
|
||||
int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done));
|
||||
double learning_constant =
|
||||
learning_constant_initial * pow(learning_constant_ratio, part_done);
|
||||
gursoy_atun_step(graph, space, position, diameter, learning_constant,
|
||||
vertex_index_map, weight);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexListAndIncidenceGraph, typename Topology,
|
||||
typename PositionMap, typename VertexIndexMap,
|
||||
typename EdgeWeightMap>
|
||||
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
|
||||
const Topology& space,
|
||||
PositionMap position,
|
||||
int nsteps,
|
||||
double diameter_initial,
|
||||
double diameter_final,
|
||||
double learning_constant_initial,
|
||||
double learning_constant_final,
|
||||
VertexIndexMap vertex_index_map,
|
||||
EdgeWeightMap weight)
|
||||
{
|
||||
typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
|
||||
vertex_iterator;
|
||||
vertex_iterator i, iend;
|
||||
for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) {
|
||||
put(position, *i, space.random_point());
|
||||
}
|
||||
gursoy_atun_refine(graph, space,
|
||||
position, nsteps,
|
||||
diameter_initial, diameter_final,
|
||||
learning_constant_initial, learning_constant_final,
|
||||
vertex_index_map, weight);
|
||||
}
|
||||
|
||||
template <typename VertexListAndIncidenceGraph, typename Topology,
|
||||
typename PositionMap, typename VertexIndexMap>
|
||||
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
|
||||
const Topology& space,
|
||||
PositionMap position,
|
||||
int nsteps,
|
||||
double diameter_initial,
|
||||
double diameter_final,
|
||||
double learning_constant_initial,
|
||||
double learning_constant_final,
|
||||
VertexIndexMap vertex_index_map)
|
||||
{
|
||||
gursoy_atun_layout(graph, space, position, nsteps,
|
||||
diameter_initial, diameter_final,
|
||||
learning_constant_initial, learning_constant_final,
|
||||
vertex_index_map, dummy_property_map());
|
||||
}
|
||||
|
||||
template <typename VertexListAndIncidenceGraph, typename Topology,
|
||||
typename PositionMap>
|
||||
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
|
||||
const Topology& space,
|
||||
PositionMap position,
|
||||
int nsteps,
|
||||
double diameter_initial,
|
||||
double diameter_final = 1.0,
|
||||
double learning_constant_initial = 0.8,
|
||||
double learning_constant_final = 0.2)
|
||||
{
|
||||
gursoy_atun_layout(graph, space, position, nsteps, diameter_initial,
|
||||
diameter_final, learning_constant_initial,
|
||||
learning_constant_final, get(vertex_index, graph));
|
||||
}
|
||||
|
||||
template <typename VertexListAndIncidenceGraph, typename Topology,
|
||||
typename PositionMap>
|
||||
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
|
||||
const Topology& space,
|
||||
PositionMap position,
|
||||
int nsteps)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif
|
||||
|
||||
gursoy_atun_layout(graph, space, position, nsteps,
|
||||
sqrt((double)num_vertices(graph)));
|
||||
}
|
||||
|
||||
template <typename VertexListAndIncidenceGraph, typename Topology,
|
||||
typename PositionMap>
|
||||
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
|
||||
const Topology& space,
|
||||
PositionMap position)
|
||||
{
|
||||
gursoy_atun_layout(graph, space, position, num_vertices(graph));
|
||||
}
|
||||
|
||||
template<typename VertexListAndIncidenceGraph, typename Topology,
|
||||
typename PositionMap, typename P, typename T, typename R>
|
||||
void
|
||||
gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
|
||||
const Topology& space,
|
||||
PositionMap position,
|
||||
const bgl_named_params<P,T,R>& params)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif
|
||||
|
||||
std::pair<double, double> diam(sqrt(double(num_vertices(graph))), 1.0);
|
||||
std::pair<double, double> learn(0.8, 0.2);
|
||||
gursoy_atun_layout(graph, space, position,
|
||||
choose_param(get_param(params, iterations_t()),
|
||||
num_vertices(graph)),
|
||||
choose_param(get_param(params, diameter_range_t()),
|
||||
diam).first,
|
||||
choose_param(get_param(params, diameter_range_t()),
|
||||
diam).second,
|
||||
choose_param(get_param(params, learning_constant_range_t()),
|
||||
learn).first,
|
||||
choose_param(get_param(params, learning_constant_range_t()),
|
||||
learn).second,
|
||||
choose_const_pmap(get_param(params, vertex_index), graph,
|
||||
vertex_index),
|
||||
choose_param(get_param(params, edge_weight),
|
||||
dummy_property_map()));
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Topologies *
|
||||
***********************************************************/
|
||||
template<std::size_t Dims>
|
||||
class convex_topology
|
||||
{
|
||||
struct point
|
||||
{
|
||||
point() { }
|
||||
double& operator[](std::size_t i) {return values[i];}
|
||||
const double& operator[](std::size_t i) const {return values[i];}
|
||||
|
||||
private:
|
||||
double values[Dims];
|
||||
};
|
||||
|
||||
public:
|
||||
typedef point point_type;
|
||||
|
||||
double distance(point a, point b) const
|
||||
{
|
||||
double dist = 0;
|
||||
for (std::size_t i = 0; i < Dims; ++i) {
|
||||
double diff = b[i] - a[i];
|
||||
dist += diff * diff;
|
||||
}
|
||||
// Exact properties of the distance are not important, as long as
|
||||
// < on what this returns matches real distances
|
||||
return dist;
|
||||
}
|
||||
|
||||
point move_position_toward(point a, double fraction, point b) const
|
||||
{
|
||||
point result;
|
||||
for (std::size_t i = 0; i < Dims; ++i)
|
||||
result[i] = a[i] + (b[i] - a[i]) * fraction;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<std::size_t Dims,
|
||||
typename RandomNumberGenerator = minstd_rand>
|
||||
class hypercube_topology : public convex_topology<Dims>
|
||||
{
|
||||
typedef uniform_01<RandomNumberGenerator, double> rand_t;
|
||||
|
||||
public:
|
||||
typedef typename convex_topology<Dims>::point_type point_type;
|
||||
|
||||
explicit hypercube_topology(double scaling = 1.0)
|
||||
: gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)),
|
||||
scaling(scaling)
|
||||
{ }
|
||||
|
||||
hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0)
|
||||
: gen_ptr(), rand(new rand_t(gen)), scaling(scaling) { }
|
||||
|
||||
point_type random_point() const
|
||||
{
|
||||
point_type p;
|
||||
for (std::size_t i = 0; i < Dims; ++i)
|
||||
p[i] = (*rand)() * scaling;
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<RandomNumberGenerator> gen_ptr;
|
||||
shared_ptr<rand_t> rand;
|
||||
double scaling;
|
||||
};
|
||||
|
||||
template<typename RandomNumberGenerator = minstd_rand>
|
||||
class square_topology : public hypercube_topology<2, RandomNumberGenerator>
|
||||
{
|
||||
typedef hypercube_topology<2, RandomNumberGenerator> inherited;
|
||||
|
||||
public:
|
||||
explicit square_topology(double scaling = 1.0) : inherited(scaling) { }
|
||||
|
||||
square_topology(RandomNumberGenerator& gen, double scaling = 1.0)
|
||||
: inherited(gen, scaling) { }
|
||||
};
|
||||
|
||||
template<typename RandomNumberGenerator = minstd_rand>
|
||||
class cube_topology : public hypercube_topology<3, RandomNumberGenerator>
|
||||
{
|
||||
typedef hypercube_topology<3, RandomNumberGenerator> inherited;
|
||||
|
||||
public:
|
||||
explicit cube_topology(double scaling = 1.0) : inherited(scaling) { }
|
||||
|
||||
cube_topology(RandomNumberGenerator& gen, double scaling = 1.0)
|
||||
: inherited(gen, scaling) { }
|
||||
};
|
||||
|
||||
template<std::size_t Dims,
|
||||
typename RandomNumberGenerator = minstd_rand>
|
||||
class ball_topology : public convex_topology<Dims>
|
||||
{
|
||||
typedef uniform_01<RandomNumberGenerator, double> rand_t;
|
||||
|
||||
public:
|
||||
typedef typename convex_topology<Dims>::point_type point_type;
|
||||
|
||||
explicit ball_topology(double radius = 1.0)
|
||||
: gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)),
|
||||
radius(radius)
|
||||
{ }
|
||||
|
||||
ball_topology(RandomNumberGenerator& gen, double radius = 1.0)
|
||||
: gen_ptr(), rand(new rand_t(gen)), radius(radius) { }
|
||||
|
||||
point_type random_point() const
|
||||
{
|
||||
point_type p;
|
||||
double dist_sum;
|
||||
do {
|
||||
dist_sum = 0.0;
|
||||
for (std::size_t i = 0; i < Dims; ++i) {
|
||||
double x = (*rand)() * 2*radius - radius;
|
||||
p[i] = x;
|
||||
dist_sum += x * x;
|
||||
}
|
||||
} while (dist_sum > radius*radius);
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<RandomNumberGenerator> gen_ptr;
|
||||
shared_ptr<rand_t> rand;
|
||||
double radius;
|
||||
};
|
||||
|
||||
template<typename RandomNumberGenerator = minstd_rand>
|
||||
class circle_topology : public ball_topology<2, RandomNumberGenerator>
|
||||
{
|
||||
typedef ball_topology<2, RandomNumberGenerator> inherited;
|
||||
|
||||
public:
|
||||
explicit circle_topology(double radius = 1.0) : inherited(radius) { }
|
||||
|
||||
circle_topology(RandomNumberGenerator& gen, double radius = 1.0)
|
||||
: inherited(gen, radius) { }
|
||||
};
|
||||
|
||||
template<typename RandomNumberGenerator = minstd_rand>
|
||||
class sphere_topology : public ball_topology<3, RandomNumberGenerator>
|
||||
{
|
||||
typedef ball_topology<3, RandomNumberGenerator> inherited;
|
||||
|
||||
public:
|
||||
explicit sphere_topology(double radius = 1.0) : inherited(radius) { }
|
||||
|
||||
sphere_topology(RandomNumberGenerator& gen, double radius = 1.0)
|
||||
: inherited(gen, radius) { }
|
||||
};
|
||||
|
||||
template<typename RandomNumberGenerator = minstd_rand>
|
||||
class heart_topology
|
||||
{
|
||||
// Heart is defined as the union of three shapes:
|
||||
// Square w/ corners (+-1000, -1000), (0, 0), (0, -2000)
|
||||
// Circle centered at (-500, -500) radius 500*sqrt(2)
|
||||
// Circle centered at (500, -500) radius 500*sqrt(2)
|
||||
// Bounding box (-1000, -2000) - (1000, 500*(sqrt(2) - 1))
|
||||
|
||||
struct point
|
||||
{
|
||||
point() { values[0] = 0.0; values[1] = 0.0; }
|
||||
point(double x, double y) { values[0] = x; values[1] = y; }
|
||||
|
||||
double& operator[](std::size_t i) { return values[i]; }
|
||||
double operator[](std::size_t i) const { return values[i]; }
|
||||
|
||||
private:
|
||||
double values[2];
|
||||
};
|
||||
|
||||
bool in_heart(point p) const
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::abs;
|
||||
using std::pow;
|
||||
#endif
|
||||
|
||||
if (p[1] < abs(p[0]) - 2000) return false; // Bottom
|
||||
if (p[1] <= -1000) return true; // Diagonal of square
|
||||
if (pow(p[0] - -500, 2) + pow(p[1] - -500, 2) <= 500000)
|
||||
return true; // Left circle
|
||||
if (pow(p[0] - 500, 2) + pow(p[1] - -500, 2) <= 500000)
|
||||
return true; // Right circle
|
||||
return false;
|
||||
}
|
||||
|
||||
bool segment_within_heart(point p1, point p2) const
|
||||
{
|
||||
// Assumes that p1 and p2 are within the heart
|
||||
if ((p1[0] < 0) == (p2[0] < 0)) return true; // Same side of symmetry line
|
||||
if (p1[0] == p2[0]) return true; // Vertical
|
||||
double slope = (p2[1] - p1[1]) / (p2[0] - p1[0]);
|
||||
double intercept = p1[1] - p1[0] * slope;
|
||||
if (intercept > 0) return false; // Crosses between circles
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef uniform_01<RandomNumberGenerator, double> rand_t;
|
||||
|
||||
public:
|
||||
typedef point point_type;
|
||||
|
||||
heart_topology()
|
||||
: gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)) { }
|
||||
|
||||
heart_topology(RandomNumberGenerator& gen)
|
||||
: gen_ptr(), rand(new rand_t(gen)) { }
|
||||
|
||||
point random_point() const
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif
|
||||
|
||||
point result;
|
||||
double sqrt2 = sqrt(2.);
|
||||
do {
|
||||
result[0] = (*rand)() * (1000 + 1000 * sqrt2) - (500 + 500 * sqrt2);
|
||||
result[1] = (*rand)() * (2000 + 500 * (sqrt2 - 1)) - 2000;
|
||||
} while (!in_heart(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
double distance(point a, point b) const
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif
|
||||
if (segment_within_heart(a, b)) {
|
||||
// Straight line
|
||||
return sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]));
|
||||
} else {
|
||||
// Straight line bending around (0, 0)
|
||||
return sqrt(a[0] * a[0] + a[1] * a[1]) + sqrt(b[0] * b[0] + b[1] * b[1]);
|
||||
}
|
||||
}
|
||||
|
||||
point move_position_toward(point a, double fraction, point b) const
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif
|
||||
|
||||
if (segment_within_heart(a, b)) {
|
||||
// Straight line
|
||||
return point(a[0] + (b[0] - a[0]) * fraction,
|
||||
a[1] + (b[1] - a[1]) * fraction);
|
||||
} else {
|
||||
double distance_to_point_a = sqrt(a[0] * a[0] + a[1] * a[1]);
|
||||
double distance_to_point_b = sqrt(b[0] * b[0] + b[1] * b[1]);
|
||||
double location_of_point = distance_to_point_a /
|
||||
(distance_to_point_a + distance_to_point_b);
|
||||
if (fraction < location_of_point)
|
||||
return point(a[0] * (1 - fraction / location_of_point),
|
||||
a[1] * (1 - fraction / location_of_point));
|
||||
else
|
||||
return point(
|
||||
b[0] * ((fraction - location_of_point) / (1 - location_of_point)),
|
||||
b[1] * ((fraction - location_of_point) / (1 - location_of_point)));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<RandomNumberGenerator> gen_ptr;
|
||||
shared_ptr<rand_t> rand;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
|
||||
611
libraries/include/boost/graph/howard_cycle_ratio.hpp
Normal file
611
libraries/include/boost/graph/howard_cycle_ratio.hpp
Normal file
@@ -0,0 +1,611 @@
|
||||
/*!
|
||||
* Copyright 2007 Technical University of Catalonia
|
||||
*
|
||||
* 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: Dmitry Bufistov
|
||||
* Andrey Parfenov
|
||||
*/
|
||||
|
||||
#ifndef BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP
|
||||
#define BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP
|
||||
|
||||
/*!
|
||||
* \file Maximum cycle ratio algorithm (Jean Cochet-Terrasson, Guy
|
||||
* Cochen and others)
|
||||
*/
|
||||
#include <exception>
|
||||
#include <set>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/reverse_graph.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include <boost/graph/iteration_macros.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
/// To avoid round error.
|
||||
static const double mcr_howard_ltolerance = 0.00001;
|
||||
|
||||
/*!
|
||||
* Calculate maximum cycle ratio of "good" directed multigraph
|
||||
* g. Use Howard's iteration policy algorithm ("Numerical
|
||||
* Computation of Spectral Elements in MAX-PLUS algebra" by Jean
|
||||
* Cochet-Terrasson, Guy Cochen and others).
|
||||
*
|
||||
* \param g = (V, E) - a "good" directed multigraph (out_degree of
|
||||
* each vertex is greater then 0). If graph is strongly connected
|
||||
* then it is "good".
|
||||
*
|
||||
* \param vim - Vertex Index, read property Map: V -> [0,
|
||||
* num_vertices(g)).
|
||||
*
|
||||
* \param ewm - edge weight read property map: E -> R
|
||||
*
|
||||
* \param ewm2 - edge weight2 read property map: E -> R+
|
||||
*
|
||||
* \return maximum_{for all cycles C}CR(C), or
|
||||
* -(std::numeric_limits<double>)::max() if g is not "good".
|
||||
*/
|
||||
template <typename TGraph, typename TVertexIndexMap,
|
||||
typename TWeight1EdgeMap, typename TWeight2EdgeMap >
|
||||
class Cmcr_Howard
|
||||
{
|
||||
public:
|
||||
Cmcr_Howard(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm,
|
||||
TWeight2EdgeMap ew2m)
|
||||
: m_g(g), m_vim(vim), m_ew1m(ewm), m_ew2m(ew2m),
|
||||
m_g2pi_g_vm(std::vector<pi_vertex_t>().end(), m_vim), /// Stupid dummy initialization
|
||||
m_minus_infinity(-(std::numeric_limits<double>::max)())
|
||||
{
|
||||
typedef typename boost::graph_traits<TGraph>::directed_category DirCat;
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<DirCat*, boost::directed_tag*>::value == true));
|
||||
m_cr = m_minus_infinity;
|
||||
}
|
||||
|
||||
double operator()()
|
||||
{
|
||||
return maximum_cycle_ratio_Howard();
|
||||
}
|
||||
|
||||
virtual ~Cmcr_Howard() { }
|
||||
|
||||
protected:
|
||||
typedef typename boost::graph_traits<TGraph>::vertex_descriptor
|
||||
mcr_vertex_t;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor
|
||||
mcr_edge_t;
|
||||
|
||||
const TGraph& m_g;
|
||||
typedef std::vector<double> eigenmode_t;
|
||||
eigenmode_t m_eigen_value;
|
||||
eigenmode_t m_eigen_vector;
|
||||
TVertexIndexMap m_vim;
|
||||
TWeight1EdgeMap m_ew1m;
|
||||
TWeight2EdgeMap m_ew2m;
|
||||
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeight1EdgeMap>::value_type>::type mcr_edge_weight1_t;
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeight2EdgeMap>::value_type>::type mcr_edge_weight2_t;
|
||||
typedef typename boost::adjacency_list<
|
||||
boost::listS, boost::vecS, boost::bidirectionalS,
|
||||
boost::no_property,
|
||||
boost::property<boost::edge_weight_t,
|
||||
mcr_edge_weight1_t,
|
||||
boost::property<boost::edge_weight2_t,
|
||||
mcr_edge_weight2_t> > >
|
||||
pi_graph_t;
|
||||
typedef typename boost::property_map<pi_graph_t, boost::vertex_index_t>::type TPiGraphVertexIndexMap;
|
||||
typedef typename boost::property_map<pi_graph_t, boost::edge_weight_t>::type TPiGraphEdgeWeight1Map;
|
||||
typedef typename boost::property_map<pi_graph_t, boost::edge_weight2_t>::type TPiGraphEdgeWeight2Map;
|
||||
|
||||
typedef typename boost::property_traits<TPiGraphVertexIndexMap>::value_type pigraph_vertex_index_t;
|
||||
|
||||
pi_graph_t m_pi_g;
|
||||
typedef typename boost::graph_traits<pi_graph_t>::vertex_descriptor pi_vertex_t;
|
||||
typedef typename boost::graph_traits<pi_graph_t>::edge_descriptor pi_edge_t;
|
||||
typedef typename boost::iterator_property_map<typename std::vector<pi_vertex_t>::iterator, TVertexIndexMap> g2pi_g_vm_t;
|
||||
g2pi_g_vm_t m_g2pi_g_vm; ///Graph to Pi graph vertex map
|
||||
std::vector<pi_vertex_t> m_g2pig;
|
||||
int m_step_number;
|
||||
const double m_minus_infinity;
|
||||
typedef typename std::vector<mcr_edge_t> critical_cycle_t;
|
||||
double m_cr; ///Cycle ratio that already has been found
|
||||
|
||||
class bad_graph
|
||||
{
|
||||
public:
|
||||
typedef typename boost::property_traits<TVertexIndexMap>::value_type
|
||||
v_index_t;
|
||||
|
||||
bad_graph(v_index_t bvi) : bad_vertex_index(bvi) {}
|
||||
v_index_t what() const throw()
|
||||
{
|
||||
return bad_vertex_index;
|
||||
}
|
||||
|
||||
private:
|
||||
v_index_t bad_vertex_index;
|
||||
};
|
||||
|
||||
double maximum_cycle_ratio_Howard()
|
||||
{
|
||||
try
|
||||
{
|
||||
construct_pi_graph();
|
||||
}
|
||||
catch (const bad_graph& a)
|
||||
{
|
||||
return m_minus_infinity;
|
||||
}
|
||||
std::vector<double> max_eigen_val(boost::num_vertices(m_g));
|
||||
m_eigen_value.resize(boost::num_vertices(m_g));
|
||||
m_eigen_vector.resize(boost::num_vertices(m_g));
|
||||
m_step_number = 0;
|
||||
do
|
||||
{
|
||||
pi_eingen_value(get(vertex_index, m_pi_g), get(boost::edge_weight, m_pi_g), get(boost::edge_weight2, m_pi_g));
|
||||
++m_step_number;
|
||||
}
|
||||
while (improve_policy_try1(max_eigen_val) || improve_policy_try2(max_eigen_val));
|
||||
return *(std::max_element(m_eigen_value.begin(), m_eigen_value.end()));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Construct an arbitrary policy m_pi_g.
|
||||
*/
|
||||
void construct_pi_graph()
|
||||
{
|
||||
m_g2pig.resize(boost::num_vertices(m_g));
|
||||
m_g2pi_g_vm = boost::make_iterator_property_map(m_g2pig.begin(), m_vim);
|
||||
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
|
||||
{
|
||||
m_g2pi_g_vm[vd] = boost::add_vertex(m_pi_g);
|
||||
store_pivertex(m_g2pi_g_vm[vd], vd);
|
||||
}
|
||||
BGL_FORALL_VERTICES_T(vd1, m_g, TGraph)
|
||||
{
|
||||
if (boost::out_edges(vd1, m_g).first == boost::out_edges(vd1, m_g).second) throw bad_graph(m_vim[vd1]);
|
||||
mcr_edge_t ed = *boost::out_edges(vd1, m_g).first;
|
||||
pi_edge_t pied = boost::add_edge(m_g2pi_g_vm[source(ed, m_g)], m_g2pi_g_vm[target(ed, m_g)], m_pi_g).first;
|
||||
boost::put(boost::edge_weight, m_pi_g, pied, m_ew1m[ed]);
|
||||
boost::put(boost::edge_weight2, m_pi_g, pied, m_ew2m[ed]);
|
||||
}
|
||||
}
|
||||
|
||||
class bfs_eingmode_visitor : public boost::default_bfs_visitor
|
||||
{
|
||||
public:
|
||||
bfs_eingmode_visitor(TPiGraphVertexIndexMap vi_m, TPiGraphEdgeWeight1Map w_m, TPiGraphEdgeWeight2Map& d_m,
|
||||
eigenmode_t& e_val, eigenmode_t& e_vec, double ev) : m_index_map(vi_m), m_weight_map(w_m), m_delay_map(d_m),
|
||||
m_eig_value(&e_val), m_eig_vec(&e_vec), m_eigen_value(ev) { }
|
||||
|
||||
template < typename Edge, typename g_t>
|
||||
void examine_edge(Edge e, const g_t & g) const
|
||||
{
|
||||
typedef typename boost::graph_traits<g_t>::vertex_descriptor Vertex;
|
||||
Vertex u = boost::target(e, g), v = boost::source(e, g);
|
||||
pigraph_vertex_index_t ind = m_index_map[u];
|
||||
(*m_eig_value)[ind] = m_eigen_value;
|
||||
(*m_eig_vec)[ind] = m_weight_map[e] - m_eigen_value * m_delay_map[e] + (*m_eig_vec)[m_index_map[v]];
|
||||
}
|
||||
private:
|
||||
TPiGraphVertexIndexMap m_index_map;
|
||||
TPiGraphEdgeWeight1Map m_weight_map;
|
||||
TPiGraphEdgeWeight2Map m_delay_map;
|
||||
eigenmode_t* m_eig_value;
|
||||
eigenmode_t* m_eig_vec;
|
||||
double m_eigen_value;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Find a vertex in the Pi Graph which belongs to cycle, just a DFV until back edge found
|
||||
*/
|
||||
pi_vertex_t find_good_source(const pi_vertex_t start_vertex)
|
||||
{
|
||||
pi_vertex_t good_vertex = start_vertex;
|
||||
typename std::set<pi_vertex_t> s;
|
||||
s.insert(start_vertex);
|
||||
do
|
||||
{
|
||||
good_vertex = boost::target(*boost::out_edges(good_vertex, m_pi_g).first, m_pi_g);
|
||||
}
|
||||
while (s.insert(good_vertex).second);
|
||||
return good_vertex;
|
||||
}
|
||||
virtual void store_pivertex(pi_vertex_t pivd, mcr_vertex_t vd) {}
|
||||
virtual void store_critical_edge(pi_edge_t ed, critical_cycle_t& cc) {}
|
||||
virtual void store_critical_cycle(critical_cycle_t& cc) {}
|
||||
|
||||
/*!
|
||||
* \param startV - vertex that belongs to a cycle in policy graph m_pi_g
|
||||
*/
|
||||
double calculate_eigen_value(pi_vertex_t startV)
|
||||
{
|
||||
std::pair<double, double> accum_sums(0., 0.);
|
||||
pi_vertex_t vd = startV;
|
||||
critical_cycle_t cc;
|
||||
do
|
||||
{
|
||||
pi_edge_t tmp_ed = *(boost::out_edges(vd, m_pi_g).first);
|
||||
store_critical_edge(tmp_ed, cc);
|
||||
accum_sums.first += boost::get(boost::edge_weight, m_pi_g, tmp_ed);
|
||||
accum_sums.second += boost::get(boost::edge_weight2, m_pi_g, tmp_ed);
|
||||
vd = boost::target(tmp_ed, m_pi_g);
|
||||
}
|
||||
while (vd != startV);
|
||||
//assert((std::abs<double>(accum_sums.first) <= 0.00000001) && "Division by zerro!");
|
||||
double cr = accum_sums.first / accum_sums.second;
|
||||
if (cr > m_cr)
|
||||
{
|
||||
m_cr = cr;
|
||||
store_critical_cycle(cc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Value determination. Find a generalized eigenmode (n^{k+1}, x^{k+1}) of A^{I_{k+1}} of the pi graph (Algorithm IV.1).
|
||||
*/
|
||||
void pi_eingen_value(
|
||||
TPiGraphVertexIndexMap index_map,
|
||||
TPiGraphEdgeWeight1Map weight_map,
|
||||
TPiGraphEdgeWeight2Map weigh2_map)
|
||||
{
|
||||
using namespace boost;
|
||||
typedef std::vector<default_color_type> color_map_t;
|
||||
color_map_t vcm(num_vertices(m_pi_g), white_color);//Vertex color map
|
||||
color_map_t::iterator uv_itr = vcm.begin(); //Undiscovered vertex
|
||||
reverse_graph<pi_graph_t> rev_g(m_pi_g); //For backward breadth visit
|
||||
|
||||
while ((uv_itr = std::find_if(uv_itr, vcm.end(),
|
||||
boost::bind(std::equal_to<default_color_type>(), boost::white_color, _1))) != vcm.end())
|
||||
///While there are undiscovered vertices
|
||||
{
|
||||
pi_vertex_t gv = find_good_source(pi_vertex_t(uv_itr - vcm.begin()));
|
||||
pigraph_vertex_index_t gv_ind = index_map[gv];
|
||||
m_eigen_value[gv_ind] = calculate_eigen_value(gv) ;
|
||||
bfs_eingmode_visitor bfs_vis(index_map, weight_map, weigh2_map, m_eigen_value, m_eigen_vector, m_eigen_value[gv_ind]);
|
||||
typename boost::queue<pi_vertex_t> Q;
|
||||
breadth_first_visit(rev_g, gv, Q, bfs_vis, make_iterator_property_map(vcm.begin(), index_map));
|
||||
}
|
||||
}
|
||||
|
||||
void improve_policy(mcr_vertex_t vd, mcr_edge_t new_edge)
|
||||
{
|
||||
remove_edge(*(out_edges(m_g2pi_g_vm[vd], m_pi_g).first), m_pi_g);
|
||||
pi_edge_t ned = add_edge(m_g2pi_g_vm[vd], m_g2pi_g_vm[target(new_edge, m_g)], m_pi_g).first;
|
||||
put(edge_weight, m_pi_g, ned, m_ew1m[new_edge]);
|
||||
put(edge_weight2, m_pi_g, ned, m_ew2m[new_edge]);
|
||||
}
|
||||
/*!
|
||||
* Policy Improvement. Improve the policy graph. The new policy graph has greater cycle ratio.
|
||||
* \return false if nothing can be improved.
|
||||
*/
|
||||
bool improve_policy_try1(std::vector<double>& max_eing_vals)
|
||||
{
|
||||
bool improved = false;
|
||||
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
|
||||
{
|
||||
double max_ev = m_minus_infinity;/// Maximum eigen value for vertex
|
||||
mcr_edge_t cr_ed;///Critical edge
|
||||
|
||||
BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph)
|
||||
{
|
||||
if (m_eigen_value[m_vim[target(outed, m_g)]] > max_ev)
|
||||
{
|
||||
max_ev = m_eigen_value[m_vim[boost::target(outed, m_g)]];
|
||||
cr_ed = outed;
|
||||
}
|
||||
}
|
||||
if (max_ev > m_eigen_value[get(m_vim,vd)])
|
||||
{
|
||||
improve_policy(vd, cr_ed);
|
||||
improved = true;
|
||||
}
|
||||
max_eing_vals[get(m_vim,vd)] = max_ev;
|
||||
}
|
||||
return improved;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \param max_eigen_values[u] = max_(for all adjacent vertices (u,v)) m_eigen_value[v]
|
||||
*/
|
||||
bool improve_policy_try2(const std::vector<double>& max_eigen_values)
|
||||
{
|
||||
bool improved = false;
|
||||
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
|
||||
{
|
||||
mcr_edge_t impr_edge;
|
||||
double max_val = m_minus_infinity;
|
||||
BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph)
|
||||
{
|
||||
///If vertex vd is in the K(vd) set
|
||||
if (max_eigen_values[get(m_vim, vd)] <= m_eigen_value[get(m_vim, target(outed, m_g))])
|
||||
{
|
||||
double c_val = m_ew1m[outed] - m_ew2m[outed] * m_eigen_value[m_vim[boost::target(outed, m_g)]] +
|
||||
m_eigen_vector[m_vim[boost::target(outed, m_g)]];
|
||||
if (c_val > max_val)
|
||||
{
|
||||
max_val = c_val;
|
||||
impr_edge = outed;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((max_val - m_eigen_vector[get(m_vim, vd)]) > mcr_howard_ltolerance)
|
||||
///If m_eigen_vector[vd] == max_val
|
||||
{
|
||||
improve_policy(vd, impr_edge);
|
||||
improved = true;
|
||||
}
|
||||
}
|
||||
return improved;
|
||||
}
|
||||
};///Cmcr_Howard
|
||||
|
||||
/*!
|
||||
* \return maximum cycle ratio and one critical cycle.
|
||||
*/
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
|
||||
class Cmcr_Howard1 : public Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap>
|
||||
{
|
||||
public:
|
||||
typedef Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap> inhr_t;
|
||||
Cmcr_Howard1(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m) : inhr_t(g, vim, ewm, ew2m)
|
||||
{
|
||||
m_pi_g2g.resize(boost::num_vertices(g));
|
||||
m_pi_g2g_vm = boost::make_iterator_property_map(m_pi_g2g.begin(), boost::get(boost::vertex_index, this->m_pi_g));
|
||||
}
|
||||
|
||||
void get_critical_cycle(typename inhr_t::critical_cycle_t& cc) { return cc.swap(m_critical_cycle); }
|
||||
protected:
|
||||
void store_pivertex(typename inhr_t::pi_vertex_t pivd, typename inhr_t::mcr_vertex_t vd)
|
||||
{
|
||||
m_pi_g2g_vm[pivd] = vd;
|
||||
}
|
||||
void store_critical_edge(typename inhr_t::pi_edge_t ed, typename inhr_t::critical_cycle_t& cc)
|
||||
{
|
||||
typename inhr_t::pi_vertex_t s = boost::source(ed, this->m_pi_g);
|
||||
typename inhr_t::pi_vertex_t t = boost::target(ed, this->m_pi_g);
|
||||
assert(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).second);
|
||||
cc.push_back(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).first); ///Store corresponding edge of the m_g
|
||||
}
|
||||
void store_critical_cycle(typename inhr_t::critical_cycle_t& cc)
|
||||
{
|
||||
m_critical_cycle.swap(cc);
|
||||
}
|
||||
private:
|
||||
typename inhr_t::critical_cycle_t m_critical_cycle;
|
||||
typedef typename boost::iterator_property_map<typename std::vector<typename inhr_t::mcr_vertex_t>::iterator, typename inhr_t::TPiGraphVertexIndexMap> pi_g2g_vm_t;
|
||||
pi_g2g_vm_t m_pi_g2g_vm; ///Maps policy graph vertices to input graph vertices
|
||||
typename std::vector<typename inhr_t::mcr_vertex_t> m_pi_g2g;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Add sink vertex - this will make any graph good, the selfloop will have ratio equal to infinity
|
||||
* Properties must be "self increasing"
|
||||
*/
|
||||
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
|
||||
typename boost::graph_traits<TGraph>::vertex_descriptor
|
||||
make_graph_good(TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
|
||||
typename boost::property_traits<TWeight1EdgeMap>::value_type infinity)
|
||||
{
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
typename boost::graph_traits<TGraph>::vertex_descriptor sink = boost::add_vertex(g);
|
||||
|
||||
BGL_FORALL_VERTICES_T(vd, g, TGraph)
|
||||
{
|
||||
Edge newed = boost::add_edge(vd, sink, g).first;
|
||||
boost::put(ewm, newed, 0);
|
||||
boost::put(ew2m, newed, 1);
|
||||
}
|
||||
Edge selfed = boost::edge(sink, sink, g).first;
|
||||
boost::put(ewm, selfed, infinity);
|
||||
return sink;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Construct from input graph g "safe" (suitable for maximum_cycle_ratio1() call) version - safeg
|
||||
*/
|
||||
template <typename TG, typename TIndVertexMap, typename TW1EdgeMap, typename TW2EdgeMap, typename TSafeG, typename SafeG2GEdgeMap>
|
||||
void construct_safe_graph(const TG& g, TIndVertexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TSafeG& safeg, SafeG2GEdgeMap& sg2gm)
|
||||
{
|
||||
assert(num_vertices(g) == num_vertices(safeg));
|
||||
typedef typename graph_traits<TSafeG>::edge_descriptor tmp_edge_t;
|
||||
typedef typename graph_traits<TG>::edge_descriptor edge_t;
|
||||
typename graph_traits<TG>::edge_iterator ei, ei_end;
|
||||
|
||||
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
{
|
||||
tmp_edge_t tmped = add_edge(vim[source(*ei, g)], vim[target(*ei, g)], safeg).first;
|
||||
sg2gm[tmped] = *ei;
|
||||
put(edge_weight, safeg, tmped, get(ew1m, *ei));
|
||||
put(edge_weight2, safeg, tmped, get(ew2m, *ei));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
|
||||
double maximum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0)
|
||||
{
|
||||
if (pcc == 0)
|
||||
{
|
||||
return detail::Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap>(g, vim, ewm, ew2m)();
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::Cmcr_Howard1<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap> obj(g, vim, ewm, ew2m);
|
||||
double maxcr = obj();
|
||||
obj.get_critical_cycle(*pcc);
|
||||
return maxcr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap, typename TEdgeIndexMap>
|
||||
double minimum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm,
|
||||
TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0)
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeight1EdgeMap>::value_type>::type weight_value_t;
|
||||
BOOST_STATIC_ASSERT(!is_integral<weight_value_t>::value || is_signed<weight_value_t>::value);
|
||||
typename std::vector<weight_value_t> ne_w(boost::num_edges(g));
|
||||
BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ewm[ed];
|
||||
return -maximum_cycle_ratio_good_graph(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \param g directed multigraph.
|
||||
* \param pcc - pointer to the critical edges list.
|
||||
* \param minus_infinity must be small enough to garanty that g has at least one cycle with greater ratio.
|
||||
* \return minus_infinity if there're no cycles in the graph
|
||||
*/
|
||||
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
|
||||
double maximum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TWeight1EdgeMap>::value_type minus_infinity = -(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename boost::graph_traits<TGraph>::vertex_descriptor Vertex;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight1EdgeMap, Edge> >();
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight2EdgeMap, Edge> >();
|
||||
|
||||
TGraph& ncg = const_cast<TGraph&>(g);
|
||||
Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, minus_infinity );
|
||||
|
||||
double res = maximum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, g), ewm, ew2m, pcc);
|
||||
boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Edge index MUST be in diapazon [0,..., num_edges(g)-1]
|
||||
* \return plus_infinity if g has no cycles.
|
||||
*/
|
||||
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap, typename TEdgeIndexMap>
|
||||
double minimum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TWeight1EdgeMap>::value_type plus_infinity = (std::numeric_limits<int>::max)()
|
||||
)
|
||||
{
|
||||
typedef typename boost::property_traits<TEdgeIndexMap>::value_type ei_t;
|
||||
typedef typename boost::graph_traits<TGraph>::vertex_descriptor Vertex;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight1EdgeMap, Edge> >();
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight2EdgeMap, Edge> >();
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TEdgeIndexMap, Edge> >();
|
||||
|
||||
TGraph& ncg = const_cast<TGraph&>(g);
|
||||
|
||||
ei_t nei = ei_t(boost::num_edges(g));
|
||||
Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, plus_infinity );
|
||||
///Maintain edge index invariant
|
||||
BGL_FORALL_VERTICES_T(vd, ncg, TGraph)
|
||||
{
|
||||
typename boost::graph_traits<TGraph>::edge_descriptor ed = boost::edge(vd, sink, ncg).first;
|
||||
boost::put(eim, ed, nei++);
|
||||
}
|
||||
double res = minimum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, ncg), ewm, ew2m, eim, pcc);
|
||||
boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg);
|
||||
return res;
|
||||
}
|
||||
struct edge_less_than
|
||||
{
|
||||
template <typename TEdgeDescriptor> bool operator()(const TEdgeDescriptor& x, const TEdgeDescriptor& y) const
|
||||
{
|
||||
return x.get_property() < y.get_property();
|
||||
}
|
||||
};
|
||||
}///namespace detail
|
||||
namespace
|
||||
{
|
||||
template <typename TW1, typename TW2> struct safe_graph
|
||||
{
|
||||
typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::no_property,
|
||||
typename boost::property<boost::edge_weight_t, TW1, typename boost::property<boost::edge_weight2_t, TW2> > > type;
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* Calculate the maximum cycle ratio (mcr) of the directed multigraph g.
|
||||
* \param g directed multigraph
|
||||
* \param pcc - If provided then a critical cycle will be written to corresponding vector.
|
||||
* \param minus_infinity small enough value to garanty that g has at least one cycle with greater ratio.
|
||||
* \return mcr or minus_infinity if g has no cycles.
|
||||
*/
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TW1EdgeMap, typename TW2EdgeMap>
|
||||
double maximum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TW1EdgeMap>::value_type minus_infinity =
|
||||
-(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename remove_const<typename property_traits<TW1EdgeMap>::value_type>::type w1_t;
|
||||
typedef typename remove_const<typename property_traits<TW2EdgeMap>::value_type>::type w2_t;
|
||||
typedef typename safe_graph<w1_t, w2_t>::type safe_graph_t;
|
||||
typedef typename graph_traits<safe_graph_t>::edge_descriptor tmp_edge_t;
|
||||
typedef typename graph_traits<TGraph>::edge_descriptor edge_t;
|
||||
typename std::map<tmp_edge_t, edge_t, detail::edge_less_than> tmpg2g;
|
||||
std::vector<tmp_edge_t> cc;
|
||||
safe_graph_t sg(num_vertices(g));
|
||||
detail::construct_safe_graph(g, vim, ew1m, ew2m, sg, tmpg2g);
|
||||
double mcr = maximum_cycle_ratio1(sg, get(edge_weight, sg), get(edge_weight2, sg), pcc ? &cc : 0, minus_infinity);
|
||||
if (pcc && (mcr > minus_infinity))
|
||||
{
|
||||
pcc->clear();
|
||||
for (typename std::vector<tmp_edge_t>::iterator it = cc.begin(); it != cc.end(); ++it) pcc->push_back(tmpg2g[*it]);
|
||||
}
|
||||
return mcr;
|
||||
}
|
||||
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TW1EdgeMap, typename TW2EdgeMap, typename TIndEdgeMap>
|
||||
double minimum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TIndEdgeMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TW1EdgeMap>::value_type plus_infinity =
|
||||
(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TW1EdgeMap>::value_type>::type weight_value_t;
|
||||
BOOST_STATIC_ASSERT(!is_integral<weight_value_t>::value || is_signed<weight_value_t>::value);
|
||||
typename std::vector<weight_value_t> ne_w(boost::num_edges(g));
|
||||
BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ew1m[ed];
|
||||
return -maximum_cycle_ratio(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc, -plus_infinity);
|
||||
}
|
||||
/*!
|
||||
* Calculate maximum mean cycle of directed weighted multigraph.
|
||||
* \param g directed multigraph
|
||||
* \return maximum mean cycle of g or minus_infinity if g has no cycles.
|
||||
*/
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeightEdgeMap, typename TIndEdgeMap>
|
||||
double maximum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TWeightEdgeMap>::value_type minus_infinity =
|
||||
-(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeightEdgeMap>::value_type>::type weight_value_t;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
typename std::vector<weight_value_t> ed_w2(boost::num_edges(g), 1);
|
||||
return maximum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), pcc, minus_infinity);
|
||||
}
|
||||
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeightEdgeMap, typename TIndEdgeMap>
|
||||
double minimum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TWeightEdgeMap>::value_type plus_infinity =
|
||||
(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeightEdgeMap>::value_type>::type weight_value_t;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
typename std::vector<weight_value_t> ed_w2(boost::num_edges(g), 1);
|
||||
return minimum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), eim, pcc, plus_infinity);
|
||||
}
|
||||
} //namespace boost
|
||||
#endif
|
||||
170
libraries/include/boost/graph/incremental_components.hpp
Normal file
170
libraries/include/boost/graph/incremental_components.hpp
Normal file
@@ -0,0 +1,170 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 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_INCREMENTAL_COMPONENTS_HPP
|
||||
#define BOOST_INCREMENTAL_COMPONENTS_HPP
|
||||
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/graph/detail/incremental_components.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// A connected component algorithm for the case when dynamically
|
||||
// adding (but not removing) edges is common. The
|
||||
// incremental_components() function is a preparing operation. Call
|
||||
// same_component to check whether two vertices are in the same
|
||||
// component, or use disjoint_set::find_set to determine the
|
||||
// representative for a vertex.
|
||||
|
||||
// This version of connected components does not require a full
|
||||
// Graph. Instead, it just needs an edge list, where the vertices of
|
||||
// each edge need to be of integer type. The edges are assumed to
|
||||
// be undirected. The other difference is that the result is stored in
|
||||
// a container, instead of just a decorator. The container should be
|
||||
// empty before the algorithm is called. It will grow during the
|
||||
// course of the algorithm. The container must be a model of
|
||||
// BackInsertionSequence and RandomAccessContainer
|
||||
// (std::vector is a good choice). After running the algorithm the
|
||||
// index container will map each vertex to the representative
|
||||
// vertex of the component to which it belongs.
|
||||
//
|
||||
// Adapted from an implementation by Alex Stepanov. The disjoint
|
||||
// sets data structure is from Tarjan's "Data Structures and Network
|
||||
// Algorithms", and the application to connected components is
|
||||
// similar to the algorithm described in Ch. 22 of "Intro to
|
||||
// Algorithms" by Cormen, et. all.
|
||||
//
|
||||
// RankContainer is a random accessable container (operator[] is
|
||||
// defined) with a value type that can represent an integer part of
|
||||
// a binary log of the value type of the corresponding
|
||||
// ParentContainer (char is always enough) its size_type is no less
|
||||
// than the size_type of the corresponding ParentContainer
|
||||
|
||||
// An implementation of disjoint sets can be found in
|
||||
// boost/pending/disjoint_sets.hpp
|
||||
|
||||
template <class EdgeListGraph, class DisjointSets>
|
||||
void incremental_components(EdgeListGraph& g, DisjointSets& ds)
|
||||
{
|
||||
typename graph_traits<EdgeListGraph>::edge_iterator e, end;
|
||||
for (tie(e,end) = edges(g); e != end; ++e)
|
||||
ds.union_set(source(*e,g),target(*e,g));
|
||||
}
|
||||
|
||||
template <class ParentIterator>
|
||||
void compress_components(ParentIterator first, ParentIterator last)
|
||||
{
|
||||
for (ParentIterator current = first; current != last; ++current)
|
||||
detail::find_representative_with_full_compression(first, current-first);
|
||||
}
|
||||
|
||||
template <class ParentIterator>
|
||||
typename boost::detail::iterator_traits<ParentIterator>::difference_type
|
||||
component_count(ParentIterator first, ParentIterator last)
|
||||
{
|
||||
std::ptrdiff_t count = 0;
|
||||
for (ParentIterator current = first; current != last; ++current)
|
||||
if (*current == current - first) ++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
// This algorithm can be applied to the result container of the
|
||||
// connected_components algorithm to normalize
|
||||
// the components.
|
||||
template <class ParentIterator>
|
||||
void normalize_components(ParentIterator first, ParentIterator last)
|
||||
{
|
||||
for (ParentIterator current = first; current != last; ++current)
|
||||
detail::normalize_node(first, current - first);
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class DisjointSets>
|
||||
void initialize_incremental_components(VertexListGraph& G, DisjointSets& ds)
|
||||
{
|
||||
typename graph_traits<VertexListGraph>
|
||||
::vertex_iterator v, vend;
|
||||
for (tie(v, vend) = vertices(G); v != vend; ++v)
|
||||
ds.make_set(*v);
|
||||
}
|
||||
|
||||
template <class Vertex, class DisjointSet>
|
||||
inline bool same_component(Vertex u, Vertex v, DisjointSet& ds)
|
||||
{
|
||||
return ds.find_set(u) == ds.find_set(v);
|
||||
}
|
||||
|
||||
// considering changing the so that it initializes with a pair of
|
||||
// vertex iterators and a parent PA.
|
||||
|
||||
template <class IndexT>
|
||||
class component_index
|
||||
{
|
||||
public://protected: (avoid friends for now)
|
||||
typedef std::vector<IndexT> MyIndexContainer;
|
||||
MyIndexContainer header;
|
||||
MyIndexContainer index;
|
||||
typedef typename MyIndexContainer::size_type SizeT;
|
||||
typedef typename MyIndexContainer::const_iterator IndexIter;
|
||||
public:
|
||||
typedef detail::component_iterator<IndexIter, IndexT, SizeT>
|
||||
component_iterator;
|
||||
class component {
|
||||
friend class component_index;
|
||||
protected:
|
||||
IndexT number;
|
||||
const component_index<IndexT>* comp_ind_ptr;
|
||||
component(IndexT i, const component_index<IndexT>* p)
|
||||
: number(i), comp_ind_ptr(p) {}
|
||||
public:
|
||||
typedef component_iterator iterator;
|
||||
typedef component_iterator const_iterator;
|
||||
typedef IndexT value_type;
|
||||
iterator begin() const {
|
||||
return iterator( comp_ind_ptr->index.begin(),
|
||||
(comp_ind_ptr->header)[number] );
|
||||
}
|
||||
iterator end() const {
|
||||
return iterator( comp_ind_ptr->index.begin(),
|
||||
comp_ind_ptr->index.size() );
|
||||
}
|
||||
};
|
||||
typedef SizeT size_type;
|
||||
typedef component value_type;
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
|
||||
template <class Iterator>
|
||||
component_index(Iterator first, Iterator last)
|
||||
: index(std::distance(first, last))
|
||||
{
|
||||
std::copy(first, last, index.begin());
|
||||
detail::construct_component_index(index, header);
|
||||
}
|
||||
#else
|
||||
template <class Iterator>
|
||||
component_index(Iterator first, Iterator last)
|
||||
: index(first, last)
|
||||
{
|
||||
detail::construct_component_index(index, header);
|
||||
}
|
||||
#endif
|
||||
|
||||
component operator[](IndexT i) const {
|
||||
return component(i, this);
|
||||
}
|
||||
SizeT size() const {
|
||||
return header.size();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_INCREMENTAL_COMPONENTS_HPP
|
||||
332
libraries/include/boost/graph/is_kuratowski_subgraph.hpp
Normal file
332
libraries/include/boost/graph/is_kuratowski_subgraph.hpp
Normal file
@@ -0,0 +1,332 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// 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 __IS_KURATOWSKI_SUBGRAPH_HPP__
|
||||
#define __IS_KURATOWSKI_SUBGRAPH_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next/prior
|
||||
#include <boost/tuple/tuple.hpp> //for tie
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/isomorphism.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Graph>
|
||||
Graph make_K_5()
|
||||
{
|
||||
typename graph_traits<Graph>::vertex_iterator vi, vi_end, inner_vi;
|
||||
Graph K_5(5);
|
||||
for(tie(vi,vi_end) = vertices(K_5); vi != vi_end; ++vi)
|
||||
for(inner_vi = next(vi); inner_vi != vi_end; ++inner_vi)
|
||||
add_edge(*vi, *inner_vi, K_5);
|
||||
return K_5;
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
Graph make_K_3_3()
|
||||
{
|
||||
typename graph_traits<Graph>::vertex_iterator
|
||||
vi, vi_end, bipartition_start, inner_vi;
|
||||
Graph K_3_3(6);
|
||||
bipartition_start = next(next(next(vertices(K_3_3).first)));
|
||||
for(tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; ++vi)
|
||||
for(inner_vi= bipartition_start; inner_vi != vi_end; ++inner_vi)
|
||||
add_edge(*vi, *inner_vi, K_3_3);
|
||||
return K_3_3;
|
||||
}
|
||||
|
||||
|
||||
template <typename AdjacencyList, typename Vertex>
|
||||
void contract_edge(AdjacencyList& neighbors, Vertex u, Vertex v)
|
||||
{
|
||||
// Remove u from v's neighbor list
|
||||
neighbors[v].erase(std::remove(neighbors[v].begin(),
|
||||
neighbors[v].end(), u
|
||||
),
|
||||
neighbors[v].end()
|
||||
);
|
||||
|
||||
// Replace any references to u with references to v
|
||||
typedef typename AdjacencyList::value_type::iterator
|
||||
adjacency_iterator_t;
|
||||
|
||||
adjacency_iterator_t u_neighbor_end = neighbors[u].end();
|
||||
for(adjacency_iterator_t u_neighbor_itr = neighbors[u].begin();
|
||||
u_neighbor_itr != u_neighbor_end; ++u_neighbor_itr
|
||||
)
|
||||
{
|
||||
Vertex u_neighbor(*u_neighbor_itr);
|
||||
std::replace(neighbors[u_neighbor].begin(),
|
||||
neighbors[u_neighbor].end(), u, v
|
||||
);
|
||||
}
|
||||
|
||||
// Remove v from u's neighbor list
|
||||
neighbors[u].erase(std::remove(neighbors[u].begin(),
|
||||
neighbors[u].end(), v
|
||||
),
|
||||
neighbors[u].end()
|
||||
);
|
||||
|
||||
// Add everything in u's neighbor list to v's neighbor list
|
||||
std::copy(neighbors[u].begin(),
|
||||
neighbors[u].end(),
|
||||
std::back_inserter(neighbors[v])
|
||||
);
|
||||
|
||||
// Clear u's neighbor list
|
||||
neighbors[u].clear();
|
||||
|
||||
}
|
||||
|
||||
enum target_graph_t { tg_k_3_3, tg_k_5};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename ForwardIterator, typename VertexIndexMap>
|
||||
bool is_kuratowski_subgraph(const Graph& g,
|
||||
ForwardIterator begin,
|
||||
ForwardIterator end,
|
||||
VertexIndexMap vm
|
||||
)
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::edges_size_type e_size_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef typename std::vector<vertex_t> v_list_t;
|
||||
typedef typename v_list_t::iterator v_list_iterator_t;
|
||||
typedef iterator_property_map
|
||||
<typename std::vector<v_list_t>::iterator, VertexIndexMap>
|
||||
vertex_to_v_list_map_t;
|
||||
|
||||
typedef adjacency_list<vecS, vecS, undirectedS> small_graph_t;
|
||||
|
||||
detail::target_graph_t target_graph = detail::tg_k_3_3; //unless we decide otherwise later
|
||||
|
||||
static small_graph_t K_5(detail::make_K_5<small_graph_t>());
|
||||
|
||||
static small_graph_t K_3_3(detail::make_K_3_3<small_graph_t>());
|
||||
|
||||
v_size_t n_vertices(num_vertices(g));
|
||||
v_size_t max_num_edges(3*n_vertices - 5);
|
||||
|
||||
std::vector<v_list_t> neighbors_vector(n_vertices);
|
||||
vertex_to_v_list_map_t neighbors(neighbors_vector.begin(), vm);
|
||||
|
||||
e_size_t count = 0;
|
||||
for(ForwardIterator itr = begin; itr != end; ++itr)
|
||||
{
|
||||
|
||||
if (count++ > max_num_edges)
|
||||
return false;
|
||||
|
||||
edge_t e(*itr);
|
||||
vertex_t u(source(e,g));
|
||||
vertex_t v(target(e,g));
|
||||
|
||||
neighbors[u].push_back(v);
|
||||
neighbors[v].push_back(u);
|
||||
|
||||
}
|
||||
|
||||
|
||||
for(v_size_t max_size = 2; max_size < 5; ++max_size)
|
||||
{
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_t v(*vi);
|
||||
|
||||
//a hack to make sure we don't contract the middle edge of a path
|
||||
//of four degree-3 vertices
|
||||
if (max_size == 4 && neighbors[v].size() == 3)
|
||||
{
|
||||
if (neighbors[neighbors[v][0]].size() +
|
||||
neighbors[neighbors[v][1]].size() +
|
||||
neighbors[neighbors[v][2]].size()
|
||||
< 11 // so, it has two degree-3 neighbors
|
||||
)
|
||||
continue;
|
||||
}
|
||||
|
||||
while (neighbors[v].size() > 0 && neighbors[v].size() < max_size)
|
||||
{
|
||||
// Find one of v's neighbors u such that that v and u
|
||||
// have no neighbors in common. We'll look for such a
|
||||
// neighbor with a naive cubic-time algorithm since the
|
||||
// max size of any of the neighbor sets we'll consider
|
||||
// merging is 3
|
||||
|
||||
bool neighbor_sets_intersect = false;
|
||||
|
||||
vertex_t min_u = graph_traits<Graph>::null_vertex();
|
||||
vertex_t u;
|
||||
v_list_iterator_t v_neighbor_end = neighbors[v].end();
|
||||
for(v_list_iterator_t v_neighbor_itr = neighbors[v].begin();
|
||||
v_neighbor_itr != v_neighbor_end;
|
||||
++v_neighbor_itr
|
||||
)
|
||||
{
|
||||
neighbor_sets_intersect = false;
|
||||
u = *v_neighbor_itr;
|
||||
v_list_iterator_t u_neighbor_end = neighbors[u].end();
|
||||
for(v_list_iterator_t u_neighbor_itr =
|
||||
neighbors[u].begin();
|
||||
u_neighbor_itr != u_neighbor_end &&
|
||||
!neighbor_sets_intersect;
|
||||
++u_neighbor_itr
|
||||
)
|
||||
{
|
||||
for(v_list_iterator_t inner_v_neighbor_itr =
|
||||
neighbors[v].begin();
|
||||
inner_v_neighbor_itr != v_neighbor_end;
|
||||
++inner_v_neighbor_itr
|
||||
)
|
||||
{
|
||||
if (*u_neighbor_itr == *inner_v_neighbor_itr)
|
||||
{
|
||||
neighbor_sets_intersect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!neighbor_sets_intersect &&
|
||||
(min_u == graph_traits<Graph>::null_vertex() ||
|
||||
neighbors[u].size() < neighbors[min_u].size())
|
||||
)
|
||||
{
|
||||
min_u = u;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (min_u == graph_traits<Graph>::null_vertex())
|
||||
// Exited the loop without finding an appropriate neighbor of
|
||||
// v, so v must be a lost cause. Move on to other vertices.
|
||||
break;
|
||||
else
|
||||
u = min_u;
|
||||
|
||||
detail::contract_edge(neighbors, u, v);
|
||||
|
||||
}//end iteration over v's neighbors
|
||||
|
||||
}//end iteration through vertices v
|
||||
|
||||
if (max_size == 3)
|
||||
{
|
||||
// check to see whether we should go on to find a K_5
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
if (neighbors[*vi].size() == 4)
|
||||
{
|
||||
target_graph = detail::tg_k_5;
|
||||
break;
|
||||
}
|
||||
|
||||
if (target_graph == detail::tg_k_3_3)
|
||||
break;
|
||||
}
|
||||
|
||||
}//end iteration through max degree 2,3, and 4
|
||||
|
||||
|
||||
//Now, there should only be 5 or 6 vertices with any neighbors. Find them.
|
||||
|
||||
v_list_t main_vertices;
|
||||
vertex_iterator_t vi, vi_end;
|
||||
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
if (!neighbors[*vi].empty())
|
||||
main_vertices.push_back(*vi);
|
||||
}
|
||||
|
||||
// create a graph isomorphic to the contracted graph to test
|
||||
// against K_5 and K_3_3
|
||||
small_graph_t contracted_graph(main_vertices.size());
|
||||
std::map<vertex_t,typename graph_traits<small_graph_t>::vertex_descriptor>
|
||||
contracted_vertex_map;
|
||||
|
||||
typename v_list_t::iterator itr, itr_end;
|
||||
itr_end = main_vertices.end();
|
||||
typename graph_traits<small_graph_t>::vertex_iterator
|
||||
si = vertices(contracted_graph).first;
|
||||
|
||||
for(itr = main_vertices.begin(); itr != itr_end; ++itr, ++si)
|
||||
{
|
||||
contracted_vertex_map[*itr] = *si;
|
||||
}
|
||||
|
||||
typename v_list_t::iterator jtr, jtr_end;
|
||||
for(itr = main_vertices.begin(); itr != itr_end; ++itr)
|
||||
{
|
||||
jtr_end = neighbors[*itr].end();
|
||||
for(jtr = neighbors[*itr].begin(); jtr != jtr_end; ++jtr)
|
||||
{
|
||||
if (get(vm,*itr) < get(vm,*jtr))
|
||||
{
|
||||
add_edge(contracted_vertex_map[*itr],
|
||||
contracted_vertex_map[*jtr],
|
||||
contracted_graph
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target_graph == detail::tg_k_5)
|
||||
{
|
||||
return isomorphism(K_5,contracted_graph);
|
||||
}
|
||||
else //target_graph == tg_k_3_3
|
||||
{
|
||||
return isomorphism(K_3_3,contracted_graph);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename ForwardIterator>
|
||||
bool is_kuratowski_subgraph(const Graph& g,
|
||||
ForwardIterator begin,
|
||||
ForwardIterator end
|
||||
)
|
||||
{
|
||||
return is_kuratowski_subgraph(g, begin, end, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //__IS_KURATOWSKI_SUBGRAPH_HPP__
|
||||
252
libraries/include/boost/graph/is_straight_line_drawing.hpp
Normal file
252
libraries/include/boost/graph/is_straight_line_drawing.hpp
Normal file
@@ -0,0 +1,252 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// 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 __IS_STRAIGHT_LINE_DRAWING_HPP__
|
||||
#define __IS_STRAIGHT_LINE_DRAWING_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next and prior
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/tuple/tuple_comparison.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/planar_detail/bucket_sort.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// Return true exactly when the line segments s1 = ((x1,y1), (x2,y2)) and
|
||||
// s2 = ((a1,b1), (a2,b2)) intersect in a point other than the endpoints of
|
||||
// the line segments. The one exception to this rule is when s1 = s2, in
|
||||
// which case false is returned - this is to accomodate multiple edges
|
||||
// between the same pair of vertices, which shouldn't invalidate the straight
|
||||
// line embedding. A tolerance variable epsilon can also be used, which
|
||||
// defines how far away from the endpoints of s1 and s2 we want to consider
|
||||
// an intersection.
|
||||
|
||||
bool intersects(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double a1, double b1,
|
||||
double a2, double b2,
|
||||
double epsilon = 0.000001
|
||||
)
|
||||
{
|
||||
|
||||
if (x1 - x2 == 0)
|
||||
{
|
||||
std::swap(x1,a1);
|
||||
std::swap(y1,b1);
|
||||
std::swap(x2,a2);
|
||||
std::swap(y2,b2);
|
||||
}
|
||||
|
||||
if (x1 - x2 == 0)
|
||||
{
|
||||
BOOST_USING_STD_MAX();
|
||||
BOOST_USING_STD_MIN();
|
||||
|
||||
//two vertical line segments
|
||||
double min_y = min BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2);
|
||||
double max_y = max BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2);
|
||||
double min_b = min BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2);
|
||||
double max_b = max BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2);
|
||||
if ((max_y > max_b && max_b > min_y) ||
|
||||
(max_b > max_y && max_y > min_b)
|
||||
)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
double x_diff = x1 - x2;
|
||||
double y_diff = y1 - y2;
|
||||
double a_diff = a2 - a1;
|
||||
double b_diff = b2 - b1;
|
||||
|
||||
double beta_denominator = b_diff - (y_diff/((double)x_diff)) * a_diff;
|
||||
|
||||
if (beta_denominator == 0)
|
||||
{
|
||||
//parallel lines
|
||||
return false;
|
||||
}
|
||||
|
||||
double beta = (b2 - y2 - (y_diff/((double)x_diff)) * (a2 - x2)) /
|
||||
beta_denominator;
|
||||
double alpha = (a2 - x2 - beta*(a_diff))/x_diff;
|
||||
|
||||
double upper_bound = 1 - epsilon;
|
||||
double lower_bound = 0 + epsilon;
|
||||
|
||||
return (beta < upper_bound && beta > lower_bound &&
|
||||
alpha < upper_bound && alpha > lower_bound);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename GridPositionMap,
|
||||
typename VertexIndexMap
|
||||
>
|
||||
bool is_straight_line_drawing(const Graph& g,
|
||||
GridPositionMap drawing,
|
||||
VertexIndexMap vm
|
||||
)
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
|
||||
typedef typename graph_traits<Graph>::edges_size_type e_size_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
|
||||
typedef std::size_t x_coord_t;
|
||||
typedef std::size_t y_coord_t;
|
||||
typedef boost::tuple<edge_t, x_coord_t, y_coord_t> edge_event_t;
|
||||
typedef typename std::vector< edge_event_t > edge_event_queue_t;
|
||||
|
||||
typedef tuple<y_coord_t, y_coord_t, x_coord_t, x_coord_t> active_map_key_t;
|
||||
typedef edge_t active_map_value_t;
|
||||
typedef std::map< active_map_key_t, active_map_value_t > active_map_t;
|
||||
typedef typename active_map_t::iterator active_map_iterator_t;
|
||||
|
||||
|
||||
edge_event_queue_t edge_event_queue;
|
||||
active_map_t active_edges;
|
||||
|
||||
edge_iterator_t ei, ei_end;
|
||||
for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
{
|
||||
edge_t e(*ei);
|
||||
vertex_t s(source(e,g));
|
||||
vertex_t t(target(e,g));
|
||||
edge_event_queue.push_back
|
||||
(make_tuple(e,
|
||||
static_cast<std::size_t>(drawing[s].x),
|
||||
static_cast<std::size_t>(drawing[s].y)
|
||||
)
|
||||
);
|
||||
edge_event_queue.push_back
|
||||
(make_tuple(e,
|
||||
static_cast<std::size_t>(drawing[t].x),
|
||||
static_cast<std::size_t>(drawing[t].y)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Order by edge_event_queue by first, then second coordinate
|
||||
// (bucket_sort is a stable sort.)
|
||||
bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
|
||||
property_map_tuple_adaptor<edge_event_t, 2>()
|
||||
);
|
||||
|
||||
bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
|
||||
property_map_tuple_adaptor<edge_event_t, 1>()
|
||||
);
|
||||
|
||||
typedef typename edge_event_queue_t::iterator event_queue_iterator_t;
|
||||
event_queue_iterator_t itr_end = edge_event_queue.end();
|
||||
for(event_queue_iterator_t itr = edge_event_queue.begin();
|
||||
itr != itr_end; ++itr
|
||||
)
|
||||
{
|
||||
edge_t e(get<0>(*itr));
|
||||
vertex_t source_v(source(e,g));
|
||||
vertex_t target_v(target(e,g));
|
||||
if (drawing[source_v].y > drawing[target_v].y)
|
||||
std::swap(source_v, target_v);
|
||||
|
||||
active_map_key_t key(get(drawing, source_v).y,
|
||||
get(drawing, target_v).y,
|
||||
get(drawing, source_v).x,
|
||||
get(drawing, target_v).x
|
||||
);
|
||||
|
||||
active_map_iterator_t a_itr = active_edges.find(key);
|
||||
if (a_itr == active_edges.end())
|
||||
{
|
||||
active_edges[key] = e;
|
||||
}
|
||||
else
|
||||
{
|
||||
active_map_iterator_t before, after;
|
||||
if (a_itr == active_edges.begin())
|
||||
before = active_edges.end();
|
||||
else
|
||||
before = prior(a_itr);
|
||||
after = next(a_itr);
|
||||
|
||||
if (before != active_edges.end())
|
||||
{
|
||||
|
||||
edge_t f = before->second;
|
||||
vertex_t e_source(source(e,g));
|
||||
vertex_t e_target(target(e,g));
|
||||
vertex_t f_source(source(f,g));
|
||||
vertex_t f_target(target(f,g));
|
||||
|
||||
if (intersects(drawing[e_source].x,
|
||||
drawing[e_source].y,
|
||||
drawing[e_target].x,
|
||||
drawing[e_target].y,
|
||||
drawing[f_source].x,
|
||||
drawing[f_source].y,
|
||||
drawing[f_target].x,
|
||||
drawing[f_target].y
|
||||
)
|
||||
)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (after != active_edges.end())
|
||||
{
|
||||
|
||||
edge_t f = after->second;
|
||||
vertex_t e_source(source(e,g));
|
||||
vertex_t e_target(target(e,g));
|
||||
vertex_t f_source(source(f,g));
|
||||
vertex_t f_target(target(f,g));
|
||||
|
||||
if (intersects(drawing[e_source].x,
|
||||
drawing[e_source].y,
|
||||
drawing[e_target].x,
|
||||
drawing[e_target].y,
|
||||
drawing[f_source].x,
|
||||
drawing[f_source].y,
|
||||
drawing[f_target].x,
|
||||
drawing[f_target].y
|
||||
)
|
||||
)
|
||||
return false;
|
||||
}
|
||||
|
||||
active_edges.erase(a_itr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph, typename GridPositionMap>
|
||||
bool is_straight_line_drawing(const Graph& g, GridPositionMap drawing)
|
||||
{
|
||||
return is_straight_line_drawing(g, drawing, get(vertex_index,g));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // __IS_STRAIGHT_LINE_DRAWING_HPP__
|
||||
467
libraries/include/boost/graph/isomorphism.hpp
Normal file
467
libraries/include/boost/graph/isomorphism.hpp
Normal file
@@ -0,0 +1,467 @@
|
||||
// Copyright (C) 2001 Jeremy Siek, Douglas Gregor, Brian Osman
|
||||
//
|
||||
// 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_ISOMORPHISM_HPP
|
||||
#define BOOST_GRAPH_ISOMORPHISM_HPP
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/detail/algorithm.hpp>
|
||||
#include <boost/pending/indirect_cmp.hpp> // for make_indirect_pmap
|
||||
|
||||
#ifndef BOOST_GRAPH_ITERATION_MACROS_HPP
|
||||
#define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file
|
||||
#include <boost/graph/iteration_macros.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Graph1, typename Graph2, typename IsoMapping,
|
||||
typename Invariant1, typename Invariant2,
|
||||
typename IndexMap1, typename IndexMap2>
|
||||
class isomorphism_algo
|
||||
{
|
||||
typedef typename graph_traits<Graph1>::vertex_descriptor vertex1_t;
|
||||
typedef typename graph_traits<Graph2>::vertex_descriptor vertex2_t;
|
||||
typedef typename graph_traits<Graph1>::edge_descriptor edge1_t;
|
||||
typedef typename graph_traits<Graph1>::vertices_size_type size_type;
|
||||
typedef typename Invariant1::result_type invar1_value;
|
||||
typedef typename Invariant2::result_type invar2_value;
|
||||
|
||||
const Graph1& G1;
|
||||
const Graph2& G2;
|
||||
IsoMapping f;
|
||||
Invariant1 invariant1;
|
||||
Invariant2 invariant2;
|
||||
std::size_t max_invariant;
|
||||
IndexMap1 index_map1;
|
||||
IndexMap2 index_map2;
|
||||
|
||||
std::vector<vertex1_t> dfs_vertices;
|
||||
typedef typename std::vector<vertex1_t>::iterator vertex_iter;
|
||||
std::vector<int> dfs_num_vec;
|
||||
typedef safe_iterator_property_map<typename std::vector<int>::iterator,
|
||||
IndexMap1
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, int, int&
|
||||
#endif /* BOOST_NO_STD_ITERATOR_TRAITS */
|
||||
> DFSNumMap;
|
||||
DFSNumMap dfs_num;
|
||||
std::vector<edge1_t> ordered_edges;
|
||||
typedef typename std::vector<edge1_t>::iterator edge_iter;
|
||||
|
||||
std::vector<char> in_S_vec;
|
||||
typedef safe_iterator_property_map<typename std::vector<char>::iterator,
|
||||
IndexMap2
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, char, char&
|
||||
#endif /* BOOST_NO_STD_ITERATOR_TRAITS */
|
||||
> InSMap;
|
||||
InSMap in_S;
|
||||
|
||||
int num_edges_on_k;
|
||||
|
||||
friend struct compare_multiplicity;
|
||||
struct compare_multiplicity
|
||||
{
|
||||
compare_multiplicity(Invariant1 invariant1, size_type* multiplicity)
|
||||
: invariant1(invariant1), multiplicity(multiplicity) { }
|
||||
bool operator()(const vertex1_t& x, const vertex1_t& y) const {
|
||||
return multiplicity[invariant1(x)] < multiplicity[invariant1(y)];
|
||||
}
|
||||
Invariant1 invariant1;
|
||||
size_type* multiplicity;
|
||||
};
|
||||
|
||||
struct record_dfs_order : default_dfs_visitor
|
||||
{
|
||||
record_dfs_order(std::vector<vertex1_t>& v, std::vector<edge1_t>& e)
|
||||
: vertices(v), edges(e) { }
|
||||
|
||||
void discover_vertex(vertex1_t v, const Graph1&) const {
|
||||
vertices.push_back(v);
|
||||
}
|
||||
void examine_edge(edge1_t e, const Graph1& G1) const {
|
||||
edges.push_back(e);
|
||||
}
|
||||
std::vector<vertex1_t>& vertices;
|
||||
std::vector<edge1_t>& edges;
|
||||
};
|
||||
|
||||
struct edge_cmp {
|
||||
edge_cmp(const Graph1& G1, DFSNumMap dfs_num)
|
||||
: G1(G1), dfs_num(dfs_num) { }
|
||||
bool operator()(const edge1_t& e1, const edge1_t& e2) const {
|
||||
using namespace std;
|
||||
int u1 = dfs_num[source(e1,G1)], v1 = dfs_num[target(e1,G1)];
|
||||
int u2 = dfs_num[source(e2,G1)], v2 = dfs_num[target(e2,G1)];
|
||||
int m1 = (max)(u1, v1);
|
||||
int m2 = (max)(u2, v2);
|
||||
// lexicographical comparison
|
||||
return std::make_pair(m1, std::make_pair(u1, v1))
|
||||
< std::make_pair(m2, std::make_pair(u2, v2));
|
||||
}
|
||||
const Graph1& G1;
|
||||
DFSNumMap dfs_num;
|
||||
};
|
||||
|
||||
public:
|
||||
isomorphism_algo(const Graph1& G1, const Graph2& G2, IsoMapping f,
|
||||
Invariant1 invariant1, Invariant2 invariant2, std::size_t max_invariant,
|
||||
IndexMap1 index_map1, IndexMap2 index_map2)
|
||||
: G1(G1), G2(G2), f(f), invariant1(invariant1), invariant2(invariant2),
|
||||
max_invariant(max_invariant),
|
||||
index_map1(index_map1), index_map2(index_map2)
|
||||
{
|
||||
in_S_vec.resize(num_vertices(G1));
|
||||
in_S = make_safe_iterator_property_map
|
||||
(in_S_vec.begin(), in_S_vec.size(), index_map2
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, in_S_vec.front()
|
||||
#endif /* BOOST_NO_STD_ITERATOR_TRAITS */
|
||||
);
|
||||
}
|
||||
|
||||
bool test_isomorphism()
|
||||
{
|
||||
{
|
||||
std::vector<invar1_value> invar1_array;
|
||||
BGL_FORALL_VERTICES_T(v, G1, Graph1)
|
||||
invar1_array.push_back(invariant1(v));
|
||||
sort(invar1_array);
|
||||
|
||||
std::vector<invar2_value> invar2_array;
|
||||
BGL_FORALL_VERTICES_T(v, G2, Graph2)
|
||||
invar2_array.push_back(invariant2(v));
|
||||
sort(invar2_array);
|
||||
if (! equal(invar1_array, invar2_array))
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<vertex1_t> V_mult;
|
||||
BGL_FORALL_VERTICES_T(v, G1, Graph1)
|
||||
V_mult.push_back(v);
|
||||
{
|
||||
std::vector<size_type> multiplicity(max_invariant, 0);
|
||||
BGL_FORALL_VERTICES_T(v, G1, Graph1)
|
||||
++multiplicity[invariant1(v)];
|
||||
sort(V_mult, compare_multiplicity(invariant1, &multiplicity[0]));
|
||||
}
|
||||
|
||||
std::vector<default_color_type> color_vec(num_vertices(G1));
|
||||
safe_iterator_property_map<std::vector<default_color_type>::iterator,
|
||||
IndexMap1
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, default_color_type, default_color_type&
|
||||
#endif /* BOOST_NO_STD_ITERATOR_TRAITS */
|
||||
>
|
||||
color_map(color_vec.begin(), color_vec.size(), index_map1);
|
||||
record_dfs_order dfs_visitor(dfs_vertices, ordered_edges);
|
||||
typedef color_traits<default_color_type> Color;
|
||||
for (vertex_iter u = V_mult.begin(); u != V_mult.end(); ++u) {
|
||||
if (color_map[*u] == Color::white()) {
|
||||
dfs_visitor.start_vertex(*u, G1);
|
||||
depth_first_visit(G1, *u, dfs_visitor, color_map);
|
||||
}
|
||||
}
|
||||
// Create the dfs_num array and dfs_num_map
|
||||
dfs_num_vec.resize(num_vertices(G1));
|
||||
dfs_num = make_safe_iterator_property_map(dfs_num_vec.begin(),
|
||||
dfs_num_vec.size(),
|
||||
index_map1
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, dfs_num_vec.front()
|
||||
#endif /* BOOST_NO_STD_ITERATOR_TRAITS */
|
||||
);
|
||||
size_type n = 0;
|
||||
for (vertex_iter v = dfs_vertices.begin(); v != dfs_vertices.end(); ++v)
|
||||
dfs_num[*v] = n++;
|
||||
|
||||
sort(ordered_edges, edge_cmp(G1, dfs_num));
|
||||
|
||||
|
||||
int dfs_num_k = -1;
|
||||
return this->match(ordered_edges.begin(), dfs_num_k);
|
||||
}
|
||||
|
||||
private:
|
||||
bool match(edge_iter iter, int dfs_num_k)
|
||||
{
|
||||
if (iter != ordered_edges.end()) {
|
||||
vertex1_t i = source(*iter, G1), j = target(*iter, G2);
|
||||
if (dfs_num[i] > dfs_num_k) {
|
||||
vertex1_t kp1 = dfs_vertices[dfs_num_k + 1];
|
||||
BGL_FORALL_VERTICES_T(u, G2, Graph2) {
|
||||
if (invariant1(kp1) == invariant2(u) && in_S[u] == false) {
|
||||
f[kp1] = u;
|
||||
in_S[u] = true;
|
||||
num_edges_on_k = 0;
|
||||
|
||||
if (match(iter, dfs_num_k + 1))
|
||||
#if 0
|
||||
// dwa 2003/7/11 -- this *HAS* to be a bug!
|
||||
;
|
||||
#endif
|
||||
return true;
|
||||
|
||||
in_S[u] = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (dfs_num[j] > dfs_num_k) {
|
||||
vertex1_t k = dfs_vertices[dfs_num_k];
|
||||
num_edges_on_k -=
|
||||
count_if(adjacent_vertices(f[k], G2), make_indirect_pmap(in_S));
|
||||
|
||||
for (int jj = 0; jj < dfs_num_k; ++jj) {
|
||||
vertex1_t j = dfs_vertices[jj];
|
||||
num_edges_on_k -= count(adjacent_vertices(f[j], G2), f[k]);
|
||||
}
|
||||
|
||||
if (num_edges_on_k != 0)
|
||||
return false;
|
||||
BGL_FORALL_ADJ_T(f[i], v, G2, Graph2)
|
||||
if (invariant2(v) == invariant1(j) && in_S[v] == false) {
|
||||
f[j] = v;
|
||||
in_S[v] = true;
|
||||
num_edges_on_k = 1;
|
||||
BOOST_USING_STD_MAX();
|
||||
int next_k = max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num_k, max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num[i], dfs_num[j]));
|
||||
if (match(next(iter), next_k))
|
||||
return true;
|
||||
in_S[v] = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
if (container_contains(adjacent_vertices(f[i], G2), f[j])) {
|
||||
++num_edges_on_k;
|
||||
if (match(next(iter), dfs_num_k))
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
} else
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename Graph, typename InDegreeMap>
|
||||
void compute_in_degree(const Graph& g, InDegreeMap in_degree_map)
|
||||
{
|
||||
BGL_FORALL_VERTICES_T(v, g, Graph)
|
||||
put(in_degree_map, v, 0);
|
||||
|
||||
BGL_FORALL_VERTICES_T(u, g, Graph)
|
||||
BGL_FORALL_ADJ_T(u, v, g, Graph)
|
||||
put(in_degree_map, v, get(in_degree_map, v) + 1);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template <typename InDegreeMap, typename Graph>
|
||||
class degree_vertex_invariant
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::degree_size_type size_type;
|
||||
public:
|
||||
typedef vertex_t argument_type;
|
||||
typedef size_type result_type;
|
||||
|
||||
degree_vertex_invariant(const InDegreeMap& in_degree_map, const Graph& g)
|
||||
: m_in_degree_map(in_degree_map), m_g(g) { }
|
||||
|
||||
size_type operator()(vertex_t v) const {
|
||||
return (num_vertices(m_g) + 1) * out_degree(v, m_g)
|
||||
+ get(m_in_degree_map, v);
|
||||
}
|
||||
// The largest possible vertex invariant number
|
||||
size_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const {
|
||||
return num_vertices(m_g) * num_vertices(m_g) + num_vertices(m_g);
|
||||
}
|
||||
private:
|
||||
InDegreeMap m_in_degree_map;
|
||||
const Graph& m_g;
|
||||
};
|
||||
|
||||
|
||||
template <typename Graph1, typename Graph2, typename IsoMapping,
|
||||
typename Invariant1, typename Invariant2,
|
||||
typename IndexMap1, typename IndexMap2>
|
||||
bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f,
|
||||
Invariant1 invariant1, Invariant2 invariant2,
|
||||
std::size_t max_invariant,
|
||||
IndexMap1 index_map1, IndexMap2 index_map2)
|
||||
|
||||
{
|
||||
// Graph requirements
|
||||
function_requires< VertexListGraphConcept<Graph1> >();
|
||||
function_requires< EdgeListGraphConcept<Graph1> >();
|
||||
function_requires< VertexListGraphConcept<Graph2> >();
|
||||
function_requires< BidirectionalGraphConcept<Graph2> >();
|
||||
|
||||
typedef typename graph_traits<Graph1>::vertex_descriptor vertex1_t;
|
||||
typedef typename graph_traits<Graph2>::vertex_descriptor vertex2_t;
|
||||
typedef typename graph_traits<Graph1>::vertices_size_type size_type;
|
||||
|
||||
// Vertex invariant requirement
|
||||
function_requires< AdaptableUnaryFunctionConcept<Invariant1,
|
||||
size_type, vertex1_t> >();
|
||||
function_requires< AdaptableUnaryFunctionConcept<Invariant2,
|
||||
size_type, vertex2_t> >();
|
||||
|
||||
// Property map requirements
|
||||
function_requires< ReadWritePropertyMapConcept<IsoMapping, vertex1_t> >();
|
||||
typedef typename property_traits<IsoMapping>::value_type IsoMappingValue;
|
||||
BOOST_STATIC_ASSERT((is_same<IsoMappingValue, vertex2_t>::value));
|
||||
|
||||
function_requires< ReadablePropertyMapConcept<IndexMap1, vertex1_t> >();
|
||||
typedef typename property_traits<IndexMap1>::value_type IndexMap1Value;
|
||||
BOOST_STATIC_ASSERT((is_convertible<IndexMap1Value, size_type>::value));
|
||||
|
||||
function_requires< ReadablePropertyMapConcept<IndexMap2, vertex2_t> >();
|
||||
typedef typename property_traits<IndexMap2>::value_type IndexMap2Value;
|
||||
BOOST_STATIC_ASSERT((is_convertible<IndexMap2Value, size_type>::value));
|
||||
|
||||
if (num_vertices(G1) != num_vertices(G2))
|
||||
return false;
|
||||
if (num_vertices(G1) == 0 && num_vertices(G2) == 0)
|
||||
return true;
|
||||
|
||||
detail::isomorphism_algo<Graph1, Graph2, IsoMapping, Invariant1,
|
||||
Invariant2, IndexMap1, IndexMap2>
|
||||
algo(G1, G2, f, invariant1, invariant2, max_invariant,
|
||||
index_map1, index_map2);
|
||||
return algo.test_isomorphism();
|
||||
}
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Graph1, typename Graph2,
|
||||
typename IsoMapping,
|
||||
typename IndexMap1, typename IndexMap2,
|
||||
typename P, typename T, typename R>
|
||||
bool isomorphism_impl(const Graph1& G1, const Graph2& G2,
|
||||
IsoMapping f, IndexMap1 index_map1, IndexMap2 index_map2,
|
||||
const bgl_named_params<P,T,R>& params)
|
||||
{
|
||||
std::vector<std::size_t> in_degree1_vec(num_vertices(G1));
|
||||
typedef safe_iterator_property_map<std::vector<std::size_t>::iterator,
|
||||
IndexMap1
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, std::size_t, std::size_t&
|
||||
#endif /* BOOST_NO_STD_ITERATOR_TRAITS */
|
||||
> InDeg1;
|
||||
InDeg1 in_degree1(in_degree1_vec.begin(), in_degree1_vec.size(), index_map1);
|
||||
compute_in_degree(G1, in_degree1);
|
||||
|
||||
std::vector<std::size_t> in_degree2_vec(num_vertices(G2));
|
||||
typedef safe_iterator_property_map<std::vector<std::size_t>::iterator,
|
||||
IndexMap2
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, std::size_t, std::size_t&
|
||||
#endif /* BOOST_NO_STD_ITERATOR_TRAITS */
|
||||
> InDeg2;
|
||||
InDeg2 in_degree2(in_degree2_vec.begin(), in_degree2_vec.size(), index_map2);
|
||||
compute_in_degree(G2, in_degree2);
|
||||
|
||||
degree_vertex_invariant<InDeg1, Graph1> invariant1(in_degree1, G1);
|
||||
degree_vertex_invariant<InDeg2, Graph2> invariant2(in_degree2, G2);
|
||||
|
||||
return isomorphism(G1, G2, f,
|
||||
choose_param(get_param(params, vertex_invariant1_t()), invariant1),
|
||||
choose_param(get_param(params, vertex_invariant2_t()), invariant2),
|
||||
choose_param(get_param(params, vertex_max_invariant_t()), (invariant2.max)()),
|
||||
index_map1, index_map2
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// Named parameter interface
|
||||
template <typename Graph1, typename Graph2, class P, class T, class R>
|
||||
bool isomorphism(const Graph1& g1,
|
||||
const Graph2& g2,
|
||||
const bgl_named_params<P,T,R>& params)
|
||||
{
|
||||
typedef typename graph_traits<Graph2>::vertex_descriptor vertex2_t;
|
||||
typename std::vector<vertex2_t>::size_type n = num_vertices(g1);
|
||||
std::vector<vertex2_t> f(n);
|
||||
return detail::isomorphism_impl
|
||||
(g1, g2,
|
||||
choose_param(get_param(params, vertex_isomorphism_t()),
|
||||
make_safe_iterator_property_map(f.begin(), f.size(),
|
||||
choose_const_pmap(get_param(params, vertex_index1),
|
||||
g1, vertex_index), vertex2_t())),
|
||||
choose_const_pmap(get_param(params, vertex_index1), g1, vertex_index),
|
||||
choose_const_pmap(get_param(params, vertex_index2), g2, vertex_index),
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
// All defaults interface
|
||||
template <typename Graph1, typename Graph2>
|
||||
bool isomorphism(const Graph1& g1, const Graph2& g2)
|
||||
{
|
||||
return isomorphism(g1, g2,
|
||||
bgl_named_params<int, buffer_param_t>(0));// bogus named param
|
||||
}
|
||||
|
||||
|
||||
// Verify that the given mapping iso_map from the vertices of g1 to the
|
||||
// vertices of g2 describes an isomorphism.
|
||||
// Note: this could be made much faster by specializing based on the graph
|
||||
// concepts modeled, but since we're verifying an O(n^(lg n)) algorithm,
|
||||
// O(n^4) won't hurt us.
|
||||
template<typename Graph1, typename Graph2, typename IsoMap>
|
||||
inline bool verify_isomorphism(const Graph1& g1, const Graph2& g2, IsoMap iso_map)
|
||||
{
|
||||
#if 0
|
||||
// problematic for filtered_graph!
|
||||
if (num_vertices(g1) != num_vertices(g2) || num_edges(g1) != num_edges(g2))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
for (typename graph_traits<Graph1>::edge_iterator e1 = edges(g1).first;
|
||||
e1 != edges(g1).second; ++e1) {
|
||||
bool found_edge = false;
|
||||
for (typename graph_traits<Graph2>::edge_iterator e2 = edges(g2).first;
|
||||
e2 != edges(g2).second && !found_edge; ++e2) {
|
||||
if (source(*e2, g2) == get(iso_map, source(*e1, g1)) &&
|
||||
target(*e2, g2) == get(iso_map, target(*e1, g1))) {
|
||||
found_edge = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_edge)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_ISO_INCLUDED_ITER_MACROS
|
||||
#undef BOOST_ISO_INCLUDED_ITER_MACROS
|
||||
#include <boost/graph/iteration_macros_undef.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_GRAPH_ISOMORPHISM_HPP
|
||||
129
libraries/include/boost/graph/iteration_macros.hpp
Normal file
129
libraries/include/boost/graph/iteration_macros.hpp
Normal file
@@ -0,0 +1,129 @@
|
||||
//=======================================================================
|
||||
// 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
|
||||
|
||||
#define BGL_CAT(x,y) x ## y
|
||||
#define BGL_FIRST(linenum) BGL_CAT(bgl_first_,linenum)
|
||||
#define BGL_LAST(linenum) BGL_CAT(bgl_last_,linenum)
|
||||
|
||||
/*
|
||||
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 ? (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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define BGL_FORALL_VERTICES_T(VNAME, GNAME, GraphType) \
|
||||
for (typename boost::graph_traits<GraphType>::vertex_iterator \
|
||||
BGL_FIRST(__LINE__) = vertices(GNAME).first, BGL_LAST(__LINE__) = vertices(GNAME).second; \
|
||||
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 (boost::graph_traits<GraphType>::vertex_iterator \
|
||||
BGL_FIRST(__LINE__) = vertices(GNAME).first, BGL_LAST(__LINE__) = vertices(GNAME).second; \
|
||||
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 (typename boost::graph_traits<GraphType>::edge_iterator \
|
||||
BGL_FIRST(__LINE__) = edges(GNAME).first, BGL_LAST(__LINE__) = edges(GNAME).second; \
|
||||
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 (boost::graph_traits<GraphType>::edge_iterator \
|
||||
BGL_FIRST(__LINE__) = edges(GNAME).first, BGL_LAST(__LINE__) = edges(GNAME).second; \
|
||||
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 (typename boost::graph_traits<GraphType>::adjacency_iterator \
|
||||
BGL_FIRST(__LINE__) = adjacent_vertices(UNAME, GNAME).first,\
|
||||
BGL_LAST(__LINE__) = adjacent_vertices(UNAME, GNAME).second; \
|
||||
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 (boost::graph_traits<GraphType>::adjacency_iterator \
|
||||
BGL_FIRST(__LINE__) = adjacent_vertices(UNAME, GNAME).first,\
|
||||
BGL_LAST(__LINE__) = adjacent_vertices(UNAME, GNAME).second; \
|
||||
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 (typename boost::graph_traits<GraphType>::out_edge_iterator \
|
||||
BGL_FIRST(__LINE__) = out_edges(UNAME, GNAME).first,\
|
||||
BGL_LAST(__LINE__) = out_edges(UNAME, GNAME).second; \
|
||||
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 (boost::graph_traits<GraphType>::out_edge_iterator \
|
||||
BGL_FIRST(__LINE__) = out_edges(UNAME, GNAME).first,\
|
||||
BGL_LAST(__LINE__) = out_edges(UNAME, GNAME).second; \
|
||||
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 (typename boost::graph_traits<GraphType>::in_edge_iterator \
|
||||
BGL_FIRST(__LINE__) = in_edges(UNAME, GNAME).first,\
|
||||
BGL_LAST(__LINE__) = in_edges(UNAME, GNAME).second; \
|
||||
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 (boost::graph_traits<GraphType>::in_edge_iterator \
|
||||
BGL_FIRST(__LINE__) = in_edges(UNAME, GNAME).first,\
|
||||
BGL_LAST(__LINE__) = in_edges(UNAME, GNAME).second; \
|
||||
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
|
||||
22
libraries/include/boost/graph/iteration_macros_undef.hpp
Normal file
22
libraries/include/boost/graph/iteration_macros_undef.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
//=======================================================================
|
||||
// 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)
|
||||
//=======================================================================
|
||||
|
||||
#ifdef BOOST_GRAPH_ITERATION_MACROS_HPP
|
||||
|
||||
#undef BOOST_GRAPH_ITERATION_MACROS_HPP
|
||||
#undef BGL_CAT
|
||||
#undef BGL_FIRST
|
||||
#undef BGL_LAST
|
||||
#undef BGL_FORALL_VERTICES
|
||||
#undef BGL_FORALL_EDGES
|
||||
#undef BGL_FORALL_ADJACENT
|
||||
#undef BGL_FORALL_OUTEDGES
|
||||
#undef BGL_FORALL_INEDGES
|
||||
|
||||
#endif
|
||||
205
libraries/include/boost/graph/johnson_all_pairs_shortest.hpp
Normal file
205
libraries/include/boost/graph/johnson_all_pairs_shortest.hpp
Normal file
@@ -0,0 +1,205 @@
|
||||
//=======================================================================
|
||||
// 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)
|
||||
//=======================================================================
|
||||
|
||||
/*
|
||||
This file implements the function
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix,
|
||||
class P, class T, class R>
|
||||
bool
|
||||
johnson_all_pairs_shortest_paths
|
||||
(VertexAndEdgeListGraph& g,
|
||||
DistanceMatrix& D,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_GRAPH_JOHNSON_HPP
|
||||
#define BOOST_GRAPH_JOHNSON_HPP
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/bellman_ford_shortest_paths.hpp>
|
||||
#include <boost/graph/dijkstra_shortest_paths.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix,
|
||||
class VertexID, class Weight, typename BinaryPredicate,
|
||||
typename BinaryFunction, typename Infinity, class DistanceZero>
|
||||
bool
|
||||
johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g1,
|
||||
DistanceMatrix& D,
|
||||
VertexID id1, Weight w1, const BinaryPredicate& compare,
|
||||
const BinaryFunction& combine, const Infinity& inf,
|
||||
DistanceZero zero)
|
||||
{
|
||||
typedef graph_traits<VertexAndEdgeListGraph> Traits1;
|
||||
typedef typename property_traits<Weight>::value_type DT;
|
||||
function_requires< BasicMatrixConcept<DistanceMatrix,
|
||||
typename Traits1::vertices_size_type, DT> >();
|
||||
|
||||
typedef typename Traits1::directed_category DirCat;
|
||||
bool is_undirected = is_same<DirCat, undirected_tag>::value;
|
||||
|
||||
typedef adjacency_list<vecS, vecS, directedS,
|
||||
property< vertex_distance_t, DT>,
|
||||
property< edge_weight_t, DT,
|
||||
property< edge_weight2_t, DT > > > Graph2;
|
||||
typedef graph_traits<Graph2> Traits2;
|
||||
|
||||
Graph2 g2(num_vertices(g1) + 1);
|
||||
typename property_map<Graph2, edge_weight_t>::type
|
||||
w = get(edge_weight, g2);
|
||||
typename property_map<Graph2, edge_weight2_t>::type
|
||||
w_hat = get(edge_weight2, g2);
|
||||
typename property_map<Graph2, vertex_distance_t>::type
|
||||
d = get(vertex_distance, g2);
|
||||
typedef typename property_map<Graph2, vertex_index_t>::type VertexID2;
|
||||
VertexID2 id2 = get(vertex_index, g2);
|
||||
|
||||
// Construct g2 where V[g2] = V[g1] U {s}
|
||||
// and E[g2] = E[g1] U {(s,v)| v in V[g1]}
|
||||
std::vector<typename Traits1::vertex_descriptor>
|
||||
verts1(num_vertices(g1) + 1);
|
||||
typename Traits2::vertex_descriptor s = *vertices(g2).first;
|
||||
{
|
||||
typename Traits1::vertex_iterator v, v_end;
|
||||
int i = 1;
|
||||
for (tie(v, v_end) = vertices(g1); v != v_end; ++v, ++i) {
|
||||
typename Traits2::edge_descriptor e; bool z;
|
||||
tie(e, z) = add_edge(s, get(id1, *v) + 1, g2);
|
||||
put(w, e, zero);
|
||||
verts1[i] = *v;
|
||||
}
|
||||
typename Traits1::edge_iterator e, e_end;
|
||||
for (tie(e, e_end) = edges(g1); e != e_end; ++e) {
|
||||
typename Traits2::edge_descriptor e2; bool z;
|
||||
tie(e2, z) = add_edge(get(id1, source(*e, g1)) + 1,
|
||||
get(id1, target(*e, g1)) + 1, g2);
|
||||
put(w, e2, get(w1, *e));
|
||||
if (is_undirected) {
|
||||
tie(e2, z) = add_edge(get(id1, target(*e, g1)) + 1,
|
||||
get(id1, source(*e, g1)) + 1, g2);
|
||||
put(w, e2, get(w1, *e));
|
||||
}
|
||||
}
|
||||
}
|
||||
typename Traits2::vertex_iterator v, v_end, u, u_end;
|
||||
typename Traits2::edge_iterator e, e_end;
|
||||
std::vector<DT> h_vec(num_vertices(g2));
|
||||
typedef typename std::vector<DT>::iterator iter_t;
|
||||
iterator_property_map<iter_t,VertexID2,DT,DT&> h(h_vec.begin(), id2);
|
||||
|
||||
for (tie(v, v_end) = vertices(g2); v != v_end; ++v)
|
||||
d[*v] = inf;
|
||||
|
||||
put(d, s, zero);
|
||||
// Using the non-named parameter versions of bellman_ford and
|
||||
// dijkstra for portability reasons.
|
||||
dummy_property_map pred; bellman_visitor<> bvis;
|
||||
if (bellman_ford_shortest_paths
|
||||
(g2, num_vertices(g2), w, pred, d, combine, compare, bvis)) {
|
||||
for (tie(v, v_end) = vertices(g2); v != v_end; ++v)
|
||||
put(h, *v, get(d, *v));
|
||||
// Reweight the edges to remove negatives
|
||||
for (tie(e, e_end) = edges(g2); e != e_end; ++e) {
|
||||
typename Traits2::vertex_descriptor a = source(*e, g2),
|
||||
b = target(*e, g2);
|
||||
put(w_hat, *e, combine(get(w, *e), (get(h, a) - get(h, b))));
|
||||
}
|
||||
for (tie(u, u_end) = vertices(g2); u != u_end; ++u) {
|
||||
dijkstra_visitor<> dvis;
|
||||
dijkstra_shortest_paths
|
||||
(g2, *u, pred, d, w_hat, id2, compare, combine, inf, zero,dvis);
|
||||
for (tie(v, v_end) = vertices(g2); v != v_end; ++v) {
|
||||
if (*u != s && *v != s) {
|
||||
typename Traits1::vertex_descriptor u1, v1;
|
||||
u1 = verts1[id2[*u]]; v1 = verts1[id2[*v]];
|
||||
D[id2[*u]-1][id2[*v]-1] = combine(get(d, *v), (get(h, *v) - get(h, *u)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix,
|
||||
class VertexID, class Weight, class DistanceZero>
|
||||
bool
|
||||
johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g1,
|
||||
DistanceMatrix& D,
|
||||
VertexID id1, Weight w1, DistanceZero zero)
|
||||
{
|
||||
typedef typename property_traits<Weight>::value_type WT;
|
||||
return johnson_all_pairs_shortest_paths(g1, D, id1, w1,
|
||||
std::less<WT>(),
|
||||
closed_plus<WT>(),
|
||||
(std::numeric_limits<WT>::max)(),
|
||||
zero);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix,
|
||||
class P, class T, class R, class Weight,
|
||||
class VertexID>
|
||||
bool
|
||||
johnson_dispatch(VertexAndEdgeListGraph& g,
|
||||
DistanceMatrix& D,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
Weight w, VertexID id)
|
||||
{
|
||||
typedef typename property_traits<Weight>::value_type WT;
|
||||
|
||||
return johnson_all_pairs_shortest_paths
|
||||
(g, D, id, w,
|
||||
choose_param(get_param(params, distance_compare_t()),
|
||||
std::less<WT>()),
|
||||
choose_param(get_param(params, distance_combine_t()),
|
||||
closed_plus<WT>()),
|
||||
choose_param(get_param(params, distance_inf_t()),
|
||||
std::numeric_limits<WT>::max BOOST_PREVENT_MACRO_SUBSTITUTION()),
|
||||
choose_param(get_param(params, distance_zero_t()), WT()) );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix,
|
||||
class P, class T, class R>
|
||||
bool
|
||||
johnson_all_pairs_shortest_paths
|
||||
(VertexAndEdgeListGraph& g,
|
||||
DistanceMatrix& D,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return detail::johnson_dispatch
|
||||
(g, D, params,
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index)
|
||||
);
|
||||
}
|
||||
|
||||
template <class VertexAndEdgeListGraph, class DistanceMatrix>
|
||||
bool
|
||||
johnson_all_pairs_shortest_paths
|
||||
(VertexAndEdgeListGraph& g, DistanceMatrix& D)
|
||||
{
|
||||
bgl_named_params<int,int> params(1);
|
||||
return detail::johnson_dispatch
|
||||
(g, D, params, get(edge_weight, g), get(vertex_index, g));
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_JOHNSON_HPP
|
||||
|
||||
|
||||
542
libraries/include/boost/graph/kamada_kawai_spring_layout.hpp
Normal file
542
libraries/include/boost/graph/kamada_kawai_spring_layout.hpp
Normal file
@@ -0,0 +1,542 @@
|
||||
// Copyright 2004 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: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP
|
||||
#define BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/johnson_all_pairs_shortest.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail { namespace graph {
|
||||
/**
|
||||
* Denotes an edge or display area side length used to scale a
|
||||
* Kamada-Kawai drawing.
|
||||
*/
|
||||
template<bool Edge, typename T>
|
||||
struct edge_or_side
|
||||
{
|
||||
explicit edge_or_side(T value) : value(value) {}
|
||||
|
||||
T value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute the edge length from an edge length. This is trivial.
|
||||
*/
|
||||
template<typename Graph, typename DistanceMap, typename IndexMap,
|
||||
typename T>
|
||||
T compute_edge_length(const Graph&, DistanceMap, IndexMap,
|
||||
edge_or_side<true, T> length)
|
||||
{ return length.value; }
|
||||
|
||||
/**
|
||||
* Compute the edge length based on the display area side
|
||||
length. We do this by dividing the side length by the largest
|
||||
shortest distance between any two vertices in the graph.
|
||||
*/
|
||||
template<typename Graph, typename DistanceMap, typename IndexMap,
|
||||
typename T>
|
||||
T
|
||||
compute_edge_length(const Graph& g, DistanceMap distance, IndexMap index,
|
||||
edge_or_side<false, T> length)
|
||||
{
|
||||
T result(0);
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
|
||||
for (vertex_iterator ui = vertices(g).first, end = vertices(g).second;
|
||||
ui != end; ++ui) {
|
||||
vertex_iterator vi = ui;
|
||||
for (++vi; vi != end; ++vi) {
|
||||
T dij = distance[get(index, *ui)][get(index, *vi)];
|
||||
if (dij > result) result = dij;
|
||||
}
|
||||
}
|
||||
return length.value / result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the Kamada-Kawai spring layout algorithm.
|
||||
*/
|
||||
template<typename Graph, typename PositionMap, typename WeightMap,
|
||||
typename EdgeOrSideLength, typename Done,
|
||||
typename VertexIndexMap, typename DistanceMatrix,
|
||||
typename SpringStrengthMatrix, typename PartialDerivativeMap>
|
||||
struct kamada_kawai_spring_layout_impl
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type weight_type;
|
||||
typedef std::pair<weight_type, weight_type> deriv_type;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor
|
||||
vertex_descriptor;
|
||||
|
||||
kamada_kawai_spring_layout_impl(
|
||||
const Graph& g,
|
||||
PositionMap position,
|
||||
WeightMap weight,
|
||||
EdgeOrSideLength edge_or_side_length,
|
||||
Done done,
|
||||
weight_type spring_constant,
|
||||
VertexIndexMap index,
|
||||
DistanceMatrix distance,
|
||||
SpringStrengthMatrix spring_strength,
|
||||
PartialDerivativeMap partial_derivatives)
|
||||
: g(g), position(position), weight(weight),
|
||||
edge_or_side_length(edge_or_side_length), done(done),
|
||||
spring_constant(spring_constant), index(index), distance(distance),
|
||||
spring_strength(spring_strength),
|
||||
partial_derivatives(partial_derivatives) {}
|
||||
|
||||
// Compute contribution of vertex i to the first partial
|
||||
// derivatives (dE/dx_m, dE/dy_m) (for vertex m)
|
||||
deriv_type
|
||||
compute_partial_derivative(vertex_descriptor m, vertex_descriptor i)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif // BOOST_NO_STDC_NAMESPACE
|
||||
|
||||
deriv_type result(0, 0);
|
||||
if (i != m) {
|
||||
weight_type x_diff = position[m].x - position[i].x;
|
||||
weight_type y_diff = position[m].y - position[i].y;
|
||||
weight_type dist = sqrt(x_diff * x_diff + y_diff * y_diff);
|
||||
result.first = spring_strength[get(index, m)][get(index, i)]
|
||||
* (x_diff - distance[get(index, m)][get(index, i)]*x_diff/dist);
|
||||
result.second = spring_strength[get(index, m)][get(index, i)]
|
||||
* (y_diff - distance[get(index, m)][get(index, i)]*y_diff/dist);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compute partial derivatives dE/dx_m and dE/dy_m
|
||||
deriv_type
|
||||
compute_partial_derivatives(vertex_descriptor m)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif // BOOST_NO_STDC_NAMESPACE
|
||||
|
||||
deriv_type result(0, 0);
|
||||
|
||||
// TBD: looks like an accumulate to me
|
||||
std::pair<vertex_iterator, vertex_iterator> verts = vertices(g);
|
||||
for (/* no init */; verts.first != verts.second; ++verts.first) {
|
||||
vertex_descriptor i = *verts.first;
|
||||
deriv_type deriv = compute_partial_derivative(m, i);
|
||||
result.first += deriv.first;
|
||||
result.second += deriv.second;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// The actual Kamada-Kawai spring layout algorithm implementation
|
||||
bool run()
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::sqrt;
|
||||
#endif // BOOST_NO_STDC_NAMESPACE
|
||||
|
||||
// Compute d_{ij} and place it in the distance matrix
|
||||
if (!johnson_all_pairs_shortest_paths(g, distance, index, weight,
|
||||
weight_type(0)))
|
||||
return false;
|
||||
|
||||
// Compute L based on side length (if needed), or retrieve L
|
||||
weight_type edge_length =
|
||||
detail::graph::compute_edge_length(g, distance, index,
|
||||
edge_or_side_length);
|
||||
|
||||
// Compute l_{ij} and k_{ij}
|
||||
const weight_type K = spring_constant;
|
||||
vertex_iterator ui, end = vertices(g).second;
|
||||
for (ui = vertices(g).first; ui != end; ++ui) {
|
||||
vertex_iterator vi = ui;
|
||||
for (++vi; vi != end; ++vi) {
|
||||
weight_type dij = distance[get(index, *ui)][get(index, *vi)];
|
||||
if (dij == (std::numeric_limits<weight_type>::max)())
|
||||
return false;
|
||||
distance[get(index, *ui)][get(index, *vi)] = edge_length * dij;
|
||||
distance[get(index, *vi)][get(index, *ui)] = edge_length * dij;
|
||||
spring_strength[get(index, *ui)][get(index, *vi)] = K/(dij*dij);
|
||||
spring_strength[get(index, *vi)][get(index, *ui)] = K/(dij*dij);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute Delta_i and find max
|
||||
vertex_descriptor p = *vertices(g).first;
|
||||
weight_type delta_p(0);
|
||||
|
||||
for (ui = vertices(g).first; ui != end; ++ui) {
|
||||
deriv_type deriv = compute_partial_derivatives(*ui);
|
||||
put(partial_derivatives, *ui, deriv);
|
||||
|
||||
weight_type delta =
|
||||
sqrt(deriv.first*deriv.first + deriv.second*deriv.second);
|
||||
|
||||
if (delta > delta_p) {
|
||||
p = *ui;
|
||||
delta_p = delta;
|
||||
}
|
||||
}
|
||||
|
||||
while (!done(delta_p, p, g, true)) {
|
||||
// The contribution p makes to the partial derivatives of
|
||||
// each vertex. Computing this (at O(n) cost) allows us to
|
||||
// update the delta_i values in O(n) time instead of O(n^2)
|
||||
// time.
|
||||
std::vector<deriv_type> p_partials(num_vertices(g));
|
||||
for (ui = vertices(g).first; ui != end; ++ui) {
|
||||
vertex_descriptor i = *ui;
|
||||
p_partials[get(index, i)] = compute_partial_derivative(i, p);
|
||||
}
|
||||
|
||||
do {
|
||||
// Compute the 4 elements of the Jacobian
|
||||
weight_type dE_dx_dx = 0, dE_dx_dy = 0, dE_dy_dx = 0, dE_dy_dy = 0;
|
||||
for (ui = vertices(g).first; ui != end; ++ui) {
|
||||
vertex_descriptor i = *ui;
|
||||
if (i != p) {
|
||||
weight_type x_diff = position[p].x - position[i].x;
|
||||
weight_type y_diff = position[p].y - position[i].y;
|
||||
weight_type dist = sqrt(x_diff * x_diff + y_diff * y_diff);
|
||||
weight_type dist_cubed = dist * dist * dist;
|
||||
weight_type k_mi = spring_strength[get(index,p)][get(index,i)];
|
||||
weight_type l_mi = distance[get(index, p)][get(index, i)];
|
||||
dE_dx_dx += k_mi * (1 - (l_mi * y_diff * y_diff)/dist_cubed);
|
||||
dE_dx_dy += k_mi * l_mi * x_diff * y_diff / dist_cubed;
|
||||
dE_dy_dx += k_mi * l_mi * x_diff * y_diff / dist_cubed;
|
||||
dE_dy_dy += k_mi * (1 - (l_mi * x_diff * x_diff)/dist_cubed);
|
||||
}
|
||||
}
|
||||
|
||||
// Solve for delta_x and delta_y
|
||||
weight_type dE_dx = get(partial_derivatives, p).first;
|
||||
weight_type dE_dy = get(partial_derivatives, p).second;
|
||||
|
||||
weight_type delta_x =
|
||||
(dE_dx_dy * dE_dy - dE_dy_dy * dE_dx)
|
||||
/ (dE_dx_dx * dE_dy_dy - dE_dx_dy * dE_dy_dx);
|
||||
|
||||
weight_type delta_y =
|
||||
(dE_dx_dx * dE_dy - dE_dy_dx * dE_dx)
|
||||
/ (dE_dy_dx * dE_dx_dy - dE_dx_dx * dE_dy_dy);
|
||||
|
||||
|
||||
// Move p by (delta_x, delta_y)
|
||||
position[p].x += delta_x;
|
||||
position[p].y += delta_y;
|
||||
|
||||
// Recompute partial derivatives and delta_p
|
||||
deriv_type deriv = compute_partial_derivatives(p);
|
||||
put(partial_derivatives, p, deriv);
|
||||
|
||||
delta_p =
|
||||
sqrt(deriv.first*deriv.first + deriv.second*deriv.second);
|
||||
} while (!done(delta_p, p, g, false));
|
||||
|
||||
// Select new p by updating each partial derivative and delta
|
||||
vertex_descriptor old_p = p;
|
||||
for (ui = vertices(g).first; ui != end; ++ui) {
|
||||
deriv_type old_deriv_p = p_partials[get(index, *ui)];
|
||||
deriv_type old_p_partial =
|
||||
compute_partial_derivative(*ui, old_p);
|
||||
deriv_type deriv = get(partial_derivatives, *ui);
|
||||
|
||||
deriv.first += old_p_partial.first - old_deriv_p.first;
|
||||
deriv.second += old_p_partial.second - old_deriv_p.second;
|
||||
|
||||
put(partial_derivatives, *ui, deriv);
|
||||
weight_type delta =
|
||||
sqrt(deriv.first*deriv.first + deriv.second*deriv.second);
|
||||
|
||||
if (delta > delta_p) {
|
||||
p = *ui;
|
||||
delta_p = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const Graph& g;
|
||||
PositionMap position;
|
||||
WeightMap weight;
|
||||
EdgeOrSideLength edge_or_side_length;
|
||||
Done done;
|
||||
weight_type spring_constant;
|
||||
VertexIndexMap index;
|
||||
DistanceMatrix distance;
|
||||
SpringStrengthMatrix spring_strength;
|
||||
PartialDerivativeMap partial_derivatives;
|
||||
};
|
||||
} } // end namespace detail::graph
|
||||
|
||||
/// States that the given quantity is an edge length.
|
||||
template<typename T>
|
||||
inline detail::graph::edge_or_side<true, T>
|
||||
edge_length(T x)
|
||||
{ return detail::graph::edge_or_side<true, T>(x); }
|
||||
|
||||
/// States that the given quantity is a display area side length.
|
||||
template<typename T>
|
||||
inline detail::graph::edge_or_side<false, T>
|
||||
side_length(T x)
|
||||
{ return detail::graph::edge_or_side<false, T>(x); }
|
||||
|
||||
/**
|
||||
* \brief Determines when to terminate layout of a particular graph based
|
||||
* on a given relative tolerance.
|
||||
*/
|
||||
template<typename T = double>
|
||||
struct layout_tolerance
|
||||
{
|
||||
layout_tolerance(const T& tolerance = T(0.001))
|
||||
: tolerance(tolerance), last_energy((std::numeric_limits<T>::max)()),
|
||||
last_local_energy((std::numeric_limits<T>::max)()) { }
|
||||
|
||||
template<typename Graph>
|
||||
bool
|
||||
operator()(T delta_p,
|
||||
typename boost::graph_traits<Graph>::vertex_descriptor p,
|
||||
const Graph& g,
|
||||
bool global)
|
||||
{
|
||||
if (global) {
|
||||
if (last_energy == (std::numeric_limits<T>::max)()) {
|
||||
last_energy = delta_p;
|
||||
return false;
|
||||
}
|
||||
|
||||
T diff = last_energy - delta_p;
|
||||
if (diff < T(0)) diff = -diff;
|
||||
bool done = (delta_p == T(0) || diff / last_energy < tolerance);
|
||||
last_energy = delta_p;
|
||||
return done;
|
||||
} else {
|
||||
if (last_local_energy == (std::numeric_limits<T>::max)()) {
|
||||
last_local_energy = delta_p;
|
||||
return delta_p == T(0);
|
||||
}
|
||||
|
||||
T diff = last_local_energy - delta_p;
|
||||
bool done = (delta_p == T(0) || (diff / last_local_energy) < tolerance);
|
||||
last_local_energy = delta_p;
|
||||
return done;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T tolerance;
|
||||
T last_energy;
|
||||
T last_local_energy;
|
||||
};
|
||||
|
||||
/** \brief Kamada-Kawai spring layout for undirected graphs.
|
||||
*
|
||||
* This algorithm performs graph layout (in two dimensions) for
|
||||
* connected, undirected graphs. It operates by relating the layout
|
||||
* of graphs to a dynamic spring system and minimizing the energy
|
||||
* within that system. The strength of a spring between two vertices
|
||||
* is inversely proportional to the square of the shortest distance
|
||||
* (in graph terms) between those two vertices. Essentially,
|
||||
* vertices that are closer in the graph-theoretic sense (i.e., by
|
||||
* following edges) will have stronger springs and will therefore be
|
||||
* placed closer together.
|
||||
*
|
||||
* Prior to invoking this algorithm, it is recommended that the
|
||||
* vertices be placed along the vertices of a regular n-sided
|
||||
* polygon.
|
||||
*
|
||||
* \param g (IN) must be a model of Vertex List Graph, Edge List
|
||||
* Graph, and Incidence Graph and must be undirected.
|
||||
*
|
||||
* \param position (OUT) must be a model of Lvalue Property Map,
|
||||
* where the value type is a class containing fields @c x and @c y
|
||||
* that will be set to the @c x and @c y coordinates of each vertex.
|
||||
*
|
||||
* \param weight (IN) must be a model of Readable Property Map,
|
||||
* which provides the weight of each edge in the graph @p g.
|
||||
*
|
||||
* \param edge_or_side_length (IN) provides either the unit length
|
||||
* @c e of an edge in the layout or the length of a side @c s of the
|
||||
* display area, and must be either @c boost::edge_length(e) or @c
|
||||
* boost::side_length(s), respectively.
|
||||
*
|
||||
* \param done (IN) is a 4-argument function object that is passed
|
||||
* the current value of delta_p (i.e., the energy of vertex @p p),
|
||||
* the vertex @p p, the graph @p g, and a boolean flag indicating
|
||||
* whether @p delta_p is the maximum energy in the system (when @c
|
||||
* true) or the energy of the vertex being moved. Defaults to @c
|
||||
* layout_tolerance instantiated over the value type of the weight
|
||||
* map.
|
||||
*
|
||||
* \param spring_constant (IN) is the constant multiplied by each
|
||||
* spring's strength. Larger values create systems with more energy
|
||||
* that can take longer to stabilize; smaller values create systems
|
||||
* with less energy that stabilize quickly but do not necessarily
|
||||
* result in pleasing layouts. The default value is 1.
|
||||
*
|
||||
* \param index (IN) is a mapping from vertices to index values
|
||||
* between 0 and @c num_vertices(g). The default is @c
|
||||
* get(vertex_index,g).
|
||||
*
|
||||
* \param distance (UTIL/OUT) will be used to store the distance
|
||||
* from every vertex to every other vertex, which is computed in the
|
||||
* first stages of the algorithm. This value's type must be a model
|
||||
* of BasicMatrix with value type equal to the value type of the
|
||||
* weight map. The default is a a vector of vectors.
|
||||
*
|
||||
* \param spring_strength (UTIL/OUT) will be used to store the
|
||||
* strength of the spring between every pair of vertices. This
|
||||
* value's type must be a model of BasicMatrix with value type equal
|
||||
* to the value type of the weight map. The default is a a vector of
|
||||
* vectors.
|
||||
*
|
||||
* \param partial_derivatives (UTIL) will be used to store the
|
||||
* partial derivates of each vertex with respect to the @c x and @c
|
||||
* y coordinates. This must be a Read/Write Property Map whose value
|
||||
* type is a pair with both types equivalent to the value type of
|
||||
* the weight map. The default is an iterator property map.
|
||||
*
|
||||
* \returns @c true if layout was successful or @c false if a
|
||||
* negative weight cycle was detected.
|
||||
*/
|
||||
template<typename Graph, typename PositionMap, typename WeightMap,
|
||||
typename T, bool EdgeOrSideLength, typename Done,
|
||||
typename VertexIndexMap, typename DistanceMatrix,
|
||||
typename SpringStrengthMatrix, typename PartialDerivativeMap>
|
||||
bool
|
||||
kamada_kawai_spring_layout(
|
||||
const Graph& g,
|
||||
PositionMap position,
|
||||
WeightMap weight,
|
||||
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
|
||||
Done done,
|
||||
typename property_traits<WeightMap>::value_type spring_constant,
|
||||
VertexIndexMap index,
|
||||
DistanceMatrix distance,
|
||||
SpringStrengthMatrix spring_strength,
|
||||
PartialDerivativeMap partial_derivatives)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((is_convertible<
|
||||
typename graph_traits<Graph>::directed_category*,
|
||||
undirected_tag*
|
||||
>::value));
|
||||
|
||||
detail::graph::kamada_kawai_spring_layout_impl<
|
||||
Graph, PositionMap, WeightMap,
|
||||
detail::graph::edge_or_side<EdgeOrSideLength, T>, Done, VertexIndexMap,
|
||||
DistanceMatrix, SpringStrengthMatrix, PartialDerivativeMap>
|
||||
alg(g, position, weight, edge_or_side_length, done, spring_constant,
|
||||
index, distance, spring_strength, partial_derivatives);
|
||||
return alg.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
template<typename Graph, typename PositionMap, typename WeightMap,
|
||||
typename T, bool EdgeOrSideLength, typename Done,
|
||||
typename VertexIndexMap>
|
||||
bool
|
||||
kamada_kawai_spring_layout(
|
||||
const Graph& g,
|
||||
PositionMap position,
|
||||
WeightMap weight,
|
||||
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
|
||||
Done done,
|
||||
typename property_traits<WeightMap>::value_type spring_constant,
|
||||
VertexIndexMap index)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type weight_type;
|
||||
|
||||
typename graph_traits<Graph>::vertices_size_type n = num_vertices(g);
|
||||
typedef std::vector<weight_type> weight_vec;
|
||||
|
||||
std::vector<weight_vec> distance(n, weight_vec(n));
|
||||
std::vector<weight_vec> spring_strength(n, weight_vec(n));
|
||||
std::vector<std::pair<weight_type, weight_type> > partial_derivatives(n);
|
||||
|
||||
return
|
||||
kamada_kawai_spring_layout(
|
||||
g, position, weight, edge_or_side_length, done, spring_constant, index,
|
||||
distance.begin(),
|
||||
spring_strength.begin(),
|
||||
make_iterator_property_map(partial_derivatives.begin(), index,
|
||||
std::pair<weight_type, weight_type>()));
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
template<typename Graph, typename PositionMap, typename WeightMap,
|
||||
typename T, bool EdgeOrSideLength, typename Done>
|
||||
bool
|
||||
kamada_kawai_spring_layout(
|
||||
const Graph& g,
|
||||
PositionMap position,
|
||||
WeightMap weight,
|
||||
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
|
||||
Done done,
|
||||
typename property_traits<WeightMap>::value_type spring_constant)
|
||||
{
|
||||
return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length,
|
||||
done, spring_constant,
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
template<typename Graph, typename PositionMap, typename WeightMap,
|
||||
typename T, bool EdgeOrSideLength, typename Done>
|
||||
bool
|
||||
kamada_kawai_spring_layout(
|
||||
const Graph& g,
|
||||
PositionMap position,
|
||||
WeightMap weight,
|
||||
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
|
||||
Done done)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type weight_type;
|
||||
return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length,
|
||||
done, weight_type(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* \overload
|
||||
*/
|
||||
template<typename Graph, typename PositionMap, typename WeightMap,
|
||||
typename T, bool EdgeOrSideLength>
|
||||
bool
|
||||
kamada_kawai_spring_layout(
|
||||
const Graph& g,
|
||||
PositionMap position,
|
||||
WeightMap weight,
|
||||
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type weight_type;
|
||||
return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length,
|
||||
layout_tolerance<weight_type>(),
|
||||
weight_type(1.0),
|
||||
get(vertex_index, g));
|
||||
}
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP
|
||||
320
libraries/include/boost/graph/king_ordering.hpp
Normal file
320
libraries/include/boost/graph/king_ordering.hpp
Normal file
@@ -0,0 +1,320 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Copyright 2004, 2005 Trustees of Indiana University
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek,
|
||||
// Doug Gregor, D. Kevin McGrath
|
||||
//
|
||||
// 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_KING_HPP
|
||||
#define BOOST_GRAPH_KING_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/detail/sparse_ordering.hpp>
|
||||
|
||||
/*
|
||||
King Algorithm for matrix reordering
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
template<typename OutputIterator, typename Buffer, typename Compare,
|
||||
typename PseudoDegreeMap, typename VecMap, typename VertexIndexMap>
|
||||
class bfs_king_visitor:public default_bfs_visitor
|
||||
{
|
||||
public:
|
||||
bfs_king_visitor(OutputIterator *iter, Buffer *b, Compare compare,
|
||||
PseudoDegreeMap deg, std::vector<int> loc, VecMap color,
|
||||
VertexIndexMap vertices):
|
||||
permutation(iter), Qptr(b), degree(deg), comp(compare),
|
||||
Qlocation(loc), colors(color), vertex_map(vertices) { }
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void finish_vertex(Vertex, Graph& g) {
|
||||
typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
|
||||
Vertex v, w;
|
||||
|
||||
typedef typename std::deque<Vertex>::iterator iterator;
|
||||
typedef typename std::deque<Vertex>::reverse_iterator reverse_iterator;
|
||||
|
||||
reverse_iterator rend = Qptr->rend()-index_begin;
|
||||
reverse_iterator rbegin = Qptr->rbegin();
|
||||
|
||||
|
||||
//heap the vertices already there
|
||||
std::make_heap(rbegin, rend, boost::bind<bool>(comp, _2, _1));
|
||||
|
||||
unsigned i = 0;
|
||||
|
||||
for(i = index_begin; i != Qptr->size(); ++i){
|
||||
colors[get(vertex_map, (*Qptr)[i])] = 1;
|
||||
Qlocation[get(vertex_map, (*Qptr)[i])] = i;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
for( ; rbegin != rend; rend--){
|
||||
percolate_down<Vertex>(i);
|
||||
w = (*Qptr)[index_begin+i];
|
||||
for (tie(ei, ei_end) = out_edges(w, g); ei != ei_end; ++ei) {
|
||||
v = target(*ei, g);
|
||||
put(degree, v, get(degree, v) - 1);
|
||||
|
||||
if (colors[get(vertex_map, v)] == 1) {
|
||||
percolate_up<Vertex>(get(vertex_map, v), i);
|
||||
}
|
||||
}
|
||||
|
||||
colors[get(vertex_map, w)] = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void examine_vertex(Vertex u, const Graph&) {
|
||||
|
||||
*(*permutation)++ = u;
|
||||
index_begin = Qptr->size();
|
||||
|
||||
}
|
||||
protected:
|
||||
|
||||
|
||||
//this function replaces pop_heap, and tracks state information
|
||||
template <typename Vertex>
|
||||
void percolate_down(int offset){
|
||||
typedef typename std::deque<Vertex>::reverse_iterator reverse_iterator;
|
||||
|
||||
int heap_last = index_begin + offset;
|
||||
int heap_first = Qptr->size() - 1;
|
||||
|
||||
//pop_heap functionality:
|
||||
//swap first, last
|
||||
std::swap((*Qptr)[heap_last], (*Qptr)[heap_first]);
|
||||
|
||||
//swap in the location queue
|
||||
std::swap(Qlocation[heap_first], Qlocation[heap_last]);
|
||||
|
||||
//set drifter, children
|
||||
int drifter = heap_first;
|
||||
int drifter_heap = Qptr->size() - drifter;
|
||||
|
||||
int right_child_heap = drifter_heap * 2 + 1;
|
||||
int right_child = Qptr->size() - right_child_heap;
|
||||
|
||||
int left_child_heap = drifter_heap * 2;
|
||||
int left_child = Qptr->size() - left_child_heap;
|
||||
|
||||
//check that we are staying in the heap
|
||||
bool valid = (right_child < heap_last) ? false : true;
|
||||
|
||||
//pick smallest child of drifter, and keep in mind there might only be left child
|
||||
int smallest_child = (valid && get(degree, (*Qptr)[left_child]) > get(degree,(*Qptr)[right_child])) ?
|
||||
right_child : left_child;
|
||||
|
||||
while(valid && smallest_child < heap_last && comp((*Qptr)[drifter], (*Qptr)[smallest_child])){
|
||||
|
||||
//if smallest child smaller than drifter, swap them
|
||||
std::swap((*Qptr)[smallest_child], (*Qptr)[drifter]);
|
||||
std::swap(Qlocation[drifter], Qlocation[smallest_child]);
|
||||
|
||||
//update the values, run again, as necessary
|
||||
drifter = smallest_child;
|
||||
drifter_heap = Qptr->size() - drifter;
|
||||
|
||||
right_child_heap = drifter_heap * 2 + 1;
|
||||
right_child = Qptr->size() - right_child_heap;
|
||||
|
||||
left_child_heap = drifter_heap * 2;
|
||||
left_child = Qptr->size() - left_child_heap;
|
||||
|
||||
valid = (right_child < heap_last) ? false : true;
|
||||
|
||||
smallest_child = (valid && get(degree, (*Qptr)[left_child]) > get(degree,(*Qptr)[right_child])) ?
|
||||
right_child : left_child;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// this is like percolate down, but we always compare against the
|
||||
// parent, as there is only a single choice
|
||||
template <typename Vertex>
|
||||
void percolate_up(int vertex, int offset){
|
||||
|
||||
int child_location = Qlocation[vertex];
|
||||
int heap_child_location = Qptr->size() - child_location;
|
||||
int heap_parent_location = (int)(heap_child_location/2);
|
||||
unsigned parent_location = Qptr->size() - heap_parent_location;
|
||||
|
||||
bool valid = (heap_parent_location != 0 && child_location > index_begin + offset &&
|
||||
parent_location < Qptr->size());
|
||||
|
||||
while(valid && comp((*Qptr)[child_location], (*Qptr)[parent_location])){
|
||||
|
||||
//swap in the heap
|
||||
std::swap((*Qptr)[child_location], (*Qptr)[parent_location]);
|
||||
|
||||
//swap in the location queue
|
||||
std::swap(Qlocation[child_location], Qlocation[parent_location]);
|
||||
|
||||
child_location = parent_location;
|
||||
heap_child_location = heap_parent_location;
|
||||
heap_parent_location = (int)(heap_child_location/2);
|
||||
parent_location = Qptr->size() - heap_parent_location;
|
||||
valid = (heap_parent_location != 0 && child_location > index_begin + offset);
|
||||
}
|
||||
}
|
||||
|
||||
OutputIterator *permutation;
|
||||
int index_begin;
|
||||
Buffer *Qptr;
|
||||
PseudoDegreeMap degree;
|
||||
Compare comp;
|
||||
std::vector<int> Qlocation;
|
||||
VecMap colors;
|
||||
VertexIndexMap vertex_map;
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template<class Graph, class OutputIterator, class ColorMap, class DegreeMap,
|
||||
typename VertexIndexMap>
|
||||
OutputIterator
|
||||
king_ordering(const Graph& g,
|
||||
std::deque< typename graph_traits<Graph>::vertex_descriptor >
|
||||
vertex_queue,
|
||||
OutputIterator permutation,
|
||||
ColorMap color, DegreeMap degree,
|
||||
VertexIndexMap index_map)
|
||||
{
|
||||
typedef typename property_traits<DegreeMap>::value_type ds_type;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef iterator_property_map<typename std::vector<ds_type>::iterator, VertexIndexMap, ds_type, ds_type&> PseudoDegreeMap;
|
||||
typedef indirect_cmp<PseudoDegreeMap, std::less<ds_type> > Compare;
|
||||
typedef typename boost::sparse::sparse_ordering_queue<Vertex> queue;
|
||||
typedef typename detail::bfs_king_visitor<OutputIterator, queue, Compare,
|
||||
PseudoDegreeMap, std::vector<int>, VertexIndexMap > Visitor;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type
|
||||
vertices_size_type;
|
||||
std::vector<ds_type> pseudo_degree_vec(num_vertices(g));
|
||||
PseudoDegreeMap pseudo_degree(pseudo_degree_vec.begin(), index_map);
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
queue Q;
|
||||
// Copy degree to pseudo_degree
|
||||
// initialize the color map
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui){
|
||||
put(pseudo_degree, *ui, get(degree, *ui));
|
||||
put(color, *ui, Color::white());
|
||||
}
|
||||
|
||||
Compare comp(pseudo_degree);
|
||||
std::vector<int> colors(num_vertices(g));
|
||||
|
||||
for(vertices_size_type i = 0; i < num_vertices(g); i++)
|
||||
colors[i] = 0;
|
||||
|
||||
std::vector<int> loc(num_vertices(g));
|
||||
|
||||
//create the visitor
|
||||
Visitor vis(&permutation, &Q, comp, pseudo_degree, loc, colors, index_map);
|
||||
|
||||
while( !vertex_queue.empty() ) {
|
||||
Vertex s = vertex_queue.front();
|
||||
vertex_queue.pop_front();
|
||||
|
||||
//call BFS with visitor
|
||||
breadth_first_visit(g, s, Q, vis, color);
|
||||
}
|
||||
|
||||
return permutation;
|
||||
}
|
||||
|
||||
|
||||
// This is the case where only a single starting vertex is supplied.
|
||||
template <class Graph, class OutputIterator,
|
||||
class ColorMap, class DegreeMap, typename VertexIndexMap>
|
||||
OutputIterator
|
||||
king_ordering(const Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
OutputIterator permutation,
|
||||
ColorMap color, DegreeMap degree, VertexIndexMap index_map)
|
||||
{
|
||||
|
||||
std::deque< typename graph_traits<Graph>::vertex_descriptor > vertex_queue;
|
||||
vertex_queue.push_front( s );
|
||||
return king_ordering(g, vertex_queue, permutation, color, degree,
|
||||
index_map);
|
||||
}
|
||||
|
||||
|
||||
template < class Graph, class OutputIterator,
|
||||
class ColorMap, class DegreeMap, class VertexIndexMap>
|
||||
OutputIterator
|
||||
king_ordering(const Graph& G, OutputIterator permutation,
|
||||
ColorMap color, DegreeMap degree, VertexIndexMap index_map)
|
||||
{
|
||||
if (vertices(G).first == vertices(G).second)
|
||||
return permutation;
|
||||
|
||||
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename boost::graph_traits<Graph>::vertex_iterator VerIter;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
std::deque<Vertex> vertex_queue;
|
||||
|
||||
// Mark everything white
|
||||
BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white());
|
||||
|
||||
// Find one vertex from each connected component
|
||||
BGL_FORALL_VERTICES_T(v, G, Graph) {
|
||||
if (get(color, v) == Color::white()) {
|
||||
depth_first_visit(G, v, dfs_visitor<>(), color);
|
||||
vertex_queue.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
// Find starting nodes for all vertices
|
||||
// TBD: How to do this with a directed graph?
|
||||
for (typename std::deque<Vertex>::iterator i = vertex_queue.begin();
|
||||
i != vertex_queue.end(); ++i)
|
||||
*i = find_starting_node(G, *i, color, degree);
|
||||
|
||||
return king_ordering(G, vertex_queue, permutation, color, degree,
|
||||
index_map);
|
||||
}
|
||||
|
||||
template<typename Graph, typename OutputIterator, typename VertexIndexMap>
|
||||
OutputIterator
|
||||
king_ordering(const Graph& G, OutputIterator permutation,
|
||||
VertexIndexMap index_map)
|
||||
{
|
||||
if (vertices(G).first == vertices(G).second)
|
||||
return permutation;
|
||||
|
||||
typedef out_degree_property_map<Graph> DegreeMap;
|
||||
std::vector<default_color_type> colors(num_vertices(G));
|
||||
return king_ordering(G, permutation,
|
||||
make_iterator_property_map(&colors[0], index_map,
|
||||
colors[0]),
|
||||
make_out_degree_map(G), index_map);
|
||||
}
|
||||
|
||||
template<typename Graph, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
king_ordering(const Graph& G, OutputIterator permutation)
|
||||
{ return king_ordering(G, permutation, get(vertex_index, G)); }
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_KING_HPP
|
||||
807
libraries/include/boost/graph/kolmogorov_max_flow.hpp
Normal file
807
libraries/include/boost/graph/kolmogorov_max_flow.hpp
Normal file
@@ -0,0 +1,807 @@
|
||||
// Copyright (c) 2006, Stephan Diederich
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// 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_KOLMOGOROV_MAX_FLOW_HPP
|
||||
#define BOOST_KOLMOGOROV_MAX_FLOW_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <iosfwd>
|
||||
#include <algorithm> // for std::min and std::max
|
||||
|
||||
#include <boost/pending/queue.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/none_t.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template <class Graph,
|
||||
class EdgeCapacityMap,
|
||||
class ResidualCapacityEdgeMap,
|
||||
class ReverseEdgeMap,
|
||||
class PredecessorMap,
|
||||
class ColorMap,
|
||||
class DistanceMap,
|
||||
class IndexMap>
|
||||
class kolmogorov{
|
||||
typedef typename property_traits<EdgeCapacityMap>::value_type tEdgeVal;
|
||||
typedef graph_traits<Graph> tGraphTraits;
|
||||
typedef typename tGraphTraits::vertex_iterator vertex_iterator;
|
||||
typedef typename tGraphTraits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename tGraphTraits::edge_descriptor edge_descriptor;
|
||||
typedef typename tGraphTraits::edge_iterator edge_iterator;
|
||||
typedef typename tGraphTraits::out_edge_iterator out_edge_iterator;
|
||||
typedef boost::queue<vertex_descriptor> tQueue; //queue of vertices, used in adoption-stage
|
||||
typedef typename property_traits<ColorMap>::value_type tColorValue;
|
||||
typedef color_traits<tColorValue> tColorTraits;
|
||||
typedef typename property_traits<DistanceMap>::value_type tDistanceVal;
|
||||
|
||||
public:
|
||||
kolmogorov(Graph& g,
|
||||
EdgeCapacityMap cap,
|
||||
ResidualCapacityEdgeMap res,
|
||||
ReverseEdgeMap rev,
|
||||
PredecessorMap pre,
|
||||
ColorMap color,
|
||||
DistanceMap dist,
|
||||
IndexMap idx,
|
||||
vertex_descriptor src,
|
||||
vertex_descriptor sink):
|
||||
m_g(g),
|
||||
m_index_map(idx),
|
||||
m_cap_map(cap),
|
||||
m_res_cap_map(res),
|
||||
m_rev_edge_map(rev),
|
||||
m_pre_map(pre),
|
||||
m_tree_map(color),
|
||||
m_dist_map(dist),
|
||||
m_source(src),
|
||||
m_sink(sink),
|
||||
m_active_nodes(),
|
||||
m_in_active_list_vec(num_vertices(g), false),
|
||||
m_in_active_list_map(make_iterator_property_map(m_in_active_list_vec.begin(), m_index_map)),
|
||||
m_has_parent_vec(num_vertices(g), false),
|
||||
m_has_parent_map(make_iterator_property_map(m_has_parent_vec.begin(), m_index_map)),
|
||||
m_time_vec(num_vertices(g), 0),
|
||||
m_time_map(make_iterator_property_map(m_time_vec.begin(), m_index_map)),
|
||||
m_flow(0),
|
||||
m_time(1),
|
||||
m_last_grow_vertex(graph_traits<Graph>::null_vertex()){
|
||||
// initialize the color-map with gray-values
|
||||
vertex_iterator vi, v_end;
|
||||
for(tie(vi, v_end) = vertices(m_g); vi != v_end; ++vi){
|
||||
set_tree(*vi, tColorTraits::gray());
|
||||
}
|
||||
// Initialize flow to zero which means initializing
|
||||
// the residual capacity equal to the capacity
|
||||
edge_iterator ei, e_end;
|
||||
for(tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) {
|
||||
m_res_cap_map[*ei] = m_cap_map[*ei];
|
||||
assert(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly
|
||||
}
|
||||
//init the search trees with the two terminals
|
||||
set_tree(m_source, tColorTraits::black());
|
||||
set_tree(m_sink, tColorTraits::white());
|
||||
m_time_map[m_source] = 1;
|
||||
m_time_map[m_sink] = 1;
|
||||
}
|
||||
|
||||
~kolmogorov(){}
|
||||
|
||||
tEdgeVal max_flow(){
|
||||
//augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK
|
||||
augment_direct_paths();
|
||||
//start the main-loop
|
||||
while(true){
|
||||
bool path_found;
|
||||
edge_descriptor connecting_edge;
|
||||
tie(connecting_edge, path_found) = grow(); //find a path from source to sink
|
||||
if(!path_found){
|
||||
//we're finished, no more paths were found
|
||||
break;
|
||||
}
|
||||
++m_time;
|
||||
augment(connecting_edge); //augment that path
|
||||
adopt(); //rebuild search tree structure
|
||||
}
|
||||
return m_flow;
|
||||
}
|
||||
|
||||
//the complete class is protected, as we want access to members in derived test-class (see $(BOOST_ROOT)/libs/graph/test/kolmogorov_max_flow_test.cpp)
|
||||
protected:
|
||||
void augment_direct_paths(){
|
||||
//in a first step, we augment all direct paths from source->NODE->sink
|
||||
//and additionally paths from source->sink
|
||||
//this improves especially graphcuts for segmentation, as most of the nodes have source/sink connects
|
||||
//but shouldn't have an impact on other maxflow problems (this is done in grow() anyway)
|
||||
out_edge_iterator ei, e_end;
|
||||
for(tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end; ++ei){
|
||||
edge_descriptor from_source = *ei;
|
||||
vertex_descriptor current_node = target(from_source, m_g);
|
||||
if(current_node == m_sink){
|
||||
tEdgeVal cap = m_res_cap_map[from_source];
|
||||
m_res_cap_map[from_source] = 0;
|
||||
m_flow += cap;
|
||||
continue;
|
||||
}
|
||||
edge_descriptor to_sink;
|
||||
bool is_there;
|
||||
tie(to_sink, is_there) = edge(current_node, m_sink, m_g);
|
||||
if(is_there){
|
||||
tEdgeVal cap_from_source = m_res_cap_map[from_source];
|
||||
tEdgeVal cap_to_sink = m_res_cap_map[to_sink];
|
||||
if(cap_from_source > cap_to_sink){
|
||||
set_tree(current_node, tColorTraits::black());
|
||||
add_active_node(current_node);
|
||||
set_edge_to_parent(current_node, from_source);
|
||||
m_dist_map[current_node] = 1;
|
||||
m_time_map[current_node] = 1;
|
||||
//add stuff to flow and update residuals
|
||||
//we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow
|
||||
m_res_cap_map[from_source] -= cap_to_sink;
|
||||
m_res_cap_map[to_sink] = 0;
|
||||
m_flow += cap_to_sink;
|
||||
} else if(cap_to_sink > 0){
|
||||
set_tree(current_node, tColorTraits::white());
|
||||
add_active_node(current_node);
|
||||
set_edge_to_parent(current_node, to_sink);
|
||||
m_dist_map[current_node] = 1;
|
||||
m_time_map[current_node] = 1;
|
||||
//add stuff to flow and update residuals
|
||||
//we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow
|
||||
m_res_cap_map[to_sink] -= cap_from_source;
|
||||
m_res_cap_map[from_source] = 0;
|
||||
m_flow += cap_from_source;
|
||||
}
|
||||
} else if(m_res_cap_map[from_source]){
|
||||
//there is no sink connect, so we can't augment this path
|
||||
//but to avoid adding m_source to the active nodes, we just activate this node and set the approciate things
|
||||
set_tree(current_node, tColorTraits::black());
|
||||
set_edge_to_parent(current_node, from_source);
|
||||
m_dist_map[current_node] = 1;
|
||||
m_time_map[current_node] = 1;
|
||||
add_active_node(current_node);
|
||||
}
|
||||
}
|
||||
for(tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){
|
||||
edge_descriptor to_sink = m_rev_edge_map[*ei];
|
||||
vertex_descriptor current_node = source(to_sink, m_g);
|
||||
if(m_res_cap_map[to_sink]){
|
||||
set_tree(current_node, tColorTraits::white());
|
||||
set_edge_to_parent(current_node, to_sink);
|
||||
m_dist_map[current_node] = 1;
|
||||
m_time_map[current_node] = 1;
|
||||
add_active_node(current_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a pair of an edge and a boolean. if the bool is true, the edge is a connection of a found path from s->t , read "the link" and
|
||||
* source(returnVal, m_g) is the end of the path found in the source-tree
|
||||
* target(returnVal, m_g) is the beginning of the path found in the sink-tree
|
||||
*/
|
||||
std::pair<edge_descriptor, bool> grow(){
|
||||
assert(m_orphans.empty());
|
||||
vertex_descriptor current_node;
|
||||
while((current_node = get_next_active_node()) != graph_traits<Graph>::null_vertex()){ //if there is one
|
||||
assert(get_tree(current_node) != tColorTraits::gray() && (has_parent(current_node) || current_node==m_source || current_node==m_sink));
|
||||
if(get_tree(current_node) == tColorTraits::black()){
|
||||
//source tree growing
|
||||
out_edge_iterator ei, e_end;
|
||||
if(current_node != m_last_grow_vertex){
|
||||
m_last_grow_vertex = current_node;
|
||||
tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
|
||||
}
|
||||
for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){
|
||||
edge_descriptor out_edge = *m_last_grow_edge_it;
|
||||
if(m_res_cap_map[out_edge] > 0){ //check if we have capacity left on this edge
|
||||
vertex_descriptor other_node = target(out_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
|
||||
set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree
|
||||
set_edge_to_parent(other_node, out_edge); //set us as parent
|
||||
m_dist_map[other_node] = m_dist_map[current_node] + 1; //and update the distance-heuristic
|
||||
m_time_map[other_node] = m_time_map[current_node];
|
||||
add_active_node(other_node);
|
||||
} else if(get_tree(other_node) == tColorTraits::black()){
|
||||
if(is_closer_to_terminal(current_node, other_node)){ //we do this to get shorter paths. check if we are nearer to the source as its parent is
|
||||
set_edge_to_parent(other_node, out_edge);
|
||||
m_dist_map[other_node] = m_dist_map[current_node] + 1;
|
||||
m_time_map[other_node] = m_time_map[current_node];
|
||||
}
|
||||
} else{
|
||||
assert(get_tree(other_node)==tColorTraits::white());
|
||||
//kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir
|
||||
return std::make_pair(out_edge, true);
|
||||
}
|
||||
}
|
||||
} //for all out-edges
|
||||
} //source-tree-growing
|
||||
else{
|
||||
assert(get_tree(current_node) == tColorTraits::white());
|
||||
out_edge_iterator ei, e_end;
|
||||
if(current_node != m_last_grow_vertex){
|
||||
m_last_grow_vertex = current_node;
|
||||
tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
|
||||
}
|
||||
for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){
|
||||
edge_descriptor in_edge = m_rev_edge_map[*m_last_grow_edge_it];
|
||||
if(m_res_cap_map[in_edge] > 0){ //check if there is capacity left
|
||||
vertex_descriptor other_node = source(in_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
|
||||
set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree
|
||||
set_edge_to_parent(other_node, in_edge); //set us as parent
|
||||
add_active_node(other_node); //activate that node
|
||||
m_dist_map[other_node] = m_dist_map[current_node] + 1; //set its distance
|
||||
m_time_map[other_node] = m_time_map[current_node]; //and time
|
||||
} else if(get_tree(other_node) == tColorTraits::white()){
|
||||
if(is_closer_to_terminal(current_node, other_node)){
|
||||
//we are closer to the sink than its parent is, so we "adopt" him
|
||||
set_edge_to_parent(other_node, in_edge);
|
||||
m_dist_map[other_node] = m_dist_map[current_node] + 1;
|
||||
m_time_map[other_node] = m_time_map[current_node];
|
||||
}
|
||||
} else{
|
||||
assert(get_tree(other_node)==tColorTraits::black());
|
||||
//kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir
|
||||
return std::make_pair(in_edge, true);
|
||||
}
|
||||
}
|
||||
} //for all out-edges
|
||||
} //sink-tree growing
|
||||
//all edges of that node are processed, and no more paths were found. so remove if from the front of the active queue
|
||||
finish_node(current_node);
|
||||
} //while active_nodes not empty
|
||||
return std::make_pair(edge_descriptor(), false); //no active nodes anymore and no path found, we're done
|
||||
}
|
||||
|
||||
/**
|
||||
* augments path from s->t and updates residual graph
|
||||
* source(e, m_g) is the end of the path found in the source-tree
|
||||
* target(e, m_g) is the beginning of the path found in the sink-tree
|
||||
* this phase generates orphans on satured edges, if the attached verts are from different search-trees
|
||||
* orphans are ordered in distance to sink/source. first the farest from the source are front_inserted into the orphans list,
|
||||
* and after that the sink-tree-orphans are front_inserted. when going to adoption stage the orphans are popped_front, and so we process the nearest
|
||||
* verts to the terminals first
|
||||
*/
|
||||
void augment(edge_descriptor e){
|
||||
assert(get_tree(target(e, m_g)) == tColorTraits::white());
|
||||
assert(get_tree(source(e, m_g)) == tColorTraits::black());
|
||||
assert(m_orphans.empty());
|
||||
|
||||
const tEdgeVal bottleneck = find_bottleneck(e);
|
||||
//now we push the found flow through the path
|
||||
//for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans
|
||||
//now process the connecting edge
|
||||
m_res_cap_map[e] -= bottleneck;
|
||||
assert(m_res_cap_map[e] >= 0);
|
||||
m_res_cap_map[m_rev_edge_map[e]] += bottleneck;
|
||||
|
||||
//now we follow the path back to the source
|
||||
vertex_descriptor current_node = source(e, m_g);
|
||||
while(current_node != m_source){
|
||||
edge_descriptor pred = get_edge_to_parent(current_node);
|
||||
m_res_cap_map[pred] -= bottleneck;
|
||||
assert(m_res_cap_map[pred] >= 0);
|
||||
m_res_cap_map[m_rev_edge_map[pred]] += bottleneck;
|
||||
if(m_res_cap_map[pred] == 0){
|
||||
set_no_parent(current_node);
|
||||
m_orphans.push_front(current_node);
|
||||
}
|
||||
current_node = source(pred, m_g);
|
||||
}
|
||||
//then go forward in the sink-tree
|
||||
current_node = target(e, m_g);
|
||||
while(current_node != m_sink){
|
||||
edge_descriptor pred = get_edge_to_parent(current_node);
|
||||
m_res_cap_map[pred] -= bottleneck;
|
||||
assert(m_res_cap_map[pred] >= 0);
|
||||
m_res_cap_map[m_rev_edge_map[pred]] += bottleneck;
|
||||
if(m_res_cap_map[pred] == 0){
|
||||
set_no_parent(current_node);
|
||||
m_orphans.push_front(current_node);
|
||||
}
|
||||
current_node = target(pred, m_g);
|
||||
}
|
||||
//and add it to the max-flow
|
||||
m_flow += bottleneck;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the bottleneck of a s->t path (end_of_path is last vertex in source-tree, begin_of_path is first vertex in sink-tree)
|
||||
*/
|
||||
inline tEdgeVal find_bottleneck(edge_descriptor e){
|
||||
BOOST_USING_STD_MIN();
|
||||
tEdgeVal minimum_cap = m_res_cap_map[e];
|
||||
vertex_descriptor current_node = source(e, m_g);
|
||||
//first go back in the source tree
|
||||
while(current_node != m_source){
|
||||
edge_descriptor pred = get_edge_to_parent(current_node);
|
||||
minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]);
|
||||
current_node = source(pred, m_g);
|
||||
}
|
||||
//then go forward in the sink-tree
|
||||
current_node = target(e, m_g);
|
||||
while(current_node != m_sink){
|
||||
edge_descriptor pred = get_edge_to_parent(current_node);
|
||||
minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]);
|
||||
current_node = target(pred, m_g);
|
||||
}
|
||||
return minimum_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* rebuild search trees
|
||||
* empty the queue of orphans, and find new parents for them or just drop them from the search trees
|
||||
*/
|
||||
void adopt(){
|
||||
while(!m_orphans.empty() || !m_child_orphans.empty()){
|
||||
vertex_descriptor current_node;
|
||||
if(m_child_orphans.empty()){
|
||||
//get the next orphan from the main-queue and remove it
|
||||
current_node = m_orphans.front();
|
||||
m_orphans.pop_front();
|
||||
} else{
|
||||
current_node = m_child_orphans.front();
|
||||
m_child_orphans.pop();
|
||||
}
|
||||
if(get_tree(current_node) == tColorTraits::black()){
|
||||
//we're in the source-tree
|
||||
tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
|
||||
edge_descriptor new_parent_edge;
|
||||
out_edge_iterator ei, e_end;
|
||||
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
|
||||
const edge_descriptor in_edge = m_rev_edge_map[*ei];
|
||||
assert(target(in_edge, m_g) == current_node); //we should be the target of this edge
|
||||
if(m_res_cap_map[in_edge] > 0){
|
||||
vertex_descriptor other_node = source(in_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){
|
||||
if(m_dist_map[other_node] < min_distance){
|
||||
min_distance = m_dist_map[other_node];
|
||||
new_parent_edge = in_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
|
||||
set_edge_to_parent(current_node, new_parent_edge);
|
||||
m_dist_map[current_node] = min_distance + 1;
|
||||
m_time_map[current_node] = m_time;
|
||||
} else{
|
||||
m_time_map[current_node] = 0;
|
||||
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
|
||||
edge_descriptor in_edge = m_rev_edge_map[*ei];
|
||||
vertex_descriptor other_node = source(in_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){
|
||||
if(m_res_cap_map[in_edge] > 0){
|
||||
add_active_node(other_node);
|
||||
}
|
||||
if(source(get_edge_to_parent(other_node), m_g) == current_node){
|
||||
//we are the parent of that node
|
||||
//it has to find a new parent, too
|
||||
set_no_parent(other_node);
|
||||
m_child_orphans.push(other_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
set_tree(current_node, tColorTraits::gray());
|
||||
} //no parent found
|
||||
} //source-tree-adoption
|
||||
else{
|
||||
//now we should be in the sink-tree, check that...
|
||||
assert(get_tree(current_node) == tColorTraits::white());
|
||||
out_edge_iterator ei, e_end;
|
||||
edge_descriptor new_parent_edge;
|
||||
tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
|
||||
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
|
||||
const edge_descriptor out_edge = *ei;
|
||||
if(m_res_cap_map[out_edge] > 0){
|
||||
const vertex_descriptor other_node = target(out_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node))
|
||||
if(m_dist_map[other_node] < min_distance){
|
||||
min_distance = m_dist_map[other_node];
|
||||
new_parent_edge = out_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
|
||||
set_edge_to_parent(current_node, new_parent_edge);
|
||||
m_dist_map[current_node] = min_distance + 1;
|
||||
m_time_map[current_node] = m_time;
|
||||
} else{
|
||||
m_time_map[current_node] = 0;
|
||||
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
|
||||
const edge_descriptor out_edge = *ei;
|
||||
const vertex_descriptor other_node = target(out_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){
|
||||
if(m_res_cap_map[out_edge] > 0){
|
||||
add_active_node(other_node);
|
||||
}
|
||||
if(target(get_edge_to_parent(other_node), m_g) == current_node){
|
||||
//we were it's parent, so it has to find a new one, too
|
||||
set_no_parent(other_node);
|
||||
m_child_orphans.push(other_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
set_tree(current_node, tColorTraits::gray());
|
||||
} //no parent found
|
||||
} //sink-tree adoption
|
||||
} //while !orphans.empty()
|
||||
} //adopt
|
||||
|
||||
/**
|
||||
* return next active vertex if there is one, otherwise a null_vertex
|
||||
*/
|
||||
inline vertex_descriptor get_next_active_node(){
|
||||
while(true){
|
||||
if(m_active_nodes.empty())
|
||||
return graph_traits<Graph>::null_vertex();
|
||||
vertex_descriptor v = m_active_nodes.front();
|
||||
|
||||
if(!has_parent(v) && v != m_source && v != m_sink){ //if it has no parent, this node can't be active(if its not source or sink)
|
||||
m_active_nodes.pop();
|
||||
m_in_active_list_map[v] = false;
|
||||
} else{
|
||||
assert(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white());
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* adds v as an active vertex, but only if its not in the list already
|
||||
*/
|
||||
inline void add_active_node(vertex_descriptor v){
|
||||
assert(get_tree(v) != tColorTraits::gray());
|
||||
if(m_in_active_list_map[v]){
|
||||
return;
|
||||
} else{
|
||||
m_in_active_list_map[v] = true;
|
||||
m_active_nodes.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node)
|
||||
*/
|
||||
inline void finish_node(vertex_descriptor v){
|
||||
assert(m_active_nodes.front() == v);
|
||||
m_active_nodes.pop();
|
||||
m_in_active_list_map[v] = false;
|
||||
m_last_grow_vertex = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a vertex from the queue of active nodes (actually this does nothing,
|
||||
* but checks if this node has no parent edge, as this is the criteria for beeing no more active)
|
||||
*/
|
||||
inline void remove_active_node(vertex_descriptor v){
|
||||
assert(!has_parent(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree
|
||||
*/
|
||||
inline tColorValue get_tree(vertex_descriptor v) const {
|
||||
return m_tree_map[v];
|
||||
}
|
||||
|
||||
/**
|
||||
* sets search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree
|
||||
*/
|
||||
inline void set_tree(vertex_descriptor v, tColorValue t){
|
||||
m_tree_map[v] = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns edge to parent vertex of v;
|
||||
*/
|
||||
inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{
|
||||
return m_pre_map[v];
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the edge stored in m_pre_map[v] is a valid entry
|
||||
*/
|
||||
inline bool has_parent(vertex_descriptor v) const{
|
||||
return m_has_parent_map[v];
|
||||
}
|
||||
|
||||
/**
|
||||
* sets edge to parent vertex of v;
|
||||
*/
|
||||
inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){
|
||||
assert(m_res_cap_map[f_edge_to_parent] > 0);
|
||||
m_pre_map[v] = f_edge_to_parent;
|
||||
m_has_parent_map[v] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* removes the edge to parent of v (this is done by invalidating the entry an additional map)
|
||||
*/
|
||||
inline void set_no_parent(vertex_descriptor v){
|
||||
m_has_parent_map[v] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if vertex v has a connect to the sink-vertex (@var m_sink)
|
||||
* @param v the vertex which is checked
|
||||
* @return true if a path to the sink was found, false if not
|
||||
*/
|
||||
inline bool has_sink_connect(vertex_descriptor v){
|
||||
tDistanceVal current_distance = 0;
|
||||
vertex_descriptor current_vertex = v;
|
||||
while(true){
|
||||
if(m_time_map[current_vertex] == m_time){
|
||||
//we found a node which was already checked this round. use it for distance calculations
|
||||
current_distance += m_dist_map[current_vertex];
|
||||
break;
|
||||
}
|
||||
if(current_vertex == m_sink){
|
||||
m_time_map[m_sink] = m_time;
|
||||
break;
|
||||
}
|
||||
if(has_parent(current_vertex)){
|
||||
//it has a parent, so get it
|
||||
current_vertex = target(get_edge_to_parent(current_vertex), m_g);
|
||||
++current_distance;
|
||||
} else{
|
||||
//no path found
|
||||
return false;
|
||||
}
|
||||
}
|
||||
current_vertex=v;
|
||||
while(m_time_map[current_vertex] != m_time){
|
||||
m_dist_map[current_vertex] = current_distance--;
|
||||
m_time_map[current_vertex] = m_time;
|
||||
current_vertex = target(get_edge_to_parent(current_vertex), m_g);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if vertex v has a connect to the source-vertex (@var m_source)
|
||||
* @param v the vertex which is checked
|
||||
* @return true if a path to the source was found, false if not
|
||||
*/
|
||||
inline bool has_source_connect(vertex_descriptor v){
|
||||
tDistanceVal current_distance = 0;
|
||||
vertex_descriptor current_vertex = v;
|
||||
while(true){
|
||||
if(m_time_map[current_vertex] == m_time){
|
||||
//we found a node which was already checked this round. use it for distance calculations
|
||||
current_distance += m_dist_map[current_vertex];
|
||||
break;
|
||||
}
|
||||
if(current_vertex == m_source){
|
||||
m_time_map[m_source] = m_time;
|
||||
break;
|
||||
}
|
||||
if(has_parent(current_vertex)){
|
||||
//it has a parent, so get it
|
||||
current_vertex = source(get_edge_to_parent(current_vertex), m_g);
|
||||
++current_distance;
|
||||
} else{
|
||||
//no path found
|
||||
return false;
|
||||
}
|
||||
}
|
||||
current_vertex=v;
|
||||
while(m_time_map[current_vertex] != m_time){
|
||||
m_dist_map[current_vertex] = current_distance-- ;
|
||||
m_time_map[current_vertex] = m_time;
|
||||
current_vertex = source(get_edge_to_parent(current_vertex), m_g);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true, if p is closer to a terminal than q
|
||||
*/
|
||||
inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){
|
||||
//checks the timestamps first, to build no cycles, and after that the real distance
|
||||
return (m_time_map[q] <= m_time_map[p] && m_dist_map[q] > m_dist_map[p]+1);
|
||||
}
|
||||
|
||||
////////
|
||||
// member vars
|
||||
////////
|
||||
Graph& m_g;
|
||||
IndexMap m_index_map;
|
||||
EdgeCapacityMap m_cap_map;
|
||||
ResidualCapacityEdgeMap m_res_cap_map;
|
||||
ReverseEdgeMap m_rev_edge_map;
|
||||
PredecessorMap m_pre_map; //stores paths found in the growth stage
|
||||
ColorMap m_tree_map; //maps each vertex into one of the two search tree or none (gray())
|
||||
DistanceMap m_dist_map; //stores distance to source/sink nodes
|
||||
vertex_descriptor m_source;
|
||||
vertex_descriptor m_sink;
|
||||
|
||||
tQueue m_active_nodes;
|
||||
std::vector<bool> m_in_active_list_vec;
|
||||
iterator_property_map<std::vector<bool>::iterator, IndexMap> m_in_active_list_map;
|
||||
|
||||
std::list<vertex_descriptor> m_orphans;
|
||||
tQueue m_child_orphans; // we use a second queuqe for child orphans, as they are FIFO processed
|
||||
|
||||
std::vector<bool> m_has_parent_vec;
|
||||
iterator_property_map<std::vector<bool>::iterator, IndexMap> m_has_parent_map;
|
||||
|
||||
std::vector<long> m_time_vec; //timestamp of each node, used for sink/source-path calculations
|
||||
iterator_property_map<std::vector<long>::iterator, IndexMap> m_time_map;
|
||||
tEdgeVal m_flow;
|
||||
long m_time;
|
||||
vertex_descriptor m_last_grow_vertex;
|
||||
out_edge_iterator m_last_grow_edge_it;
|
||||
out_edge_iterator m_last_grow_edge_end;
|
||||
};
|
||||
} //namespace detail
|
||||
|
||||
/**
|
||||
* non-named-parameter version, given everything
|
||||
* this is the catch all version
|
||||
*/
|
||||
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap,
|
||||
class PredecessorMap, class ColorMap, class DistanceMap, class IndexMap>
|
||||
typename property_traits<CapacityEdgeMap>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
CapacityEdgeMap cap,
|
||||
ResidualCapacityEdgeMap res_cap,
|
||||
ReverseEdgeMap rev_map,
|
||||
PredecessorMap pre_map,
|
||||
ColorMap color,
|
||||
DistanceMap dist,
|
||||
IndexMap idx,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink
|
||||
)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
//as this method is the last one before we instantiate the solver, we do the concept checks here
|
||||
function_requires<VertexListGraphConcept<Graph> >(); //to have vertices(), num_vertices(),
|
||||
function_requires<EdgeListGraphConcept<Graph> >(); //to have edges()
|
||||
function_requires<IncidenceGraphConcept<Graph> >(); //to have source(), target() and out_edges()
|
||||
function_requires<LvaluePropertyMapConcept<CapacityEdgeMap, edge_descriptor> >(); //read flow-values from edges
|
||||
function_requires<Mutable_LvaluePropertyMapConcept<ResidualCapacityEdgeMap, edge_descriptor> >(); //write flow-values to residuals
|
||||
function_requires<LvaluePropertyMapConcept<ReverseEdgeMap, edge_descriptor> >(); //read out reverse edges
|
||||
function_requires<Mutable_LvaluePropertyMapConcept<PredecessorMap, vertex_descriptor> >(); //store predecessor there
|
||||
function_requires<Mutable_LvaluePropertyMapConcept<ColorMap, vertex_descriptor> >(); //write corresponding tree
|
||||
function_requires<Mutable_LvaluePropertyMapConcept<DistanceMap, vertex_descriptor> >(); //write distance to source/sink
|
||||
function_requires<ReadablePropertyMapConcept<IndexMap, vertex_descriptor> >(); //get index 0...|V|-1
|
||||
assert(num_vertices(g) >= 2 && src != sink);
|
||||
detail::kolmogorov<Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, ReverseEdgeMap, PredecessorMap, ColorMap, DistanceMap, IndexMap>
|
||||
algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink);
|
||||
return algo.max_flow();
|
||||
}
|
||||
|
||||
/**
|
||||
* non-named-parameter version, given: capacity, residucal_capacity, reverse_edges, and an index map.
|
||||
*/
|
||||
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap, class IndexMap>
|
||||
typename property_traits<CapacityEdgeMap>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
CapacityEdgeMap cap,
|
||||
ResidualCapacityEdgeMap res_cap,
|
||||
ReverseEdgeMap rev,
|
||||
IndexMap idx,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink)
|
||||
{
|
||||
typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
|
||||
std::vector<default_color_type> color_vec(n_verts);
|
||||
std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
|
||||
return kolmogorov_max_flow
|
||||
(g, cap, res_cap, rev,
|
||||
make_iterator_property_map(predecessor_vec.begin(), idx),
|
||||
make_iterator_property_map(color_vec.begin(), idx),
|
||||
make_iterator_property_map(distance_vec.begin(), idx),
|
||||
idx, src, sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* non-named-parameter version, some given: capacity, residual_capacity, reverse_edges, color_map and an index map.
|
||||
* Use this if you are interested in the minimum cut, as the color map provides that info
|
||||
*/
|
||||
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap, class ColorMap, class IndexMap>
|
||||
typename property_traits<CapacityEdgeMap>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
CapacityEdgeMap cap,
|
||||
ResidualCapacityEdgeMap res_cap,
|
||||
ReverseEdgeMap rev,
|
||||
ColorMap color,
|
||||
IndexMap idx,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink)
|
||||
{
|
||||
typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
|
||||
std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
|
||||
|
||||
return kolmogorov_max_flow
|
||||
(g, cap, res_cap, rev,
|
||||
make_iterator_property_map(predecessor_vec.begin(), idx),
|
||||
color,
|
||||
make_iterator_property_map(distance_vec.begin(), idx),
|
||||
idx, src, sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* named-parameter version, some given
|
||||
*/
|
||||
template <class Graph, class P, class T, class R>
|
||||
typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return kolmogorov_max_flow(g,
|
||||
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
|
||||
choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity),
|
||||
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
|
||||
choose_pmap(get_param(params, vertex_predecessor), g, vertex_predecessor),
|
||||
choose_pmap(get_param(params, vertex_color), g, vertex_color),
|
||||
choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
|
||||
src, sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* named-parameter version, none given
|
||||
*/
|
||||
template <class Graph>
|
||||
typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink)
|
||||
{
|
||||
bgl_named_params<int, buffer_param_t> params(0); // bogus empty param
|
||||
return kolmogorov_max_flow(g, src, sink, params);
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_KOLMOGOROV_MAX_FLOW_HPP
|
||||
|
||||
155
libraries/include/boost/graph/kruskal_min_spanning_tree.hpp
Normal file
155
libraries/include/boost/graph/kruskal_min_spanning_tree.hpp
Normal file
@@ -0,0 +1,155 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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_MST_KRUSKAL_HPP
|
||||
#define BOOST_GRAPH_MST_KRUSKAL_HPP
|
||||
|
||||
/*
|
||||
*Minimum Spanning Tree
|
||||
* Kruskal Algorithm
|
||||
*
|
||||
*Requirement:
|
||||
* undirected graph
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
#include <boost/pending/disjoint_sets.hpp>
|
||||
#include <boost/pending/indirect_cmp.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Kruskal's algorithm for Minimum Spanning Tree
|
||||
//
|
||||
// This is a greedy algorithm to calculate the Minimum Spanning Tree
|
||||
// for an undirected graph with weighted edges. The output will be a
|
||||
// set of edges.
|
||||
//
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Graph, class OutputIterator,
|
||||
class Rank, class Parent, class Weight>
|
||||
void
|
||||
kruskal_mst_impl(const Graph& G,
|
||||
OutputIterator spanning_tree_edges,
|
||||
Rank rank, Parent parent, Weight weight)
|
||||
{
|
||||
if (num_vertices(G) == 0) return; // Nothing to do in this case
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor Edge;
|
||||
function_requires<VertexListGraphConcept<Graph> >();
|
||||
function_requires<EdgeListGraphConcept<Graph> >();
|
||||
function_requires<OutputIteratorConcept<OutputIterator, Edge> >();
|
||||
function_requires<ReadWritePropertyMapConcept<Rank, Vertex> >();
|
||||
function_requires<ReadWritePropertyMapConcept<Parent, Vertex> >();
|
||||
function_requires<ReadablePropertyMapConcept<Weight, Edge> >();
|
||||
typedef typename property_traits<Weight>::value_type W_value;
|
||||
typedef typename property_traits<Rank>::value_type R_value;
|
||||
typedef typename property_traits<Parent>::value_type P_value;
|
||||
function_requires<ComparableConcept<W_value> >();
|
||||
function_requires<ConvertibleConcept<P_value, Vertex> >();
|
||||
function_requires<IntegerConcept<R_value> >();
|
||||
|
||||
disjoint_sets<Rank, Parent> dset(rank, parent);
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator ui, uiend;
|
||||
for (boost::tie(ui, uiend) = vertices(G); ui != uiend; ++ui)
|
||||
dset.make_set(*ui);
|
||||
|
||||
typedef indirect_cmp<Weight, std::greater<W_value> > weight_greater;
|
||||
weight_greater wl(weight);
|
||||
std::priority_queue<Edge, std::vector<Edge>, weight_greater> Q(wl);
|
||||
/*push all edge into Q*/
|
||||
typename graph_traits<Graph>::edge_iterator ei, eiend;
|
||||
for (boost::tie(ei, eiend) = edges(G); ei != eiend; ++ei)
|
||||
Q.push(*ei);
|
||||
|
||||
while (! Q.empty()) {
|
||||
Edge e = Q.top();
|
||||
Q.pop();
|
||||
Vertex u = dset.find_set(source(e, G));
|
||||
Vertex v = dset.find_set(target(e, G));
|
||||
if ( u != v ) {
|
||||
*spanning_tree_edges++ = e;
|
||||
dset.link(u, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Named Parameters Variants
|
||||
|
||||
template <class Graph, class OutputIterator>
|
||||
inline void
|
||||
kruskal_minimum_spanning_tree(const Graph& g,
|
||||
OutputIterator spanning_tree_edges)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename property_map<Graph, vertex_index_t>::type index_map_t;
|
||||
if (num_vertices(g) == 0) return; // Nothing to do in this case
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
n = num_vertices(g);
|
||||
std::vector<size_type> rank_map(n);
|
||||
std::vector<vertex_t> pred_map(n);
|
||||
|
||||
detail::kruskal_mst_impl
|
||||
(g, spanning_tree_edges,
|
||||
make_iterator_property_map(rank_map.begin(), get(vertex_index, g), rank_map[0]),
|
||||
make_iterator_property_map(pred_map.begin(), get(vertex_index, g), pred_map[0]),
|
||||
get(edge_weight, g));
|
||||
}
|
||||
|
||||
template <class Graph, class OutputIterator, class P, class T, class R>
|
||||
inline void
|
||||
kruskal_minimum_spanning_tree(const Graph& g,
|
||||
OutputIterator spanning_tree_edges,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
if (num_vertices(g) == 0) return; // Nothing to do in this case
|
||||
typename graph_traits<Graph>::vertices_size_type n;
|
||||
n = is_default_param(get_param(params, vertex_rank))
|
||||
? num_vertices(g) : 1;
|
||||
std::vector<size_type> rank_map(n);
|
||||
n = is_default_param(get_param(params, vertex_predecessor))
|
||||
? num_vertices(g) : 1;
|
||||
std::vector<vertex_t> pred_map(n);
|
||||
|
||||
detail::kruskal_mst_impl
|
||||
(g, spanning_tree_edges,
|
||||
choose_param
|
||||
(get_param(params, vertex_rank),
|
||||
make_iterator_property_map
|
||||
(rank_map.begin(),
|
||||
choose_pmap(get_param(params, vertex_index), g, vertex_index), rank_map[0])),
|
||||
choose_param
|
||||
(get_param(params, vertex_predecessor),
|
||||
make_iterator_property_map
|
||||
(pred_map.begin(),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
|
||||
pred_map[0])),
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight));
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_MST_KRUSKAL_HPP
|
||||
|
||||
952
libraries/include/boost/graph/leda_graph.hpp
Normal file
952
libraries/include/boost/graph/leda_graph.hpp
Normal file
@@ -0,0 +1,952 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
// Copyright 2007 University of Karlsruhe
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor,
|
||||
// Jens Mueller
|
||||
//
|
||||
// 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_LEDA_HPP
|
||||
#define BOOST_GRAPH_LEDA_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
|
||||
#include <LEDA/graph.h>
|
||||
#include <LEDA/node_array.h>
|
||||
#include <LEDA/node_map.h>
|
||||
|
||||
// The functions and classes in this file allows the user to
|
||||
// treat a LEDA GRAPH object as a boost graph "as is". No
|
||||
// wrapper is needed for the GRAPH object.
|
||||
|
||||
// Warning: this implementation relies on partial specialization
|
||||
// for the graph_traits class (so it won't compile with Visual C++)
|
||||
|
||||
// Warning: this implementation is in alpha and has not been tested
|
||||
|
||||
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost {
|
||||
|
||||
struct leda_graph_traversal_category :
|
||||
public virtual bidirectional_graph_tag,
|
||||
public virtual adjacency_graph_tag,
|
||||
public virtual vertex_list_graph_tag { };
|
||||
|
||||
template <class vtype, class etype>
|
||||
struct graph_traits< leda::GRAPH<vtype,etype> > {
|
||||
typedef leda::node vertex_descriptor;
|
||||
typedef leda::edge edge_descriptor;
|
||||
|
||||
class adjacency_iterator
|
||||
: public iterator_facade<adjacency_iterator,
|
||||
leda::node,
|
||||
bidirectional_traversal_tag,
|
||||
leda::node,
|
||||
const leda::node*>
|
||||
{
|
||||
public:
|
||||
adjacency_iterator(leda::node node = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(node), g(g) {}
|
||||
private:
|
||||
leda::node dereference() const { return leda::target(base); }
|
||||
|
||||
bool equal(const adjacency_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->adj_succ(base); }
|
||||
void decrement() { base = g->adj_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class out_edge_iterator
|
||||
: public iterator_facade<out_edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
out_edge_iterator(leda::node node = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(node), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const out_edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->adj_succ(base); }
|
||||
void decrement() { base = g->adj_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class in_edge_iterator
|
||||
: public iterator_facade<in_edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
in_edge_iterator(leda::node node = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(node), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const in_edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->in_succ(base); }
|
||||
void decrement() { base = g->in_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class vertex_iterator
|
||||
: public iterator_facade<vertex_iterator,
|
||||
leda::node,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::node&,
|
||||
const leda::node*>
|
||||
{
|
||||
public:
|
||||
vertex_iterator(leda::node node = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(node), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::node& dereference() const { return base; }
|
||||
|
||||
bool equal(const vertex_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->succ_node(base); }
|
||||
void decrement() { base = g->pred_node(base); }
|
||||
|
||||
leda::node base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class edge_iterator
|
||||
: public iterator_facade<edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
edge_iterator(leda::edge edge = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->succ_edge(base); }
|
||||
void decrement() { base = g->pred_edge(base); }
|
||||
|
||||
leda::node base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
typedef directed_tag directed_category;
|
||||
typedef allow_parallel_edge_tag edge_parallel_category; // not sure here
|
||||
typedef leda_graph_traversal_category traversal_category;
|
||||
typedef int vertices_size_type;
|
||||
typedef int edges_size_type;
|
||||
typedef int degree_size_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<>
|
||||
struct graph_traits<leda::graph> {
|
||||
typedef leda::node vertex_descriptor;
|
||||
typedef leda::edge edge_descriptor;
|
||||
|
||||
class adjacency_iterator
|
||||
: public iterator_facade<adjacency_iterator,
|
||||
leda::node,
|
||||
bidirectional_traversal_tag,
|
||||
leda::node,
|
||||
const leda::node*>
|
||||
{
|
||||
public:
|
||||
adjacency_iterator(leda::edge edge = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
leda::node dereference() const { return leda::target(base); }
|
||||
|
||||
bool equal(const adjacency_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->adj_succ(base); }
|
||||
void decrement() { base = g->adj_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class out_edge_iterator
|
||||
: public iterator_facade<out_edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
out_edge_iterator(leda::edge edge = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const out_edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->adj_succ(base); }
|
||||
void decrement() { base = g->adj_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class in_edge_iterator
|
||||
: public iterator_facade<in_edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
in_edge_iterator(leda::edge edge = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const in_edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->in_succ(base); }
|
||||
void decrement() { base = g->in_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class vertex_iterator
|
||||
: public iterator_facade<vertex_iterator,
|
||||
leda::node,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::node&,
|
||||
const leda::node*>
|
||||
{
|
||||
public:
|
||||
vertex_iterator(leda::node node = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(node), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::node& dereference() const { return base; }
|
||||
|
||||
bool equal(const vertex_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->succ_node(base); }
|
||||
void decrement() { base = g->pred_node(base); }
|
||||
|
||||
leda::node base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class edge_iterator
|
||||
: public iterator_facade<edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
edge_iterator(leda::edge edge = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->succ_edge(base); }
|
||||
void decrement() { base = g->pred_edge(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
typedef directed_tag directed_category;
|
||||
typedef allow_parallel_edge_tag edge_parallel_category; // not sure here
|
||||
typedef leda_graph_traversal_category traversal_category;
|
||||
typedef int vertices_size_type;
|
||||
typedef int edges_size_type;
|
||||
typedef int degree_size_type;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
//===========================================================================
|
||||
// functions for GRAPH<vtype,etype>
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor
|
||||
source(typename graph_traits< leda::GRAPH<vtype,etype> >::edge_descriptor e,
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return source(e);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor
|
||||
target(typename graph_traits< leda::GRAPH<vtype,etype> >::edge_descriptor e,
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return target(e);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_iterator,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_iterator >
|
||||
vertices(const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_iterator
|
||||
Iter;
|
||||
return std::make_pair( Iter(g.first_node(),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::edge_iterator,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::edge_iterator >
|
||||
edges(const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >::edge_iterator
|
||||
Iter;
|
||||
return std::make_pair( Iter(g.first_edge(),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::out_edge_iterator,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::out_edge_iterator >
|
||||
out_edges(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
|
||||
::out_edge_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_adj_edge(u,0),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::in_edge_iterator,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::in_edge_iterator >
|
||||
in_edges(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
|
||||
::in_edge_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_adj_edge(u,1),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::adjacency_iterator,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::adjacency_iterator >
|
||||
adjacent_vertices(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
|
||||
::adjacency_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_adj_edge(u,0),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertices_size_type
|
||||
num_vertices(const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.number_of_nodes();
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::edges_size_type
|
||||
num_edges(const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.number_of_edges();
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
|
||||
out_degree(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.outdeg(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
|
||||
in_degree(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.indeg(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
|
||||
degree(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.outdeg(u) + g.indeg(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor
|
||||
add_vertex(leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.new_node();
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor
|
||||
add_vertex(const vtype& vp, leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.new_node(vp);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
void clear_vertex(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end)=out_edges(u,g); ei!=ei_end; ei++)
|
||||
remove_edge(*ei);
|
||||
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::in_edge_iterator iei, iei_end;
|
||||
for (tie(iei, iei_end)=in_edges(u,g); iei!=iei_end; iei++)
|
||||
remove_edge(*iei);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
void remove_vertex(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
g.del_node(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
std::pair<
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::edge_descriptor,
|
||||
bool>
|
||||
add_edge(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor v,
|
||||
leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return std::make_pair(g.new_edge(u, v), true);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
std::pair<
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::edge_descriptor,
|
||||
bool>
|
||||
add_edge(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor v,
|
||||
const etype& et,
|
||||
leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return std::make_pair(g.new_edge(u, v, et), true);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
void
|
||||
remove_edge(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor v,
|
||||
leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::out_edge_iterator
|
||||
i,iend;
|
||||
for (boost::tie(i,iend) = out_edges(u,g); i != iend; ++i)
|
||||
if (target(*i,g) == v)
|
||||
g.del_edge(*i);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
void
|
||||
remove_edge(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::edge_descriptor e,
|
||||
leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
g.del_edge(e);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// functions for graph (non-templated version)
|
||||
|
||||
graph_traits<leda::graph>::vertex_descriptor
|
||||
source(graph_traits<leda::graph>::edge_descriptor e,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return source(e);
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::vertex_descriptor
|
||||
target(graph_traits<leda::graph>::edge_descriptor e,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return target(e);
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::vertex_iterator,
|
||||
graph_traits<leda::graph>::vertex_iterator >
|
||||
vertices(const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>::vertex_iterator
|
||||
Iter;
|
||||
return std::make_pair( Iter(g.first_node(),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::edge_iterator,
|
||||
graph_traits<leda::graph>::edge_iterator >
|
||||
edges(const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>::edge_iterator
|
||||
Iter;
|
||||
return std::make_pair( Iter(g.first_edge(),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::out_edge_iterator,
|
||||
graph_traits<leda::graph>::out_edge_iterator >
|
||||
out_edges(
|
||||
graph_traits<leda::graph>::vertex_descriptor u, const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>::out_edge_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_adj_edge(u),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::in_edge_iterator,
|
||||
graph_traits<leda::graph>::in_edge_iterator >
|
||||
in_edges(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>
|
||||
::in_edge_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_in_edge(u),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::adjacency_iterator,
|
||||
graph_traits<leda::graph>::adjacency_iterator >
|
||||
adjacent_vertices(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>
|
||||
::adjacency_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_adj_edge(u),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::vertices_size_type
|
||||
num_vertices(const leda::graph& g)
|
||||
{
|
||||
return g.number_of_nodes();
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::edges_size_type
|
||||
num_edges(const leda::graph& g)
|
||||
{
|
||||
return g.number_of_edges();
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::degree_size_type
|
||||
out_degree(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return g.outdeg(u);
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::degree_size_type
|
||||
in_degree(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return g.indeg(u);
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::degree_size_type
|
||||
degree(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return g.outdeg(u) + g.indeg(u);
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::vertex_descriptor
|
||||
add_vertex(leda::graph& g)
|
||||
{
|
||||
return g.new_node();
|
||||
}
|
||||
|
||||
void
|
||||
remove_edge(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
graph_traits<leda::graph>::vertex_descriptor v,
|
||||
leda::graph& g)
|
||||
{
|
||||
graph_traits<leda::graph>::out_edge_iterator
|
||||
i,iend;
|
||||
for (boost::tie(i,iend) = out_edges(u,g); i != iend; ++i)
|
||||
if (target(*i,g) == v)
|
||||
g.del_edge(*i);
|
||||
}
|
||||
|
||||
void
|
||||
remove_edge(
|
||||
graph_traits<leda::graph>::edge_descriptor e,
|
||||
leda::graph& g)
|
||||
{
|
||||
g.del_edge(e);
|
||||
}
|
||||
|
||||
void clear_vertex(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
leda::graph& g)
|
||||
{
|
||||
graph_traits<leda::graph>::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end)=out_edges(u,g); ei!=ei_end; ei++)
|
||||
remove_edge(*ei, g);
|
||||
|
||||
graph_traits<leda::graph>::in_edge_iterator iei, iei_end;
|
||||
for (tie(iei, iei_end)=in_edges(u,g); iei!=iei_end; iei++)
|
||||
remove_edge(*iei, g);
|
||||
}
|
||||
|
||||
void remove_vertex(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
leda::graph& g)
|
||||
{
|
||||
g.del_node(u);
|
||||
}
|
||||
|
||||
std::pair<
|
||||
graph_traits<leda::graph>::edge_descriptor,
|
||||
bool>
|
||||
add_edge(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
graph_traits<leda::graph>::vertex_descriptor v,
|
||||
leda::graph& g)
|
||||
{
|
||||
return std::make_pair(g.new_edge(u, v), true);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// property maps for GRAPH<vtype,etype>
|
||||
|
||||
class leda_graph_id_map
|
||||
: public put_get_helper<int, leda_graph_id_map>
|
||||
{
|
||||
public:
|
||||
typedef readable_property_map_tag category;
|
||||
typedef int value_type;
|
||||
typedef int reference;
|
||||
typedef leda::node key_type;
|
||||
leda_graph_id_map() { }
|
||||
template <class T>
|
||||
long operator[](T x) const { return x->id(); }
|
||||
};
|
||||
template <class vtype, class etype>
|
||||
inline leda_graph_id_map
|
||||
get(vertex_index_t, const leda::GRAPH<vtype, etype>& g) {
|
||||
return leda_graph_id_map();
|
||||
}
|
||||
template <class vtype, class etype>
|
||||
inline leda_graph_id_map
|
||||
get(edge_index_t, const leda::GRAPH<vtype, etype>& g) {
|
||||
return leda_graph_id_map();
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
struct leda_property_map { };
|
||||
|
||||
template <>
|
||||
struct leda_property_map<vertex_index_t> {
|
||||
template <class vtype, class etype>
|
||||
struct bind_ {
|
||||
typedef leda_graph_id_map type;
|
||||
typedef leda_graph_id_map const_type;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct leda_property_map<edge_index_t> {
|
||||
template <class vtype, class etype>
|
||||
struct bind_ {
|
||||
typedef leda_graph_id_map type;
|
||||
typedef leda_graph_id_map const_type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class Data, class DataRef, class GraphPtr>
|
||||
class leda_graph_data_map
|
||||
: public put_get_helper<DataRef,
|
||||
leda_graph_data_map<Data,DataRef,GraphPtr> >
|
||||
{
|
||||
public:
|
||||
typedef Data value_type;
|
||||
typedef DataRef reference;
|
||||
typedef void key_type;
|
||||
typedef lvalue_property_map_tag category;
|
||||
leda_graph_data_map(GraphPtr g) : m_g(g) { }
|
||||
template <class NodeOrEdge>
|
||||
DataRef operator[](NodeOrEdge x) const { return (*m_g)[x]; }
|
||||
protected:
|
||||
GraphPtr m_g;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct leda_property_map<vertex_all_t> {
|
||||
template <class vtype, class etype>
|
||||
struct bind_ {
|
||||
typedef leda_graph_data_map<vtype, vtype&, leda::GRAPH<vtype, etype>*> type;
|
||||
typedef leda_graph_data_map<vtype, const vtype&,
|
||||
const leda::GRAPH<vtype, etype>*> const_type;
|
||||
};
|
||||
};
|
||||
template <class vtype, class etype >
|
||||
inline typename property_map< leda::GRAPH<vtype, etype>, vertex_all_t>::type
|
||||
get(vertex_all_t, leda::GRAPH<vtype, etype>& g) {
|
||||
typedef typename property_map< leda::GRAPH<vtype, etype>, vertex_all_t>::type
|
||||
pmap_type;
|
||||
return pmap_type(&g);
|
||||
}
|
||||
template <class vtype, class etype >
|
||||
inline typename property_map< leda::GRAPH<vtype, etype>, vertex_all_t>::const_type
|
||||
get(vertex_all_t, const leda::GRAPH<vtype, etype>& g) {
|
||||
typedef typename property_map< leda::GRAPH<vtype, etype>,
|
||||
vertex_all_t>::const_type pmap_type;
|
||||
return pmap_type(&g);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct leda_property_map<edge_all_t> {
|
||||
template <class vtype, class etype>
|
||||
struct bind_ {
|
||||
typedef leda_graph_data_map<etype, etype&, leda::GRAPH<vtype, etype>*> type;
|
||||
typedef leda_graph_data_map<etype, const etype&,
|
||||
const leda::GRAPH<vtype, etype>*> const_type;
|
||||
};
|
||||
};
|
||||
template <class vtype, class etype >
|
||||
inline typename property_map< leda::GRAPH<vtype, etype>, edge_all_t>::type
|
||||
get(edge_all_t, leda::GRAPH<vtype, etype>& g) {
|
||||
typedef typename property_map< leda::GRAPH<vtype, etype>, edge_all_t>::type
|
||||
pmap_type;
|
||||
return pmap_type(&g);
|
||||
}
|
||||
template <class vtype, class etype >
|
||||
inline typename property_map< leda::GRAPH<vtype, etype>, edge_all_t>::const_type
|
||||
get(edge_all_t, const leda::GRAPH<vtype, etype>& g) {
|
||||
typedef typename property_map< leda::GRAPH<vtype, etype>,
|
||||
edge_all_t>::const_type pmap_type;
|
||||
return pmap_type(&g);
|
||||
}
|
||||
|
||||
// property map interface to the LEDA node_array class
|
||||
|
||||
template <class E, class ERef, class NodeMapPtr>
|
||||
class leda_node_property_map
|
||||
: public put_get_helper<ERef, leda_node_property_map<E, ERef, NodeMapPtr> >
|
||||
{
|
||||
public:
|
||||
typedef E value_type;
|
||||
typedef ERef reference;
|
||||
typedef leda::node key_type;
|
||||
typedef lvalue_property_map_tag category;
|
||||
leda_node_property_map(NodeMapPtr a) : m_array(a) { }
|
||||
ERef operator[](leda::node n) const { return (*m_array)[n]; }
|
||||
protected:
|
||||
NodeMapPtr m_array;
|
||||
};
|
||||
template <class E>
|
||||
leda_node_property_map<E, const E&, const leda::node_array<E>*>
|
||||
make_leda_node_property_map(const leda::node_array<E>& a)
|
||||
{
|
||||
typedef leda_node_property_map<E, const E&, const leda::node_array<E>*>
|
||||
pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
template <class E>
|
||||
leda_node_property_map<E, E&, leda::node_array<E>*>
|
||||
make_leda_node_property_map(leda::node_array<E>& a)
|
||||
{
|
||||
typedef leda_node_property_map<E, E&, leda::node_array<E>*> pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
leda_node_property_map<E, const E&, const leda::node_map<E>*>
|
||||
make_leda_node_property_map(const leda::node_map<E>& a)
|
||||
{
|
||||
typedef leda_node_property_map<E,const E&,const leda::node_map<E>*>
|
||||
pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
template <class E>
|
||||
leda_node_property_map<E, E&, leda::node_map<E>*>
|
||||
make_leda_node_property_map(leda::node_map<E>& a)
|
||||
{
|
||||
typedef leda_node_property_map<E, E&, leda::node_map<E>*> pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
|
||||
// g++ 'enumeral_type' in template unification not implemented workaround
|
||||
template <class vtype, class etype, class Tag>
|
||||
struct property_map<leda::GRAPH<vtype, etype>, Tag> {
|
||||
typedef typename
|
||||
leda_property_map<Tag>::template bind_<vtype, etype> map_gen;
|
||||
typedef typename map_gen::type type;
|
||||
typedef typename map_gen::const_type const_type;
|
||||
};
|
||||
|
||||
template <class vtype, class etype, class PropertyTag, class Key>
|
||||
inline
|
||||
typename boost::property_traits<
|
||||
typename boost::property_map<leda::GRAPH<vtype, etype>,PropertyTag>::const_type
|
||||
::value_type
|
||||
get(PropertyTag p, const leda::GRAPH<vtype, etype>& g, const Key& key) {
|
||||
return get(get(p, g), key);
|
||||
}
|
||||
|
||||
template <class vtype, class etype, class PropertyTag, class Key,class Value>
|
||||
inline void
|
||||
put(PropertyTag p, leda::GRAPH<vtype, etype>& g,
|
||||
const Key& key, const Value& value)
|
||||
{
|
||||
typedef typename property_map<leda::GRAPH<vtype, etype>, PropertyTag>::type Map;
|
||||
Map pmap = get(p, g);
|
||||
put(pmap, key, value);
|
||||
}
|
||||
|
||||
// property map interface to the LEDA edge_array class
|
||||
|
||||
template <class E, class ERef, class EdgeMapPtr>
|
||||
class leda_edge_property_map
|
||||
: public put_get_helper<ERef, leda_edge_property_map<E, ERef, EdgeMapPtr> >
|
||||
{
|
||||
public:
|
||||
typedef E value_type;
|
||||
typedef ERef reference;
|
||||
typedef leda::edge key_type;
|
||||
typedef lvalue_property_map_tag category;
|
||||
leda_edge_property_map(EdgeMapPtr a) : m_array(a) { }
|
||||
ERef operator[](leda::edge n) const { return (*m_array)[n]; }
|
||||
protected:
|
||||
EdgeMapPtr m_array;
|
||||
};
|
||||
template <class E>
|
||||
leda_edge_property_map<E, const E&, const leda::edge_array<E>*>
|
||||
make_leda_node_property_map(const leda::node_array<E>& a)
|
||||
{
|
||||
typedef leda_edge_property_map<E, const E&, const leda::node_array<E>*>
|
||||
pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
template <class E>
|
||||
leda_edge_property_map<E, E&, leda::edge_array<E>*>
|
||||
make_leda_edge_property_map(leda::edge_array<E>& a)
|
||||
{
|
||||
typedef leda_edge_property_map<E, E&, leda::edge_array<E>*> pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
leda_edge_property_map<E, const E&, const leda::edge_map<E>*>
|
||||
make_leda_edge_property_map(const leda::edge_map<E>& a)
|
||||
{
|
||||
typedef leda_edge_property_map<E,const E&,const leda::edge_map<E>*>
|
||||
pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
template <class E>
|
||||
leda_edge_property_map<E, E&, leda::edge_map<E>*>
|
||||
make_leda_edge_property_map(leda::edge_map<E>& a)
|
||||
{
|
||||
typedef leda_edge_property_map<E, E&, leda::edge_map<E>*> pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_LEDA_HPP
|
||||
121
libraries/include/boost/graph/make_biconnected_planar.hpp
Normal file
121
libraries/include/boost/graph/make_biconnected_planar.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// 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 __MAKE_BICONNECTED_PLANAR_HPP__
|
||||
#define __MAKE_BICONNECTED_PLANAR_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/tuple/tuple.hpp> //for tie
|
||||
#include <boost/graph/biconnected_components.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename EdgeIndexMap,
|
||||
typename AddEdgeVisitor
|
||||
>
|
||||
void make_biconnected_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
EdgeIndexMap em,
|
||||
AddEdgeVisitor& vis
|
||||
)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::edges_size_type edge_size_t;
|
||||
typedef typename
|
||||
property_traits<PlanarEmbedding>::value_type embedding_value_t;
|
||||
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
|
||||
typedef iterator_property_map
|
||||
<std::vector<std::size_t>::iterator, EdgeIndexMap> component_map_t;
|
||||
|
||||
edge_size_t n_edges(num_edges(g));
|
||||
std::vector<vertex_t> articulation_points;
|
||||
std::vector<edge_size_t> component_vector(n_edges);
|
||||
component_map_t component_map(component_vector.begin(), em);
|
||||
|
||||
biconnected_components(g, component_map,
|
||||
std::back_inserter(articulation_points));
|
||||
|
||||
typename std::vector<vertex_t>::iterator ap, ap_end;
|
||||
ap_end = articulation_points.end();
|
||||
for(ap = articulation_points.begin(); ap != ap_end; ++ap)
|
||||
{
|
||||
vertex_t v(*ap);
|
||||
embedding_iterator_t pi = embedding[v].begin();
|
||||
embedding_iterator_t pi_end = embedding[v].end();
|
||||
edge_size_t previous_component(n_edges + 1);
|
||||
vertex_t previous_vertex = graph_traits<Graph>::null_vertex();
|
||||
|
||||
for(; pi != pi_end; ++pi)
|
||||
{
|
||||
edge_t e(*pi);
|
||||
vertex_t e_source(source(e,g));
|
||||
vertex_t e_target(target(e,g));
|
||||
|
||||
//Skip self-loops and parallel edges
|
||||
if (e_source == e_target || previous_vertex == e_target)
|
||||
continue;
|
||||
|
||||
vertex_t current_vertex = e_source == v ? e_target : e_source;
|
||||
edge_size_t current_component = component_map[e];
|
||||
if (previous_vertex != graph_traits<Graph>::null_vertex() &&
|
||||
current_component != previous_component)
|
||||
{
|
||||
vis.visit_vertex_pair(current_vertex, previous_vertex, g);
|
||||
}
|
||||
previous_vertex = current_vertex;
|
||||
previous_component = current_component;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename EdgeIndexMap
|
||||
>
|
||||
inline void make_biconnected_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
EdgeIndexMap em
|
||||
)
|
||||
{
|
||||
default_add_edge_visitor vis;
|
||||
make_biconnected_planar(g, embedding, em, vis);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding
|
||||
>
|
||||
inline void make_biconnected_planar(Graph& g, PlanarEmbedding embedding)
|
||||
{
|
||||
make_biconnected_planar(g, embedding, get(edge_index,g));
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif //__MAKE_BICONNECTED_PLANAR_HPP__
|
||||
99
libraries/include/boost/graph/make_connected.hpp
Normal file
99
libraries/include/boost/graph/make_connected.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// 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 __MAKE_CONNECTED_HPP__
|
||||
#define __MAKE_CONNECTED_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next
|
||||
#include <boost/tuple/tuple.hpp> //for tie
|
||||
#include <boost/graph/connected_components.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
|
||||
#include <boost/graph/planar_detail/bucket_sort.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename VertexIndexMap,
|
||||
typename AddEdgeVisitor
|
||||
>
|
||||
void make_connected(Graph& g, VertexIndexMap vm, AddEdgeVisitor& vis)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef iterator_property_map< typename std::vector<v_size_t>::iterator,
|
||||
VertexIndexMap
|
||||
> vertex_to_v_size_map_t;
|
||||
|
||||
std::vector<v_size_t> component_vector(num_vertices(g));
|
||||
vertex_to_v_size_map_t component(component_vector.begin(), vm);
|
||||
std::vector<vertex_t> vertices_by_component(num_vertices(g));
|
||||
|
||||
v_size_t num_components = connected_components(g, component);
|
||||
|
||||
if (num_components < 2)
|
||||
return;
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
tie(vi,vi_end) = vertices(g);
|
||||
std::copy(vi, vi_end, vertices_by_component.begin());
|
||||
|
||||
bucket_sort(vertices_by_component.begin(),
|
||||
vertices_by_component.end(),
|
||||
component,
|
||||
num_components
|
||||
);
|
||||
|
||||
typedef typename std::vector<vertex_t>::iterator vec_of_vertices_itr_t;
|
||||
|
||||
vec_of_vertices_itr_t ci_end = vertices_by_component.end();
|
||||
vec_of_vertices_itr_t ci_prev = vertices_by_component.begin();
|
||||
if (ci_prev == ci_end)
|
||||
return;
|
||||
|
||||
for(vec_of_vertices_itr_t ci = next(ci_prev);
|
||||
ci != ci_end; ci_prev = ci, ++ci
|
||||
)
|
||||
{
|
||||
if (component[*ci_prev] != component[*ci])
|
||||
vis.visit_vertex_pair(*ci_prev, *ci, g);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
inline void make_connected(Graph& g, VertexIndexMap vm)
|
||||
{
|
||||
default_add_edge_visitor vis;
|
||||
make_connected(g, vm, vis);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
inline void make_connected(Graph& g)
|
||||
{
|
||||
make_connected(g, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //__MAKE_CONNECTED_HPP__
|
||||
275
libraries/include/boost/graph/make_maximal_planar.hpp
Normal file
275
libraries/include/boost/graph/make_maximal_planar.hpp
Normal file
@@ -0,0 +1,275 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// 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 __MAKE_MAXIMAL_PLANAR_HPP__
|
||||
#define __MAKE_MAXIMAL_PLANAR_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/tuple/tuple.hpp> //for tie
|
||||
#include <boost/graph/biconnected_components.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/graph/planar_face_traversal.hpp>
|
||||
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap, typename AddEdgeVisitor>
|
||||
struct triangulation_visitor : public planar_face_traversal_visitor
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef typename graph_traits<Graph>::degree_size_type degree_size_t;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::adjacency_iterator
|
||||
adjacency_iterator_t;
|
||||
typedef typename std::vector<vertex_t> vertex_vector_t;
|
||||
typedef typename std::vector<v_size_t> v_size_vector_t;
|
||||
typedef typename std::vector<degree_size_t> degree_size_vector_t;
|
||||
typedef iterator_property_map
|
||||
< typename v_size_vector_t::iterator, VertexIndexMap >
|
||||
vertex_to_v_size_map_t;
|
||||
typedef iterator_property_map
|
||||
< typename degree_size_vector_t::iterator, VertexIndexMap >
|
||||
vertex_to_degree_size_map_t;
|
||||
typedef typename vertex_vector_t::iterator face_iterator;
|
||||
|
||||
|
||||
triangulation_visitor(Graph& arg_g,
|
||||
VertexIndexMap arg_vm,
|
||||
AddEdgeVisitor arg_add_edge_visitor
|
||||
) :
|
||||
g(arg_g),
|
||||
vm(arg_vm),
|
||||
add_edge_visitor(arg_add_edge_visitor),
|
||||
timestamp(0),
|
||||
marked_vector(num_vertices(g), timestamp),
|
||||
degree_vector(num_vertices(g), 0),
|
||||
marked(marked_vector.begin(), vm),
|
||||
degree(degree_vector.begin(), vm)
|
||||
{
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(degree, *vi, out_degree(*vi, g));
|
||||
}
|
||||
|
||||
template <typename Vertex>
|
||||
void next_vertex(Vertex v)
|
||||
{
|
||||
// Self-loops will appear as consecutive vertices in the list of
|
||||
// vertices on a face. We want to skip these.
|
||||
if (!vertices_on_face.empty() &&
|
||||
(vertices_on_face.back() == v || vertices_on_face.front() == v)
|
||||
)
|
||||
return;
|
||||
|
||||
vertices_on_face.push_back(v);
|
||||
}
|
||||
|
||||
void end_face()
|
||||
{
|
||||
++timestamp;
|
||||
|
||||
if (vertices_on_face.size() <= 3)
|
||||
{
|
||||
// At most three vertices on this face - don't need to triangulate
|
||||
vertices_on_face.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find vertex on face of minimum degree
|
||||
degree_size_t min_degree = num_vertices(g);
|
||||
typename vertex_vector_t::iterator min_degree_vertex_itr;
|
||||
face_iterator fi_end = vertices_on_face.end();
|
||||
for(face_iterator fi = vertices_on_face.begin(); fi != fi_end; ++fi)
|
||||
{
|
||||
degree_size_t deg = get(degree,*fi);
|
||||
if (deg < min_degree)
|
||||
{
|
||||
min_degree_vertex_itr = fi;
|
||||
min_degree = deg;
|
||||
}
|
||||
}
|
||||
|
||||
// To simplify some of the manipulations, we'll re-arrange
|
||||
// vertices_on_face so that it still contains the same
|
||||
// (counter-clockwise) order of the vertices on this face, but now the
|
||||
// min_degree_vertex is the first element in vertices_on_face.
|
||||
vertex_vector_t temp_vector;
|
||||
std::copy(min_degree_vertex_itr, vertices_on_face.end(),
|
||||
std::back_inserter(temp_vector));
|
||||
std::copy(vertices_on_face.begin(), min_degree_vertex_itr,
|
||||
std::back_inserter(temp_vector));
|
||||
vertices_on_face.swap(temp_vector);
|
||||
|
||||
// Mark all of the min degree vertex's neighbors
|
||||
adjacency_iterator_t ai, ai_end;
|
||||
for(tie(ai,ai_end) = adjacent_vertices(vertices_on_face.front(),g);
|
||||
ai != ai_end; ++ai
|
||||
)
|
||||
{
|
||||
put(marked, *ai, timestamp);
|
||||
}
|
||||
|
||||
typename vertex_vector_t::iterator marked_neighbor
|
||||
= vertices_on_face.end();
|
||||
|
||||
// The iterator manipulations on the next two lines are safe because
|
||||
// vertices_on_face.size() > 3 (from the first test in this function)
|
||||
fi_end = prior(vertices_on_face.end());
|
||||
for(face_iterator fi = next(next(vertices_on_face.begin()));
|
||||
fi != fi_end; ++fi
|
||||
)
|
||||
{
|
||||
if (get(marked, *fi) == timestamp)
|
||||
{
|
||||
marked_neighbor = fi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (marked_neighbor == vertices_on_face.end())
|
||||
{
|
||||
add_edge_range(
|
||||
vertices_on_face[0],
|
||||
next(next(vertices_on_face.begin())),
|
||||
prior(vertices_on_face.end())
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_edge_range(
|
||||
vertices_on_face[1],
|
||||
next(marked_neighbor),
|
||||
vertices_on_face.end()
|
||||
);
|
||||
|
||||
add_edge_range(
|
||||
*next(marked_neighbor),
|
||||
next(next(vertices_on_face.begin())),
|
||||
marked_neighbor
|
||||
);
|
||||
}
|
||||
|
||||
//reset for the next face
|
||||
vertices_on_face.clear();
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void add_edge_range(vertex_t anchor,
|
||||
face_iterator fi,
|
||||
face_iterator fi_end
|
||||
)
|
||||
{
|
||||
for (; fi != fi_end; ++fi)
|
||||
{
|
||||
vertex_t v(*fi);
|
||||
add_edge_visitor.visit_vertex_pair(anchor, v, g);
|
||||
put(degree, anchor, get(degree, anchor) + 1);
|
||||
put(degree, v, get(degree, v) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Graph& g;
|
||||
VertexIndexMap vm;
|
||||
AddEdgeVisitor add_edge_visitor;
|
||||
v_size_t timestamp;
|
||||
vertex_vector_t vertices_on_face;
|
||||
v_size_vector_t marked_vector;
|
||||
degree_size_vector_t degree_vector;
|
||||
vertex_to_v_size_map_t marked;
|
||||
vertex_to_degree_size_map_t degree;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename VertexIndexMap,
|
||||
typename EdgeIndexMap,
|
||||
typename AddEdgeVisitor
|
||||
>
|
||||
void make_maximal_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
VertexIndexMap vm,
|
||||
EdgeIndexMap em,
|
||||
AddEdgeVisitor& vis)
|
||||
{
|
||||
triangulation_visitor<Graph,VertexIndexMap,AddEdgeVisitor>
|
||||
visitor(g, vm, vis);
|
||||
planar_face_traversal(g, embedding, visitor, em);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename VertexIndexMap,
|
||||
typename EdgeIndexMap
|
||||
>
|
||||
void make_maximal_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
VertexIndexMap vm,
|
||||
EdgeIndexMap em
|
||||
)
|
||||
{
|
||||
default_add_edge_visitor vis;
|
||||
make_maximal_planar(g, embedding, vm, em, vis);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename VertexIndexMap
|
||||
>
|
||||
void make_maximal_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
VertexIndexMap vm
|
||||
)
|
||||
{
|
||||
make_maximal_planar(g, embedding, vm, get(edge_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding
|
||||
>
|
||||
void make_maximal_planar(Graph& g,
|
||||
PlanarEmbedding embedding
|
||||
)
|
||||
{
|
||||
make_maximal_planar(g, embedding, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif //__MAKE_MAXIMAL_PLANAR_HPP__
|
||||
127
libraries/include/boost/graph/matrix_as_graph.hpp
Normal file
127
libraries/include/boost/graph/matrix_as_graph.hpp
Normal file
@@ -0,0 +1,127 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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_MATRIX2GRAPH_HPP
|
||||
#define BOOST_GRAPH_MATRIX2GRAPH_HPP
|
||||
|
||||
#include <utility>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/int_iterator.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Iter, class Vertex>
|
||||
class matrix_adj_iterator;
|
||||
|
||||
template <class Iter, class Vertex>
|
||||
class matrix_incidence_iterator;
|
||||
|
||||
}
|
||||
|
||||
#define BOOST_GRAPH_ADAPT_MATRIX_TO_GRAPH(Matrix) \
|
||||
namespace boost { \
|
||||
template <> \
|
||||
struct graph_traits< Matrix > { \
|
||||
typedef Matrix::OneD::const_iterator Iter; \
|
||||
typedef Matrix::size_type V; \
|
||||
typedef V vertex_descriptor; \
|
||||
typedef Iter E; \
|
||||
typedef E edge_descriptor; \
|
||||
typedef boost::matrix_incidence_iterator<Iter, V> out_edge_iterator; \
|
||||
typedef boost::matrix_adj_iterator<Iter, V> adjacency_iterator; \
|
||||
typedef Matrix::size_type size_type; \
|
||||
typedef boost::int_iterator<size_type> vertex_iterator; \
|
||||
\
|
||||
friend std::pair<vertex_iterator, vertex_iterator> \
|
||||
vertices(const Matrix& g) { \
|
||||
typedef vertex_iterator VIter; \
|
||||
return std::make_pair(VIter(0), VIter(g.nrows())); \
|
||||
} \
|
||||
\
|
||||
friend std::pair<out_edge_iterator, out_edge_iterator> \
|
||||
out_edges(V v, const Matrix& g) { \
|
||||
typedef out_edge_iterator IncIter; \
|
||||
return std::make_pair(IncIter(g[v].begin()), \
|
||||
IncIter(g[v].end())); \
|
||||
} \
|
||||
friend std::pair<adjacency_iterator, adjacency_iterator> \
|
||||
adjacent_vertices(V v, const Matrix& g) { \
|
||||
typedef adjacency_iterator AdjIter; \
|
||||
return std::make_pair(AdjIter(g[v].begin()), \
|
||||
AdjIter(g[v].end())); \
|
||||
} \
|
||||
friend vertex_descriptor \
|
||||
source(E e, const Matrix& g) { \
|
||||
return e.row(); \
|
||||
} \
|
||||
friend vertex_descriptor \
|
||||
target(E e, const Matrix& g) { \
|
||||
return e.column(); \
|
||||
} \
|
||||
friend size_type \
|
||||
num_vertices(const Matrix& g) { \
|
||||
return g.nrows(); \
|
||||
} \
|
||||
friend size_type \
|
||||
num_edges(const Matrix& g) { \
|
||||
return g.nnz(); \
|
||||
} \
|
||||
friend size_type \
|
||||
out_degree(V i, const Matrix& g) { \
|
||||
return g[i].nnz(); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Iter, class Vertex>
|
||||
class matrix_adj_iterator
|
||||
: public std::iterator<std::input_iterator_tag, Vertex >
|
||||
{
|
||||
typedef matrix_adj_iterator self;
|
||||
public:
|
||||
matrix_adj_iterator() { }
|
||||
matrix_adj_iterator(Iter i) : _iter(i) { }
|
||||
matrix_adj_iterator(const self& x) : _iter(x._iter) { }
|
||||
self& operator=(const self& x) { _iter = x._iter; return *this; }
|
||||
Vertex operator*() { return _iter.column(); }
|
||||
self& operator++() { ++_iter; return *this; }
|
||||
self operator++(int) { self t = *this; ++_iter; return t; }
|
||||
bool operator==(const self& x) const { return _iter == x._iter; }
|
||||
bool operator!=(const self& x) const { return _iter != x._iter; }
|
||||
protected:
|
||||
Iter _iter;
|
||||
};
|
||||
|
||||
template <class Iter, class Vertex>
|
||||
class matrix_incidence_iterator
|
||||
: public std::iterator<std::input_iterator_tag, Iter >
|
||||
{
|
||||
typedef matrix_incidence_iterator self;
|
||||
public:
|
||||
matrix_incidence_iterator() { }
|
||||
matrix_incidence_iterator(Iter i) : _iter(i) { }
|
||||
matrix_incidence_iterator(const self& x) : _iter(x._iter) { }
|
||||
self& operator=(const self& x) { _iter = x._iter; return *this; }
|
||||
Iter operator*() { return _iter; }
|
||||
self& operator++() { ++_iter; return *this; }
|
||||
self operator++(int) { self t = *this; ++_iter; return t; }
|
||||
bool operator==(const self& x) const { return _iter == x._iter; }
|
||||
bool operator!=(const self& x) const { return _iter != x._iter; }
|
||||
protected:
|
||||
Iter _iter;
|
||||
};
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_GRAPH_MATRIX2GRAPH_HPP*/
|
||||
883
libraries/include/boost/graph/max_cardinality_matching.hpp
Normal file
883
libraries/include/boost/graph/max_cardinality_matching.hpp
Normal file
@@ -0,0 +1,883 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) 2005 Aaron Windsor
|
||||
//
|
||||
// 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_MAXIMUM_CARDINALITY_MATCHING_HPP
|
||||
#define BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <algorithm> // for std::sort and std::stable_sort
|
||||
#include <utility> // for std::pair
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/utility.hpp> // for boost::tie
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/visitors.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
#include <boost/graph/filtered_graph.hpp>
|
||||
#include <boost/pending/disjoint_sets.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace graph { namespace detail {
|
||||
enum { V_EVEN, V_ODD, V_UNREACHED };
|
||||
} } // end namespace graph::detail
|
||||
|
||||
template <typename Graph, typename MateMap, typename VertexIndexMap>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
matching_size(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor
|
||||
vertex_descriptor_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
|
||||
v_size_t size_of_matching = 0;
|
||||
vertex_iterator_t vi, vi_end;
|
||||
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_descriptor_t v = *vi;
|
||||
if (get(mate,v) != graph_traits<Graph>::null_vertex()
|
||||
&& get(vm,v) < get(vm,get(mate,v)))
|
||||
++size_of_matching;
|
||||
}
|
||||
return size_of_matching;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap>
|
||||
inline typename graph_traits<Graph>::vertices_size_type
|
||||
matching_size(const Graph& g, MateMap mate)
|
||||
{
|
||||
return matching_size(g, mate, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap, typename VertexIndexMap>
|
||||
bool is_a_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor
|
||||
vertex_descriptor_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for( tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_descriptor_t v = *vi;
|
||||
if (get(mate,v) != graph_traits<Graph>::null_vertex()
|
||||
&& v != get(mate,get(mate,v)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap>
|
||||
inline bool is_a_matching(const Graph& g, MateMap mate)
|
||||
{
|
||||
return is_a_matching(g, mate, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
// Maximum Cardinality Matching Functors
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
|
||||
template <typename Graph, typename MateMap,
|
||||
typename VertexIndexMap = dummy_property_map>
|
||||
struct no_augmenting_path_finder
|
||||
{
|
||||
no_augmenting_path_finder(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{ }
|
||||
|
||||
inline bool augment_matching() { return false; }
|
||||
|
||||
template <typename PropertyMap>
|
||||
void get_current_matching(PropertyMap p) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap, typename VertexIndexMap>
|
||||
class edmonds_augmenting_path_finder
|
||||
{
|
||||
// This implementation of Edmonds' matching algorithm closely
|
||||
// follows Tarjan's description of the algorithm in "Data
|
||||
// Structures and Network Algorithms."
|
||||
|
||||
public:
|
||||
|
||||
//generates the type of an iterator property map from vertices to type X
|
||||
template <typename X>
|
||||
struct map_vertex_to_
|
||||
{
|
||||
typedef boost::iterator_property_map<typename std::vector<X>::iterator,
|
||||
VertexIndexMap> type;
|
||||
};
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor
|
||||
vertex_descriptor_t;
|
||||
typedef typename std::pair< vertex_descriptor_t, vertex_descriptor_t >
|
||||
vertex_pair_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef typename graph_traits<Graph>::edges_size_type e_size_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::out_edge_iterator
|
||||
out_edge_iterator_t;
|
||||
typedef typename std::deque<vertex_descriptor_t> vertex_list_t;
|
||||
typedef typename std::vector<edge_descriptor_t> edge_list_t;
|
||||
typedef typename map_vertex_to_<vertex_descriptor_t>::type
|
||||
vertex_to_vertex_map_t;
|
||||
typedef typename map_vertex_to_<int>::type vertex_to_int_map_t;
|
||||
typedef typename map_vertex_to_<vertex_pair_t>::type
|
||||
vertex_to_vertex_pair_map_t;
|
||||
typedef typename map_vertex_to_<v_size_t>::type vertex_to_vsize_map_t;
|
||||
typedef typename map_vertex_to_<e_size_t>::type vertex_to_esize_map_t;
|
||||
|
||||
|
||||
|
||||
|
||||
edmonds_augmenting_path_finder(const Graph& arg_g, MateMap arg_mate,
|
||||
VertexIndexMap arg_vm) :
|
||||
g(arg_g),
|
||||
vm(arg_vm),
|
||||
n_vertices(num_vertices(arg_g)),
|
||||
|
||||
mate_vector(n_vertices),
|
||||
ancestor_of_v_vector(n_vertices),
|
||||
ancestor_of_w_vector(n_vertices),
|
||||
vertex_state_vector(n_vertices),
|
||||
origin_vector(n_vertices),
|
||||
pred_vector(n_vertices),
|
||||
bridge_vector(n_vertices),
|
||||
ds_parent_vector(n_vertices),
|
||||
ds_rank_vector(n_vertices),
|
||||
|
||||
mate(mate_vector.begin(), vm),
|
||||
ancestor_of_v(ancestor_of_v_vector.begin(), vm),
|
||||
ancestor_of_w(ancestor_of_w_vector.begin(), vm),
|
||||
vertex_state(vertex_state_vector.begin(), vm),
|
||||
origin(origin_vector.begin(), vm),
|
||||
pred(pred_vector.begin(), vm),
|
||||
bridge(bridge_vector.begin(), vm),
|
||||
ds_parent_map(ds_parent_vector.begin(), vm),
|
||||
ds_rank_map(ds_rank_vector.begin(), vm),
|
||||
|
||||
ds(ds_rank_map, ds_parent_map)
|
||||
{
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
mate[*vi] = get(arg_mate, *vi);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool augment_matching()
|
||||
{
|
||||
//As an optimization, some of these values can be saved from one
|
||||
//iteration to the next instead of being re-initialized each
|
||||
//iteration, allowing for "lazy blossom expansion." This is not
|
||||
//currently implemented.
|
||||
|
||||
e_size_t timestamp = 0;
|
||||
even_edges.clear();
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_descriptor_t u = *vi;
|
||||
|
||||
origin[u] = u;
|
||||
pred[u] = u;
|
||||
ancestor_of_v[u] = 0;
|
||||
ancestor_of_w[u] = 0;
|
||||
ds.make_set(u);
|
||||
|
||||
if (mate[u] == graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
vertex_state[u] = graph::detail::V_EVEN;
|
||||
out_edge_iterator_t ei, ei_end;
|
||||
for(tie(ei,ei_end) = out_edges(u,g); ei != ei_end; ++ei)
|
||||
even_edges.push_back( *ei );
|
||||
}
|
||||
else
|
||||
vertex_state[u] = graph::detail::V_UNREACHED;
|
||||
}
|
||||
|
||||
//end initializations
|
||||
|
||||
vertex_descriptor_t v,w,w_free_ancestor,v_free_ancestor;
|
||||
w_free_ancestor = graph_traits<Graph>::null_vertex();
|
||||
v_free_ancestor = graph_traits<Graph>::null_vertex();
|
||||
bool found_alternating_path = false;
|
||||
|
||||
while(!even_edges.empty() && !found_alternating_path)
|
||||
{
|
||||
// since we push even edges onto the back of the list as
|
||||
// they're discovered, taking them off the back will search
|
||||
// for augmenting paths depth-first.
|
||||
edge_descriptor_t current_edge = even_edges.back();
|
||||
even_edges.pop_back();
|
||||
|
||||
v = source(current_edge,g);
|
||||
w = target(current_edge,g);
|
||||
|
||||
vertex_descriptor_t v_prime = origin[ds.find_set(v)];
|
||||
vertex_descriptor_t w_prime = origin[ds.find_set(w)];
|
||||
|
||||
// because of the way we put all of the edges on the queue,
|
||||
// v_prime should be labeled V_EVEN; the following is a
|
||||
// little paranoid but it could happen...
|
||||
if (vertex_state[v_prime] != graph::detail::V_EVEN)
|
||||
{
|
||||
std::swap(v_prime,w_prime);
|
||||
std::swap(v,w);
|
||||
}
|
||||
|
||||
if (vertex_state[w_prime] == graph::detail::V_UNREACHED)
|
||||
{
|
||||
vertex_state[w_prime] = graph::detail::V_ODD;
|
||||
vertex_state[mate[w_prime]] = graph::detail::V_EVEN;
|
||||
out_edge_iterator_t ei, ei_end;
|
||||
for( tie(ei,ei_end) = out_edges(mate[w_prime], g); ei != ei_end; ++ei)
|
||||
even_edges.push_back(*ei);
|
||||
pred[w_prime] = v;
|
||||
}
|
||||
|
||||
//w_prime == v_prime can happen below if we get an edge that has been
|
||||
//shrunk into a blossom
|
||||
else if (vertex_state[w_prime] == graph::detail::V_EVEN && w_prime != v_prime)
|
||||
{
|
||||
vertex_descriptor_t w_up = w_prime;
|
||||
vertex_descriptor_t v_up = v_prime;
|
||||
vertex_descriptor_t nearest_common_ancestor
|
||||
= graph_traits<Graph>::null_vertex();
|
||||
w_free_ancestor = graph_traits<Graph>::null_vertex();
|
||||
v_free_ancestor = graph_traits<Graph>::null_vertex();
|
||||
|
||||
// We now need to distinguish between the case that
|
||||
// w_prime and v_prime share an ancestor under the
|
||||
// "parent" relation, in which case we've found a
|
||||
// blossom and should shrink it, or the case that
|
||||
// w_prime and v_prime both have distinct ancestors that
|
||||
// are free, in which case we've found an alternating
|
||||
// path between those two ancestors.
|
||||
|
||||
++timestamp;
|
||||
|
||||
while (nearest_common_ancestor == graph_traits<Graph>::null_vertex() &&
|
||||
(v_free_ancestor == graph_traits<Graph>::null_vertex() ||
|
||||
w_free_ancestor == graph_traits<Graph>::null_vertex()
|
||||
)
|
||||
)
|
||||
{
|
||||
ancestor_of_w[w_up] = timestamp;
|
||||
ancestor_of_v[v_up] = timestamp;
|
||||
|
||||
if (w_free_ancestor == graph_traits<Graph>::null_vertex())
|
||||
w_up = parent(w_up);
|
||||
if (v_free_ancestor == graph_traits<Graph>::null_vertex())
|
||||
v_up = parent(v_up);
|
||||
|
||||
if (mate[v_up] == graph_traits<Graph>::null_vertex())
|
||||
v_free_ancestor = v_up;
|
||||
if (mate[w_up] == graph_traits<Graph>::null_vertex())
|
||||
w_free_ancestor = w_up;
|
||||
|
||||
if (ancestor_of_w[v_up] == timestamp)
|
||||
nearest_common_ancestor = v_up;
|
||||
else if (ancestor_of_v[w_up] == timestamp)
|
||||
nearest_common_ancestor = w_up;
|
||||
else if (v_free_ancestor == w_free_ancestor &&
|
||||
v_free_ancestor != graph_traits<Graph>::null_vertex())
|
||||
nearest_common_ancestor = v_up;
|
||||
}
|
||||
|
||||
if (nearest_common_ancestor == graph_traits<Graph>::null_vertex())
|
||||
found_alternating_path = true; //to break out of the loop
|
||||
else
|
||||
{
|
||||
//shrink the blossom
|
||||
link_and_set_bridges(w_prime, nearest_common_ancestor, std::make_pair(w,v));
|
||||
link_and_set_bridges(v_prime, nearest_common_ancestor, std::make_pair(v,w));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_alternating_path)
|
||||
return false;
|
||||
|
||||
// retrieve the augmenting path and put it in aug_path
|
||||
reversed_retrieve_augmenting_path(v, v_free_ancestor);
|
||||
retrieve_augmenting_path(w, w_free_ancestor);
|
||||
|
||||
// augment the matching along aug_path
|
||||
vertex_descriptor_t a,b;
|
||||
while (!aug_path.empty())
|
||||
{
|
||||
a = aug_path.front();
|
||||
aug_path.pop_front();
|
||||
b = aug_path.front();
|
||||
aug_path.pop_front();
|
||||
mate[a] = b;
|
||||
mate[b] = a;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename PropertyMap>
|
||||
void get_current_matching(PropertyMap pm)
|
||||
{
|
||||
vertex_iterator_t vi,vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(pm, *vi, mate[*vi]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename PropertyMap>
|
||||
void get_vertex_state_map(PropertyMap pm)
|
||||
{
|
||||
vertex_iterator_t vi,vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
vertex_descriptor_t parent(vertex_descriptor_t x)
|
||||
{
|
||||
if (vertex_state[x] == graph::detail::V_EVEN
|
||||
&& mate[x] != graph_traits<Graph>::null_vertex())
|
||||
return mate[x];
|
||||
else if (vertex_state[x] == graph::detail::V_ODD)
|
||||
return origin[ds.find_set(pred[x])];
|
||||
else
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void link_and_set_bridges(vertex_descriptor_t x,
|
||||
vertex_descriptor_t stop_vertex,
|
||||
vertex_pair_t the_bridge)
|
||||
{
|
||||
for(vertex_descriptor_t v = x; v != stop_vertex; v = parent(v))
|
||||
{
|
||||
ds.union_set(v, stop_vertex);
|
||||
origin[ds.find_set(stop_vertex)] = stop_vertex;
|
||||
|
||||
if (vertex_state[v] == graph::detail::V_ODD)
|
||||
{
|
||||
bridge[v] = the_bridge;
|
||||
out_edge_iterator_t oei, oei_end;
|
||||
for(tie(oei, oei_end) = out_edges(v,g); oei != oei_end; ++oei)
|
||||
even_edges.push_back(*oei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Since none of the STL containers support both constant-time
|
||||
// concatenation and reversal, the process of expanding an
|
||||
// augmenting path once we know one exists is a little more
|
||||
// complicated than it has to be. If we know the path is from v to
|
||||
// w, then the augmenting path is recursively defined as:
|
||||
//
|
||||
// path(v,w) = [v], if v = w
|
||||
// = concat([v, mate[v]], path(pred[mate[v]], w),
|
||||
// if v != w and vertex_state[v] == graph::detail::V_EVEN
|
||||
// = concat([v], reverse(path(x,mate[v])), path(y,w)),
|
||||
// if v != w, vertex_state[v] == graph::detail::V_ODD, and bridge[v] = (x,y)
|
||||
//
|
||||
// These next two mutually recursive functions implement this definition.
|
||||
|
||||
void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w)
|
||||
{
|
||||
if (v == w)
|
||||
aug_path.push_back(v);
|
||||
else if (vertex_state[v] == graph::detail::V_EVEN)
|
||||
{
|
||||
aug_path.push_back(v);
|
||||
aug_path.push_back(mate[v]);
|
||||
retrieve_augmenting_path(pred[mate[v]], w);
|
||||
}
|
||||
else //vertex_state[v] == graph::detail::V_ODD
|
||||
{
|
||||
aug_path.push_back(v);
|
||||
reversed_retrieve_augmenting_path(bridge[v].first, mate[v]);
|
||||
retrieve_augmenting_path(bridge[v].second, w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reversed_retrieve_augmenting_path(vertex_descriptor_t v,
|
||||
vertex_descriptor_t w)
|
||||
{
|
||||
|
||||
if (v == w)
|
||||
aug_path.push_back(v);
|
||||
else if (vertex_state[v] == graph::detail::V_EVEN)
|
||||
{
|
||||
reversed_retrieve_augmenting_path(pred[mate[v]], w);
|
||||
aug_path.push_back(mate[v]);
|
||||
aug_path.push_back(v);
|
||||
}
|
||||
else //vertex_state[v] == graph::detail::V_ODD
|
||||
{
|
||||
reversed_retrieve_augmenting_path(bridge[v].second, w);
|
||||
retrieve_augmenting_path(bridge[v].first, mate[v]);
|
||||
aug_path.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//private data members
|
||||
|
||||
const Graph& g;
|
||||
VertexIndexMap vm;
|
||||
v_size_t n_vertices;
|
||||
|
||||
//storage for the property maps below
|
||||
std::vector<vertex_descriptor_t> mate_vector;
|
||||
std::vector<e_size_t> ancestor_of_v_vector;
|
||||
std::vector<e_size_t> ancestor_of_w_vector;
|
||||
std::vector<int> vertex_state_vector;
|
||||
std::vector<vertex_descriptor_t> origin_vector;
|
||||
std::vector<vertex_descriptor_t> pred_vector;
|
||||
std::vector<vertex_pair_t> bridge_vector;
|
||||
std::vector<vertex_descriptor_t> ds_parent_vector;
|
||||
std::vector<v_size_t> ds_rank_vector;
|
||||
|
||||
//iterator property maps
|
||||
vertex_to_vertex_map_t mate;
|
||||
vertex_to_esize_map_t ancestor_of_v;
|
||||
vertex_to_esize_map_t ancestor_of_w;
|
||||
vertex_to_int_map_t vertex_state;
|
||||
vertex_to_vertex_map_t origin;
|
||||
vertex_to_vertex_map_t pred;
|
||||
vertex_to_vertex_pair_map_t bridge;
|
||||
vertex_to_vertex_map_t ds_parent_map;
|
||||
vertex_to_vsize_map_t ds_rank_map;
|
||||
|
||||
vertex_list_t aug_path;
|
||||
edge_list_t even_edges;
|
||||
disjoint_sets< vertex_to_vsize_map_t, vertex_to_vertex_map_t > ds;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
// Initial Matching Functors
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
|
||||
template <typename Graph, typename MateMap>
|
||||
struct greedy_matching
|
||||
{
|
||||
typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
|
||||
typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;
|
||||
typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;
|
||||
|
||||
static void find_matching(const Graph& g, MateMap mate)
|
||||
{
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
|
||||
edge_iterator_t ei, ei_end;
|
||||
for( tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
{
|
||||
edge_descriptor_t e = *ei;
|
||||
vertex_descriptor_t u = source(e,g);
|
||||
vertex_descriptor_t v = target(e,g);
|
||||
|
||||
if (get(mate,u) == get(mate,v))
|
||||
//only way equality can hold is if
|
||||
// mate[u] == mate[v] == null_vertex
|
||||
{
|
||||
put(mate,u,v);
|
||||
put(mate,v,u);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap>
|
||||
struct extra_greedy_matching
|
||||
{
|
||||
// The "extra greedy matching" is formed by repeating the
|
||||
// following procedure as many times as possible: Choose the
|
||||
// unmatched vertex v of minimum non-zero degree. Choose the
|
||||
// neighbor w of v which is unmatched and has minimum degree over
|
||||
// all of v's neighbors. Add (u,v) to the matching. Ties for
|
||||
// either choice are broken arbitrarily. This procedure takes time
|
||||
// O(m log n), where m is the number of edges in the graph and n
|
||||
// is the number of vertices.
|
||||
|
||||
typedef typename graph_traits< Graph >::vertex_descriptor
|
||||
vertex_descriptor_t;
|
||||
typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;
|
||||
typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;
|
||||
typedef std::pair<vertex_descriptor_t, vertex_descriptor_t> vertex_pair_t;
|
||||
|
||||
struct select_first
|
||||
{
|
||||
inline static vertex_descriptor_t select_vertex(const vertex_pair_t p)
|
||||
{return p.first;}
|
||||
};
|
||||
|
||||
struct select_second
|
||||
{
|
||||
inline static vertex_descriptor_t select_vertex(const vertex_pair_t p)
|
||||
{return p.second;}
|
||||
};
|
||||
|
||||
template <class PairSelector>
|
||||
class less_than_by_degree
|
||||
{
|
||||
public:
|
||||
less_than_by_degree(const Graph& g): m_g(g) {}
|
||||
bool operator() (const vertex_pair_t x, const vertex_pair_t y)
|
||||
{
|
||||
return
|
||||
out_degree(PairSelector::select_vertex(x), m_g)
|
||||
< out_degree(PairSelector::select_vertex(y), m_g);
|
||||
}
|
||||
private:
|
||||
const Graph& m_g;
|
||||
};
|
||||
|
||||
|
||||
static void find_matching(const Graph& g, MateMap mate)
|
||||
{
|
||||
typedef std::vector<std::pair<vertex_descriptor_t, vertex_descriptor_t> >
|
||||
directed_edges_vector_t;
|
||||
|
||||
directed_edges_vector_t edge_list;
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
|
||||
edge_iterator_t ei, ei_end;
|
||||
for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
{
|
||||
edge_descriptor_t e = *ei;
|
||||
vertex_descriptor_t u = source(e,g);
|
||||
vertex_descriptor_t v = target(e,g);
|
||||
edge_list.push_back(std::make_pair(u,v));
|
||||
edge_list.push_back(std::make_pair(v,u));
|
||||
}
|
||||
|
||||
//sort the edges by the degree of the target, then (using a
|
||||
//stable sort) by degree of the source
|
||||
std::sort(edge_list.begin(), edge_list.end(),
|
||||
less_than_by_degree<select_second>(g));
|
||||
std::stable_sort(edge_list.begin(), edge_list.end(),
|
||||
less_than_by_degree<select_first>(g));
|
||||
|
||||
//construct the extra greedy matching
|
||||
for(typename directed_edges_vector_t::const_iterator itr = edge_list.begin(); itr != edge_list.end(); ++itr)
|
||||
{
|
||||
if (get(mate,itr->first) == get(mate,itr->second))
|
||||
//only way equality can hold is if mate[itr->first] == mate[itr->second] == null_vertex
|
||||
{
|
||||
put(mate, itr->first, itr->second);
|
||||
put(mate, itr->second, itr->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap>
|
||||
struct empty_matching
|
||||
{
|
||||
typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
|
||||
|
||||
static void find_matching(const Graph& g, MateMap mate)
|
||||
{
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
// Matching Verifiers
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename SizeType>
|
||||
class odd_components_counter : public dfs_visitor<>
|
||||
// This depth-first search visitor will count the number of connected
|
||||
// components with an odd number of vertices. It's used by
|
||||
// maximum_matching_verifier.
|
||||
{
|
||||
public:
|
||||
odd_components_counter(SizeType& c_count):
|
||||
m_count(c_count)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void start_vertex(Vertex v, Graph&)
|
||||
{
|
||||
m_parity = false;
|
||||
}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph&)
|
||||
{
|
||||
m_parity = !m_parity;
|
||||
m_parity ? ++m_count : --m_count;
|
||||
}
|
||||
|
||||
protected:
|
||||
SizeType& m_count;
|
||||
|
||||
private:
|
||||
bool m_parity;
|
||||
|
||||
};
|
||||
|
||||
}//namespace detail
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap,
|
||||
typename VertexIndexMap = dummy_property_map>
|
||||
struct no_matching_verifier
|
||||
{
|
||||
inline static bool
|
||||
verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{ return true;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap, typename VertexIndexMap>
|
||||
struct maximum_cardinality_matching_verifier
|
||||
{
|
||||
|
||||
template <typename X>
|
||||
struct map_vertex_to_
|
||||
{
|
||||
typedef boost::iterator_property_map<typename std::vector<X>::iterator,
|
||||
VertexIndexMap> type;
|
||||
};
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor
|
||||
vertex_descriptor_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename map_vertex_to_<int>::type vertex_to_int_map_t;
|
||||
typedef typename map_vertex_to_<vertex_descriptor_t>::type
|
||||
vertex_to_vertex_map_t;
|
||||
|
||||
|
||||
template <typename VertexStateMap>
|
||||
struct non_odd_vertex {
|
||||
//this predicate is used to create a filtered graph that
|
||||
//excludes vertices labeled "graph::detail::V_ODD"
|
||||
non_odd_vertex() : vertex_state(0) { }
|
||||
|
||||
non_odd_vertex(VertexStateMap* arg_vertex_state)
|
||||
: vertex_state(arg_vertex_state) { }
|
||||
|
||||
template <typename Vertex>
|
||||
bool operator()(const Vertex& v) const
|
||||
{
|
||||
BOOST_ASSERT(vertex_state);
|
||||
return get(*vertex_state, v) != graph::detail::V_ODD;
|
||||
}
|
||||
|
||||
VertexStateMap* vertex_state;
|
||||
};
|
||||
|
||||
|
||||
static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{
|
||||
//For any graph G, let o(G) be the number of connected
|
||||
//components in G of odd size. For a subset S of G's vertex set
|
||||
//V(G), let (G - S) represent the subgraph of G induced by
|
||||
//removing all vertices in S from G. Let M(G) be the size of the
|
||||
//maximum cardinality matching in G. Then the Tutte-Berge
|
||||
//formula guarantees that
|
||||
//
|
||||
// 2 * M(G) = min ( |V(G)| + |U| + o(G - U) )
|
||||
//
|
||||
//where the minimum is taken over all subsets U of
|
||||
//V(G). Edmonds' algorithm finds a set U that achieves the
|
||||
//minimum in the above formula, namely the vertices labeled
|
||||
//"ODD." This function runs one iteration of Edmonds' algorithm
|
||||
//to find U, then verifies that the size of the matching given
|
||||
//by mate satisfies the Tutte-Berge formula.
|
||||
|
||||
//first, make sure it's a valid matching
|
||||
if (!is_a_matching(g,mate,vm))
|
||||
return false;
|
||||
|
||||
//We'll try to augment the matching once. This serves two
|
||||
//purposes: first, if we find some augmenting path, the matching
|
||||
//is obviously non-maximum. Second, running edmonds' algorithm
|
||||
//on a graph with no augmenting path will create the
|
||||
//Edmonds-Gallai decomposition that we need as a certificate of
|
||||
//maximality - we can get it by looking at the vertex_state map
|
||||
//that results.
|
||||
edmonds_augmenting_path_finder<Graph,MateMap,VertexIndexMap>
|
||||
augmentor(g,mate,vm);
|
||||
if (augmentor.augment_matching())
|
||||
return false;
|
||||
|
||||
std::vector<int> vertex_state_vector(num_vertices(g));
|
||||
vertex_to_int_map_t vertex_state(vertex_state_vector.begin(), vm);
|
||||
augmentor.get_vertex_state_map(vertex_state);
|
||||
|
||||
//count the number of graph::detail::V_ODD vertices
|
||||
v_size_t num_odd_vertices = 0;
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
if (vertex_state[*vi] == graph::detail::V_ODD)
|
||||
++num_odd_vertices;
|
||||
|
||||
//count the number of connected components with odd cardinality
|
||||
//in the graph without graph::detail::V_ODD vertices
|
||||
non_odd_vertex<vertex_to_int_map_t> filter(&vertex_state);
|
||||
filtered_graph<Graph, keep_all, non_odd_vertex<vertex_to_int_map_t> > fg(g, keep_all(), filter);
|
||||
|
||||
v_size_t num_odd_components;
|
||||
detail::odd_components_counter<v_size_t> occ(num_odd_components);
|
||||
depth_first_search(fg, visitor(occ).vertex_index_map(vm));
|
||||
|
||||
if (2 * matching_size(g,mate,vm) == num_vertices(g) + num_odd_vertices - num_odd_components)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename MateMap,
|
||||
typename VertexIndexMap,
|
||||
template <typename, typename, typename> class AugmentingPathFinder,
|
||||
template <typename, typename> class InitialMatchingFinder,
|
||||
template <typename, typename, typename> class MatchingVerifier>
|
||||
bool matching(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{
|
||||
|
||||
InitialMatchingFinder<Graph,MateMap>::find_matching(g,mate);
|
||||
|
||||
AugmentingPathFinder<Graph,MateMap,VertexIndexMap> augmentor(g,mate,vm);
|
||||
bool not_maximum_yet = true;
|
||||
while(not_maximum_yet)
|
||||
{
|
||||
not_maximum_yet = augmentor.augment_matching();
|
||||
}
|
||||
augmentor.get_current_matching(mate);
|
||||
|
||||
return MatchingVerifier<Graph,MateMap,VertexIndexMap>::verify_matching(g,mate,vm);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap, typename VertexIndexMap>
|
||||
inline bool checked_edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{
|
||||
return matching
|
||||
< Graph, MateMap, VertexIndexMap,
|
||||
edmonds_augmenting_path_finder, extra_greedy_matching, maximum_cardinality_matching_verifier>
|
||||
(g, mate, vm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap>
|
||||
inline bool checked_edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate)
|
||||
{
|
||||
return checked_edmonds_maximum_cardinality_matching(g, mate, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap, typename VertexIndexMap>
|
||||
inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{
|
||||
matching < Graph, MateMap, VertexIndexMap,
|
||||
edmonds_augmenting_path_finder, extra_greedy_matching, no_matching_verifier>
|
||||
(g, mate, vm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename MateMap>
|
||||
inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate)
|
||||
{
|
||||
edmonds_maximum_cardinality_matching(g, mate, get(vertex_index,g));
|
||||
}
|
||||
|
||||
}//namespace boost
|
||||
|
||||
#endif //BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP
|
||||
313
libraries/include/boost/graph/metric_tsp_approx.hpp
Normal file
313
libraries/include/boost/graph/metric_tsp_approx.hpp
Normal file
@@ -0,0 +1,313 @@
|
||||
|
||||
//=======================================================================
|
||||
// Copyright 2008
|
||||
// Author: Matyas W Egyhazy
|
||||
//
|
||||
// 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_METRIC_TSP_APPROX_HPP
|
||||
#define BOOST_GRAPH_METRIC_TSP_APPROX_HPP
|
||||
|
||||
// metric_tsp_approx
|
||||
// Generates an approximate tour solution for the traveling salesperson
|
||||
// problem in polynomial time. The current algorithm guarantees a tour with a
|
||||
// length at most as long as 2x optimal solution. The graph should have
|
||||
// 'natural' (metric) weights such that the triangle inequality is maintained.
|
||||
// Graphs must be fully interconnected.
|
||||
|
||||
// TODO:
|
||||
// There are a couple of improvements that could be made.
|
||||
// 1) Change implementation to lower uppper bound Christofides heuristic
|
||||
// 2) Implement a less restrictive TSP heuristic (one that does not rely on
|
||||
// triangle inequality).
|
||||
// 3) Determine if the algorithm can be implemented without creating a new
|
||||
// graph.
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/graph_as_tree.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/prim_minimum_spanning_tree.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// Define a concept for the concept-checking library.
|
||||
template <typename Visitor, typename Graph>
|
||||
struct TSPVertexVisitorConcept
|
||||
{
|
||||
private:
|
||||
Visitor vis_;
|
||||
public:
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
|
||||
BOOST_CONCEPT_USAGE(TSPVertexVisitorConcept)
|
||||
{
|
||||
Visitor vis(vis_); // require copy construction
|
||||
Graph g(1);
|
||||
Vertex v(*vertices(g).first);
|
||||
vis_.visit_vertex(v, g); // require visit_vertex
|
||||
}
|
||||
};
|
||||
|
||||
// Tree visitor that keeps track of a preorder traversal of a tree
|
||||
// TODO: Consider migrating this to the graph_as_tree header.
|
||||
// TODO: Parameterize the underlying stores o it doesn't have to be a vector.
|
||||
template<typename Node, typename Tree> class PreorderTraverser
|
||||
{
|
||||
private:
|
||||
std::vector<Node>& path_;
|
||||
public:
|
||||
typedef typename std::vector<Node>::const_iterator const_iterator;
|
||||
|
||||
PreorderTraverser(std::vector<Node>& p) : path_(p) {}
|
||||
|
||||
void preorder(Node n, const Tree& t)
|
||||
{ path_.push_back(n); }
|
||||
|
||||
void inorder(Node n, const Tree& t) const {}
|
||||
void postorder(Node, const Tree& t) const {}
|
||||
|
||||
const_iterator begin() const { return path_.begin(); }
|
||||
const_iterator end() const { return path_.end(); }
|
||||
};
|
||||
|
||||
// Forward declarations
|
||||
template <typename> class tsp_tour_visitor;
|
||||
template <typename, typename, typename, typename> class tsp_tour_len_visitor;
|
||||
|
||||
template<typename VertexListGraph, typename OutputIterator>
|
||||
void metric_tsp_approx_tour(VertexListGraph& g, OutputIterator o)
|
||||
{
|
||||
metric_tsp_approx_from_vertex(g, *vertices(g).first,
|
||||
get(edge_weight, g), get(vertex_index, g),
|
||||
tsp_tour_visitor<OutputIterator>(o));
|
||||
}
|
||||
|
||||
template<typename VertexListGraph, typename WeightMap, typename OutputIterator>
|
||||
void metric_tsp_approx_tour(VertexListGraph& g, WeightMap w, OutputIterator o)
|
||||
{
|
||||
metric_tsp_approx_from_vertex(g, *vertices(g).first,
|
||||
w, tsp_tour_visitor<OutputIterator>(o));
|
||||
}
|
||||
|
||||
template<typename VertexListGraph, typename OutputIterator>
|
||||
void metric_tsp_approx_tour_from_vertex(VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor start,
|
||||
OutputIterator o)
|
||||
{
|
||||
metric_tsp_approx_from_vertex(g, start, get(edge_weight, g),
|
||||
get(vertex_index, g), tsp_tour_visitor<OutputIterator>(o));
|
||||
}
|
||||
|
||||
template<typename VertexListGraph, typename WeightMap,
|
||||
typename OutputIterator>
|
||||
void metric_tsp_approx_tour_from_vertex(VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor start,
|
||||
WeightMap w, OutputIterator o)
|
||||
{
|
||||
metric_tsp_approx_from_vertex(g, start, w, get(vertex_index, g),
|
||||
tsp_tour_visitor<OutputIterator>(o));
|
||||
}
|
||||
|
||||
template<typename VertexListGraph, typename TSPVertexVisitor>
|
||||
void metric_tsp_approx(VertexListGraph& g, TSPVertexVisitor vis)
|
||||
{
|
||||
metric_tsp_approx_from_vertex(g, *vertices(g).first,
|
||||
get(edge_weight, g), get(vertex_index, g), vis);
|
||||
}
|
||||
|
||||
template<typename VertexListGraph, typename Weightmap,
|
||||
typename VertexIndexMap, typename TSPVertexVisitor>
|
||||
void metric_tsp_approx(VertexListGraph& g, Weightmap w,
|
||||
TSPVertexVisitor vis)
|
||||
{
|
||||
metric_tsp_approx_from_vertex(g, *vertices(g).first, w,
|
||||
get(vertex_index, g), vis);
|
||||
}
|
||||
|
||||
template<typename VertexListGraph, typename WeightMap,
|
||||
typename VertexIndexMap, typename TSPVertexVisitor>
|
||||
void metric_tsp_approx(VertexListGraph& g, WeightMap w, VertexIndexMap id,
|
||||
TSPVertexVisitor vis)
|
||||
{
|
||||
metric_tsp_approx_from_vertex(g, *vertices(g).first, w, id, vis);
|
||||
}
|
||||
|
||||
template<typename VertexListGraph, typename WeightMap,
|
||||
typename TSPVertexVisitor>
|
||||
void metric_tsp_approx_from_vertex(VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor start,
|
||||
WeightMap w, TSPVertexVisitor vis)
|
||||
{
|
||||
metric_tsp_approx_from_vertex(g, start, w, get(vertex_index, g), vis);
|
||||
}
|
||||
|
||||
template <
|
||||
typename VertexListGraph,
|
||||
typename WeightMap,
|
||||
typename VertexIndexMap,
|
||||
typename TSPVertexVisitor>
|
||||
void metric_tsp_approx_from_vertex(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor start,
|
||||
WeightMap weightmap,
|
||||
VertexIndexMap indexmap,
|
||||
TSPVertexVisitor vis)
|
||||
{
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
BOOST_CONCEPT_ASSERT((VertexListGraphConcept<VertexListGraph>));
|
||||
BOOST_CONCEPT_ASSERT((TSPVertexVisitorConcept<TSPVertexVisitor, VertexListGraph>));
|
||||
|
||||
// Types related to the input graph (GVertex is a template parameter).
|
||||
typedef typename graph_traits<VertexListGraph>::vertex_descriptor GVertex;
|
||||
typedef typename graph_traits<VertexListGraph>::vertex_iterator GVItr;
|
||||
|
||||
// We build a custom graph in this algorithm.
|
||||
typedef adjacency_list <vecS, vecS, directedS, no_property, no_property > MSTImpl;
|
||||
typedef graph_traits<MSTImpl>::edge_descriptor Edge;
|
||||
typedef graph_traits<MSTImpl>::vertex_descriptor Vertex;
|
||||
typedef graph_traits<MSTImpl>::vertex_iterator VItr;
|
||||
|
||||
// And then re-cast it as a tree.
|
||||
typedef iterator_property_map<vector<Vertex>::iterator, property_map<MSTImpl, vertex_index_t>::type> ParentMap;
|
||||
typedef graph_as_tree<MSTImpl, ParentMap> Tree;
|
||||
typedef tree_traits<Tree>::node_descriptor Node;
|
||||
|
||||
// A predecessor map.
|
||||
typedef vector<GVertex> PredMap;
|
||||
typedef iterator_property_map<typename PredMap::iterator, VertexIndexMap> PredPMap;
|
||||
|
||||
PredMap preds(num_vertices(g));
|
||||
PredPMap pred_pmap(preds.begin(), indexmap);
|
||||
|
||||
// Compute a spanning tree over the in put g.
|
||||
prim_minimum_spanning_tree(g, pred_pmap,
|
||||
root_vertex(start)
|
||||
.vertex_index_map(indexmap)
|
||||
.weight_map(weightmap));
|
||||
|
||||
// Build a MST using the predecessor map from prim mst
|
||||
MSTImpl mst(num_vertices(g));
|
||||
std::size_t cnt = 0;
|
||||
pair<VItr, VItr> mst_verts(vertices(mst));
|
||||
for(typename PredMap::iterator vi(preds.begin()); vi != preds.end(); ++vi, ++cnt)
|
||||
{
|
||||
if(indexmap[*vi] != cnt) {
|
||||
add_edge(*next(mst_verts.first, indexmap[*vi]),
|
||||
*next(mst_verts.first, cnt), mst);
|
||||
}
|
||||
}
|
||||
|
||||
// Build a tree abstraction over the MST.
|
||||
vector<Vertex> parent(num_vertices(mst));
|
||||
Tree t(mst, *vertices(mst).first,
|
||||
make_iterator_property_map(parent.begin(),
|
||||
get(vertex_index, mst)));
|
||||
|
||||
// Create tour using a preorder traversal of the mst
|
||||
vector<Node> tour;
|
||||
PreorderTraverser<Node, Tree> tvis(tour);
|
||||
traverse_tree(0, t, tvis);
|
||||
|
||||
pair<GVItr, GVItr> g_verts(vertices(g));
|
||||
for(PreorderTraverser<Node, Tree>::const_iterator curr(tvis.begin());
|
||||
curr != tvis.end(); ++curr)
|
||||
{
|
||||
// TODO: This is will be O(n^2) if vertex storage of g != vecS.
|
||||
GVertex v = *next(g_verts.first, get(vertex_index, mst)[*curr]);
|
||||
vis.visit_vertex(v, g);
|
||||
}
|
||||
|
||||
// Connect back to the start of the tour
|
||||
vis.visit_vertex(*g_verts.first, g);
|
||||
}
|
||||
|
||||
// Default tsp tour visitor that puts the tour in an OutputIterator
|
||||
template <typename OutItr>
|
||||
class tsp_tour_visitor
|
||||
{
|
||||
OutItr itr_;
|
||||
public:
|
||||
tsp_tour_visitor(OutItr itr)
|
||||
: itr_(itr)
|
||||
{ }
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void visit_vertex(Vertex v, const Graph& g)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((OutputIterator<OutItr, Vertex>));
|
||||
*itr_++ = v;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Tsp tour visitor that adds the total tour length.
|
||||
template<typename Graph, typename WeightMap, typename OutIter, typename Length>
|
||||
class tsp_tour_len_visitor
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
BOOST_CONCEPT_ASSERT((OutputIterator<OutIter, Vertex>));
|
||||
|
||||
OutIter iter_;
|
||||
Length& tourlen_;
|
||||
WeightMap& wmap_;
|
||||
Vertex previous_;
|
||||
|
||||
// Helper function for getting the null vertex.
|
||||
Vertex null()
|
||||
{ return graph_traits<Graph>::null_vertex(); }
|
||||
|
||||
public:
|
||||
tsp_tour_len_visitor(Graph const&, OutIter iter, Length& l, WeightMap map)
|
||||
: iter_(iter), tourlen_(l), wmap_(map), previous_(null())
|
||||
{ }
|
||||
|
||||
void visit_vertex(Vertex v, const Graph& g)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_descriptor Edge;
|
||||
|
||||
// If it is not the start, then there is a
|
||||
// previous vertex
|
||||
if(previous_ != null())
|
||||
{
|
||||
// NOTE: For non-adjacency matrix graphs g, this bit of code
|
||||
// will be linear in the degree of previous_ or v. A better
|
||||
// solution would be to visit edges of the graph, but that
|
||||
// would require revisiting the core algorithm.
|
||||
Edge e;
|
||||
bool found;
|
||||
tie(e, found) = edge(previous_, v, g);
|
||||
if(!found) {
|
||||
throw not_complete();
|
||||
}
|
||||
|
||||
tourlen_ += wmap_[e];
|
||||
}
|
||||
|
||||
previous_ = v;
|
||||
*iter_++ = v;
|
||||
}
|
||||
};
|
||||
|
||||
// Object generator(s)
|
||||
template <typename OutIter>
|
||||
inline tsp_tour_visitor<OutIter>
|
||||
make_tsp_tour_visitor(OutIter iter)
|
||||
{ return tsp_tour_visitor<OutIter>(iter); }
|
||||
|
||||
template <typename Graph, typename WeightMap, typename OutIter, typename Length>
|
||||
inline tsp_tour_len_visitor<Graph, WeightMap, OutIter, Length>
|
||||
make_tsp_tour_len_visitor(Graph const& g, OutIter iter, Length& l, WeightMap map)
|
||||
{ return tsp_tour_len_visitor<Graph, WeightMap, OutIter, Length>(g, iter, l, map); }
|
||||
|
||||
} //boost
|
||||
|
||||
#endif // BOOST_GRAPH_METRIC_TSP_APPROX_HPP
|
||||
655
libraries/include/boost/graph/minimum_degree_ordering.hpp
Normal file
655
libraries/include/boost/graph/minimum_degree_ordering.hpp
Normal file
@@ -0,0 +1,655 @@
|
||||
//-*-c++-*-
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 University of Notre Dame.
|
||||
// Authors: Lie-Quan Lee, Jeremy 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 MINIMUM_DEGREE_ORDERING_HPP
|
||||
#define MINIMUM_DEGREE_ORDERING_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/pending/bucket_sorter.hpp>
|
||||
#include <boost/detail/numeric_traits.hpp> // for integer_traits
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
//
|
||||
// Given a set of n integers (where the integer values range from
|
||||
// zero to n-1), we want to keep track of a collection of stacks
|
||||
// of integers. It so happens that an integer will appear in at
|
||||
// most one stack at a time, so the stacks form disjoint sets.
|
||||
// Because of these restrictions, we can use one big array to
|
||||
// store all the stacks, intertwined with one another.
|
||||
// No allocation/deallocation happens in the push()/pop() methods
|
||||
// so this is faster than using std::stack's.
|
||||
//
|
||||
template <class SignedInteger>
|
||||
class Stacks {
|
||||
typedef SignedInteger value_type;
|
||||
typedef typename std::vector<value_type>::size_type size_type;
|
||||
public:
|
||||
Stacks(size_type n) : data(n) {}
|
||||
|
||||
//: stack
|
||||
class stack {
|
||||
typedef typename std::vector<value_type>::iterator Iterator;
|
||||
public:
|
||||
stack(Iterator _data, const value_type& head)
|
||||
: data(_data), current(head) {}
|
||||
|
||||
// did not use default argument here to avoid internal compiler error
|
||||
// in g++.
|
||||
stack(Iterator _data)
|
||||
: data(_data), current(-(std::numeric_limits<value_type>::max)()) {}
|
||||
|
||||
void pop() {
|
||||
assert(! empty());
|
||||
current = data[current];
|
||||
}
|
||||
void push(value_type v) {
|
||||
data[v] = current;
|
||||
current = v;
|
||||
}
|
||||
bool empty() {
|
||||
return current == -(std::numeric_limits<value_type>::max)();
|
||||
}
|
||||
value_type& top() { return current; }
|
||||
private:
|
||||
Iterator data;
|
||||
value_type current;
|
||||
};
|
||||
|
||||
// To return a stack object
|
||||
stack make_stack()
|
||||
{ return stack(data.begin()); }
|
||||
protected:
|
||||
std::vector<value_type> data;
|
||||
};
|
||||
|
||||
|
||||
// marker class, a generalization of coloring.
|
||||
//
|
||||
// This class is to provide a generalization of coloring which has
|
||||
// complexity of amortized constant time to set all vertices' color
|
||||
// back to be untagged. It implemented by increasing a tag.
|
||||
//
|
||||
// The colors are:
|
||||
// not tagged
|
||||
// tagged
|
||||
// multiple_tagged
|
||||
// done
|
||||
//
|
||||
template <class SignedInteger, class Vertex, class VertexIndexMap>
|
||||
class Marker {
|
||||
typedef SignedInteger value_type;
|
||||
typedef typename std::vector<value_type>::size_type size_type;
|
||||
|
||||
static value_type done()
|
||||
{ return (std::numeric_limits<value_type>::max)()/2; }
|
||||
public:
|
||||
Marker(size_type _num, VertexIndexMap index_map)
|
||||
: tag(1 - (std::numeric_limits<value_type>::max)()),
|
||||
data(_num, - (std::numeric_limits<value_type>::max)()),
|
||||
id(index_map) {}
|
||||
|
||||
void mark_done(Vertex node) { data[get(id, node)] = done(); }
|
||||
|
||||
bool is_done(Vertex node) { return data[get(id, node)] == done(); }
|
||||
|
||||
void mark_tagged(Vertex node) { data[get(id, node)] = tag; }
|
||||
|
||||
void mark_multiple_tagged(Vertex node) { data[get(id, node)] = multiple_tag; }
|
||||
|
||||
bool is_tagged(Vertex node) const { return data[get(id, node)] >= tag; }
|
||||
|
||||
bool is_not_tagged(Vertex node) const { return data[get(id, node)] < tag; }
|
||||
|
||||
bool is_multiple_tagged(Vertex node) const
|
||||
{ return data[get(id, node)] >= multiple_tag; }
|
||||
|
||||
void increment_tag() {
|
||||
const size_type num = data.size();
|
||||
++tag;
|
||||
if ( tag >= done() ) {
|
||||
tag = 1 - (std::numeric_limits<value_type>::max)();
|
||||
for (size_type i = 0; i < num; ++i)
|
||||
if ( data[i] < done() )
|
||||
data[i] = - (std::numeric_limits<value_type>::max)();
|
||||
}
|
||||
}
|
||||
|
||||
void set_multiple_tag(value_type mdeg0)
|
||||
{
|
||||
const size_type num = data.size();
|
||||
multiple_tag = tag + mdeg0;
|
||||
|
||||
if ( multiple_tag >= done() ) {
|
||||
tag = 1-(std::numeric_limits<value_type>::max)();
|
||||
|
||||
for (size_type i=0; i<num; i++)
|
||||
if ( data[i] < done() )
|
||||
data[i] = -(std::numeric_limits<value_type>::max)();
|
||||
|
||||
multiple_tag = tag + mdeg0;
|
||||
}
|
||||
}
|
||||
|
||||
void set_tag_as_multiple_tag() { tag = multiple_tag; }
|
||||
|
||||
protected:
|
||||
value_type tag;
|
||||
value_type multiple_tag;
|
||||
std::vector<value_type> data;
|
||||
VertexIndexMap id;
|
||||
};
|
||||
|
||||
template< class Iterator, class SignedInteger,
|
||||
class Vertex, class VertexIndexMap, int offset = 1 >
|
||||
class Numbering {
|
||||
typedef SignedInteger number_type;
|
||||
number_type num; //start from 1 instead of zero
|
||||
Iterator data;
|
||||
number_type max_num;
|
||||
VertexIndexMap id;
|
||||
public:
|
||||
Numbering(Iterator _data, number_type _max_num, VertexIndexMap id)
|
||||
: num(1), data(_data), max_num(_max_num), id(id) {}
|
||||
void operator()(Vertex node) { data[get(id, node)] = -num; }
|
||||
bool all_done(number_type i = 0) const { return num + i > max_num; }
|
||||
void increment(number_type i = 1) { num += i; }
|
||||
bool is_numbered(Vertex node) const {
|
||||
return data[get(id, node)] < 0;
|
||||
}
|
||||
void indistinguishable(Vertex i, Vertex j) {
|
||||
data[get(id, i)] = - (get(id, j) + offset);
|
||||
}
|
||||
};
|
||||
|
||||
template <class SignedInteger, class Vertex, class VertexIndexMap>
|
||||
class degreelists_marker {
|
||||
public:
|
||||
typedef SignedInteger value_type;
|
||||
typedef typename std::vector<value_type>::size_type size_type;
|
||||
degreelists_marker(size_type n, VertexIndexMap id)
|
||||
: marks(n, 0), id(id) {}
|
||||
void mark_need_update(Vertex i) { marks[get(id, i)] = 1; }
|
||||
bool need_update(Vertex i) { return marks[get(id, i)] == 1; }
|
||||
bool outmatched_or_done (Vertex i) { return marks[get(id, i)] == -1; }
|
||||
void mark(Vertex i) { marks[get(id, i)] = -1; }
|
||||
void unmark(Vertex i) { marks[get(id, i)] = 0; }
|
||||
private:
|
||||
std::vector<value_type> marks;
|
||||
VertexIndexMap id;
|
||||
};
|
||||
|
||||
// Helper function object for edge removal
|
||||
template <class Graph, class MarkerP, class NumberD, class Stack,
|
||||
class VertexIndexMap>
|
||||
class predicateRemoveEdge1 {
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
public:
|
||||
predicateRemoveEdge1(Graph& _g, MarkerP& _marker,
|
||||
NumberD _numbering, Stack& n_e, VertexIndexMap id)
|
||||
: g(&_g), marker(&_marker), numbering(_numbering),
|
||||
neighbor_elements(&n_e), id(id) {}
|
||||
|
||||
bool operator()(edge_t e) {
|
||||
vertex_t dist = target(e, *g);
|
||||
if ( marker->is_tagged(dist) )
|
||||
return true;
|
||||
marker->mark_tagged(dist);
|
||||
if (numbering.is_numbered(dist)) {
|
||||
neighbor_elements->push(get(id, dist));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
Graph* g;
|
||||
MarkerP* marker;
|
||||
NumberD numbering;
|
||||
Stack* neighbor_elements;
|
||||
VertexIndexMap id;
|
||||
};
|
||||
|
||||
// Helper function object for edge removal
|
||||
template <class Graph, class MarkerP>
|
||||
class predicate_remove_tagged_edges
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
public:
|
||||
predicate_remove_tagged_edges(Graph& _g, MarkerP& _marker)
|
||||
: g(&_g), marker(&_marker) {}
|
||||
|
||||
bool operator()(edge_t e) {
|
||||
vertex_t dist = target(e, *g);
|
||||
if ( marker->is_tagged(dist) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
Graph* g;
|
||||
MarkerP* marker;
|
||||
};
|
||||
|
||||
template<class Graph, class DegreeMap,
|
||||
class InversePermutationMap,
|
||||
class PermutationMap,
|
||||
class SuperNodeMap,
|
||||
class VertexIndexMap>
|
||||
class mmd_impl
|
||||
{
|
||||
// Typedefs
|
||||
typedef graph_traits<Graph> Traits;
|
||||
typedef typename Traits::vertices_size_type size_type;
|
||||
typedef typename detail::integer_traits<size_type>::difference_type
|
||||
diff_t;
|
||||
typedef typename Traits::vertex_descriptor vertex_t;
|
||||
typedef typename Traits::adjacency_iterator adj_iter;
|
||||
typedef iterator_property_map<vertex_t*,
|
||||
identity_property_map, vertex_t, vertex_t&> IndexVertexMap;
|
||||
typedef detail::Stacks<diff_t> Workspace;
|
||||
typedef bucket_sorter<size_type, vertex_t, DegreeMap, VertexIndexMap>
|
||||
DegreeLists;
|
||||
typedef Numbering<InversePermutationMap, diff_t, vertex_t,VertexIndexMap>
|
||||
NumberingD;
|
||||
typedef degreelists_marker<diff_t, vertex_t, VertexIndexMap>
|
||||
DegreeListsMarker;
|
||||
typedef Marker<diff_t, vertex_t, VertexIndexMap> MarkerP;
|
||||
|
||||
// Data Members
|
||||
|
||||
// input parameters
|
||||
Graph& G;
|
||||
int delta;
|
||||
DegreeMap degree;
|
||||
InversePermutationMap inverse_perm;
|
||||
PermutationMap perm;
|
||||
SuperNodeMap supernode_size;
|
||||
VertexIndexMap vertex_index_map;
|
||||
|
||||
// internal data-structures
|
||||
std::vector<vertex_t> index_vertex_vec;
|
||||
size_type n;
|
||||
IndexVertexMap index_vertex_map;
|
||||
DegreeLists degreelists;
|
||||
NumberingD numbering;
|
||||
DegreeListsMarker degree_lists_marker;
|
||||
MarkerP marker;
|
||||
Workspace work_space;
|
||||
public:
|
||||
mmd_impl(Graph& g, size_type n_, int delta, DegreeMap degree,
|
||||
InversePermutationMap inverse_perm,
|
||||
PermutationMap perm,
|
||||
SuperNodeMap supernode_size,
|
||||
VertexIndexMap id)
|
||||
: G(g), delta(delta), degree(degree),
|
||||
inverse_perm(inverse_perm),
|
||||
perm(perm),
|
||||
supernode_size(supernode_size),
|
||||
vertex_index_map(id),
|
||||
index_vertex_vec(n_),
|
||||
n(n_),
|
||||
degreelists(n_ + 1, n_, degree, id),
|
||||
numbering(inverse_perm, n_, vertex_index_map),
|
||||
degree_lists_marker(n_, vertex_index_map),
|
||||
marker(n_, vertex_index_map),
|
||||
work_space(n_)
|
||||
{
|
||||
typename graph_traits<Graph>::vertex_iterator v, vend;
|
||||
size_type vid = 0;
|
||||
for (tie(v, vend) = vertices(G); v != vend; ++v, ++vid)
|
||||
index_vertex_vec[vid] = *v;
|
||||
index_vertex_map = IndexVertexMap(&index_vertex_vec[0]);
|
||||
|
||||
// Initialize degreelists. Degreelists organizes the nodes
|
||||
// according to their degree.
|
||||
for (tie(v, vend) = vertices(G); v != vend; ++v) {
|
||||
put(degree, *v, out_degree(*v, G));
|
||||
degreelists.push(*v);
|
||||
}
|
||||
}
|
||||
|
||||
void do_mmd()
|
||||
{
|
||||
// Eliminate the isolated nodes -- these are simply the nodes
|
||||
// with no neighbors, which are accessible as a list (really, a
|
||||
// stack) at location 0. Since these don't affect any other
|
||||
// nodes, we can eliminate them without doing degree updates.
|
||||
typename DegreeLists::stack list_isolated = degreelists[0];
|
||||
while (!list_isolated.empty()) {
|
||||
vertex_t node = list_isolated.top();
|
||||
marker.mark_done(node);
|
||||
numbering(node);
|
||||
numbering.increment();
|
||||
list_isolated.pop();
|
||||
}
|
||||
size_type min_degree = 1;
|
||||
typename DegreeLists::stack list_min_degree = degreelists[min_degree];
|
||||
|
||||
while (list_min_degree.empty()) {
|
||||
++min_degree;
|
||||
list_min_degree = degreelists[min_degree];
|
||||
}
|
||||
|
||||
// check if the whole eliminating process is done
|
||||
while (!numbering.all_done()) {
|
||||
|
||||
size_type min_degree_limit = min_degree + delta; // WARNING
|
||||
typename Workspace::stack llist = work_space.make_stack();
|
||||
|
||||
// multiple elimination
|
||||
while (delta >= 0) {
|
||||
|
||||
// Find the next non-empty degree
|
||||
for (list_min_degree = degreelists[min_degree];
|
||||
list_min_degree.empty() && min_degree <= min_degree_limit;
|
||||
++min_degree, list_min_degree = degreelists[min_degree])
|
||||
;
|
||||
if (min_degree > min_degree_limit)
|
||||
break;
|
||||
|
||||
const vertex_t node = list_min_degree.top();
|
||||
const size_type node_id = get(vertex_index_map, node);
|
||||
list_min_degree.pop();
|
||||
numbering(node);
|
||||
|
||||
// check if node is the last one
|
||||
if (numbering.all_done(supernode_size[node])) {
|
||||
numbering.increment(supernode_size[node]);
|
||||
break;
|
||||
}
|
||||
marker.increment_tag();
|
||||
marker.mark_tagged(node);
|
||||
|
||||
this->eliminate(node);
|
||||
|
||||
numbering.increment(supernode_size[node]);
|
||||
llist.push(node_id);
|
||||
} // multiple elimination
|
||||
|
||||
if (numbering.all_done())
|
||||
break;
|
||||
|
||||
this->update( llist, min_degree);
|
||||
}
|
||||
|
||||
} // do_mmd()
|
||||
|
||||
void eliminate(vertex_t node)
|
||||
{
|
||||
typename Workspace::stack element_neighbor = work_space.make_stack();
|
||||
|
||||
// Create two function objects for edge removal
|
||||
typedef typename Workspace::stack WorkStack;
|
||||
predicateRemoveEdge1<Graph, MarkerP, NumberingD,
|
||||
WorkStack, VertexIndexMap>
|
||||
p(G, marker, numbering, element_neighbor, vertex_index_map);
|
||||
|
||||
predicate_remove_tagged_edges<Graph, MarkerP> p2(G, marker);
|
||||
|
||||
// Reconstruct the adjacent node list, push element neighbor in a List.
|
||||
remove_out_edge_if(node, p, G);
|
||||
//during removal element neighbors are collected.
|
||||
|
||||
while (!element_neighbor.empty()) {
|
||||
// element absorb
|
||||
size_type e_id = element_neighbor.top();
|
||||
vertex_t element = get(index_vertex_map, e_id);
|
||||
adj_iter i, i_end;
|
||||
for (tie(i, i_end) = adjacent_vertices(element, G); i != i_end; ++i){
|
||||
vertex_t i_node = *i;
|
||||
if (!marker.is_tagged(i_node) && !numbering.is_numbered(i_node)) {
|
||||
marker.mark_tagged(i_node);
|
||||
add_edge(node, i_node, G);
|
||||
}
|
||||
}
|
||||
element_neighbor.pop();
|
||||
}
|
||||
adj_iter v, ve;
|
||||
for (tie(v, ve) = adjacent_vertices(node, G); v != ve; ++v) {
|
||||
vertex_t v_node = *v;
|
||||
if (!degree_lists_marker.need_update(v_node)
|
||||
&& !degree_lists_marker.outmatched_or_done(v_node)) {
|
||||
degreelists.remove(v_node);
|
||||
}
|
||||
//update out edges of v_node
|
||||
remove_out_edge_if(v_node, p2, G);
|
||||
|
||||
if ( out_degree(v_node, G) == 0 ) { // indistinguishable nodes
|
||||
supernode_size[node] += supernode_size[v_node];
|
||||
supernode_size[v_node] = 0;
|
||||
numbering.indistinguishable(v_node, node);
|
||||
marker.mark_done(v_node);
|
||||
degree_lists_marker.mark(v_node);
|
||||
} else { // not indistinguishable nodes
|
||||
add_edge(v_node, node, G);
|
||||
degree_lists_marker.mark_need_update(v_node);
|
||||
}
|
||||
}
|
||||
} // eliminate()
|
||||
|
||||
|
||||
template <class Stack>
|
||||
void update(Stack llist, size_type& min_degree)
|
||||
{
|
||||
size_type min_degree0 = min_degree + delta + 1;
|
||||
|
||||
while (! llist.empty()) {
|
||||
size_type deg, deg0 = 0;
|
||||
|
||||
marker.set_multiple_tag(min_degree0);
|
||||
typename Workspace::stack q2list = work_space.make_stack();
|
||||
typename Workspace::stack qxlist = work_space.make_stack();
|
||||
|
||||
vertex_t current = get(index_vertex_map, llist.top());
|
||||
adj_iter i, ie;
|
||||
for (tie(i,ie) = adjacent_vertices(current, G); i != ie; ++i) {
|
||||
vertex_t i_node = *i;
|
||||
const size_type i_id = get(vertex_index_map, i_node);
|
||||
if (supernode_size[i_node] != 0) {
|
||||
deg0 += supernode_size[i_node];
|
||||
marker.mark_multiple_tagged(i_node);
|
||||
if (degree_lists_marker.need_update(i_node)) {
|
||||
if (out_degree(i_node, G) == 2)
|
||||
q2list.push(i_id);
|
||||
else
|
||||
qxlist.push(i_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!q2list.empty()) {
|
||||
const size_type u_id = q2list.top();
|
||||
vertex_t u_node = get(index_vertex_map, u_id);
|
||||
// if u_id is outmatched by others, no need to update degree
|
||||
if (degree_lists_marker.outmatched_or_done(u_node)) {
|
||||
q2list.pop();
|
||||
continue;
|
||||
}
|
||||
marker.increment_tag();
|
||||
deg = deg0;
|
||||
|
||||
adj_iter nu = adjacent_vertices(u_node, G).first;
|
||||
vertex_t neighbor = *nu;
|
||||
if (neighbor == u_node) {
|
||||
++nu;
|
||||
neighbor = *nu;
|
||||
}
|
||||
if (numbering.is_numbered(neighbor)) {
|
||||
adj_iter i, ie;
|
||||
for (tie(i,ie) = adjacent_vertices(neighbor, G);
|
||||
i != ie; ++i) {
|
||||
const vertex_t i_node = *i;
|
||||
if (i_node == u_node || supernode_size[i_node] == 0)
|
||||
continue;
|
||||
if (marker.is_tagged(i_node)) {
|
||||
if (degree_lists_marker.need_update(i_node)) {
|
||||
if ( out_degree(i_node, G) == 2 ) { // is indistinguishable
|
||||
supernode_size[u_node] += supernode_size[i_node];
|
||||
supernode_size[i_node] = 0;
|
||||
numbering.indistinguishable(i_node, u_node);
|
||||
marker.mark_done(i_node);
|
||||
degree_lists_marker.mark(i_node);
|
||||
} else // is outmatched
|
||||
degree_lists_marker.mark(i_node);
|
||||
}
|
||||
} else {
|
||||
marker.mark_tagged(i_node);
|
||||
deg += supernode_size[i_node];
|
||||
}
|
||||
}
|
||||
} else
|
||||
deg += supernode_size[neighbor];
|
||||
|
||||
deg -= supernode_size[u_node];
|
||||
degree[u_node] = deg; //update degree
|
||||
degreelists[deg].push(u_node);
|
||||
//u_id has been pushed back into degreelists
|
||||
degree_lists_marker.unmark(u_node);
|
||||
if (min_degree > deg)
|
||||
min_degree = deg;
|
||||
q2list.pop();
|
||||
} // while (!q2list.empty())
|
||||
|
||||
while (!qxlist.empty()) {
|
||||
const size_type u_id = qxlist.top();
|
||||
const vertex_t u_node = get(index_vertex_map, u_id);
|
||||
|
||||
// if u_id is outmatched by others, no need to update degree
|
||||
if (degree_lists_marker.outmatched_or_done(u_node)) {
|
||||
qxlist.pop();
|
||||
continue;
|
||||
}
|
||||
marker.increment_tag();
|
||||
deg = deg0;
|
||||
adj_iter i, ie;
|
||||
for (tie(i, ie) = adjacent_vertices(u_node, G); i != ie; ++i) {
|
||||
vertex_t i_node = *i;
|
||||
if (marker.is_tagged(i_node))
|
||||
continue;
|
||||
marker.mark_tagged(i_node);
|
||||
|
||||
if (numbering.is_numbered(i_node)) {
|
||||
adj_iter j, je;
|
||||
for (tie(j, je) = adjacent_vertices(i_node, G); j != je; ++j) {
|
||||
const vertex_t j_node = *j;
|
||||
if (marker.is_not_tagged(j_node)) {
|
||||
marker.mark_tagged(j_node);
|
||||
deg += supernode_size[j_node];
|
||||
}
|
||||
}
|
||||
} else
|
||||
deg += supernode_size[i_node];
|
||||
} // for adjacent vertices of u_node
|
||||
deg -= supernode_size[u_node];
|
||||
degree[u_node] = deg;
|
||||
degreelists[deg].push(u_node);
|
||||
// u_id has been pushed back into degreelists
|
||||
degree_lists_marker.unmark(u_node);
|
||||
if (min_degree > deg)
|
||||
min_degree = deg;
|
||||
qxlist.pop();
|
||||
} // while (!qxlist.empty()) {
|
||||
|
||||
marker.set_tag_as_multiple_tag();
|
||||
llist.pop();
|
||||
} // while (! llist.empty())
|
||||
|
||||
} // update()
|
||||
|
||||
|
||||
void build_permutation(InversePermutationMap next,
|
||||
PermutationMap prev)
|
||||
{
|
||||
// collect the permutation info
|
||||
size_type i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
diff_t size = supernode_size[get(index_vertex_map, i)];
|
||||
if ( size <= 0 ) {
|
||||
prev[i] = next[i];
|
||||
supernode_size[get(index_vertex_map, i)]
|
||||
= next[i] + 1; // record the supernode info
|
||||
} else
|
||||
prev[i] = - next[i];
|
||||
}
|
||||
for (i = 1; i < n + 1; ++i) {
|
||||
if ( prev[i-1] > 0 )
|
||||
continue;
|
||||
diff_t parent = i;
|
||||
while ( prev[parent - 1] < 0 ) {
|
||||
parent = - prev[parent - 1];
|
||||
}
|
||||
|
||||
diff_t root = parent;
|
||||
diff_t num = prev[root - 1] + 1;
|
||||
next[i-1] = - num;
|
||||
prev[root-1] = num;
|
||||
|
||||
parent = i;
|
||||
diff_t next_node = - prev[parent - 1];
|
||||
while (next_node > 0) {
|
||||
prev[parent-1] = - root;
|
||||
parent = next_node;
|
||||
next_node = - prev[parent - 1];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
diff_t num = - next[i] - 1;
|
||||
next[i] = num;
|
||||
prev[num] = i;
|
||||
}
|
||||
} // build_permutation()
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
|
||||
|
||||
// MMD algorithm
|
||||
//
|
||||
//The implementation presently includes the enhancements for mass
|
||||
//elimination, incomplete degree update, multiple elimination, and
|
||||
//external degree.
|
||||
//
|
||||
//Important Note: This implementation requires the BGL graph to be
|
||||
//directed. Therefore, nonzero entry (i, j) in a symmetrical matrix
|
||||
//A coresponds to two directed edges (i->j and j->i).
|
||||
//
|
||||
//see Alan George and Joseph W. H. Liu, The Evolution of the Minimum
|
||||
//Degree Ordering Algorithm, SIAM Review, 31, 1989, Page 1-19
|
||||
template<class Graph, class DegreeMap,
|
||||
class InversePermutationMap,
|
||||
class PermutationMap,
|
||||
class SuperNodeMap, class VertexIndexMap>
|
||||
void minimum_degree_ordering
|
||||
(Graph& G,
|
||||
DegreeMap degree,
|
||||
InversePermutationMap inverse_perm,
|
||||
PermutationMap perm,
|
||||
SuperNodeMap supernode_size,
|
||||
int delta,
|
||||
VertexIndexMap vertex_index_map)
|
||||
{
|
||||
detail::mmd_impl<Graph,DegreeMap,InversePermutationMap,
|
||||
PermutationMap, SuperNodeMap, VertexIndexMap>
|
||||
impl(G, num_vertices(G), delta, degree, inverse_perm,
|
||||
perm, supernode_size, vertex_index_map);
|
||||
impl.do_mmd();
|
||||
impl.build_permutation(inverse_perm, perm);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // MINIMUM_DEGREE_ORDERING_HPP
|
||||
795
libraries/include/boost/graph/named_function_params.hpp
Normal file
795
libraries/include/boost/graph/named_function_params.hpp
Normal file
@@ -0,0 +1,795 @@
|
||||
//=======================================================================
|
||||
// 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 <boost/graph/properties.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
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 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 { };
|
||||
|
||||
namespace detail {
|
||||
template <class T>
|
||||
struct wrap_ref {
|
||||
wrap_ref(T& r) : ref(r) {}
|
||||
T& ref;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T, typename Tag, typename Base = no_property>
|
||||
struct bgl_named_params : public Base
|
||||
{
|
||||
typedef bgl_named_params self;
|
||||
typedef Base next_type;
|
||||
typedef Tag tag_type;
|
||||
typedef T value_type;
|
||||
bgl_named_params(T v) : m_value(v) { }
|
||||
bgl_named_params(T v, const Base& b) : Base(b), m_value(v) { }
|
||||
T m_value;
|
||||
|
||||
template <typename WeightMap>
|
||||
bgl_named_params<WeightMap, edge_weight_t, self>
|
||||
weight_map(const WeightMap& pmap) const {
|
||||
typedef bgl_named_params<WeightMap, edge_weight_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename WeightMap>
|
||||
bgl_named_params<WeightMap, edge_weight2_t, self>
|
||||
weight_map2(const WeightMap& pmap) const {
|
||||
typedef bgl_named_params<WeightMap, edge_weight2_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename DistanceMap>
|
||||
bgl_named_params<DistanceMap, vertex_distance_t, self>
|
||||
distance_map(const DistanceMap& pmap) const {
|
||||
typedef bgl_named_params<DistanceMap, vertex_distance_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename PredecessorMap>
|
||||
bgl_named_params<PredecessorMap, vertex_predecessor_t, self>
|
||||
predecessor_map(const PredecessorMap& pmap) const {
|
||||
typedef bgl_named_params<PredecessorMap, vertex_predecessor_t, self>
|
||||
Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename RankMap>
|
||||
bgl_named_params<RankMap, vertex_rank_t, self>
|
||||
rank_map(const RankMap& pmap) const {
|
||||
typedef bgl_named_params<RankMap, vertex_rank_t, self>
|
||||
Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename RootMap>
|
||||
bgl_named_params<RootMap, vertex_root_t, self>
|
||||
root_map(const RootMap& pmap) const {
|
||||
typedef bgl_named_params<RootMap, vertex_root_t, self>
|
||||
Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename Vertex>
|
||||
bgl_named_params<Vertex, root_vertex_t, self>
|
||||
root_vertex(const Vertex& r) const {
|
||||
typedef bgl_named_params<Vertex, root_vertex_t, self> Params;
|
||||
return Params(r, *this);
|
||||
}
|
||||
|
||||
template <typename EdgeCentralityMap>
|
||||
bgl_named_params<EdgeCentralityMap, edge_centrality_t, self>
|
||||
edge_centrality_map(const EdgeCentralityMap& r) const {
|
||||
typedef bgl_named_params<EdgeCentralityMap, edge_centrality_t, self> Params;
|
||||
return Params(r, *this);
|
||||
}
|
||||
|
||||
template <typename CentralityMap>
|
||||
bgl_named_params<CentralityMap, vertex_centrality_t, self>
|
||||
centrality_map(const CentralityMap& r) const {
|
||||
typedef bgl_named_params<CentralityMap, vertex_centrality_t, self> Params;
|
||||
return Params(r, *this);
|
||||
}
|
||||
|
||||
template <typename ColorMap>
|
||||
bgl_named_params<ColorMap, vertex_color_t, self>
|
||||
color_map(const ColorMap& pmap) const {
|
||||
typedef bgl_named_params<ColorMap, vertex_color_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename ColorMap>
|
||||
bgl_named_params<ColorMap, vertex_color_t, self>
|
||||
vertex_color_map(const ColorMap& pmap) const {
|
||||
typedef bgl_named_params<ColorMap, vertex_color_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename ColorMap>
|
||||
bgl_named_params<ColorMap, edge_color_t, self>
|
||||
edge_color_map(const ColorMap& pmap) const {
|
||||
typedef bgl_named_params<ColorMap, edge_color_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename CapacityMap>
|
||||
bgl_named_params<CapacityMap, edge_capacity_t, self>
|
||||
capacity_map(CapacityMap pmap) {
|
||||
typedef bgl_named_params<CapacityMap, edge_capacity_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename Residual_CapacityMap>
|
||||
bgl_named_params<Residual_CapacityMap, edge_residual_capacity_t, self>
|
||||
residual_capacity_map(Residual_CapacityMap pmap) {
|
||||
typedef bgl_named_params<Residual_CapacityMap,
|
||||
edge_residual_capacity_t, self>
|
||||
Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename ReverseMap>
|
||||
bgl_named_params<ReverseMap, edge_reverse_t, self>
|
||||
reverse_edge_map(ReverseMap pmap) {
|
||||
typedef bgl_named_params<ReverseMap,
|
||||
edge_reverse_t, self>
|
||||
Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename DiscoverTimeMap>
|
||||
bgl_named_params<DiscoverTimeMap, vertex_discover_time_t, self>
|
||||
discover_time_map(const DiscoverTimeMap& pmap) const {
|
||||
typedef bgl_named_params<DiscoverTimeMap, vertex_discover_time_t, self>
|
||||
Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename LowPointMap>
|
||||
bgl_named_params<LowPointMap, vertex_lowpoint_t, self>
|
||||
lowpoint_map(const LowPointMap& pmap) const {
|
||||
typedef bgl_named_params<LowPointMap, vertex_lowpoint_t, self>
|
||||
Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename IndexMap>
|
||||
bgl_named_params<IndexMap, vertex_index_t, self>
|
||||
vertex_index_map(const IndexMap& pmap) const {
|
||||
typedef bgl_named_params<IndexMap, vertex_index_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename IndexMap>
|
||||
bgl_named_params<IndexMap, vertex_index1_t, self>
|
||||
vertex_index1_map(const IndexMap& pmap) const {
|
||||
typedef bgl_named_params<IndexMap, vertex_index1_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename IndexMap>
|
||||
bgl_named_params<IndexMap, vertex_index2_t, self>
|
||||
vertex_index2_map(const IndexMap& pmap) const {
|
||||
typedef bgl_named_params<IndexMap, vertex_index2_t, self> Params;
|
||||
return Params(pmap, *this);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
bgl_named_params<Visitor, graph_visitor_t, self>
|
||||
visitor(const Visitor& vis) const {
|
||||
typedef bgl_named_params<Visitor, graph_visitor_t, self> Params;
|
||||
return Params(vis, *this);
|
||||
}
|
||||
|
||||
template <typename Compare>
|
||||
bgl_named_params<Compare, distance_compare_t, self>
|
||||
distance_compare(Compare cmp) const {
|
||||
typedef bgl_named_params<Compare, distance_compare_t, self> Params;
|
||||
return Params(cmp, *this);
|
||||
}
|
||||
|
||||
template <typename Combine>
|
||||
bgl_named_params<Combine, distance_combine_t, self>
|
||||
distance_combine(Combine cmb) const {
|
||||
typedef bgl_named_params<Combine, distance_combine_t, self> Params;
|
||||
return Params(cmb, *this);
|
||||
}
|
||||
|
||||
template <typename Init>
|
||||
bgl_named_params<Init, distance_inf_t, self>
|
||||
distance_inf(Init init) const {
|
||||
typedef bgl_named_params<Init, distance_inf_t, self> Params;
|
||||
return Params(init, *this);
|
||||
}
|
||||
|
||||
template <typename Init>
|
||||
bgl_named_params<Init, distance_zero_t, self>
|
||||
distance_zero(Init init) const {
|
||||
typedef bgl_named_params<Init, distance_zero_t, self> Params;
|
||||
return Params(init, *this);
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
bgl_named_params<detail::wrap_ref<Buffer>, buffer_param_t, self>
|
||||
buffer(Buffer& b) const {
|
||||
typedef bgl_named_params<detail::wrap_ref<Buffer>, buffer_param_t, self>
|
||||
Params;
|
||||
return Params(detail::wrap_ref<Buffer>(b), *this);
|
||||
}
|
||||
|
||||
template <typename Copier>
|
||||
bgl_named_params<Copier, edge_copy_t, self>
|
||||
edge_copy(const Copier& c) const {
|
||||
typedef bgl_named_params<Copier, edge_copy_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename Copier>
|
||||
bgl_named_params<Copier, vertex_copy_t, self>
|
||||
vertex_copy(const Copier& c) const {
|
||||
typedef bgl_named_params<Copier, vertex_copy_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename Orig2CopyMap>
|
||||
bgl_named_params<Orig2CopyMap, orig_to_copy_t, self>
|
||||
orig_to_copy(const Orig2CopyMap& c) const {
|
||||
typedef bgl_named_params<Orig2CopyMap, orig_to_copy_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename IsoMap>
|
||||
bgl_named_params<IsoMap, vertex_isomorphism_t, self>
|
||||
isomorphism_map(const IsoMap& c) const {
|
||||
typedef bgl_named_params<IsoMap, vertex_isomorphism_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant_t, self>
|
||||
vertex_invariant(const VertexInvar& c) const {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant1_t, self>
|
||||
vertex_invariant1(const VertexInvar& c) const {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant1_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant2_t, self>
|
||||
vertex_invariant2(const VertexInvar& c) const {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant2_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexMaxInvar>
|
||||
bgl_named_params<VertexMaxInvar, vertex_max_invariant_t, self>
|
||||
vertex_max_invariant(const VertexMaxInvar& c) const {
|
||||
typedef bgl_named_params<VertexMaxInvar, vertex_max_invariant_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexDisplacement>
|
||||
bgl_named_params<VertexDisplacement, vertex_displacement_t, self>
|
||||
displacement_map(const VertexDisplacement& c) const {
|
||||
typedef bgl_named_params<VertexDisplacement, vertex_displacement_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename AttractiveForce>
|
||||
bgl_named_params<AttractiveForce, attractive_force_t, self>
|
||||
attractive_force(const AttractiveForce& c) {
|
||||
typedef bgl_named_params<AttractiveForce, attractive_force_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename RepulsiveForce>
|
||||
bgl_named_params<RepulsiveForce, repulsive_force_t, self>
|
||||
repulsive_force(const RepulsiveForce& c) {
|
||||
typedef bgl_named_params<RepulsiveForce, repulsive_force_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename ForcePairs>
|
||||
bgl_named_params<ForcePairs, force_pairs_t, self>
|
||||
force_pairs(const ForcePairs& c) {
|
||||
typedef bgl_named_params<ForcePairs, force_pairs_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename Cooling>
|
||||
bgl_named_params<Cooling, cooling_t, self>
|
||||
cooling(const Cooling& c) {
|
||||
typedef bgl_named_params<Cooling, cooling_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename TP>
|
||||
bgl_named_params<TP, iterations_t, self>
|
||||
iterations(const TP& c) {
|
||||
typedef bgl_named_params<TP, iterations_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template<typename TP>
|
||||
bgl_named_params<std::pair<TP, TP>, diameter_range_t, self>
|
||||
diameter_range(const std::pair<TP, TP>& c) {
|
||||
typedef bgl_named_params<std::pair<TP, TP>, diameter_range_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template<typename TP>
|
||||
bgl_named_params<std::pair<TP, TP>, learning_constant_range_t, self>
|
||||
learning_constant_range(const std::pair<TP, TP>& c) {
|
||||
typedef bgl_named_params<std::pair<TP, TP>, learning_constant_range_t, self>
|
||||
Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename WeightMap>
|
||||
bgl_named_params<WeightMap, edge_weight_t>
|
||||
weight_map(WeightMap pmap) {
|
||||
typedef bgl_named_params<WeightMap, edge_weight_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename WeightMap>
|
||||
bgl_named_params<WeightMap, edge_weight2_t>
|
||||
weight_map2(WeightMap pmap) {
|
||||
typedef bgl_named_params<WeightMap, edge_weight2_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename DistanceMap>
|
||||
bgl_named_params<DistanceMap, vertex_distance_t>
|
||||
distance_map(DistanceMap pmap) {
|
||||
typedef bgl_named_params<DistanceMap, vertex_distance_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename PredecessorMap>
|
||||
bgl_named_params<PredecessorMap, vertex_predecessor_t>
|
||||
predecessor_map(PredecessorMap pmap) {
|
||||
typedef bgl_named_params<PredecessorMap, vertex_predecessor_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename RankMap>
|
||||
bgl_named_params<RankMap, vertex_rank_t>
|
||||
rank_map(RankMap pmap) {
|
||||
typedef bgl_named_params<RankMap, vertex_rank_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename RootMap>
|
||||
bgl_named_params<RootMap, vertex_root_t>
|
||||
root_map(RootMap pmap) {
|
||||
typedef bgl_named_params<RootMap, vertex_root_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename Vertex>
|
||||
bgl_named_params<Vertex, root_vertex_t>
|
||||
root_vertex(const Vertex& r) {
|
||||
typedef bgl_named_params<Vertex, root_vertex_t> Params;
|
||||
return Params(r);
|
||||
}
|
||||
|
||||
template <typename EdgeCentralityMap>
|
||||
bgl_named_params<EdgeCentralityMap, edge_centrality_t>
|
||||
edge_centrality_map(const EdgeCentralityMap& r) {
|
||||
typedef bgl_named_params<EdgeCentralityMap, edge_centrality_t> Params;
|
||||
return Params(r);
|
||||
}
|
||||
|
||||
template <typename CentralityMap>
|
||||
bgl_named_params<CentralityMap, vertex_centrality_t>
|
||||
centrality_map(const CentralityMap& r) {
|
||||
typedef bgl_named_params<CentralityMap, vertex_centrality_t> Params;
|
||||
return Params(r);
|
||||
}
|
||||
|
||||
template <typename ColorMap>
|
||||
bgl_named_params<ColorMap, vertex_color_t>
|
||||
color_map(ColorMap pmap) {
|
||||
typedef bgl_named_params<ColorMap, vertex_color_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename CapacityMap>
|
||||
bgl_named_params<CapacityMap, edge_capacity_t>
|
||||
capacity_map(CapacityMap pmap) {
|
||||
typedef bgl_named_params<CapacityMap, edge_capacity_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename Residual_CapacityMap>
|
||||
bgl_named_params<Residual_CapacityMap, edge_residual_capacity_t>
|
||||
residual_capacity_map(Residual_CapacityMap pmap) {
|
||||
typedef bgl_named_params<Residual_CapacityMap, edge_residual_capacity_t>
|
||||
Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename ReverseMap>
|
||||
bgl_named_params<ReverseMap, edge_reverse_t>
|
||||
reverse_edge_map(ReverseMap pmap) {
|
||||
typedef bgl_named_params<ReverseMap, edge_reverse_t>
|
||||
Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename DiscoverTimeMap>
|
||||
bgl_named_params<DiscoverTimeMap, vertex_discover_time_t>
|
||||
discover_time_map(DiscoverTimeMap pmap) {
|
||||
typedef bgl_named_params<DiscoverTimeMap, vertex_discover_time_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename LowPointMap>
|
||||
bgl_named_params<LowPointMap, vertex_lowpoint_t>
|
||||
lowpoint_map(LowPointMap pmap) {
|
||||
typedef bgl_named_params<LowPointMap, vertex_lowpoint_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename IndexMap>
|
||||
bgl_named_params<IndexMap, vertex_index_t>
|
||||
vertex_index_map(IndexMap pmap) {
|
||||
typedef bgl_named_params<IndexMap, vertex_index_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename IndexMap>
|
||||
bgl_named_params<IndexMap, vertex_index1_t>
|
||||
vertex_index1_map(const IndexMap& pmap) {
|
||||
typedef bgl_named_params<IndexMap, vertex_index1_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename IndexMap>
|
||||
bgl_named_params<IndexMap, vertex_index2_t>
|
||||
vertex_index2_map(const IndexMap& pmap) {
|
||||
typedef bgl_named_params<IndexMap, vertex_index2_t> Params;
|
||||
return Params(pmap);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
bgl_named_params<Visitor, graph_visitor_t>
|
||||
visitor(const Visitor& vis) {
|
||||
typedef bgl_named_params<Visitor, graph_visitor_t> Params;
|
||||
return Params(vis);
|
||||
}
|
||||
|
||||
template <typename Compare>
|
||||
bgl_named_params<Compare, distance_compare_t>
|
||||
distance_compare(Compare cmp) {
|
||||
typedef bgl_named_params<Compare, distance_compare_t> Params;
|
||||
return Params(cmp);
|
||||
}
|
||||
|
||||
template <typename Combine>
|
||||
bgl_named_params<Combine, distance_combine_t>
|
||||
distance_combine(Combine cmb) {
|
||||
typedef bgl_named_params<Combine, distance_combine_t> Params;
|
||||
return Params(cmb);
|
||||
}
|
||||
|
||||
template <typename Init>
|
||||
bgl_named_params<Init, distance_inf_t>
|
||||
distance_inf(Init init) {
|
||||
typedef bgl_named_params<Init, distance_inf_t> Params;
|
||||
return Params(init);
|
||||
}
|
||||
|
||||
template <typename Init>
|
||||
bgl_named_params<Init, distance_zero_t>
|
||||
distance_zero(Init init) {
|
||||
typedef bgl_named_params<Init, distance_zero_t> Params;
|
||||
return Params(init);
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
bgl_named_params<detail::wrap_ref<Buffer>, buffer_param_t>
|
||||
buffer(Buffer& b) {
|
||||
typedef bgl_named_params<detail::wrap_ref<Buffer>, buffer_param_t> Params;
|
||||
return Params(detail::wrap_ref<Buffer>(b));
|
||||
}
|
||||
|
||||
template <typename Copier>
|
||||
bgl_named_params<Copier, edge_copy_t>
|
||||
edge_copy(const Copier& c) {
|
||||
typedef bgl_named_params<Copier, edge_copy_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename Copier>
|
||||
bgl_named_params<Copier, vertex_copy_t>
|
||||
vertex_copy(const Copier& c) {
|
||||
typedef bgl_named_params<Copier, vertex_copy_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename Orig2CopyMap>
|
||||
bgl_named_params<Orig2CopyMap, orig_to_copy_t>
|
||||
orig_to_copy(const Orig2CopyMap& c) {
|
||||
typedef bgl_named_params<Orig2CopyMap, orig_to_copy_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename IsoMap>
|
||||
bgl_named_params<IsoMap, vertex_isomorphism_t>
|
||||
isomorphism_map(const IsoMap& c) {
|
||||
typedef bgl_named_params<IsoMap, vertex_isomorphism_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant_t>
|
||||
vertex_invariant(const VertexInvar& c) {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant1_t>
|
||||
vertex_invariant1(const VertexInvar& c) {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant1_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant2_t>
|
||||
vertex_invariant2(const VertexInvar& c) {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant2_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexMaxInvar>
|
||||
bgl_named_params<VertexMaxInvar, vertex_max_invariant_t>
|
||||
vertex_max_invariant(const VertexMaxInvar& c) {
|
||||
typedef bgl_named_params<VertexMaxInvar, vertex_max_invariant_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexDisplacement>
|
||||
bgl_named_params<VertexDisplacement, vertex_displacement_t>
|
||||
displacement_map(const VertexDisplacement& c) {
|
||||
typedef bgl_named_params<VertexDisplacement, vertex_displacement_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename AttractiveForce>
|
||||
bgl_named_params<AttractiveForce, attractive_force_t>
|
||||
attractive_force(const AttractiveForce& c) {
|
||||
typedef bgl_named_params<AttractiveForce, attractive_force_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename RepulsiveForce>
|
||||
bgl_named_params<RepulsiveForce, repulsive_force_t>
|
||||
repulsive_force(const RepulsiveForce& c) {
|
||||
typedef bgl_named_params<RepulsiveForce, repulsive_force_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename ForcePairs>
|
||||
bgl_named_params<ForcePairs, force_pairs_t>
|
||||
force_pairs(const ForcePairs& c) {
|
||||
typedef bgl_named_params<ForcePairs, force_pairs_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename Cooling>
|
||||
bgl_named_params<Cooling, cooling_t>
|
||||
cooling(const Cooling& c) {
|
||||
typedef bgl_named_params<Cooling, cooling_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bgl_named_params<T, iterations_t>
|
||||
iterations(const T& c) {
|
||||
typedef bgl_named_params<T, iterations_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bgl_named_params<std::pair<T, T>, diameter_range_t>
|
||||
diameter_range(const std::pair<T, T>& c) {
|
||||
typedef bgl_named_params<std::pair<T, T>, diameter_range_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bgl_named_params<std::pair<T, T>, learning_constant_range_t>
|
||||
learning_constant_range(const std::pair<T, T>& c) {
|
||||
typedef bgl_named_params<std::pair<T, T>, learning_constant_range_t>
|
||||
Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Functions for extracting parameters from bgl_named_params
|
||||
|
||||
template <class Tag1, class Tag2, class T1, class Base>
|
||||
inline
|
||||
typename property_value< bgl_named_params<T1,Tag1,Base>, Tag2>::type
|
||||
get_param(const bgl_named_params<T1,Tag1,Base>& p, Tag2 tag2)
|
||||
{
|
||||
enum { match = detail::same_property<Tag1,Tag2>::value };
|
||||
typedef typename
|
||||
property_value< bgl_named_params<T1,Tag1,Base>, Tag2>::type T2;
|
||||
T2* t2 = 0;
|
||||
typedef detail::property_value_dispatch<match> Dispatcher;
|
||||
return Dispatcher::const_get_value(p, t2, tag2);
|
||||
}
|
||||
|
||||
|
||||
namespace detail {
|
||||
// MSVC++ workaround
|
||||
template <class Param>
|
||||
struct choose_param_helper {
|
||||
template <class Default> struct result { typedef Param type; };
|
||||
template <typename Default>
|
||||
static const Param& apply(const Param& p, const Default&) { return p; }
|
||||
};
|
||||
template <>
|
||||
struct choose_param_helper<error_property_not_found> {
|
||||
template <class Default> struct result { typedef Default type; };
|
||||
template <typename Default>
|
||||
static const Default& apply(const error_property_not_found&, const Default& d)
|
||||
{ return d; }
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <class P, class Default>
|
||||
const typename detail::choose_param_helper<P>::template result<Default>::type&
|
||||
choose_param(const P& param, const Default& d) {
|
||||
return detail::choose_param_helper<P>::apply(param, d);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool is_default_param(const T&) { return false; }
|
||||
|
||||
inline bool is_default_param(const detail::error_property_not_found&)
|
||||
{ return true; }
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct choose_parameter {
|
||||
template <class P, class Graph, class Tag>
|
||||
struct bind_ {
|
||||
typedef const P& const_result_type;
|
||||
typedef const P& result_type;
|
||||
typedef P type;
|
||||
};
|
||||
|
||||
template <class P, class Graph, class Tag>
|
||||
static typename bind_<P, Graph, Tag>::const_result_type
|
||||
const_apply(const P& p, const Graph&, Tag&)
|
||||
{ return p; }
|
||||
|
||||
template <class P, class Graph, class Tag>
|
||||
static typename bind_<P, Graph, Tag>::result_type
|
||||
apply(const P& p, Graph&, Tag&)
|
||||
{ return p; }
|
||||
};
|
||||
|
||||
struct choose_default_param {
|
||||
template <class P, class Graph, class Tag>
|
||||
struct bind_ {
|
||||
typedef typename property_map<Graph, Tag>::type
|
||||
result_type;
|
||||
typedef typename property_map<Graph, Tag>::const_type
|
||||
const_result_type;
|
||||
typedef typename property_map<Graph, Tag>::const_type
|
||||
type;
|
||||
};
|
||||
|
||||
template <class P, class Graph, class Tag>
|
||||
static typename bind_<P, Graph, Tag>::const_result_type
|
||||
const_apply(const P&, const Graph& g, Tag tag) {
|
||||
return get(tag, g);
|
||||
}
|
||||
template <class P, class Graph, class Tag>
|
||||
static typename bind_<P, Graph, Tag>::result_type
|
||||
apply(const P&, Graph& g, Tag tag) {
|
||||
return get(tag, g);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Param>
|
||||
struct choose_property_map {
|
||||
typedef choose_parameter type;
|
||||
};
|
||||
template <>
|
||||
struct choose_property_map<detail::error_property_not_found> {
|
||||
typedef choose_default_param type;
|
||||
};
|
||||
|
||||
template <class Param, class Graph, class Tag>
|
||||
struct choose_pmap_helper {
|
||||
typedef typename choose_property_map<Param>::type Selector;
|
||||
typedef typename Selector:: template bind_<Param, Graph, Tag> Bind;
|
||||
typedef Bind type;
|
||||
typedef typename Bind::result_type result_type;
|
||||
typedef typename Bind::const_result_type const_result_type;
|
||||
typedef typename Bind::type result;
|
||||
};
|
||||
|
||||
// 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 property_value< Params, edge_capacity_t>::type Param;
|
||||
typedef typename detail::choose_pmap_helper<Param, Graph,
|
||||
edge_capacity_t>::result CapacityEdgeMap;
|
||||
typedef typename property_traits<CapacityEdgeMap>::value_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.
|
||||
template <typename Param, typename Graph, typename PropertyTag>
|
||||
typename
|
||||
detail::choose_pmap_helper<Param,Graph,PropertyTag>::const_result_type
|
||||
choose_const_pmap(const Param& p, const Graph& g, PropertyTag tag)
|
||||
{
|
||||
typedef typename
|
||||
detail::choose_pmap_helper<Param,Graph,PropertyTag>::Selector Choice;
|
||||
return Choice::const_apply(p, g, tag);
|
||||
}
|
||||
|
||||
template <typename Param, typename Graph, typename PropertyTag>
|
||||
typename detail::choose_pmap_helper<Param,Graph,PropertyTag>::result_type
|
||||
choose_pmap(const Param& p, Graph& g, PropertyTag tag)
|
||||
{
|
||||
typedef typename
|
||||
detail::choose_pmap_helper<Param,Graph,PropertyTag>::Selector Choice;
|
||||
return Choice::apply(p, g, tag);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP
|
||||
543
libraries/include/boost/graph/named_graph.hpp
Normal file
543
libraries/include/boost/graph/named_graph.hpp
Normal file
@@ -0,0 +1,543 @@
|
||||
// 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/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/hashed_index.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept> // for std::runtime_error
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
/**
|
||||
* 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> { };
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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& name)
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
/**
|
||||
* 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> { };
|
||||
#endif
|
||||
|
||||
/*******************************************************************
|
||||
* Named graph-specific metafunctions *
|
||||
*******************************************************************/
|
||||
namespace detail {
|
||||
/**
|
||||
* INTERNAL ONLY
|
||||
*
|
||||
* Extracts the type of a bundled vertex property from a vertex
|
||||
* property. The primary template matches when we have hit the end
|
||||
* of the @c property<> list.
|
||||
*/
|
||||
template<typename VertexProperty>
|
||||
struct extract_bundled_vertex
|
||||
{
|
||||
typedef VertexProperty type;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* INTERNAL ONLY
|
||||
*
|
||||
* Recursively extract the bundled vertex property from a vertex
|
||||
* property.
|
||||
*/
|
||||
template<typename Tag, typename T, typename Base>
|
||||
struct extract_bundled_vertex<property<Tag, T, Base> >
|
||||
: extract_bundled_vertex<Base>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* We have found the bundled vertex property type, marked with
|
||||
* vertex_bundle_t.
|
||||
*/
|
||||
template<typename T, typename Base>
|
||||
struct extract_bundled_vertex<property<vertex_bundle_t, T, Base> >
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate @c no_property into @c error_property_not_found when we
|
||||
* have failed to extract a bundled vertex property type.
|
||||
*/
|
||||
template<>
|
||||
struct extract_bundled_vertex<no_property>
|
||||
{
|
||||
typedef boost::detail::error_property_not_found type;
|
||||
};
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* 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 detail::extract_bundled_vertex<VertexProperty>::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.
|
||||
void removing_vertex(Vertex vertex);
|
||||
|
||||
/// 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>
|
||||
inline void BGL_NAMED_GRAPH::removing_vertex(Vertex vertex)
|
||||
{
|
||||
named_vertices.erase(vertex);
|
||||
}
|
||||
|
||||
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.
|
||||
template<BGL_NAMED_GRAPH_PARAMS>
|
||||
Vertex
|
||||
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());
|
||||
}
|
||||
|
||||
#undef BGL_NAMED_GRAPH
|
||||
#undef BGL_NAMED_GRAPH_PARAMS
|
||||
|
||||
/*******************************************************************
|
||||
* Maybe named graph mixin *
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
/**
|
||||
* 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 detail::extract_bundled_vertex<VertexProperty>::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.
|
||||
void removing_vertex(Vertex) { }
|
||||
|
||||
/// 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>();
|
||||
}
|
||||
};
|
||||
#else
|
||||
template<typename Graph, typename Vertex, typename VertexProperty,
|
||||
typename ExtractName
|
||||
= typename internal_vertex_name<VertexProperty>::type>
|
||||
struct maybe_named_graph
|
||||
{
|
||||
/// The type of the "bundled" property, from which the name can be
|
||||
/// extracted.
|
||||
typedef typename detail::extract_bundled_vertex<VertexProperty>::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.
|
||||
void removing_vertex(Vertex) { }
|
||||
|
||||
/// 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<>
|
||||
template<typename Property>
|
||||
optional<Vertex>
|
||||
vertex_by_property(const bundled_vertex_property_type&)
|
||||
{
|
||||
return optional<Vertex>();
|
||||
}
|
||||
};
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
} } // end namespace boost::graph
|
||||
|
||||
#endif // BOOST_GRAPH_NAMED_GRAPH_HPP
|
||||
323
libraries/include/boost/graph/neighbor_bfs.hpp
Normal file
323
libraries/include/boost/graph/neighbor_bfs.hpp
Normal file
@@ -0,0 +1,323 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// 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_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP
|
||||
#define BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP
|
||||
|
||||
/*
|
||||
Neighbor Breadth First Search
|
||||
Like BFS, but traverses in-edges as well as out-edges.
|
||||
(for directed graphs only. use normal BFS for undirected graphs)
|
||||
*/
|
||||
#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>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Visitor, class Graph>
|
||||
struct NeighborBFSVisitorConcept {
|
||||
void constraints() {
|
||||
function_requires< CopyConstructibleConcept<Visitor> >();
|
||||
vis.initialize_vertex(u, g);
|
||||
vis.discover_vertex(u, g);
|
||||
vis.examine_vertex(u, g);
|
||||
vis.examine_out_edge(e, g);
|
||||
vis.examine_in_edge(e, g);
|
||||
vis.tree_out_edge(e, g);
|
||||
vis.tree_in_edge(e, g);
|
||||
vis.non_tree_out_edge(e, g);
|
||||
vis.non_tree_in_edge(e, g);
|
||||
vis.gray_target(e, g);
|
||||
vis.black_target(e, g);
|
||||
vis.gray_source(e, g);
|
||||
vis.black_source(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;
|
||||
};
|
||||
|
||||
template <class Visitors = null_visitor>
|
||||
class neighbor_bfs_visitor {
|
||||
public:
|
||||
neighbor_bfs_visitor(Visitors vis = Visitors()) : m_vis(vis) { }
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void initialize_vertex(Vertex u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_initialize_vertex());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_discover_vertex());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void examine_vertex(Vertex u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_examine_vertex());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void examine_out_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_examine_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void tree_out_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_tree_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void non_tree_out_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_non_tree_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void gray_target(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_gray_target());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void black_target(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_black_target());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void examine_in_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_examine_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void tree_in_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_tree_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void non_tree_in_edge(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_non_tree_edge());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void gray_source(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_gray_target());
|
||||
}
|
||||
template <class Edge, class Graph>
|
||||
void black_source(Edge e, Graph& g) {
|
||||
invoke_visitors(m_vis, e, g, on_black_target());
|
||||
}
|
||||
template <class Vertex, class Graph>
|
||||
void finish_vertex(Vertex u, Graph& g) {
|
||||
invoke_visitors(m_vis, u, g, on_finish_vertex());
|
||||
}
|
||||
protected:
|
||||
Visitors m_vis;
|
||||
};
|
||||
|
||||
template <class Visitors>
|
||||
neighbor_bfs_visitor<Visitors>
|
||||
make_neighbor_bfs_visitor(Visitors vis) {
|
||||
return neighbor_bfs_visitor<Visitors>(vis);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class BidirectionalGraph, class Buffer, class BFSVisitor,
|
||||
class ColorMap>
|
||||
void neighbor_bfs_impl
|
||||
(const BidirectionalGraph& g,
|
||||
typename graph_traits<BidirectionalGraph>::vertex_descriptor s,
|
||||
Buffer& Q, BFSVisitor vis, ColorMap color)
|
||||
|
||||
{
|
||||
function_requires< BidirectionalGraphConcept<BidirectionalGraph> >();
|
||||
typedef graph_traits<BidirectionalGraph> GTraits;
|
||||
typedef typename GTraits::vertex_descriptor Vertex;
|
||||
typedef typename GTraits::edge_descriptor Edge;
|
||||
function_requires<
|
||||
NeighborBFSVisitorConcept<BFSVisitor, BidirectionalGraph> >();
|
||||
function_requires< ReadWritePropertyMapConcept<ColorMap, Vertex> >();
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
put(color, s, Color::gray());
|
||||
vis.discover_vertex(s, g);
|
||||
Q.push(s);
|
||||
while (! Q.empty()) {
|
||||
Vertex u = Q.top();
|
||||
Q.pop(); // pop before push to avoid problem if Q is priority_queue.
|
||||
vis.examine_vertex(u, g);
|
||||
|
||||
typename GTraits::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
|
||||
Edge e = *ei;
|
||||
vis.examine_out_edge(e, g);
|
||||
Vertex v = target(e, g);
|
||||
ColorValue v_color = get(color, v);
|
||||
if (v_color == Color::white()) {
|
||||
vis.tree_out_edge(e, g);
|
||||
put(color, v, Color::gray());
|
||||
vis.discover_vertex(v, g);
|
||||
Q.push(v);
|
||||
} else {
|
||||
vis.non_tree_out_edge(e, g);
|
||||
if (v_color == Color::gray())
|
||||
vis.gray_target(e, g);
|
||||
else
|
||||
vis.black_target(e, g);
|
||||
}
|
||||
} // for out-edges
|
||||
|
||||
typename GTraits::in_edge_iterator in_ei, in_ei_end;
|
||||
for (tie(in_ei, in_ei_end) = in_edges(u, g);
|
||||
in_ei != in_ei_end; ++in_ei) {
|
||||
Edge e = *in_ei;
|
||||
vis.examine_in_edge(e, g);
|
||||
Vertex v = source(e, g);
|
||||
ColorValue v_color = get(color, v);
|
||||
if (v_color == Color::white()) {
|
||||
vis.tree_in_edge(e, g);
|
||||
put(color, v, Color::gray());
|
||||
vis.discover_vertex(v, g);
|
||||
Q.push(v);
|
||||
} else {
|
||||
vis.non_tree_in_edge(e, g);
|
||||
if (v_color == Color::gray())
|
||||
vis.gray_source(e, g);
|
||||
else
|
||||
vis.black_source(e, g);
|
||||
}
|
||||
} // for in-edges
|
||||
|
||||
put(color, u, Color::black());
|
||||
vis.finish_vertex(u, g);
|
||||
} // while
|
||||
}
|
||||
|
||||
|
||||
template <class VertexListGraph, class ColorMap, class BFSVisitor,
|
||||
class P, class T, class R>
|
||||
void neighbor_bfs_helper
|
||||
(VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
ColorMap color,
|
||||
BFSVisitor vis,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef graph_traits<VertexListGraph> Traits;
|
||||
// Buffer default
|
||||
typedef typename Traits::vertex_descriptor Vertex;
|
||||
typedef boost::queue<Vertex> queue_t;
|
||||
queue_t Q;
|
||||
detail::wrap_ref<queue_t> Qref(Q);
|
||||
// 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 (tie(i, i_end) = vertices(g); i != i_end; ++i) {
|
||||
put(color, *i, Color::white());
|
||||
vis.initialize_vertex(*i, g);
|
||||
}
|
||||
neighbor_bfs_impl
|
||||
(g, s,
|
||||
choose_param(get_param(params, buffer_param_t()), Qref).ref,
|
||||
vis, color);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// 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 neighbor_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)
|
||||
{
|
||||
neighbor_bfs_helper
|
||||
(g, s, color,
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_neighbor_bfs_visitor(null_visitor())),
|
||||
params);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct neighbor_bfs_dispatch<detail::error_property_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,
|
||||
detail::error_property_not_found)
|
||||
{
|
||||
std::vector<default_color_type> color_vec(num_vertices(g));
|
||||
null_visitor null_vis;
|
||||
|
||||
neighbor_bfs_helper
|
||||
(g, s,
|
||||
make_iterator_property_map
|
||||
(color_vec.begin(),
|
||||
choose_const_pmap(get_param(params, vertex_index),
|
||||
g, vertex_index), color_vec[0]),
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_neighbor_bfs_visitor(null_vis)),
|
||||
params);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// Named Parameter Variant
|
||||
template <class VertexListGraph, class P, class T, class R>
|
||||
void neighbor_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 property_value< bgl_named_params<P,T,R>,
|
||||
vertex_color_t>::type C;
|
||||
detail::neighbor_bfs_dispatch<C>::apply(ng, s, params,
|
||||
get_param(params, vertex_color));
|
||||
}
|
||||
|
||||
|
||||
// This version does not initialize colors, user has to.
|
||||
|
||||
template <class IncidenceGraph, class P, class T, class R>
|
||||
void neighbor_breadth_first_visit
|
||||
(IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef graph_traits<IncidenceGraph> Traits;
|
||||
// Buffer default
|
||||
typedef boost::queue<typename Traits::vertex_descriptor> queue_t;
|
||||
queue_t Q;
|
||||
detail::wrap_ref<queue_t> Qref(Q);
|
||||
|
||||
detail::neighbor_bfs_impl
|
||||
(g, s,
|
||||
choose_param(get_param(params, buffer_param_t()), Qref).ref,
|
||||
choose_param(get_param(params, graph_visitor),
|
||||
make_neighbor_bfs_visitor(null_visitor())),
|
||||
choose_pmap(get_param(params, vertex_color), g, vertex_color)
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP
|
||||
|
||||
153
libraries/include/boost/graph/page_rank.hpp
Normal file
153
libraries/include/boost/graph/page_rank.hpp
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright 2004-5 The Trustees of Indiana University.
|
||||
// Copyright 2002 Brad King and Douglas Gregor
|
||||
|
||||
// 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: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
|
||||
#ifndef BOOST_GRAPH_PAGE_RANK_HPP
|
||||
#define BOOST_GRAPH_PAGE_RANK_HPP
|
||||
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/iteration_macros.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace graph {
|
||||
|
||||
struct n_iterations
|
||||
{
|
||||
explicit n_iterations(std::size_t n) : n(n) { }
|
||||
|
||||
template<typename RankMap, typename Graph>
|
||||
bool
|
||||
operator()(const RankMap&, const Graph&)
|
||||
{
|
||||
return n-- == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t n;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename Graph, typename RankMap, typename RankMap2>
|
||||
void page_rank_step(const Graph& g, RankMap from_rank, RankMap2 to_rank,
|
||||
typename property_traits<RankMap>::value_type damping,
|
||||
incidence_graph_tag)
|
||||
{
|
||||
typedef typename property_traits<RankMap>::value_type rank_type;
|
||||
|
||||
// Set new rank maps
|
||||
BGL_FORALL_VERTICES_T(v, g, Graph) put(to_rank, v, rank_type(1 - damping));
|
||||
|
||||
BGL_FORALL_VERTICES_T(u, g, Graph) {
|
||||
rank_type u_rank_out = damping * get(from_rank, u) / out_degree(u, g);
|
||||
BGL_FORALL_ADJ_T(u, v, g, Graph)
|
||||
put(to_rank, v, get(to_rank, v) + u_rank_out);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Graph, typename RankMap, typename RankMap2>
|
||||
void page_rank_step(const Graph& g, RankMap from_rank, RankMap2 to_rank,
|
||||
typename property_traits<RankMap>::value_type damping,
|
||||
bidirectional_graph_tag)
|
||||
{
|
||||
typedef typename property_traits<RankMap>::value_type damping_type;
|
||||
BGL_FORALL_VERTICES_T(v, g, Graph) {
|
||||
typename property_traits<RankMap>::value_type rank(0);
|
||||
BGL_FORALL_INEDGES_T(v, e, g, Graph)
|
||||
rank += get(from_rank, source(e, g)) / out_degree(source(e, g), g);
|
||||
put(to_rank, v, (damping_type(1) - damping) + damping * rank);
|
||||
}
|
||||
}
|
||||
} // end namespace detail
|
||||
|
||||
template<typename Graph, typename RankMap, typename Done, typename RankMap2>
|
||||
void
|
||||
page_rank(const Graph& g, RankMap rank_map, Done done,
|
||||
typename property_traits<RankMap>::value_type damping,
|
||||
typename graph_traits<Graph>::vertices_size_type n,
|
||||
RankMap2 rank_map2)
|
||||
{
|
||||
typedef typename property_traits<RankMap>::value_type rank_type;
|
||||
|
||||
rank_type initial_rank = rank_type(rank_type(1) / n);
|
||||
BGL_FORALL_VERTICES_T(v, g, Graph) put(rank_map, v, initial_rank);
|
||||
|
||||
bool to_map_2 = true;
|
||||
while ((to_map_2 && !done(rank_map, g)) ||
|
||||
(!to_map_2 && !done(rank_map2, g))) {
|
||||
typedef typename graph_traits<Graph>::traversal_category category;
|
||||
|
||||
if (to_map_2) {
|
||||
detail::page_rank_step(g, rank_map, rank_map2, damping, category());
|
||||
} else {
|
||||
detail::page_rank_step(g, rank_map2, rank_map, damping, category());
|
||||
}
|
||||
to_map_2 = !to_map_2;
|
||||
}
|
||||
|
||||
if (!to_map_2) {
|
||||
BGL_FORALL_VERTICES_T(v, g, Graph) put(rank_map, v, get(rank_map2, v));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Graph, typename RankMap, typename Done>
|
||||
void
|
||||
page_rank(const Graph& g, RankMap rank_map, Done done,
|
||||
typename property_traits<RankMap>::value_type damping,
|
||||
typename graph_traits<Graph>::vertices_size_type n)
|
||||
{
|
||||
typedef typename property_traits<RankMap>::value_type rank_type;
|
||||
|
||||
std::vector<rank_type> ranks2(num_vertices(g));
|
||||
page_rank(g, rank_map, done, damping, n,
|
||||
make_iterator_property_map(ranks2.begin(), get(vertex_index, g)));
|
||||
}
|
||||
|
||||
template<typename Graph, typename RankMap, typename Done>
|
||||
inline void
|
||||
page_rank(const Graph& g, RankMap rank_map, Done done,
|
||||
typename property_traits<RankMap>::value_type damping = 0.85)
|
||||
{
|
||||
page_rank(g, rank_map, done, damping, num_vertices(g));
|
||||
}
|
||||
|
||||
template<typename Graph, typename RankMap>
|
||||
inline void
|
||||
page_rank(const Graph& g, RankMap rank_map)
|
||||
{
|
||||
page_rank(g, rank_map, n_iterations(20));
|
||||
}
|
||||
|
||||
// TBD: this could be _much_ more efficient, using a queue to store
|
||||
// the vertices that should be reprocessed and keeping track of which
|
||||
// vertices are in the queue with a property map. Baah, this only
|
||||
// applies when we have a bidirectional graph.
|
||||
template<typename MutableGraph>
|
||||
void
|
||||
remove_dangling_links(MutableGraph& g)
|
||||
{
|
||||
typename graph_traits<MutableGraph>::vertices_size_type old_n;
|
||||
do {
|
||||
old_n = num_vertices(g);
|
||||
|
||||
typename graph_traits<MutableGraph>::vertex_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = vertices(g); vi != vi_end; /* in loop */) {
|
||||
typename graph_traits<MutableGraph>::vertex_descriptor v = *vi++;
|
||||
if (out_degree(v, g) == 0) {
|
||||
clear_vertex(v, g);
|
||||
remove_vertex(v, g);
|
||||
}
|
||||
}
|
||||
} while (num_vertices(g) < old_n);
|
||||
}
|
||||
|
||||
} } // end namespace boost::graph
|
||||
|
||||
#endif // BOOST_GRAPH_PAGE_RANK_HPP
|
||||
214
libraries/include/boost/graph/planar_canonical_ordering.hpp
Normal file
214
libraries/include/boost/graph/planar_canonical_ordering.hpp
Normal file
@@ -0,0 +1,214 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// 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 __PLANAR_CANONICAL_ORDERING_HPP__
|
||||
#define __PLANAR_CANONICAL_ORDERING_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next and prior
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
namespace detail {
|
||||
enum planar_canonical_ordering_state
|
||||
{PCO_PROCESSED,
|
||||
PCO_UNPROCESSED,
|
||||
PCO_ONE_NEIGHBOR_PROCESSED,
|
||||
PCO_READY_TO_BE_PROCESSED};
|
||||
}
|
||||
|
||||
template<typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename OutputIterator,
|
||||
typename VertexIndexMap>
|
||||
void planar_canonical_ordering(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
OutputIterator ordering,
|
||||
VertexIndexMap vm)
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::adjacency_iterator
|
||||
adjacency_iterator_t;
|
||||
typedef typename std::pair<vertex_t, vertex_t> vertex_pair_t;
|
||||
typedef typename property_traits<PlanarEmbedding>::value_type
|
||||
embedding_value_t;
|
||||
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
|
||||
typedef iterator_property_map
|
||||
<typename std::vector<vertex_t>::iterator, VertexIndexMap>
|
||||
vertex_to_vertex_map_t;
|
||||
typedef iterator_property_map
|
||||
<typename std::vector<std::size_t>::iterator, VertexIndexMap>
|
||||
vertex_to_size_t_map_t;
|
||||
|
||||
std::vector<vertex_t> processed_neighbor_vector(num_vertices(g));
|
||||
vertex_to_vertex_map_t processed_neighbor
|
||||
(processed_neighbor_vector.begin(), vm);
|
||||
|
||||
std::vector<std::size_t> status_vector(num_vertices(g), detail::PCO_UNPROCESSED);
|
||||
vertex_to_size_t_map_t status(status_vector.begin(), vm);
|
||||
|
||||
std::list<vertex_t> ready_to_be_processed;
|
||||
|
||||
vertex_t first_vertex = *vertices(g).first;
|
||||
vertex_t second_vertex;
|
||||
adjacency_iterator_t ai, ai_end;
|
||||
for(tie(ai,ai_end) = adjacent_vertices(first_vertex,g); ai != ai_end; ++ai)
|
||||
{
|
||||
if (*ai == first_vertex)
|
||||
continue;
|
||||
second_vertex = *ai;
|
||||
break;
|
||||
}
|
||||
|
||||
ready_to_be_processed.push_back(first_vertex);
|
||||
status[first_vertex] = detail::PCO_READY_TO_BE_PROCESSED;
|
||||
ready_to_be_processed.push_back(second_vertex);
|
||||
status[second_vertex] = detail::PCO_READY_TO_BE_PROCESSED;
|
||||
|
||||
while(!ready_to_be_processed.empty())
|
||||
{
|
||||
vertex_t u = ready_to_be_processed.front();
|
||||
ready_to_be_processed.pop_front();
|
||||
|
||||
if (status[u] != detail::PCO_READY_TO_BE_PROCESSED && u != second_vertex)
|
||||
continue;
|
||||
|
||||
embedding_iterator_t ei, ei_start, ei_end;
|
||||
embedding_iterator_t next_edge_itr, prior_edge_itr;
|
||||
|
||||
ei_start = embedding[u].begin();
|
||||
ei_end = embedding[u].end();
|
||||
prior_edge_itr = prior(ei_end);
|
||||
while(source(*prior_edge_itr, g) == target(*prior_edge_itr,g))
|
||||
prior_edge_itr = prior(prior_edge_itr);
|
||||
|
||||
for(ei = ei_start; ei != ei_end; ++ei)
|
||||
{
|
||||
|
||||
edge_t e(*ei); // e = (u,v)
|
||||
next_edge_itr = next(ei) == ei_end ? ei_start : next(ei);
|
||||
vertex_t v = source(e,g) == u ? target(e,g) : source(e,g);
|
||||
|
||||
vertex_t prior_vertex = source(*prior_edge_itr, g) == u ?
|
||||
target(*prior_edge_itr, g) : source(*prior_edge_itr, g);
|
||||
vertex_t next_vertex = source(*next_edge_itr, g) == u ?
|
||||
target(*next_edge_itr, g) : source(*next_edge_itr, g);
|
||||
|
||||
// Need prior_vertex, u, v, and next_vertex to all be
|
||||
// distinct. This is possible, since the input graph is
|
||||
// triangulated. It'll be true all the time in a simple
|
||||
// graph, but loops and parallel edges cause some complications.
|
||||
if (prior_vertex == v || prior_vertex == u)
|
||||
{
|
||||
prior_edge_itr = ei;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Skip any self-loops
|
||||
if (u == v)
|
||||
continue;
|
||||
|
||||
// Move next_edge_itr (and next_vertex) forwards
|
||||
// past any loops or parallel edges
|
||||
while (next_vertex == v || next_vertex == u)
|
||||
{
|
||||
next_edge_itr = next(next_edge_itr) == ei_end ?
|
||||
ei_start : next(next_edge_itr);
|
||||
next_vertex = source(*next_edge_itr, g) == u ?
|
||||
target(*next_edge_itr, g) : source(*next_edge_itr, g);
|
||||
}
|
||||
|
||||
|
||||
if (status[v] == detail::PCO_UNPROCESSED)
|
||||
{
|
||||
status[v] = detail::PCO_ONE_NEIGHBOR_PROCESSED;
|
||||
processed_neighbor[v] = u;
|
||||
}
|
||||
else if (status[v] == detail::PCO_ONE_NEIGHBOR_PROCESSED)
|
||||
{
|
||||
vertex_t x = processed_neighbor[v];
|
||||
//are edges (v,u) and (v,x) adjacent in the planar
|
||||
//embedding? if so, set status[v] = 1. otherwise, set
|
||||
//status[v] = 2.
|
||||
|
||||
if ((next_vertex == x &&
|
||||
!(first_vertex == u && second_vertex == x)
|
||||
)
|
||||
||
|
||||
(prior_vertex == x &&
|
||||
!(first_vertex == x && second_vertex == u)
|
||||
)
|
||||
)
|
||||
{
|
||||
status[v] = detail::PCO_READY_TO_BE_PROCESSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
status[v] = detail::PCO_READY_TO_BE_PROCESSED + 1;
|
||||
}
|
||||
}
|
||||
else if (status[v] > detail::PCO_ONE_NEIGHBOR_PROCESSED)
|
||||
{
|
||||
//check the two edges before and after (v,u) in the planar
|
||||
//embedding, and update status[v] accordingly
|
||||
|
||||
bool processed_before = false;
|
||||
if (status[prior_vertex] == detail::PCO_PROCESSED)
|
||||
processed_before = true;
|
||||
|
||||
bool processed_after = false;
|
||||
if (status[next_vertex] == detail::PCO_PROCESSED)
|
||||
processed_after = true;
|
||||
|
||||
if (!processed_before && !processed_after)
|
||||
++status[v];
|
||||
|
||||
else if (processed_before && processed_after)
|
||||
--status[v];
|
||||
|
||||
}
|
||||
|
||||
if (status[v] == detail::PCO_READY_TO_BE_PROCESSED)
|
||||
ready_to_be_processed.push_back(v);
|
||||
|
||||
prior_edge_itr = ei;
|
||||
|
||||
}
|
||||
|
||||
status[u] = detail::PCO_PROCESSED;
|
||||
*ordering = u;
|
||||
++ordering;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename Graph, typename PlanarEmbedding, typename OutputIterator>
|
||||
void planar_canonical_ordering(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
OutputIterator ordering
|
||||
)
|
||||
{
|
||||
planar_canonical_ordering(g, embedding, ordering, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
} //namespace boost
|
||||
|
||||
#endif //__PLANAR_CANONICAL_ORDERING_HPP__
|
||||
@@ -0,0 +1,59 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// 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 __ADD_EDGE_VISITORS_HPP__
|
||||
#define __ADD_EDGE_VISITORS_HPP__
|
||||
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
struct default_add_edge_visitor
|
||||
{
|
||||
|
||||
template <typename Graph, typename Vertex>
|
||||
void visit_vertex_pair(Vertex u, Vertex v, Graph& g)
|
||||
{
|
||||
add_edge(u,v,g);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename EdgeIndexMap>
|
||||
struct edge_index_update_visitor
|
||||
{
|
||||
|
||||
typedef typename
|
||||
property_traits<EdgeIndexMap>::value_type edge_index_value_t;
|
||||
|
||||
edge_index_update_visitor(EdgeIndexMap em,
|
||||
edge_index_value_t next_index_available
|
||||
) :
|
||||
m_em(em),
|
||||
m_next_index(next_index_available)
|
||||
{}
|
||||
|
||||
template <typename Graph, typename Vertex>
|
||||
void visit_vertex_pair(Vertex u, Vertex v, Graph& g)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
std::pair<edge_t, bool> return_value = add_edge(u,v,g);
|
||||
if (return_value.second)
|
||||
put( m_em, return_value.first, m_next_index++);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
EdgeIndexMap m_em;
|
||||
edge_index_value_t m_next_index;
|
||||
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //__ADD_EDGE_VISITORS_HPP__
|
||||
2012
libraries/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp
Normal file
2012
libraries/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp
Normal file
File diff suppressed because it is too large
Load Diff
144
libraries/include/boost/graph/planar_detail/bucket_sort.hpp
Normal file
144
libraries/include/boost/graph/planar_detail/bucket_sort.hpp
Normal file
@@ -0,0 +1,144 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// 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 __BUCKET_SORT_HPP__
|
||||
#define __BUCKET_SORT_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
template <typename ItemToRankMap>
|
||||
struct rank_comparison
|
||||
{
|
||||
rank_comparison(ItemToRankMap arg_itrm) : itrm(arg_itrm) {}
|
||||
|
||||
template <typename Item>
|
||||
bool operator() (Item x, Item y) const
|
||||
{
|
||||
return get(itrm, x) < get(itrm, y);
|
||||
}
|
||||
|
||||
private:
|
||||
ItemToRankMap itrm;
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename TupleType,
|
||||
int N,
|
||||
typename PropertyMapWrapper = identity_property_map>
|
||||
struct property_map_tuple_adaptor :
|
||||
public put_get_helper< typename PropertyMapWrapper::value_type,
|
||||
property_map_tuple_adaptor
|
||||
<TupleType, N, PropertyMapWrapper>
|
||||
>
|
||||
{
|
||||
typedef typename PropertyMapWrapper::reference reference;
|
||||
typedef typename PropertyMapWrapper::value_type value_type;
|
||||
typedef TupleType key_type;
|
||||
typedef readable_property_map_tag category;
|
||||
|
||||
property_map_tuple_adaptor() {}
|
||||
|
||||
property_map_tuple_adaptor(PropertyMapWrapper wrapper_map) :
|
||||
m_wrapper_map(wrapper_map)
|
||||
{}
|
||||
|
||||
inline value_type operator[](const key_type& x) const
|
||||
{
|
||||
return get(m_wrapper_map, get<n>(x));
|
||||
}
|
||||
|
||||
static const int n = N;
|
||||
PropertyMapWrapper m_wrapper_map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// This function sorts a sequence of n items by their ranks in linear time,
|
||||
// given that all ranks are in the range [0, range). This sort is stable.
|
||||
template <typename ForwardIterator,
|
||||
typename ItemToRankMap,
|
||||
typename SizeType>
|
||||
void bucket_sort(ForwardIterator begin,
|
||||
ForwardIterator end,
|
||||
ItemToRankMap rank,
|
||||
SizeType range = 0)
|
||||
{
|
||||
#ifdef BOOST_GRAPH_PREFER_STD_LIB
|
||||
std::stable_sort(begin, end, rank_comparison<ItemToRankMap>(rank));
|
||||
#else
|
||||
typedef std::vector
|
||||
< typename boost::property_traits<ItemToRankMap>::key_type >
|
||||
vector_of_values_t;
|
||||
typedef std::vector< vector_of_values_t > vector_of_vectors_t;
|
||||
|
||||
if (!range)
|
||||
{
|
||||
rank_comparison<ItemToRankMap> cmp(rank);
|
||||
ForwardIterator max_by_rank = std::max_element(begin, end, cmp);
|
||||
if (max_by_rank == end)
|
||||
return;
|
||||
range = get(rank, *max_by_rank) + 1;
|
||||
}
|
||||
|
||||
vector_of_vectors_t temp_values(range);
|
||||
|
||||
for(ForwardIterator itr = begin; itr != end; ++itr)
|
||||
{
|
||||
temp_values[get(rank, *itr)].push_back(*itr);
|
||||
}
|
||||
|
||||
ForwardIterator orig_seq_itr = begin;
|
||||
typename vector_of_vectors_t::iterator itr_end = temp_values.end();
|
||||
for(typename vector_of_vectors_t::iterator itr = temp_values.begin();
|
||||
itr != itr_end; ++itr
|
||||
)
|
||||
{
|
||||
typename vector_of_values_t::iterator jtr_end = itr->end();
|
||||
for(typename vector_of_values_t::iterator jtr = itr->begin();
|
||||
jtr != jtr_end; ++jtr
|
||||
)
|
||||
{
|
||||
*orig_seq_itr = *jtr;
|
||||
++orig_seq_itr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <typename ForwardIterator, typename ItemToRankMap>
|
||||
void bucket_sort(ForwardIterator begin,
|
||||
ForwardIterator end,
|
||||
ItemToRankMap rank)
|
||||
{
|
||||
bucket_sort(begin, end, rank, 0);
|
||||
}
|
||||
|
||||
template <typename ForwardIterator>
|
||||
void bucket_sort(ForwardIterator begin,
|
||||
ForwardIterator end
|
||||
)
|
||||
{
|
||||
bucket_sort(begin, end, identity_property_map());
|
||||
}
|
||||
|
||||
|
||||
} //namespace boost
|
||||
|
||||
|
||||
#endif //__BUCKET_SORT_HPP__
|
||||
497
libraries/include/boost/graph/planar_detail/face_handles.hpp
Normal file
497
libraries/include/boost/graph/planar_detail/face_handles.hpp
Normal file
@@ -0,0 +1,497 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// 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 __FACE_HANDLES_HPP__
|
||||
#define __FACE_HANDLES_HPP__
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
||||
// A "face handle" is an optimization meant to serve two purposes in
|
||||
// the implementation of the Boyer-Myrvold planarity test: (1) it holds
|
||||
// the partial planar embedding of a particular vertex as it's being
|
||||
// constructed, and (2) it allows for efficient traversal around the
|
||||
// outer face of the partial embedding at that particular vertex. A face
|
||||
// handle is lightweight, just a shared pointer to the actual implementation,
|
||||
// since it is passed around/copied liberally in the algorithm. It consists
|
||||
// of an "anchor" (the actual vertex it's associated with) as well as a
|
||||
// sequence of edges. The functions first_vertex/second_vertex and
|
||||
// first_edge/second_edge allow fast access to the beginning and end of the
|
||||
// stored sequence, which allows one to traverse the outer face of the partial
|
||||
// planar embedding as it's being created.
|
||||
//
|
||||
// There are some policies below that define the contents of the face handles:
|
||||
// in the case no embedding is needed (for example, if one just wants to use
|
||||
// the Boyer-Myrvold algorithm as a true/false test for planarity, the
|
||||
// no_embedding class can be passed as the StoreEmbedding policy. Otherwise,
|
||||
// either std_list (which uses as std::list) or recursive_lazy_list can be
|
||||
// passed as this policy. recursive_lazy_list has the best theoretical
|
||||
// performance (O(n) for a sequence of interleaved concatenations and reversals
|
||||
// of the underlying list), but I've noticed little difference between std_list
|
||||
// and recursive_lazy_list in my tests, even though using std_list changes
|
||||
// the worst-case complexity of the planarity test to O(n^2)
|
||||
//
|
||||
// Another policy is StoreOldHandlesPolicy, which specifies whether or not
|
||||
// to keep a record of the previous first/second vertex/edge - this is needed
|
||||
// if a Kuratowski subgraph needs to be isolated.
|
||||
|
||||
|
||||
namespace boost { namespace graph { namespace detail {
|
||||
|
||||
|
||||
//face handle policies
|
||||
|
||||
//EmbeddingStorage policy
|
||||
struct store_embedding {};
|
||||
struct recursive_lazy_list : public store_embedding {};
|
||||
struct std_list : public store_embedding {};
|
||||
struct no_embedding {};
|
||||
|
||||
//StoreOldHandlesPolicy
|
||||
struct store_old_handles {};
|
||||
struct no_old_handles {};
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename DataType>
|
||||
struct lazy_list_node
|
||||
{
|
||||
typedef shared_ptr< lazy_list_node<DataType> > ptr_t;
|
||||
|
||||
lazy_list_node(const DataType& data) :
|
||||
m_reversed(false),
|
||||
m_data(data),
|
||||
m_has_data(true)
|
||||
{}
|
||||
|
||||
lazy_list_node(ptr_t left_child, ptr_t right_child) :
|
||||
m_reversed(false),
|
||||
m_has_data(false),
|
||||
m_left_child(left_child),
|
||||
m_right_child(right_child)
|
||||
{}
|
||||
|
||||
bool m_reversed;
|
||||
DataType m_data;
|
||||
bool m_has_data;
|
||||
shared_ptr<lazy_list_node> m_left_child;
|
||||
shared_ptr<lazy_list_node> m_right_child;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename StoreOldHandlesPolicy, typename Vertex, typename Edge>
|
||||
struct old_handles_storage;
|
||||
|
||||
template <typename Vertex, typename Edge>
|
||||
struct old_handles_storage<store_old_handles, Vertex, Edge>
|
||||
{
|
||||
Vertex first_vertex;
|
||||
Vertex second_vertex;
|
||||
Edge first_edge;
|
||||
Edge second_edge;
|
||||
};
|
||||
|
||||
template <typename Vertex, typename Edge>
|
||||
struct old_handles_storage<no_old_handles, Vertex, Edge>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename StoreEmbeddingPolicy, typename Edge>
|
||||
struct edge_list_storage;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Edge>
|
||||
struct edge_list_storage<no_embedding, Edge>
|
||||
{
|
||||
typedef void type;
|
||||
|
||||
void push_back(Edge) {}
|
||||
void push_front(Edge) {}
|
||||
void reverse() {}
|
||||
void concat_front(edge_list_storage<no_embedding,Edge>) {}
|
||||
void concat_back(edge_list_storage<no_embedding,Edge>) {}
|
||||
template <typename OutputIterator>
|
||||
void get_list(OutputIterator) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Edge>
|
||||
struct edge_list_storage<recursive_lazy_list, Edge>
|
||||
{
|
||||
typedef lazy_list_node<Edge> node_type;
|
||||
typedef shared_ptr< node_type > type;
|
||||
type value;
|
||||
|
||||
void push_back(Edge e)
|
||||
{
|
||||
type new_node(new node_type(e));
|
||||
value = type(new node_type(value, new_node));
|
||||
}
|
||||
|
||||
void push_front(Edge e)
|
||||
{
|
||||
type new_node(new node_type(e));
|
||||
value = type(new node_type(new_node, value));
|
||||
}
|
||||
|
||||
void reverse()
|
||||
{
|
||||
value->m_reversed = !value->m_reversed;
|
||||
}
|
||||
|
||||
void concat_front(edge_list_storage<recursive_lazy_list, Edge> other)
|
||||
{
|
||||
value = type(new node_type(other.value, value));
|
||||
}
|
||||
|
||||
void concat_back(edge_list_storage<recursive_lazy_list, Edge> other)
|
||||
{
|
||||
value = type(new node_type(value, other.value));
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
void get_list(OutputIterator out)
|
||||
{
|
||||
get_list_helper(out, value);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename OutputIterator>
|
||||
void get_list_helper(OutputIterator o_itr,
|
||||
type root,
|
||||
bool flipped = false
|
||||
)
|
||||
{
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
if (root->m_has_data)
|
||||
*o_itr = root->m_data;
|
||||
|
||||
if ((flipped && !root->m_reversed) ||
|
||||
(!flipped && root->m_reversed)
|
||||
)
|
||||
{
|
||||
get_list_helper(o_itr, root->m_right_child, true);
|
||||
get_list_helper(o_itr, root->m_left_child, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_list_helper(o_itr, root->m_left_child, false);
|
||||
get_list_helper(o_itr, root->m_right_child, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Edge>
|
||||
struct edge_list_storage<std_list, Edge>
|
||||
{
|
||||
typedef std::list<Edge> type;
|
||||
type value;
|
||||
|
||||
void push_back(Edge e)
|
||||
{
|
||||
value.push_back(e);
|
||||
}
|
||||
|
||||
void push_front(Edge e)
|
||||
{
|
||||
value.push_front(e);
|
||||
}
|
||||
|
||||
void reverse()
|
||||
{
|
||||
value.reverse();
|
||||
}
|
||||
|
||||
void concat_front(edge_list_storage<std_list,Edge> other)
|
||||
{
|
||||
value.splice(value.begin(), other.value);
|
||||
}
|
||||
|
||||
void concat_back(edge_list_storage<std_list, Edge> other)
|
||||
{
|
||||
value.splice(value.end(), other.value);
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
void get_list(OutputIterator out)
|
||||
{
|
||||
std::copy(value.begin(), value.end(), out);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename StoreOldHandlesPolicy,
|
||||
typename StoreEmbeddingPolicy
|
||||
>
|
||||
struct face_handle_impl
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename edge_list_storage<StoreEmbeddingPolicy, edge_t>::type
|
||||
edge_list_storage_t;
|
||||
|
||||
|
||||
face_handle_impl() :
|
||||
cached_first_vertex(graph_traits<Graph>::null_vertex()),
|
||||
cached_second_vertex(graph_traits<Graph>::null_vertex()),
|
||||
true_first_vertex(graph_traits<Graph>::null_vertex()),
|
||||
true_second_vertex(graph_traits<Graph>::null_vertex()),
|
||||
anchor(graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
initialize_old_vertices_dispatch(StoreOldHandlesPolicy());
|
||||
}
|
||||
|
||||
void initialize_old_vertices_dispatch(store_old_handles)
|
||||
{
|
||||
old_handles.first_vertex = graph_traits<Graph>::null_vertex();
|
||||
old_handles.second_vertex = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
|
||||
void initialize_old_vertices_dispatch(no_old_handles) {}
|
||||
|
||||
vertex_t cached_first_vertex;
|
||||
vertex_t cached_second_vertex;
|
||||
vertex_t true_first_vertex;
|
||||
vertex_t true_second_vertex;
|
||||
vertex_t anchor;
|
||||
edge_t cached_first_edge;
|
||||
edge_t cached_second_edge;
|
||||
|
||||
edge_list_storage<StoreEmbeddingPolicy, edge_t> edge_list;
|
||||
old_handles_storage<StoreOldHandlesPolicy, vertex_t, edge_t> old_handles;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename StoreOldHandlesPolicy = store_old_handles,
|
||||
typename StoreEmbeddingPolicy = recursive_lazy_list
|
||||
>
|
||||
class face_handle
|
||||
{
|
||||
public:
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef face_handle_impl
|
||||
<Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> impl_t;
|
||||
typedef face_handle
|
||||
<Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> self_t;
|
||||
|
||||
face_handle(vertex_t anchor = graph_traits<Graph>::null_vertex()) :
|
||||
pimpl(new impl_t())
|
||||
{
|
||||
pimpl->anchor = anchor;
|
||||
}
|
||||
|
||||
face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) :
|
||||
pimpl(new impl_t())
|
||||
{
|
||||
vertex_t s(source(initial_edge,g));
|
||||
vertex_t t(target(initial_edge,g));
|
||||
vertex_t other_vertex = s == anchor ? t : s;
|
||||
pimpl->anchor = anchor;
|
||||
pimpl->cached_first_edge = initial_edge;
|
||||
pimpl->cached_second_edge = initial_edge;
|
||||
pimpl->cached_first_vertex = other_vertex;
|
||||
pimpl->cached_second_vertex = other_vertex;
|
||||
pimpl->true_first_vertex = other_vertex;
|
||||
pimpl->true_second_vertex = other_vertex;
|
||||
|
||||
pimpl->edge_list.push_back(initial_edge);
|
||||
store_old_face_handles_dispatch(StoreOldHandlesPolicy());
|
||||
}
|
||||
|
||||
//default copy construction, assignment okay.
|
||||
|
||||
void push_first(edge_t e, const Graph& g)
|
||||
{
|
||||
pimpl->edge_list.push_front(e);
|
||||
pimpl->cached_first_vertex = pimpl->true_first_vertex =
|
||||
source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
|
||||
pimpl->cached_first_edge = e;
|
||||
}
|
||||
|
||||
void push_second(edge_t e, const Graph& g)
|
||||
{
|
||||
pimpl->edge_list.push_back(e);
|
||||
pimpl->cached_second_vertex = pimpl->true_second_vertex =
|
||||
source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
|
||||
pimpl->cached_second_edge = e;
|
||||
}
|
||||
|
||||
inline void store_old_face_handles()
|
||||
{
|
||||
store_old_face_handles_dispatch(StoreOldHandlesPolicy());
|
||||
}
|
||||
|
||||
inline vertex_t first_vertex() const
|
||||
{
|
||||
return pimpl->cached_first_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t second_vertex() const
|
||||
{
|
||||
return pimpl->cached_second_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t true_first_vertex() const
|
||||
{
|
||||
return pimpl->true_first_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t true_second_vertex() const
|
||||
{
|
||||
return pimpl->true_second_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t old_first_vertex() const
|
||||
{
|
||||
return pimpl->old_handles.first_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t old_second_vertex() const
|
||||
{
|
||||
return pimpl->old_handles.second_vertex;
|
||||
}
|
||||
|
||||
inline edge_t old_first_edge() const
|
||||
{
|
||||
return pimpl->old_handles.first_edge;
|
||||
}
|
||||
|
||||
inline edge_t old_second_edge() const
|
||||
{
|
||||
return pimpl->old_handles.second_edge;
|
||||
}
|
||||
|
||||
inline edge_t first_edge() const
|
||||
{
|
||||
return pimpl->cached_first_edge;
|
||||
}
|
||||
|
||||
inline edge_t second_edge() const
|
||||
{
|
||||
return pimpl->cached_second_edge;
|
||||
}
|
||||
|
||||
inline vertex_t get_anchor() const
|
||||
{
|
||||
return pimpl->anchor;
|
||||
}
|
||||
|
||||
void glue_first_to_second
|
||||
(face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
|
||||
{
|
||||
pimpl->edge_list.concat_front(bottom.pimpl->edge_list);
|
||||
pimpl->true_first_vertex = bottom.pimpl->true_first_vertex;
|
||||
pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex;
|
||||
pimpl->cached_first_edge = bottom.pimpl->cached_first_edge;
|
||||
}
|
||||
|
||||
void glue_second_to_first
|
||||
(face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
|
||||
{
|
||||
pimpl->edge_list.concat_back(bottom.pimpl->edge_list);
|
||||
pimpl->true_second_vertex = bottom.pimpl->true_second_vertex;
|
||||
pimpl->cached_second_vertex = bottom.pimpl->cached_second_vertex;
|
||||
pimpl->cached_second_edge = bottom.pimpl->cached_second_edge;
|
||||
}
|
||||
|
||||
void flip()
|
||||
{
|
||||
pimpl->edge_list.reverse();
|
||||
std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex);
|
||||
std::swap(pimpl->cached_first_vertex, pimpl->cached_second_vertex);
|
||||
std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge);
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
void get_list(OutputIterator o_itr)
|
||||
{
|
||||
pimpl->edge_list.get_list(o_itr);
|
||||
}
|
||||
|
||||
void reset_vertex_cache()
|
||||
{
|
||||
pimpl->cached_first_vertex = pimpl->true_first_vertex;
|
||||
pimpl->cached_second_vertex = pimpl->true_second_vertex;
|
||||
}
|
||||
|
||||
inline void set_first_vertex(vertex_t v)
|
||||
{
|
||||
pimpl->cached_first_vertex = v;
|
||||
}
|
||||
|
||||
inline void set_second_vertex(vertex_t v)
|
||||
{
|
||||
pimpl->cached_second_vertex = v;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void store_old_face_handles_dispatch(store_old_handles)
|
||||
{
|
||||
pimpl->old_handles.first_vertex = pimpl->true_first_vertex;
|
||||
pimpl->old_handles.second_vertex = pimpl->true_second_vertex;
|
||||
pimpl->old_handles.first_edge = pimpl->cached_first_edge;
|
||||
pimpl->old_handles.second_edge = pimpl->cached_second_edge;
|
||||
}
|
||||
|
||||
void store_old_face_handles_dispatch(no_old_handles) {}
|
||||
|
||||
|
||||
|
||||
boost::shared_ptr<impl_t> pimpl;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} /* namespace detail */ } /* namespace graph */ } /* namespace boost */
|
||||
|
||||
|
||||
#endif //__FACE_HANDLES_HPP__
|
||||
375
libraries/include/boost/graph/planar_detail/face_iterators.hpp
Normal file
375
libraries/include/boost/graph/planar_detail/face_iterators.hpp
Normal file
@@ -0,0 +1,375 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// 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 __FACE_ITERATORS_HPP__
|
||||
#define __FACE_ITERATORS_HPP__
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
//tags for defining traversal properties
|
||||
|
||||
//VisitorType
|
||||
struct lead_visitor {};
|
||||
struct follow_visitor {};
|
||||
|
||||
//TraversalType
|
||||
struct single_side {};
|
||||
struct both_sides {};
|
||||
|
||||
//TraversalSubType
|
||||
struct first_side {}; //for single_side
|
||||
struct second_side {}; //for single_side
|
||||
struct alternating {}; //for both_sides
|
||||
|
||||
//Time
|
||||
struct current_iteration {};
|
||||
struct previous_iteration {};
|
||||
|
||||
// Why TraversalType AND TraversalSubType? TraversalSubType is a function
|
||||
// template parameter passed in to the constructor of the face iterator,
|
||||
// whereas TraversalType is a class template parameter. This lets us decide
|
||||
// at runtime whether to move along the first or second side of a bicomp (by
|
||||
// assigning a face_iterator that has been constructed with TraversalSubType
|
||||
// = first_side or second_side to a face_iterator variable) without any of
|
||||
// the virtual function overhead that comes with implementing this
|
||||
// functionality as a more structured form of type erasure. It also allows
|
||||
// a single face_iterator to be the end iterator of two iterators traversing
|
||||
// both sides of a bicomp.
|
||||
|
||||
//ValueType is either graph_traits<Graph>::vertex_descriptor
|
||||
//or graph_traits<Graph>::edge_descriptor
|
||||
|
||||
|
||||
//forward declaration (defining defaults)
|
||||
template <typename Graph,
|
||||
typename FaceHandlesMap,
|
||||
typename ValueType,
|
||||
typename BicompSideToTraverse = single_side,
|
||||
typename VisitorType = lead_visitor,
|
||||
typename Time = current_iteration
|
||||
>
|
||||
class face_iterator;
|
||||
|
||||
|
||||
|
||||
template <typename Graph, bool StoreEdge>
|
||||
struct edge_storage
|
||||
{};
|
||||
|
||||
template <typename Graph>
|
||||
struct edge_storage <Graph, true>
|
||||
{
|
||||
typename graph_traits<Graph>::edge_descriptor value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//specialization for TraversalType = traverse_vertices
|
||||
template <typename Graph,
|
||||
typename FaceHandlesMap,
|
||||
typename ValueType,
|
||||
typename TraversalType,
|
||||
typename VisitorType,
|
||||
typename Time
|
||||
>
|
||||
|
||||
class face_iterator
|
||||
: public boost::iterator_facade < face_iterator<Graph,
|
||||
FaceHandlesMap,
|
||||
ValueType,
|
||||
TraversalType,
|
||||
VisitorType,
|
||||
Time
|
||||
>,
|
||||
ValueType,
|
||||
boost::forward_traversal_tag,
|
||||
ValueType
|
||||
>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef face_iterator
|
||||
<Graph,FaceHandlesMap,ValueType,TraversalType,VisitorType,Time> self;
|
||||
typedef typename FaceHandlesMap::value_type face_handle_t;
|
||||
|
||||
face_iterator() :
|
||||
m_lead(graph_traits<Graph>::null_vertex()),
|
||||
m_follow(graph_traits<Graph>::null_vertex())
|
||||
{}
|
||||
|
||||
template <typename TraversalSubType>
|
||||
face_iterator(face_handle_t anchor_handle,
|
||||
FaceHandlesMap face_handles,
|
||||
TraversalSubType traversal_type):
|
||||
m_follow(anchor_handle.get_anchor()),
|
||||
m_face_handles(face_handles)
|
||||
{
|
||||
set_lead_dispatch(anchor_handle, traversal_type);
|
||||
}
|
||||
|
||||
template <typename TraversalSubType>
|
||||
face_iterator(vertex_t anchor,
|
||||
FaceHandlesMap face_handles,
|
||||
TraversalSubType traversal_type):
|
||||
m_follow(anchor),
|
||||
m_face_handles(face_handles)
|
||||
{
|
||||
set_lead_dispatch(m_face_handles[anchor], traversal_type);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
|
||||
|
||||
|
||||
inline vertex_t get_first_vertex(face_handle_t anchor_handle,
|
||||
current_iteration
|
||||
)
|
||||
{
|
||||
return anchor_handle.first_vertex();
|
||||
}
|
||||
|
||||
inline vertex_t get_second_vertex(face_handle_t anchor_handle,
|
||||
current_iteration
|
||||
)
|
||||
{
|
||||
return anchor_handle.second_vertex();
|
||||
}
|
||||
|
||||
inline vertex_t get_first_vertex(face_handle_t anchor_handle,
|
||||
previous_iteration
|
||||
)
|
||||
{
|
||||
return anchor_handle.old_first_vertex();
|
||||
}
|
||||
|
||||
inline vertex_t get_second_vertex(face_handle_t anchor_handle,
|
||||
previous_iteration
|
||||
)
|
||||
{
|
||||
return anchor_handle.old_second_vertex();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline void set_lead_dispatch(face_handle_t anchor_handle, first_side)
|
||||
{
|
||||
m_lead = get_first_vertex(anchor_handle, Time());
|
||||
set_edge_to_first_dispatch(anchor_handle, ValueType(), Time());
|
||||
}
|
||||
|
||||
inline void set_lead_dispatch(face_handle_t anchor_handle, second_side)
|
||||
{
|
||||
m_lead = get_second_vertex(anchor_handle, Time());
|
||||
set_edge_to_second_dispatch(anchor_handle, ValueType(), Time());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline void set_edge_to_first_dispatch(face_handle_t anchor_handle,
|
||||
edge_t,
|
||||
current_iteration
|
||||
)
|
||||
{
|
||||
m_edge.value = anchor_handle.first_edge();
|
||||
}
|
||||
|
||||
inline void set_edge_to_second_dispatch(face_handle_t anchor_handle,
|
||||
edge_t,
|
||||
current_iteration
|
||||
)
|
||||
{
|
||||
m_edge.value = anchor_handle.second_edge();
|
||||
}
|
||||
|
||||
inline void set_edge_to_first_dispatch(face_handle_t anchor_handle,
|
||||
edge_t,
|
||||
previous_iteration
|
||||
)
|
||||
{
|
||||
m_edge.value = anchor_handle.old_first_edge();
|
||||
}
|
||||
|
||||
inline void set_edge_to_second_dispatch(face_handle_t anchor_handle,
|
||||
edge_t,
|
||||
previous_iteration
|
||||
)
|
||||
{
|
||||
m_edge.value = anchor_handle.old_second_edge();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void set_edge_to_first_dispatch(face_handle_t, vertex_t, T)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
inline void set_edge_to_second_dispatch(face_handle_t, vertex_t, T)
|
||||
{}
|
||||
|
||||
void increment()
|
||||
{
|
||||
face_handle_t curr_face_handle(m_face_handles[m_lead]);
|
||||
vertex_t first = get_first_vertex(curr_face_handle, Time());
|
||||
vertex_t second = get_second_vertex(curr_face_handle, Time());
|
||||
if (first == m_follow)
|
||||
{
|
||||
m_follow = m_lead;
|
||||
set_edge_to_second_dispatch(curr_face_handle, ValueType(), Time());
|
||||
m_lead = second;
|
||||
}
|
||||
else if (second == m_follow)
|
||||
{
|
||||
m_follow = m_lead;
|
||||
set_edge_to_first_dispatch(curr_face_handle, ValueType(), Time());
|
||||
m_lead = first;
|
||||
}
|
||||
else
|
||||
m_lead = m_follow = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
|
||||
bool equal(self const& other) const
|
||||
{
|
||||
return m_lead == other.m_lead && m_follow == other.m_follow;
|
||||
}
|
||||
|
||||
ValueType dereference() const
|
||||
{
|
||||
return dereference_dispatch(VisitorType(), ValueType());
|
||||
}
|
||||
|
||||
inline ValueType dereference_dispatch(lead_visitor, vertex_t) const
|
||||
{ return m_lead; }
|
||||
|
||||
inline ValueType dereference_dispatch(follow_visitor, vertex_t) const
|
||||
{ return m_follow; }
|
||||
|
||||
inline ValueType dereference_dispatch(lead_visitor, edge_t) const
|
||||
{ return m_edge.value; }
|
||||
|
||||
inline ValueType dereference_dispatch(follow_visitor, edge_t) const
|
||||
{ return m_edge.value; }
|
||||
|
||||
vertex_t m_lead;
|
||||
vertex_t m_follow;
|
||||
edge_storage<Graph, boost::is_same<ValueType, edge_t>::value > m_edge;
|
||||
FaceHandlesMap m_face_handles;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename FaceHandlesMap,
|
||||
typename ValueType,
|
||||
typename VisitorType,
|
||||
typename Time
|
||||
>
|
||||
class face_iterator
|
||||
<Graph, FaceHandlesMap, ValueType, both_sides, VisitorType, Time>
|
||||
: public boost::iterator_facade< face_iterator<Graph,
|
||||
FaceHandlesMap,
|
||||
ValueType,
|
||||
both_sides,
|
||||
VisitorType,
|
||||
Time>,
|
||||
ValueType,
|
||||
boost::forward_traversal_tag,
|
||||
ValueType >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef face_iterator
|
||||
<Graph,FaceHandlesMap,ValueType,both_sides,VisitorType,Time> self;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename FaceHandlesMap::value_type face_handle_t;
|
||||
|
||||
face_iterator() {}
|
||||
|
||||
face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles):
|
||||
first_itr(anchor_handle, face_handles, first_side()),
|
||||
second_itr(anchor_handle, face_handles, second_side()),
|
||||
first_is_active(true),
|
||||
first_increment(true)
|
||||
{}
|
||||
|
||||
face_iterator(vertex_t anchor, FaceHandlesMap face_handles):
|
||||
first_itr(face_handles[anchor], face_handles, first_side()),
|
||||
second_itr(face_handles[anchor], face_handles, second_side()),
|
||||
first_is_active(true),
|
||||
first_increment(true)
|
||||
{}
|
||||
|
||||
private:
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
typedef face_iterator
|
||||
<Graph, FaceHandlesMap, ValueType, single_side, follow_visitor, Time>
|
||||
inner_itr_t;
|
||||
|
||||
void increment()
|
||||
{
|
||||
if (first_increment)
|
||||
{
|
||||
++first_itr;
|
||||
++second_itr;
|
||||
first_increment = false;
|
||||
}
|
||||
else if (first_is_active)
|
||||
++first_itr;
|
||||
else
|
||||
++second_itr;
|
||||
first_is_active = !first_is_active;
|
||||
}
|
||||
|
||||
bool equal(self const& other) const
|
||||
{
|
||||
//Want this iterator to be equal to the "end" iterator when at least
|
||||
//one of the iterators has reached the root of the current bicomp.
|
||||
//This isn't ideal, but it works.
|
||||
|
||||
return (first_itr == other.first_itr || second_itr == other.second_itr);
|
||||
}
|
||||
|
||||
ValueType dereference() const
|
||||
{
|
||||
return first_is_active ? *first_itr : *second_itr;
|
||||
}
|
||||
|
||||
inner_itr_t first_itr;
|
||||
inner_itr_t second_itr;
|
||||
inner_itr_t face_end;
|
||||
bool first_is_active;
|
||||
bool first_increment;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
|
||||
#endif //__FACE_ITERATORS_HPP__
|
||||
210
libraries/include/boost/graph/planar_face_traversal.hpp
Normal file
210
libraries/include/boost/graph/planar_face_traversal.hpp
Normal file
@@ -0,0 +1,210 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// 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 __PLANAR_FACE_TRAVERSAL_HPP__
|
||||
#define __PLANAR_FACE_TRAVERSAL_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <boost/utility.hpp> //for next and prior
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
struct planar_face_traversal_visitor
|
||||
{
|
||||
void begin_traversal()
|
||||
{}
|
||||
|
||||
void begin_face()
|
||||
{}
|
||||
|
||||
template <typename Edge>
|
||||
void next_edge(Edge e)
|
||||
{}
|
||||
|
||||
template <typename Vertex>
|
||||
void next_vertex(Vertex v)
|
||||
{}
|
||||
|
||||
void end_face()
|
||||
{}
|
||||
|
||||
void end_traversal()
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename Visitor,
|
||||
typename EdgeIndexMap>
|
||||
void planar_face_traversal(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
Visitor& visitor, EdgeIndexMap em
|
||||
)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
|
||||
typedef typename
|
||||
property_traits<PlanarEmbedding>::value_type embedding_value_t;
|
||||
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
|
||||
|
||||
typedef typename
|
||||
std::vector< std::set<vertex_t> > distinguished_edge_storage_t;
|
||||
typedef typename
|
||||
std::vector< std::map<vertex_t, edge_t> >
|
||||
distinguished_edge_to_edge_storage_t;
|
||||
|
||||
typedef typename
|
||||
boost::iterator_property_map
|
||||
<typename distinguished_edge_storage_t::iterator, EdgeIndexMap>
|
||||
distinguished_edge_map_t;
|
||||
|
||||
typedef typename
|
||||
boost::iterator_property_map
|
||||
<typename distinguished_edge_to_edge_storage_t::iterator, EdgeIndexMap>
|
||||
distinguished_edge_to_edge_map_t;
|
||||
|
||||
distinguished_edge_storage_t visited_vector(num_edges(g));
|
||||
distinguished_edge_to_edge_storage_t next_edge_vector(num_edges(g));
|
||||
|
||||
distinguished_edge_map_t visited(visited_vector.begin(), em);
|
||||
distinguished_edge_to_edge_map_t next_edge(next_edge_vector.begin(), em);
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
typename std::vector<edge_t>::iterator ei, ei_end;
|
||||
edge_iterator_t fi, fi_end;
|
||||
embedding_iterator_t pi, pi_begin, pi_end;
|
||||
|
||||
visitor.begin_traversal();
|
||||
|
||||
// Initialize the next_edge property map. This map is initialized from the
|
||||
// PlanarEmbedding so that get(next_edge, e)[v] is the edge that comes
|
||||
// after e in the clockwise embedding around vertex v.
|
||||
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_t v(*vi);
|
||||
pi_begin = embedding[v].begin();
|
||||
pi_end = embedding[v].end();
|
||||
for(pi = pi_begin; pi != pi_end; ++pi)
|
||||
{
|
||||
edge_t e(*pi);
|
||||
std::map<vertex_t, edge_t> m = get(next_edge, e);
|
||||
m[v] = next(pi) == pi_end ? *pi_begin : *next(pi);
|
||||
put(next_edge, e, m);
|
||||
}
|
||||
}
|
||||
|
||||
// Take a copy of the edges in the graph here, since we want to accomodate
|
||||
// face traversals that add edges to the graph (for triangulation, in
|
||||
// particular) and don't want to use invalidated edge iterators.
|
||||
// Also, while iterating over all edges in the graph, we single out
|
||||
// any self-loops, which need some special treatment in the face traversal.
|
||||
|
||||
std::vector<edge_t> self_loops;
|
||||
std::vector<edge_t> edges_cache;
|
||||
std::vector<vertex_t> vertices_in_edge;
|
||||
|
||||
for(tie(fi,fi_end) = edges(g); fi != fi_end; ++fi)
|
||||
{
|
||||
edge_t e(*fi);
|
||||
edges_cache.push_back(e);
|
||||
if (source(e,g) == target(e,g))
|
||||
self_loops.push_back(e);
|
||||
}
|
||||
|
||||
|
||||
// Iterate over all edges in the graph
|
||||
ei_end = edges_cache.end();
|
||||
for(ei = edges_cache.begin(); ei != ei_end; ++ei)
|
||||
{
|
||||
|
||||
edge_t e(*ei);
|
||||
vertices_in_edge.clear();
|
||||
vertices_in_edge.push_back(source(e,g));
|
||||
vertices_in_edge.push_back(target(e,g));
|
||||
|
||||
typename std::vector<vertex_t>::iterator vi, vi_end;
|
||||
vi_end = vertices_in_edge.end();
|
||||
|
||||
//Iterate over both vertices in the current edge
|
||||
for(vi = vertices_in_edge.begin(); vi != vi_end; ++vi)
|
||||
{
|
||||
|
||||
vertex_t v(*vi);
|
||||
std::set<vertex_t> e_visited = get(visited, e);
|
||||
typename std::set<vertex_t>::iterator e_visited_found
|
||||
= e_visited.find(v);
|
||||
|
||||
if (e_visited_found == e_visited.end())
|
||||
visitor.begin_face();
|
||||
|
||||
while (e_visited.find(v) == e_visited.end())
|
||||
{
|
||||
visitor.next_vertex(v);
|
||||
visitor.next_edge(e);
|
||||
e_visited.insert(v);
|
||||
put(visited, e, e_visited);
|
||||
v = source(e,g) == v ? target(e,g) : source(e,g);
|
||||
e = get(next_edge, e)[v];
|
||||
e_visited = get(visited, e);
|
||||
}
|
||||
|
||||
if (e_visited_found == e_visited.end())
|
||||
visitor.end_face();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Iterate over all self-loops, visiting them once separately
|
||||
// (they've already been visited once, this visitation is for
|
||||
// the "inside" of the self-loop)
|
||||
|
||||
ei_end = self_loops.end();
|
||||
for(ei = self_loops.begin(); ei != ei_end; ++ei)
|
||||
{
|
||||
visitor.begin_face();
|
||||
visitor.next_edge(*ei);
|
||||
visitor.next_vertex(source(*ei,g));
|
||||
visitor.end_face();
|
||||
}
|
||||
|
||||
visitor.end_traversal();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename Graph, typename PlanarEmbedding, typename Visitor>
|
||||
inline void planar_face_traversal(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
Visitor& visitor
|
||||
)
|
||||
{
|
||||
planar_face_traversal(g, embedding, visitor, get(edge_index, g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} //namespace boost
|
||||
|
||||
#endif //__PLANAR_FACE_TRAVERSAL_HPP__
|
||||
161
libraries/include/boost/graph/plod_generator.hpp
Normal file
161
libraries/include/boost/graph/plod_generator.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright 2004 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: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_PLOD_GENERATOR_HPP
|
||||
#define BOOST_GRAPH_PLOD_GENERATOR_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename RandomGenerator, typename Graph>
|
||||
class plod_iterator
|
||||
{
|
||||
typedef std::vector<std::pair<std::size_t, std::size_t> > out_degrees_t;
|
||||
typedef typename graph_traits<Graph>::directed_category directed_category;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef std::pair<std::size_t, std::size_t> value_type;
|
||||
typedef const value_type& reference;
|
||||
typedef const value_type* pointer;
|
||||
typedef void difference_type;
|
||||
|
||||
plod_iterator()
|
||||
: gen(0), out_degrees(), degrees_left(0), allow_self_loops(false) { }
|
||||
|
||||
plod_iterator(RandomGenerator& gen, std::size_t n,
|
||||
double alpha, double beta, bool allow_self_loops = false)
|
||||
: gen(&gen), n(n), out_degrees(new out_degrees_t),
|
||||
degrees_left(0), allow_self_loops(allow_self_loops)
|
||||
{
|
||||
using std::pow;
|
||||
|
||||
uniform_int<std::size_t> x(0, n-1);
|
||||
for (std::size_t i = 0; i != n; ++i) {
|
||||
std::size_t xv = x(gen);
|
||||
std::size_t degree = (xv == 0? 0 : std::size_t(beta * pow(xv, -alpha)));
|
||||
if (degree != 0) {
|
||||
out_degrees->push_back(std::make_pair(i, degree));
|
||||
}
|
||||
degrees_left += degree;
|
||||
}
|
||||
|
||||
next(directed_category());
|
||||
}
|
||||
|
||||
reference operator*() const { return current; }
|
||||
pointer operator->() const { return ¤t; }
|
||||
|
||||
plod_iterator& operator++()
|
||||
{
|
||||
next(directed_category());
|
||||
return *this;
|
||||
}
|
||||
|
||||
plod_iterator operator++(int)
|
||||
{
|
||||
plod_iterator temp(*this);
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool operator==(const plod_iterator& other) const
|
||||
{
|
||||
return degrees_left == other.degrees_left;
|
||||
}
|
||||
|
||||
bool operator!=(const plod_iterator& other) const
|
||||
{ return !(*this == other); }
|
||||
|
||||
private:
|
||||
void next(directed_tag)
|
||||
{
|
||||
uniform_int<std::size_t> x(0, out_degrees->size()-1);
|
||||
std::size_t source;
|
||||
do {
|
||||
source = x(*gen);
|
||||
} while ((*out_degrees)[source].second == 0);
|
||||
current.first = (*out_degrees)[source].first;
|
||||
do {
|
||||
current.second = x(*gen);
|
||||
} while (current.first == current.second && !allow_self_loops);
|
||||
--degrees_left;
|
||||
if (--(*out_degrees)[source].second == 0) {
|
||||
(*out_degrees)[source] = out_degrees->back();
|
||||
out_degrees->pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void next(undirected_tag)
|
||||
{
|
||||
std::size_t source, target;
|
||||
while (true) {
|
||||
/* We may get to the point where we can't actually find any
|
||||
new edges, so we just add some random edge and set the
|
||||
degrees left = 0 to signal termination. */
|
||||
if (out_degrees->size() < 2) {
|
||||
uniform_int<std::size_t> x(0, n);
|
||||
current.first = x(*gen);
|
||||
do {
|
||||
current.second = x(*gen);
|
||||
} while (current.first == current.second && !allow_self_loops);
|
||||
degrees_left = 0;
|
||||
out_degrees->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
uniform_int<std::size_t> x(0, out_degrees->size()-1);
|
||||
|
||||
// Select source vertex
|
||||
source = x(*gen);
|
||||
if ((*out_degrees)[source].second == 0) {
|
||||
(*out_degrees)[source] = out_degrees->back();
|
||||
out_degrees->pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Select target vertex
|
||||
target = x(*gen);
|
||||
if ((*out_degrees)[target].second == 0) {
|
||||
(*out_degrees)[target] = out_degrees->back();
|
||||
out_degrees->pop_back();
|
||||
continue;
|
||||
} else if (source != target
|
||||
|| (allow_self_loops && (*out_degrees)[source].second > 2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update degree counts
|
||||
--(*out_degrees)[source].second;
|
||||
--degrees_left;
|
||||
--(*out_degrees)[target].second;
|
||||
--degrees_left;
|
||||
current.first = (*out_degrees)[source].first;
|
||||
current.second = (*out_degrees)[target].first;
|
||||
}
|
||||
|
||||
RandomGenerator* gen;
|
||||
std::size_t n;
|
||||
shared_ptr<out_degrees_t> out_degrees;
|
||||
std::size_t degrees_left;
|
||||
bool allow_self_loops;
|
||||
value_type current;
|
||||
};
|
||||
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_PLOD_GENERATOR_HPP
|
||||
91
libraries/include/boost/graph/prim_minimum_spanning_tree.hpp
Normal file
91
libraries/include/boost/graph/prim_minimum_spanning_tree.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
//=======================================================================
|
||||
// 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_MST_PRIM_HPP
|
||||
#define BOOST_GRAPH_MST_PRIM_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/dijkstra_shortest_paths.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// this should be somewhere else in boost...
|
||||
template <class U, class V> struct _project2nd {
|
||||
V operator()(U, V v) const { return v; }
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This is Prim's algorithm to calculate the Minimum Spanning Tree
|
||||
// for an undirected graph with weighted edges.
|
||||
|
||||
template <class Graph, class P, class T, class R, class Weight>
|
||||
inline void
|
||||
prim_mst_impl(const Graph& G,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
const bgl_named_params<P,T,R>& params,
|
||||
Weight)
|
||||
{
|
||||
typedef typename property_traits<Weight>::value_type W;
|
||||
std::less<W> compare;
|
||||
detail::_project2nd<W,W> combine;
|
||||
dijkstra_shortest_paths(G, s, params.distance_compare(compare).
|
||||
distance_combine(combine));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <class VertexListGraph, class DijkstraVisitor,
|
||||
class PredecessorMap, class DistanceMap,
|
||||
class WeightMap, class IndexMap>
|
||||
inline void
|
||||
prim_minimum_spanning_tree
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
PredecessorMap predecessor, DistanceMap distance, WeightMap weight,
|
||||
IndexMap index_map,
|
||||
DijkstraVisitor vis)
|
||||
{
|
||||
typedef typename property_traits<WeightMap>::value_type W;
|
||||
std::less<W> compare;
|
||||
detail::_project2nd<W,W> combine;
|
||||
dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map,
|
||||
compare, combine, (std::numeric_limits<W>::max)(), 0,
|
||||
vis);
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class PredecessorMap,
|
||||
class P, class T, class R>
|
||||
inline void prim_minimum_spanning_tree
|
||||
(const VertexListGraph& g,
|
||||
PredecessorMap p_map,
|
||||
const bgl_named_params<P,T,R>& params)
|
||||
{
|
||||
detail::prim_mst_impl
|
||||
(g,
|
||||
choose_param(get_param(params, root_vertex_t()), *vertices(g).first),
|
||||
params.predecessor_map(p_map),
|
||||
choose_const_pmap(get_param(params, edge_weight), g, edge_weight));
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class PredecessorMap>
|
||||
inline void prim_minimum_spanning_tree
|
||||
(const VertexListGraph& g, PredecessorMap p_map)
|
||||
{
|
||||
detail::prim_mst_impl
|
||||
(g, *vertices(g).first, predecessor_map(p_map).
|
||||
weight_map(get(edge_weight, g)),
|
||||
get(edge_weight, g));
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_MST_PRIM_HPP
|
||||
43
libraries/include/boost/graph/profile.hpp
Normal file
43
libraries/include/boost/graph/profile.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch)
|
||||
// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st)
|
||||
//
|
||||
// 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_PROFILE_HPP
|
||||
#define BOOST_GRAPH_PROFILE_HPP
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/detail/numeric_traits.hpp>
|
||||
#include <boost/graph/bandwidth.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
profile(const Graph& g, VertexIndexMap index)
|
||||
{
|
||||
typename graph_traits<Graph>::vertices_size_type b = 0;
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
for (tie(i, end) = vertices(g); i != end; ++i){
|
||||
b += ith_bandwidth(*i, g, index) + 1;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
profile(const Graph& g)
|
||||
{
|
||||
return profile(g, get(vertex_index, g));
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_PROFILE_HPP
|
||||
389
libraries/include/boost/graph/properties.hpp
Normal file
389
libraries/include/boost/graph/properties.hpp
Normal file
@@ -0,0 +1,389 @@
|
||||
//=======================================================================
|
||||
// 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 <cassert>
|
||||
#include <boost/pending/property.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# define Graph Graph_
|
||||
# define RandomAccessContainer RandomAccessContainer_
|
||||
#endif
|
||||
|
||||
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; }
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <>
|
||||
struct property_traits<default_color_type*> {
|
||||
typedef default_color_type value_type;
|
||||
typedef std::ptrdiff_t key_type;
|
||||
typedef default_color_type& reference;
|
||||
typedef lvalue_property_map_tag category;
|
||||
};
|
||||
// get/put already defined for T*
|
||||
#endif
|
||||
|
||||
struct graph_property_tag { };
|
||||
struct vertex_property_tag { };
|
||||
struct edge_property_tag { };
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// 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; \
|
||||
}
|
||||
#else
|
||||
#define BOOST_INSTALL_PROPERTY(KIND, NAME) \
|
||||
template <> struct property_kind<KIND##_##NAME##_t> { \
|
||||
typedef KIND##_property_tag type; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define BOOST_DEF_PROPERTY(KIND, NAME) \
|
||||
enum KIND##_##NAME##_t { KIND##_##NAME }; \
|
||||
BOOST_INSTALL_PROPERTY(KIND, NAME)
|
||||
|
||||
BOOST_DEF_PROPERTY(vertex, all);
|
||||
BOOST_DEF_PROPERTY(edge, all);
|
||||
BOOST_DEF_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, 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(edge, reverse);
|
||||
BOOST_DEF_PROPERTY(edge, capacity);
|
||||
BOOST_DEF_PROPERTY(edge, residual_capacity);
|
||||
BOOST_DEF_PROPERTY(edge, centrality);
|
||||
BOOST_DEF_PROPERTY(graph, visitor);
|
||||
|
||||
// These tags are used for property bundles
|
||||
BOOST_DEF_PROPERTY(vertex, bundle);
|
||||
BOOST_DEF_PROPERTY(edge, bundle);
|
||||
|
||||
#undef BOOST_DEF_PROPERTY
|
||||
|
||||
namespace detail {
|
||||
|
||||
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 <class Graph, class PropertyTag>
|
||||
struct edge_property_map {
|
||||
typedef typename Graph::edge_property_type Property;
|
||||
typedef typename Graph::graph_tag graph_tag;
|
||||
typedef typename edge_property_selector<graph_tag>::type Selector;
|
||||
typedef typename Selector::template bind_<Graph,Property,PropertyTag>
|
||||
Bind;
|
||||
typedef typename Bind::type type;
|
||||
typedef typename Bind::const_type const_type;
|
||||
};
|
||||
template <class Graph, class PropertyTag>
|
||||
class vertex_property_map {
|
||||
typedef typename Graph::vertex_property_type Property;
|
||||
typedef typename Graph::graph_tag graph_tag;
|
||||
typedef typename vertex_property_selector<graph_tag>::type Selector;
|
||||
typedef typename Selector::template bind_<Graph,Property,PropertyTag>
|
||||
Bind;
|
||||
public:
|
||||
typedef typename Bind::type type;
|
||||
typedef typename Bind::const_type const_type;
|
||||
};
|
||||
|
||||
// This selects the kind of property map, whether is maps from
|
||||
// edges or from vertices.
|
||||
//
|
||||
// It is overly complicated because it's a workaround for
|
||||
// partial specialization.
|
||||
struct choose_vertex_property_map {
|
||||
template <class Graph, class Property>
|
||||
struct bind_ {
|
||||
typedef vertex_property_map<Graph, Property> type;
|
||||
};
|
||||
};
|
||||
struct choose_edge_property_map {
|
||||
template <class Graph, class Property>
|
||||
struct bind_ {
|
||||
typedef edge_property_map<Graph, Property> type;
|
||||
};
|
||||
};
|
||||
template <class Kind>
|
||||
struct property_map_kind_selector {
|
||||
// VC++ gets confused if this isn't defined, even though
|
||||
// this never gets used.
|
||||
typedef choose_vertex_property_map type;
|
||||
};
|
||||
template <> struct property_map_kind_selector<vertex_property_tag> {
|
||||
typedef choose_vertex_property_map type;
|
||||
};
|
||||
template <> struct property_map_kind_selector<edge_property_tag> {
|
||||
typedef choose_edge_property_map type;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <class Graph, class Property>
|
||||
struct property_map {
|
||||
private:
|
||||
typedef typename property_kind<Property>::type Kind;
|
||||
typedef typename detail::property_map_kind_selector<Kind>::type Selector;
|
||||
typedef typename Selector::template bind_<Graph, Property> Bind;
|
||||
typedef typename Bind::type Map;
|
||||
public:
|
||||
typedef typename Map::type type;
|
||||
typedef typename Map::const_type const_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 Graph::graph_property_type,
|
||||
Property>::type type;
|
||||
};
|
||||
|
||||
template <class Graph>
|
||||
class vertex_property {
|
||||
public:
|
||||
typedef typename Graph::vertex_property_type type;
|
||||
};
|
||||
template <class Graph>
|
||||
class edge_property {
|
||||
public:
|
||||
typedef typename Graph::edge_property_type type;
|
||||
};
|
||||
|
||||
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.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)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
# define BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
||||
template<typename Graph, typename Descriptor, typename Bundle, typename T>
|
||||
struct bundle_property_map
|
||||
: put_get_helper<T&, bundle_property_map<Graph, Descriptor, Bundle, T> >
|
||||
{
|
||||
typedef Descriptor key_type;
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef lvalue_property_map_tag category;
|
||||
|
||||
bundle_property_map() { }
|
||||
bundle_property_map(Graph* g_, T Bundle::* pm_) : g(g_), pm(pm_) {}
|
||||
|
||||
reference operator[](key_type k) const { return (*g)[k].*pm; }
|
||||
private:
|
||||
Graph* g;
|
||||
T Bundle::* pm;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename VertexBundle, typename EdgeBundle, typename Bundle>
|
||||
struct is_vertex_bundle : is_convertible<VertexBundle*, Bundle*> {};
|
||||
}
|
||||
|
||||
template <typename Graph, typename T, typename Bundle>
|
||||
struct property_map<Graph, T Bundle::*>
|
||||
{
|
||||
private:
|
||||
typedef graph_traits<Graph> traits;
|
||||
typedef typename Graph::vertex_bundled vertex_bundled;
|
||||
typedef typename Graph::edge_bundled edge_bundled;
|
||||
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
|
||||
typename traits::vertex_descriptor,
|
||||
typename traits::edge_descriptor>::type
|
||||
descriptor;
|
||||
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
|
||||
vertex_bundled,
|
||||
edge_bundled>::type
|
||||
actual_bundle;
|
||||
|
||||
public:
|
||||
typedef bundle_property_map<Graph, descriptor, actual_bundle, T> type;
|
||||
typedef bundle_property_map<const Graph, descriptor, actual_bundle, const T>
|
||||
const_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# undef Graph
|
||||
# undef RandomAccessIterator
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* BOOST_GRAPH_PROPERTIES_HPPA */
|
||||
118
libraries/include/boost/graph/property_iter_range.hpp
Normal file
118
libraries/include/boost/graph/property_iter_range.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
|
||||
// (C) Copyright Fran<61>ois Faure, iMAGIS-GRAVIR / UJF, 2001.
|
||||
//
|
||||
// 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:
|
||||
// 03 May 2001 Jeremy Siek
|
||||
// Generalized the property map iterator and moved that
|
||||
// part to boost/property_map.hpp. Also modified to
|
||||
// differentiate between const/mutable graphs and
|
||||
// added a workaround to avoid partial specialization.
|
||||
|
||||
// 02 May 2001 Fran<61>ois Faure
|
||||
// Initial version.
|
||||
|
||||
#ifndef BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP
|
||||
#define BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP
|
||||
|
||||
#include <boost/property_map_iterator.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//======================================================================
|
||||
// graph property iterator range
|
||||
|
||||
template <class Graph, class PropertyTag>
|
||||
class graph_property_iter_range {
|
||||
typedef typename property_map<Graph, PropertyTag>::type map_type;
|
||||
typedef typename property_map<Graph, PropertyTag>::const_type
|
||||
const_map_type;
|
||||
typedef typename property_kind<PropertyTag>::type Kind;
|
||||
typedef typename mpl::if_c<is_same<Kind, vertex_property_tag>::value,
|
||||
typename graph_traits<Graph>::vertex_iterator,
|
||||
typename graph_traits<Graph>::edge_iterator>::type iter;
|
||||
public:
|
||||
typedef typename property_map_iterator_generator<map_type, iter>::type
|
||||
iterator;
|
||||
typedef typename property_map_iterator_generator<const_map_type, iter>
|
||||
::type const_iterator;
|
||||
typedef std::pair<iterator, iterator> type;
|
||||
typedef std::pair<const_iterator, const_iterator> const_type;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Graph,class Tag>
|
||||
typename graph_property_iter_range<Graph,Tag>::type
|
||||
get_property_iter_range_kind(Graph& graph, const Tag& tag,
|
||||
const vertex_property_tag& )
|
||||
{
|
||||
typedef typename graph_property_iter_range<Graph,Tag>::iterator iter;
|
||||
return std::make_pair(iter(vertices(graph).first, get(tag, graph)),
|
||||
iter(vertices(graph).second, get(tag, graph)));
|
||||
}
|
||||
|
||||
template<class Graph,class Tag>
|
||||
typename graph_property_iter_range<Graph,Tag>::const_type
|
||||
get_property_iter_range_kind(const Graph& graph, const Tag& tag,
|
||||
const vertex_property_tag& )
|
||||
{
|
||||
typedef typename graph_property_iter_range<Graph,Tag>
|
||||
::const_iterator iter;
|
||||
return std::make_pair(iter(vertices(graph).first, get(tag, graph)),
|
||||
iter(vertices(graph).second, get(tag, graph)));
|
||||
}
|
||||
|
||||
|
||||
template<class Graph,class Tag>
|
||||
typename graph_property_iter_range<Graph,Tag>::type
|
||||
get_property_iter_range_kind(Graph& graph, const Tag& tag,
|
||||
const edge_property_tag& )
|
||||
{
|
||||
typedef typename graph_property_iter_range<Graph,Tag>::iterator iter;
|
||||
return std::make_pair(iter(edges(graph).first, get(tag, graph)),
|
||||
iter(edges(graph).second, get(tag, graph)));
|
||||
}
|
||||
|
||||
template<class Graph,class Tag>
|
||||
typename graph_property_iter_range<Graph,Tag>::const_type
|
||||
get_property_iter_range_kind(const Graph& graph, const Tag& tag,
|
||||
const edge_property_tag& )
|
||||
{
|
||||
typedef typename graph_property_iter_range<Graph,Tag>
|
||||
::const_iterator iter;
|
||||
return std::make_pair(iter(edges(graph).first, get(tag, graph)),
|
||||
iter(edges(graph).second, get(tag, graph)));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//======================================================================
|
||||
// get an iterator range of properties
|
||||
|
||||
template<class Graph, class Tag>
|
||||
typename graph_property_iter_range<Graph, Tag>::type
|
||||
get_property_iter_range(Graph& graph, const Tag& tag)
|
||||
{
|
||||
typedef typename property_kind<Tag>::type Kind;
|
||||
return detail::get_property_iter_range_kind(graph, tag, Kind());
|
||||
}
|
||||
|
||||
template<class Graph, class Tag>
|
||||
typename graph_property_iter_range<Graph, Tag>::const_type
|
||||
get_property_iter_range(const Graph& graph, const Tag& tag)
|
||||
{
|
||||
typedef typename property_kind<Tag>::type Kind;
|
||||
return detail::get_property_iter_range_kind(graph, tag, Kind());
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP
|
||||
727
libraries/include/boost/graph/push_relabel_max_flow.hpp
Normal file
727
libraries/include/boost/graph/push_relabel_max_flow.hpp
Normal file
@@ -0,0 +1,727 @@
|
||||
//=======================================================================
|
||||
// Copyright 2000 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
||||
//
|
||||
// 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_PUSH_RELABEL_MAX_FLOW_HPP
|
||||
#define BOOST_PUSH_RELABEL_MAX_FLOW_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <iosfwd>
|
||||
#include <algorithm> // for std::min and std::max
|
||||
|
||||
#include <boost/pending/queue.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This implementation is based on Goldberg's
|
||||
// "On Implementing Push-Relabel Method for the Maximum Flow Problem"
|
||||
// by B.V. Cherkassky and A.V. Goldberg, IPCO '95, pp. 157--171
|
||||
// and on the h_prf.c and hi_pr.c code written by the above authors.
|
||||
|
||||
// This implements the highest-label version of the push-relabel method
|
||||
// with the global relabeling and gap relabeling heuristics.
|
||||
|
||||
// The terms "rank", "distance", "height" are synonyms in
|
||||
// Goldberg's implementation, paper and in the CLR. A "layer" is a
|
||||
// group of vertices with the same distance. The vertices in each
|
||||
// layer are categorized as active or inactive. An active vertex
|
||||
// has positive excess flow and its distance is less than n (it is
|
||||
// not blocked).
|
||||
|
||||
template <class Vertex>
|
||||
struct preflow_layer {
|
||||
std::list<Vertex> active_vertices;
|
||||
std::list<Vertex> inactive_vertices;
|
||||
};
|
||||
|
||||
template <class Graph,
|
||||
class EdgeCapacityMap, // integer value type
|
||||
class ResidualCapacityEdgeMap,
|
||||
class ReverseEdgeMap,
|
||||
class VertexIndexMap, // vertex_descriptor -> integer
|
||||
class FlowValue>
|
||||
class push_relabel
|
||||
{
|
||||
public:
|
||||
typedef graph_traits<Graph> Traits;
|
||||
typedef typename Traits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename Traits::edge_descriptor edge_descriptor;
|
||||
typedef typename Traits::vertex_iterator vertex_iterator;
|
||||
typedef typename Traits::out_edge_iterator out_edge_iterator;
|
||||
typedef typename Traits::vertices_size_type vertices_size_type;
|
||||
typedef typename Traits::edges_size_type edges_size_type;
|
||||
|
||||
typedef preflow_layer<vertex_descriptor> Layer;
|
||||
typedef std::vector< Layer > LayerArray;
|
||||
typedef typename LayerArray::iterator layer_iterator;
|
||||
typedef typename LayerArray::size_type distance_size_type;
|
||||
|
||||
typedef color_traits<default_color_type> ColorTraits;
|
||||
|
||||
//=======================================================================
|
||||
// Some helper predicates
|
||||
|
||||
inline bool is_admissible(vertex_descriptor u, vertex_descriptor v) {
|
||||
return distance[u] == distance[v] + 1;
|
||||
}
|
||||
inline bool is_residual_edge(edge_descriptor a) {
|
||||
return 0 < residual_capacity[a];
|
||||
}
|
||||
inline bool is_saturated(edge_descriptor a) {
|
||||
return residual_capacity[a] == 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// Layer List Management Functions
|
||||
|
||||
typedef typename std::list<vertex_descriptor>::iterator list_iterator;
|
||||
|
||||
void add_to_active_list(vertex_descriptor u, Layer& layer) {
|
||||
BOOST_USING_STD_MIN();
|
||||
BOOST_USING_STD_MAX();
|
||||
layer.active_vertices.push_front(u);
|
||||
max_active = max BOOST_PREVENT_MACRO_SUBSTITUTION(distance[u], max_active);
|
||||
min_active = min BOOST_PREVENT_MACRO_SUBSTITUTION(distance[u], min_active);
|
||||
layer_list_ptr[u] = layer.active_vertices.begin();
|
||||
}
|
||||
void remove_from_active_list(vertex_descriptor u) {
|
||||
layers[distance[u]].active_vertices.erase(layer_list_ptr[u]);
|
||||
}
|
||||
|
||||
void add_to_inactive_list(vertex_descriptor u, Layer& layer) {
|
||||
layer.inactive_vertices.push_front(u);
|
||||
layer_list_ptr[u] = layer.inactive_vertices.begin();
|
||||
}
|
||||
void remove_from_inactive_list(vertex_descriptor u) {
|
||||
layers[distance[u]].inactive_vertices.erase(layer_list_ptr[u]);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// initialization
|
||||
push_relabel(Graph& g_,
|
||||
EdgeCapacityMap cap,
|
||||
ResidualCapacityEdgeMap res,
|
||||
ReverseEdgeMap rev,
|
||||
vertex_descriptor src_,
|
||||
vertex_descriptor sink_,
|
||||
VertexIndexMap idx)
|
||||
: g(g_), n(num_vertices(g_)), capacity(cap), src(src_), sink(sink_),
|
||||
index(idx),
|
||||
excess_flow(num_vertices(g_)),
|
||||
current(num_vertices(g_), out_edges(*vertices(g_).first, g_).second),
|
||||
distance(num_vertices(g_)),
|
||||
color(num_vertices(g_)),
|
||||
reverse_edge(rev),
|
||||
residual_capacity(res),
|
||||
layers(num_vertices(g_)),
|
||||
layer_list_ptr(num_vertices(g_),
|
||||
layers.front().inactive_vertices.end()),
|
||||
push_count(0), update_count(0), relabel_count(0),
|
||||
gap_count(0), gap_node_count(0),
|
||||
work_since_last_update(0)
|
||||
{
|
||||
vertex_iterator u_iter, u_end;
|
||||
// Don't count the reverse edges
|
||||
edges_size_type m = num_edges(g) / 2;
|
||||
nm = alpha() * n + m;
|
||||
|
||||
// Initialize flow to zero which means initializing
|
||||
// the residual capacity to equal the capacity.
|
||||
out_edge_iterator ei, e_end;
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
|
||||
for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) {
|
||||
residual_capacity[*ei] = capacity[*ei];
|
||||
}
|
||||
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) {
|
||||
vertex_descriptor u = *u_iter;
|
||||
excess_flow[u] = 0;
|
||||
current[u] = out_edges(u, g).first;
|
||||
}
|
||||
|
||||
bool overflow_detected = false;
|
||||
FlowValue test_excess = 0;
|
||||
|
||||
out_edge_iterator a_iter, a_end;
|
||||
for (tie(a_iter, a_end) = out_edges(src, g); a_iter != a_end; ++a_iter)
|
||||
if (target(*a_iter, g) != src)
|
||||
test_excess += residual_capacity[*a_iter];
|
||||
if (test_excess > (std::numeric_limits<FlowValue>::max)())
|
||||
overflow_detected = true;
|
||||
|
||||
if (overflow_detected)
|
||||
excess_flow[src] = (std::numeric_limits<FlowValue>::max)();
|
||||
else {
|
||||
excess_flow[src] = 0;
|
||||
for (tie(a_iter, a_end) = out_edges(src, g);
|
||||
a_iter != a_end; ++a_iter) {
|
||||
edge_descriptor a = *a_iter;
|
||||
if (target(a, g) != src) {
|
||||
++push_count;
|
||||
FlowValue delta = residual_capacity[a];
|
||||
residual_capacity[a] -= delta;
|
||||
residual_capacity[reverse_edge[a]] += delta;
|
||||
excess_flow[target(a, g)] += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
max_distance = num_vertices(g) - 1;
|
||||
max_active = 0;
|
||||
min_active = n;
|
||||
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) {
|
||||
vertex_descriptor u = *u_iter;
|
||||
if (u == sink) {
|
||||
distance[u] = 0;
|
||||
continue;
|
||||
} else if (u == src && !overflow_detected)
|
||||
distance[u] = n;
|
||||
else
|
||||
distance[u] = 1;
|
||||
|
||||
if (excess_flow[u] > 0)
|
||||
add_to_active_list(u, layers[1]);
|
||||
else if (distance[u] < n)
|
||||
add_to_inactive_list(u, layers[1]);
|
||||
}
|
||||
|
||||
} // push_relabel constructor
|
||||
|
||||
//=======================================================================
|
||||
// This is a breadth-first search over the residual graph
|
||||
// (well, actually the reverse of the residual graph).
|
||||
// Would be cool to have a graph view adaptor for hiding certain
|
||||
// edges, like the saturated (non-residual) edges in this case.
|
||||
// Goldberg's implementation abused "distance" for the coloring.
|
||||
void global_distance_update()
|
||||
{
|
||||
BOOST_USING_STD_MAX();
|
||||
++update_count;
|
||||
vertex_iterator u_iter, u_end;
|
||||
for (tie(u_iter,u_end) = vertices(g); u_iter != u_end; ++u_iter) {
|
||||
color[*u_iter] = ColorTraits::white();
|
||||
distance[*u_iter] = n;
|
||||
}
|
||||
color[sink] = ColorTraits::gray();
|
||||
distance[sink] = 0;
|
||||
|
||||
for (distance_size_type l = 0; l <= max_distance; ++l) {
|
||||
layers[l].active_vertices.clear();
|
||||
layers[l].inactive_vertices.clear();
|
||||
}
|
||||
|
||||
max_distance = max_active = 0;
|
||||
min_active = n;
|
||||
|
||||
Q.push(sink);
|
||||
while (! Q.empty()) {
|
||||
vertex_descriptor u = Q.top();
|
||||
Q.pop();
|
||||
distance_size_type d_v = distance[u] + 1;
|
||||
|
||||
out_edge_iterator ai, a_end;
|
||||
for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) {
|
||||
edge_descriptor a = *ai;
|
||||
vertex_descriptor v = target(a, g);
|
||||
if (color[v] == ColorTraits::white()
|
||||
&& is_residual_edge(reverse_edge[a])) {
|
||||
distance[v] = d_v;
|
||||
color[v] = ColorTraits::gray();
|
||||
current[v] = out_edges(v, g).first;
|
||||
max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION(d_v, max_distance);
|
||||
|
||||
if (excess_flow[v] > 0)
|
||||
add_to_active_list(v, layers[d_v]);
|
||||
else
|
||||
add_to_inactive_list(v, layers[d_v]);
|
||||
|
||||
Q.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // global_distance_update()
|
||||
|
||||
//=======================================================================
|
||||
// This function is called "push" in Goldberg's h_prf implementation,
|
||||
// but it is called "discharge" in the paper and in hi_pr.c.
|
||||
void discharge(vertex_descriptor u)
|
||||
{
|
||||
assert(excess_flow[u] > 0);
|
||||
while (1) {
|
||||
out_edge_iterator ai, ai_end;
|
||||
for (ai = current[u], ai_end = out_edges(u, g).second;
|
||||
ai != ai_end; ++ai) {
|
||||
edge_descriptor a = *ai;
|
||||
if (is_residual_edge(a)) {
|
||||
vertex_descriptor v = target(a, g);
|
||||
if (is_admissible(u, v)) {
|
||||
++push_count;
|
||||
if (v != sink && excess_flow[v] == 0) {
|
||||
remove_from_inactive_list(v);
|
||||
add_to_active_list(v, layers[distance[v]]);
|
||||
}
|
||||
push_flow(a);
|
||||
if (excess_flow[u] == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // for out_edges of i starting from current
|
||||
|
||||
Layer& layer = layers[distance[u]];
|
||||
distance_size_type du = distance[u];
|
||||
|
||||
if (ai == ai_end) { // i must be relabeled
|
||||
relabel_distance(u);
|
||||
if (layer.active_vertices.empty()
|
||||
&& layer.inactive_vertices.empty())
|
||||
gap(du);
|
||||
if (distance[u] == n)
|
||||
break;
|
||||
} else { // i is no longer active
|
||||
current[u] = ai;
|
||||
add_to_inactive_list(u, layer);
|
||||
break;
|
||||
}
|
||||
} // while (1)
|
||||
} // discharge()
|
||||
|
||||
//=======================================================================
|
||||
// This corresponds to the "push" update operation of the paper,
|
||||
// not the "push" function in Goldberg's h_prf.c implementation.
|
||||
// The idea is to push the excess flow from from vertex u to v.
|
||||
void push_flow(edge_descriptor u_v)
|
||||
{
|
||||
vertex_descriptor
|
||||
u = source(u_v, g),
|
||||
v = target(u_v, g);
|
||||
|
||||
BOOST_USING_STD_MIN();
|
||||
FlowValue flow_delta
|
||||
= min BOOST_PREVENT_MACRO_SUBSTITUTION(excess_flow[u], residual_capacity[u_v]);
|
||||
|
||||
residual_capacity[u_v] -= flow_delta;
|
||||
residual_capacity[reverse_edge[u_v]] += flow_delta;
|
||||
|
||||
excess_flow[u] -= flow_delta;
|
||||
excess_flow[v] += flow_delta;
|
||||
} // push_flow()
|
||||
|
||||
//=======================================================================
|
||||
// The main purpose of this routine is to set distance[v]
|
||||
// to the smallest value allowed by the valid labeling constraints,
|
||||
// which are:
|
||||
// distance[t] = 0
|
||||
// distance[u] <= distance[v] + 1 for every residual edge (u,v)
|
||||
//
|
||||
distance_size_type relabel_distance(vertex_descriptor u)
|
||||
{
|
||||
BOOST_USING_STD_MAX();
|
||||
++relabel_count;
|
||||
work_since_last_update += beta();
|
||||
|
||||
distance_size_type min_distance = num_vertices(g);
|
||||
distance[u] = min_distance;
|
||||
|
||||
// Examine the residual out-edges of vertex i, choosing the
|
||||
// edge whose target vertex has the minimal distance.
|
||||
out_edge_iterator ai, a_end, min_edge_iter;
|
||||
for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) {
|
||||
++work_since_last_update;
|
||||
edge_descriptor a = *ai;
|
||||
vertex_descriptor v = target(a, g);
|
||||
if (is_residual_edge(a) && distance[v] < min_distance) {
|
||||
min_distance = distance[v];
|
||||
min_edge_iter = ai;
|
||||
}
|
||||
}
|
||||
++min_distance;
|
||||
if (min_distance < n) {
|
||||
distance[u] = min_distance; // this is the main action
|
||||
current[u] = min_edge_iter;
|
||||
max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION(min_distance, max_distance);
|
||||
}
|
||||
return min_distance;
|
||||
} // relabel_distance()
|
||||
|
||||
//=======================================================================
|
||||
// cleanup beyond the gap
|
||||
void gap(distance_size_type empty_distance)
|
||||
{
|
||||
++gap_count;
|
||||
|
||||
distance_size_type r; // distance of layer before the current layer
|
||||
r = empty_distance - 1;
|
||||
|
||||
// Set the distance for the vertices beyond the gap to "infinity".
|
||||
for (layer_iterator l = layers.begin() + empty_distance + 1;
|
||||
l < layers.begin() + max_distance; ++l) {
|
||||
list_iterator i;
|
||||
for (i = l->inactive_vertices.begin();
|
||||
i != l->inactive_vertices.end(); ++i) {
|
||||
distance[*i] = n;
|
||||
++gap_node_count;
|
||||
}
|
||||
l->inactive_vertices.clear();
|
||||
}
|
||||
max_distance = r;
|
||||
max_active = r;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// This is the core part of the algorithm, "phase one".
|
||||
FlowValue maximum_preflow()
|
||||
{
|
||||
work_since_last_update = 0;
|
||||
|
||||
while (max_active >= min_active) { // "main" loop
|
||||
|
||||
Layer& layer = layers[max_active];
|
||||
list_iterator u_iter = layer.active_vertices.begin();
|
||||
|
||||
if (u_iter == layer.active_vertices.end())
|
||||
--max_active;
|
||||
else {
|
||||
vertex_descriptor u = *u_iter;
|
||||
remove_from_active_list(u);
|
||||
|
||||
discharge(u);
|
||||
|
||||
if (work_since_last_update * global_update_frequency() > nm) {
|
||||
global_distance_update();
|
||||
work_since_last_update = 0;
|
||||
}
|
||||
}
|
||||
} // while (max_active >= min_active)
|
||||
|
||||
return excess_flow[sink];
|
||||
} // maximum_preflow()
|
||||
|
||||
//=======================================================================
|
||||
// remove excess flow, the "second phase"
|
||||
// This does a DFS on the reverse flow graph of nodes with excess flow.
|
||||
// If a cycle is found, cancel it.
|
||||
// Return the nodes with excess flow in topological order.
|
||||
//
|
||||
// Unlike the prefl_to_flow() implementation, we use
|
||||
// "color" instead of "distance" for the DFS labels
|
||||
// "parent" instead of nl_prev for the DFS tree
|
||||
// "topo_next" instead of nl_next for the topological ordering
|
||||
void convert_preflow_to_flow()
|
||||
{
|
||||
vertex_iterator u_iter, u_end;
|
||||
out_edge_iterator ai, a_end;
|
||||
|
||||
vertex_descriptor r, restart, u;
|
||||
|
||||
std::vector<vertex_descriptor> parent(n);
|
||||
std::vector<vertex_descriptor> topo_next(n);
|
||||
|
||||
vertex_descriptor tos(parent[0]),
|
||||
bos(parent[0]); // bogus initialization, just to avoid warning
|
||||
bool bos_null = true;
|
||||
|
||||
// handle self-loops
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
|
||||
for (tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end; ++ai)
|
||||
if (target(*ai, g) == *u_iter)
|
||||
residual_capacity[*ai] = capacity[*ai];
|
||||
|
||||
// initialize
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) {
|
||||
u = *u_iter;
|
||||
color[u] = ColorTraits::white();
|
||||
parent[u] = u;
|
||||
current[u] = out_edges(u, g).first;
|
||||
}
|
||||
// eliminate flow cycles and topologically order the vertices
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) {
|
||||
u = *u_iter;
|
||||
if (color[u] == ColorTraits::white()
|
||||
&& excess_flow[u] > 0
|
||||
&& u != src && u != sink ) {
|
||||
r = u;
|
||||
color[r] = ColorTraits::gray();
|
||||
while (1) {
|
||||
for (; current[u] != out_edges(u, g).second; ++current[u]) {
|
||||
edge_descriptor a = *current[u];
|
||||
if (capacity[a] == 0 && is_residual_edge(a)) {
|
||||
vertex_descriptor v = target(a, g);
|
||||
if (color[v] == ColorTraits::white()) {
|
||||
color[v] = ColorTraits::gray();
|
||||
parent[v] = u;
|
||||
u = v;
|
||||
break;
|
||||
} else if (color[v] == ColorTraits::gray()) {
|
||||
// find minimum flow on the cycle
|
||||
FlowValue delta = residual_capacity[a];
|
||||
while (1) {
|
||||
BOOST_USING_STD_MIN();
|
||||
delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, residual_capacity[*current[v]]);
|
||||
if (v == u)
|
||||
break;
|
||||
else
|
||||
v = target(*current[v], g);
|
||||
}
|
||||
// remove delta flow units
|
||||
v = u;
|
||||
while (1) {
|
||||
a = *current[v];
|
||||
residual_capacity[a] -= delta;
|
||||
residual_capacity[reverse_edge[a]] += delta;
|
||||
v = target(a, g);
|
||||
if (v == u)
|
||||
break;
|
||||
}
|
||||
|
||||
// back-out of DFS to the first saturated edge
|
||||
restart = u;
|
||||
for (v = target(*current[u], g); v != u; v = target(a, g)){
|
||||
a = *current[v];
|
||||
if (color[v] == ColorTraits::white()
|
||||
|| is_saturated(a)) {
|
||||
color[target(*current[v], g)] = ColorTraits::white();
|
||||
if (color[v] != ColorTraits::white())
|
||||
restart = v;
|
||||
}
|
||||
}
|
||||
if (restart != u) {
|
||||
u = restart;
|
||||
++current[u];
|
||||
break;
|
||||
}
|
||||
} // else if (color[v] == ColorTraits::gray())
|
||||
} // if (capacity[a] == 0 ...
|
||||
} // for out_edges(u, g) (though "u" changes during loop)
|
||||
|
||||
if (current[u] == out_edges(u, g).second) {
|
||||
// scan of i is complete
|
||||
color[u] = ColorTraits::black();
|
||||
if (u != src) {
|
||||
if (bos_null) {
|
||||
bos = u;
|
||||
bos_null = false;
|
||||
tos = u;
|
||||
} else {
|
||||
topo_next[u] = tos;
|
||||
tos = u;
|
||||
}
|
||||
}
|
||||
if (u != r) {
|
||||
u = parent[u];
|
||||
++current[u];
|
||||
} else
|
||||
break;
|
||||
}
|
||||
} // while (1)
|
||||
} // if (color[u] == white && excess_flow[u] > 0 & ...)
|
||||
} // for all vertices in g
|
||||
|
||||
// return excess flows
|
||||
// note that the sink is not on the stack
|
||||
if (! bos_null) {
|
||||
for (u = tos; u != bos; u = topo_next[u]) {
|
||||
ai = out_edges(u, g).first;
|
||||
while (excess_flow[u] > 0 && ai != out_edges(u, g).second) {
|
||||
if (capacity[*ai] == 0 && is_residual_edge(*ai))
|
||||
push_flow(*ai);
|
||||
++ai;
|
||||
}
|
||||
}
|
||||
// do the bottom
|
||||
u = bos;
|
||||
ai = out_edges(u, g).first;
|
||||
while (excess_flow[u] > 0) {
|
||||
if (capacity[*ai] == 0 && is_residual_edge(*ai))
|
||||
push_flow(*ai);
|
||||
++ai;
|
||||
}
|
||||
}
|
||||
|
||||
} // convert_preflow_to_flow()
|
||||
|
||||
//=======================================================================
|
||||
inline bool is_flow()
|
||||
{
|
||||
vertex_iterator u_iter, u_end;
|
||||
out_edge_iterator ai, a_end;
|
||||
|
||||
// check edge flow values
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) {
|
||||
for (tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end; ++ai) {
|
||||
edge_descriptor a = *ai;
|
||||
if (capacity[a] > 0)
|
||||
if ((residual_capacity[a] + residual_capacity[reverse_edge[a]]
|
||||
!= capacity[a] + capacity[reverse_edge[a]])
|
||||
|| (residual_capacity[a] < 0)
|
||||
|| (residual_capacity[reverse_edge[a]] < 0))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// check conservation
|
||||
FlowValue sum;
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) {
|
||||
vertex_descriptor u = *u_iter;
|
||||
if (u != src && u != sink) {
|
||||
if (excess_flow[u] != 0)
|
||||
return false;
|
||||
sum = 0;
|
||||
for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai)
|
||||
if (capacity[*ai] > 0)
|
||||
sum -= capacity[*ai] - residual_capacity[*ai];
|
||||
else
|
||||
sum += residual_capacity[*ai];
|
||||
|
||||
if (excess_flow[u] != sum)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} // is_flow()
|
||||
|
||||
bool is_optimal() {
|
||||
// check if mincut is saturated...
|
||||
global_distance_update();
|
||||
return distance[src] >= n;
|
||||
}
|
||||
|
||||
void print_statistics(std::ostream& os) const {
|
||||
os << "pushes: " << push_count << std::endl
|
||||
<< "relabels: " << relabel_count << std::endl
|
||||
<< "updates: " << update_count << std::endl
|
||||
<< "gaps: " << gap_count << std::endl
|
||||
<< "gap nodes: " << gap_node_count << std::endl
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void print_flow_values(std::ostream& os) const {
|
||||
os << "flow values" << std::endl;
|
||||
vertex_iterator u_iter, u_end;
|
||||
out_edge_iterator ei, e_end;
|
||||
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
|
||||
for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
|
||||
if (capacity[*ei] > 0)
|
||||
os << *u_iter << " " << target(*ei, g) << " "
|
||||
<< (capacity[*ei] - residual_capacity[*ei]) << std::endl;
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
||||
Graph& g;
|
||||
vertices_size_type n;
|
||||
vertices_size_type nm;
|
||||
EdgeCapacityMap capacity;
|
||||
vertex_descriptor src;
|
||||
vertex_descriptor sink;
|
||||
VertexIndexMap index;
|
||||
|
||||
// will need to use random_access_property_map with these
|
||||
std::vector< FlowValue > excess_flow;
|
||||
std::vector< out_edge_iterator > current;
|
||||
std::vector< distance_size_type > distance;
|
||||
std::vector< default_color_type > color;
|
||||
|
||||
// Edge Property Maps that must be interior to the graph
|
||||
ReverseEdgeMap reverse_edge;
|
||||
ResidualCapacityEdgeMap residual_capacity;
|
||||
|
||||
LayerArray layers;
|
||||
std::vector< list_iterator > layer_list_ptr;
|
||||
distance_size_type max_distance; // maximal distance
|
||||
distance_size_type max_active; // maximal distance with active node
|
||||
distance_size_type min_active; // minimal distance with active node
|
||||
boost::queue<vertex_descriptor> Q;
|
||||
|
||||
// Statistics counters
|
||||
long push_count;
|
||||
long update_count;
|
||||
long relabel_count;
|
||||
long gap_count;
|
||||
long gap_node_count;
|
||||
|
||||
inline double global_update_frequency() { return 0.5; }
|
||||
inline vertices_size_type alpha() { return 6; }
|
||||
inline long beta() { return 12; }
|
||||
|
||||
long work_since_last_update;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Graph,
|
||||
class CapacityEdgeMap, class ResidualCapacityEdgeMap,
|
||||
class ReverseEdgeMap, class VertexIndexMap>
|
||||
typename property_traits<CapacityEdgeMap>::value_type
|
||||
push_relabel_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
CapacityEdgeMap cap, ResidualCapacityEdgeMap res,
|
||||
ReverseEdgeMap rev, VertexIndexMap index_map)
|
||||
{
|
||||
typedef typename property_traits<CapacityEdgeMap>::value_type FlowValue;
|
||||
|
||||
detail::push_relabel<Graph, CapacityEdgeMap, ResidualCapacityEdgeMap,
|
||||
ReverseEdgeMap, VertexIndexMap, FlowValue>
|
||||
algo(g, cap, res, rev, src, sink, index_map);
|
||||
|
||||
FlowValue flow = algo.maximum_preflow();
|
||||
|
||||
algo.convert_preflow_to_flow();
|
||||
|
||||
assert(algo.is_flow());
|
||||
assert(algo.is_optimal());
|
||||
|
||||
return flow;
|
||||
} // push_relabel_max_flow()
|
||||
|
||||
template <class Graph, class P, class T, class R>
|
||||
typename detail::edge_capacity_value<Graph, P, T, R>::type
|
||||
push_relabel_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return push_relabel_max_flow
|
||||
(g, src, sink,
|
||||
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
|
||||
choose_pmap(get_param(params, edge_residual_capacity),
|
||||
g, edge_residual_capacity),
|
||||
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index)
|
||||
);
|
||||
}
|
||||
|
||||
template <class Graph>
|
||||
typename property_traits<
|
||||
typename property_map<Graph, edge_capacity_t>::const_type
|
||||
>::value_type
|
||||
push_relabel_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink)
|
||||
{
|
||||
bgl_named_params<int, buffer_param_t> params(0); // bogus empty param
|
||||
return push_relabel_max_flow(g, src, sink, params);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_PUSH_RELABEL_MAX_FLOW_HPP
|
||||
|
||||
729
libraries/include/boost/graph/r_c_shortest_paths.hpp
Normal file
729
libraries/include/boost/graph/r_c_shortest_paths.hpp
Normal file
@@ -0,0 +1,729 @@
|
||||
// r_c_shortest_paths.hpp header file
|
||||
|
||||
// Copyright Michael Drexl 2005, 2006.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP
|
||||
#define BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// r_c_shortest_paths_label struct
|
||||
template<class Graph, class Resource_Container>
|
||||
struct r_c_shortest_paths_label
|
||||
{
|
||||
r_c_shortest_paths_label
|
||||
( const unsigned long n,
|
||||
const Resource_Container& rc = Resource_Container(),
|
||||
const r_c_shortest_paths_label* const pl = 0,
|
||||
const typename graph_traits<Graph>::edge_descriptor& ed =
|
||||
graph_traits<Graph>::edge_descriptor(),
|
||||
const typename graph_traits<Graph>::vertex_descriptor& vd =
|
||||
graph_traits<Graph>::vertex_descriptor() )
|
||||
: num( n ),
|
||||
cumulated_resource_consumption( rc ),
|
||||
p_pred_label( pl ),
|
||||
pred_edge( ed ),
|
||||
resident_vertex( vd ),
|
||||
b_is_dominated( false ),
|
||||
b_is_processed( false )
|
||||
{}
|
||||
r_c_shortest_paths_label& operator=( const r_c_shortest_paths_label& other )
|
||||
{
|
||||
if( this == &other )
|
||||
return *this;
|
||||
this->~r_c_shortest_paths_label();
|
||||
new( this ) r_c_shortest_paths_label( other );
|
||||
return *this;
|
||||
}
|
||||
const unsigned long num;
|
||||
Resource_Container cumulated_resource_consumption;
|
||||
const r_c_shortest_paths_label* const p_pred_label;
|
||||
const typename graph_traits<Graph>::edge_descriptor pred_edge;
|
||||
const typename graph_traits<Graph>::vertex_descriptor resident_vertex;
|
||||
bool b_is_dominated;
|
||||
bool b_is_processed;
|
||||
}; // r_c_shortest_paths_label
|
||||
|
||||
template<class Graph, class Resource_Container>
|
||||
inline bool operator==
|
||||
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
||||
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
||||
{
|
||||
return
|
||||
l1.cumulated_resource_consumption == l2.cumulated_resource_consumption;
|
||||
}
|
||||
|
||||
template<class Graph, class Resource_Container>
|
||||
inline bool operator!=
|
||||
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
||||
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
||||
{
|
||||
return
|
||||
!( l1 == l2 );
|
||||
}
|
||||
|
||||
template<class Graph, class Resource_Container>
|
||||
inline bool operator<
|
||||
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
||||
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
||||
{
|
||||
return
|
||||
l1.cumulated_resource_consumption < l2.cumulated_resource_consumption;
|
||||
}
|
||||
|
||||
template<class Graph, class Resource_Container>
|
||||
inline bool operator>
|
||||
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
||||
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
||||
{
|
||||
return
|
||||
l2.cumulated_resource_consumption < l1.cumulated_resource_consumption;
|
||||
}
|
||||
|
||||
template<class Graph, class Resource_Container>
|
||||
inline bool operator<=
|
||||
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
||||
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
||||
{
|
||||
return
|
||||
l1 < l2 || l1 == l2;
|
||||
}
|
||||
|
||||
template<class Graph, class Resource_Container>
|
||||
inline bool operator>=
|
||||
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
||||
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
||||
{
|
||||
return l2 < l1 || l1 == l2;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// ks_smart_pointer class
|
||||
// from:
|
||||
// Kuhlins, S.; Schader, M. (1999):
|
||||
// Die C++-Standardbibliothek
|
||||
// Springer, Berlin
|
||||
// p. 333 f.
|
||||
template<class T>
|
||||
class ks_smart_pointer
|
||||
{
|
||||
public:
|
||||
ks_smart_pointer( T* ptt = 0 ) : pt( ptt ) {}
|
||||
ks_smart_pointer( const ks_smart_pointer& other ) : pt( other.pt ) {}
|
||||
ks_smart_pointer& operator=( const ks_smart_pointer& other )
|
||||
{ pt = other.pt; return *this; }
|
||||
~ks_smart_pointer() {}
|
||||
T& operator*() const { return *pt; }
|
||||
T* operator->() const { return pt; }
|
||||
T* get() const { return pt; }
|
||||
operator T*() const { return pt; }
|
||||
friend bool operator==( const ks_smart_pointer& t,
|
||||
const ks_smart_pointer& u )
|
||||
{ return *t.pt == *u.pt; }
|
||||
friend bool operator!=( const ks_smart_pointer& t,
|
||||
const ks_smart_pointer& u )
|
||||
{ return *t.pt != *u.pt; }
|
||||
friend bool operator<( const ks_smart_pointer& t,
|
||||
const ks_smart_pointer& u )
|
||||
{ return *t.pt < *u.pt; }
|
||||
friend bool operator>( const ks_smart_pointer& t,
|
||||
const ks_smart_pointer& u )
|
||||
{ return *t.pt > *u.pt; }
|
||||
friend bool operator<=( const ks_smart_pointer& t,
|
||||
const ks_smart_pointer& u )
|
||||
{ return *t.pt <= *u.pt; }
|
||||
friend bool operator>=( const ks_smart_pointer& t,
|
||||
const ks_smart_pointer& u )
|
||||
{ return *t.pt >= *u.pt; }
|
||||
private:
|
||||
T* pt;
|
||||
}; // ks_smart_pointer
|
||||
|
||||
|
||||
// r_c_shortest_paths_dispatch function (body/implementation)
|
||||
template<class Graph,
|
||||
class VertexIndexMap,
|
||||
class EdgeIndexMap,
|
||||
class Resource_Container,
|
||||
class Resource_Extension_Function,
|
||||
class Dominance_Function,
|
||||
class Label_Allocator,
|
||||
class Visitor>
|
||||
void r_c_shortest_paths_dispatch
|
||||
( const Graph& g,
|
||||
const VertexIndexMap& vertex_index_map,
|
||||
const EdgeIndexMap& edge_index_map,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor t,
|
||||
// each inner vector corresponds to a pareto-optimal path
|
||||
std::vector
|
||||
<std::vector
|
||||
<typename graph_traits
|
||||
<Graph>::edge_descriptor> >& pareto_optimal_solutions,
|
||||
std::vector
|
||||
<Resource_Container>& pareto_optimal_resource_containers,
|
||||
bool b_all_pareto_optimal_solutions,
|
||||
// to initialize the first label/resource container
|
||||
// and to carry the type information
|
||||
const Resource_Container& rc,
|
||||
Resource_Extension_Function& ref,
|
||||
Dominance_Function& dominance,
|
||||
// to specify the memory management strategy for the labels
|
||||
Label_Allocator la,
|
||||
Visitor vis )
|
||||
{
|
||||
pareto_optimal_resource_containers.clear();
|
||||
pareto_optimal_solutions.clear();
|
||||
|
||||
unsigned long i_label_num = 0;
|
||||
typedef
|
||||
typename
|
||||
Label_Allocator::template rebind
|
||||
<r_c_shortest_paths_label
|
||||
<Graph, Resource_Container> >::other LAlloc;
|
||||
LAlloc l_alloc;
|
||||
typedef
|
||||
ks_smart_pointer
|
||||
<r_c_shortest_paths_label<Graph, Resource_Container> > Splabel;
|
||||
std::priority_queue<Splabel, std::vector<Splabel>, std::greater<Splabel> >
|
||||
unprocessed_labels;
|
||||
|
||||
bool b_feasible = true;
|
||||
r_c_shortest_paths_label<Graph, Resource_Container>* first_label =
|
||||
l_alloc.allocate( 1 );
|
||||
l_alloc.construct
|
||||
( first_label,
|
||||
r_c_shortest_paths_label
|
||||
<Graph, Resource_Container>( i_label_num++,
|
||||
rc,
|
||||
0,
|
||||
typename graph_traits<Graph>::
|
||||
edge_descriptor(),
|
||||
s ) );
|
||||
|
||||
Splabel splabel_first_label = Splabel( first_label );
|
||||
unprocessed_labels.push( splabel_first_label );
|
||||
std::vector<std::list<Splabel> > vec_vertex_labels( num_vertices( g ) );
|
||||
vec_vertex_labels[vertex_index_map[s]].push_back( splabel_first_label );
|
||||
std::vector<typename std::list<Splabel>::iterator>
|
||||
vec_last_valid_positions_for_dominance( num_vertices( g ) );
|
||||
for( int i = 0; i < static_cast<int>( num_vertices( g ) ); ++i )
|
||||
vec_last_valid_positions_for_dominance[i] = vec_vertex_labels[i].begin();
|
||||
std::vector<int> vec_last_valid_index_for_dominance( num_vertices( g ), 0 );
|
||||
std::vector<bool>
|
||||
b_vec_vertex_already_checked_for_dominance( num_vertices( g ), false );
|
||||
while( unprocessed_labels.size() )
|
||||
{
|
||||
Splabel cur_label = unprocessed_labels.top();
|
||||
unprocessed_labels.pop();
|
||||
vis.on_label_popped( *cur_label, g );
|
||||
// an Splabel object in unprocessed_labels and the respective Splabel
|
||||
// object in the respective list<Splabel> of vec_vertex_labels share their
|
||||
// embedded r_c_shortest_paths_label object
|
||||
// to avoid memory leaks, dominated
|
||||
// r_c_shortest_paths_label objects are marked and deleted when popped
|
||||
// from unprocessed_labels, as they can no longer be deleted at the end of
|
||||
// the function; only the Splabel object in unprocessed_labels still
|
||||
// references the r_c_shortest_paths_label object
|
||||
// this is also for efficiency, because the else branch is executed only
|
||||
// if there is a chance that extending the
|
||||
// label leads to new undominated labels, which in turn is possible only
|
||||
// if the label to be extended is undominated
|
||||
if( !cur_label->b_is_dominated )
|
||||
{
|
||||
int i_cur_resident_vertex_num = cur_label->resident_vertex;
|
||||
std::list<Splabel>& list_labels_cur_vertex =
|
||||
vec_vertex_labels[i_cur_resident_vertex_num];
|
||||
if( static_cast<int>( list_labels_cur_vertex.size() ) >= 2
|
||||
&& vec_last_valid_index_for_dominance[i_cur_resident_vertex_num]
|
||||
< static_cast<int>( list_labels_cur_vertex.size() ) )
|
||||
{
|
||||
typename std::list<Splabel>::iterator outer_iter =
|
||||
list_labels_cur_vertex.begin();
|
||||
bool b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = false;
|
||||
while( outer_iter != list_labels_cur_vertex.end() )
|
||||
{
|
||||
Splabel cur_outer_splabel = *outer_iter;
|
||||
typename std::list<Splabel>::iterator inner_iter = outer_iter;
|
||||
if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance
|
||||
&& outer_iter ==
|
||||
vec_last_valid_positions_for_dominance
|
||||
[i_cur_resident_vertex_num] )
|
||||
b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = true;
|
||||
if( !b_vec_vertex_already_checked_for_dominance
|
||||
[i_cur_resident_vertex_num]
|
||||
|| b_outer_iter_at_or_beyond_last_valid_pos_for_dominance )
|
||||
{
|
||||
++inner_iter;
|
||||
}
|
||||
else
|
||||
{
|
||||
inner_iter =
|
||||
vec_last_valid_positions_for_dominance
|
||||
[i_cur_resident_vertex_num];
|
||||
++inner_iter;
|
||||
}
|
||||
bool b_outer_iter_erased = false;
|
||||
while( inner_iter != list_labels_cur_vertex.end() )
|
||||
{
|
||||
Splabel cur_inner_splabel = *inner_iter;
|
||||
if( dominance( cur_outer_splabel->
|
||||
cumulated_resource_consumption,
|
||||
cur_inner_splabel->
|
||||
cumulated_resource_consumption ) )
|
||||
{
|
||||
typename std::list<Splabel>::iterator buf = inner_iter;
|
||||
++inner_iter;
|
||||
list_labels_cur_vertex.erase( buf );
|
||||
if( cur_inner_splabel->b_is_processed )
|
||||
{
|
||||
l_alloc.destroy( cur_inner_splabel.get() );
|
||||
l_alloc.deallocate( cur_inner_splabel.get(), 1 );
|
||||
}
|
||||
else
|
||||
cur_inner_splabel->b_is_dominated = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
++inner_iter;
|
||||
if( dominance( cur_inner_splabel->
|
||||
cumulated_resource_consumption,
|
||||
cur_outer_splabel->
|
||||
cumulated_resource_consumption ) )
|
||||
{
|
||||
typename std::list<Splabel>::iterator buf = outer_iter;
|
||||
++outer_iter;
|
||||
list_labels_cur_vertex.erase( buf );
|
||||
b_outer_iter_erased = true;
|
||||
if( cur_outer_splabel->b_is_processed )
|
||||
{
|
||||
l_alloc.destroy( cur_outer_splabel.get() );
|
||||
l_alloc.deallocate( cur_outer_splabel.get(), 1 );
|
||||
}
|
||||
else
|
||||
cur_outer_splabel->b_is_dominated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !b_outer_iter_erased )
|
||||
++outer_iter;
|
||||
}
|
||||
if( static_cast<int>( list_labels_cur_vertex.size() ) > 1 )
|
||||
vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] =
|
||||
(--(list_labels_cur_vertex.end()));
|
||||
else
|
||||
vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] =
|
||||
list_labels_cur_vertex.begin();
|
||||
b_vec_vertex_already_checked_for_dominance
|
||||
[i_cur_resident_vertex_num] = true;
|
||||
vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] =
|
||||
static_cast<int>( list_labels_cur_vertex.size() ) - 1;
|
||||
}
|
||||
}
|
||||
if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t )
|
||||
{
|
||||
// the devil don't sleep
|
||||
if( cur_label->b_is_dominated )
|
||||
{
|
||||
l_alloc.destroy( cur_label.get() );
|
||||
l_alloc.deallocate( cur_label.get(), 1 );
|
||||
}
|
||||
while( unprocessed_labels.size() )
|
||||
{
|
||||
Splabel l = unprocessed_labels.top();
|
||||
unprocessed_labels.pop();
|
||||
// delete only dominated labels, because nondominated labels are
|
||||
// deleted at the end of the function
|
||||
if( l->b_is_dominated )
|
||||
{
|
||||
l_alloc.destroy( l.get() );
|
||||
l_alloc.deallocate( l.get(), 1 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( !cur_label->b_is_dominated )
|
||||
{
|
||||
cur_label->b_is_processed = true;
|
||||
vis.on_label_not_dominated( *cur_label, g );
|
||||
typename graph_traits<Graph>::vertex_descriptor cur_vertex =
|
||||
cur_label->resident_vertex;
|
||||
typename graph_traits<Graph>::out_edge_iterator oei, oei_end;
|
||||
for( tie( oei, oei_end ) = out_edges( cur_vertex, g );
|
||||
oei != oei_end;
|
||||
++oei )
|
||||
{
|
||||
b_feasible = true;
|
||||
r_c_shortest_paths_label<Graph, Resource_Container>* new_label =
|
||||
l_alloc.allocate( 1 );
|
||||
l_alloc.construct( new_label,
|
||||
r_c_shortest_paths_label
|
||||
<Graph, Resource_Container>
|
||||
( i_label_num++,
|
||||
cur_label->cumulated_resource_consumption,
|
||||
cur_label.get(),
|
||||
*oei,
|
||||
target( *oei, g ) ) );
|
||||
b_feasible =
|
||||
ref( g,
|
||||
new_label->cumulated_resource_consumption,
|
||||
new_label->p_pred_label->cumulated_resource_consumption,
|
||||
new_label->pred_edge );
|
||||
|
||||
if( !b_feasible )
|
||||
{
|
||||
vis.on_label_not_feasible( *new_label, g );
|
||||
l_alloc.destroy( new_label );
|
||||
l_alloc.deallocate( new_label, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
const r_c_shortest_paths_label<Graph, Resource_Container>&
|
||||
ref_new_label = *new_label;
|
||||
vis.on_label_feasible( ref_new_label, g );
|
||||
Splabel new_sp_label( new_label );
|
||||
vec_vertex_labels[vertex_index_map[new_sp_label->resident_vertex]].
|
||||
push_back( new_sp_label );
|
||||
unprocessed_labels.push( new_sp_label );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vis.on_label_dominated( *cur_label, g );
|
||||
l_alloc.destroy( cur_label.get() );
|
||||
l_alloc.deallocate( cur_label.get(), 1 );
|
||||
}
|
||||
}
|
||||
std::list<Splabel> dsplabels = vec_vertex_labels[vertex_index_map[t]];
|
||||
typename std::list<Splabel>::const_iterator csi = dsplabels.begin();
|
||||
typename std::list<Splabel>::const_iterator csi_end = dsplabels.end();
|
||||
// if d could be reached from o
|
||||
if( dsplabels.size() )
|
||||
{
|
||||
for( ; csi != csi_end; ++csi )
|
||||
{
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor>
|
||||
cur_pareto_optimal_path;
|
||||
const r_c_shortest_paths_label<Graph, Resource_Container>* p_cur_label =
|
||||
(*csi).get();
|
||||
pareto_optimal_resource_containers.
|
||||
push_back( p_cur_label->cumulated_resource_consumption );
|
||||
while( p_cur_label->num != 0 )
|
||||
{
|
||||
cur_pareto_optimal_path.push_back( p_cur_label->pred_edge );
|
||||
p_cur_label = p_cur_label->p_pred_label;
|
||||
}
|
||||
pareto_optimal_solutions.push_back( cur_pareto_optimal_path );
|
||||
if( !b_all_pareto_optimal_solutions )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int i_size = static_cast<int>( vec_vertex_labels.size() );
|
||||
for( int i = 0; i < i_size; ++i )
|
||||
{
|
||||
const std::list<Splabel>& list_labels_cur_vertex = vec_vertex_labels[i];
|
||||
csi_end = list_labels_cur_vertex.end();
|
||||
for( csi = list_labels_cur_vertex.begin(); csi != csi_end; ++csi )
|
||||
{
|
||||
l_alloc.destroy( (*csi).get() );
|
||||
l_alloc.deallocate( (*csi).get(), 1 );
|
||||
}
|
||||
}
|
||||
} // r_c_shortest_paths_dispatch
|
||||
|
||||
} // detail
|
||||
|
||||
// default_r_c_shortest_paths_visitor struct
|
||||
struct default_r_c_shortest_paths_visitor
|
||||
{
|
||||
template<class Label, class Graph>
|
||||
void on_label_popped( const Label& l, const Graph& g ) {}
|
||||
template<class Label, class Graph>
|
||||
void on_label_feasible( const Label& l, const Graph& g ) {}
|
||||
template<class Label, class Graph>
|
||||
void on_label_not_feasible( const Label& l, const Graph& g ) {}
|
||||
template<class Label, class Graph>
|
||||
void on_label_dominated( const Label& l, const Graph& g ) {}
|
||||
template<class Label, class Graph>
|
||||
void on_label_not_dominated( const Label& l, const Graph& g ) {}
|
||||
}; // default_r_c_shortest_paths_visitor
|
||||
|
||||
|
||||
// default_r_c_shortest_paths_allocator
|
||||
typedef
|
||||
std::allocator<int> default_r_c_shortest_paths_allocator;
|
||||
// default_r_c_shortest_paths_allocator
|
||||
|
||||
|
||||
// r_c_shortest_paths functions (handle/interface)
|
||||
// first overload:
|
||||
// - return all pareto-optimal solutions
|
||||
// - specify Label_Allocator and Visitor arguments
|
||||
template<class Graph,
|
||||
class VertexIndexMap,
|
||||
class EdgeIndexMap,
|
||||
class Resource_Container,
|
||||
class Resource_Extension_Function,
|
||||
class Dominance_Function,
|
||||
class Label_Allocator,
|
||||
class Visitor>
|
||||
void r_c_shortest_paths
|
||||
( const Graph& g,
|
||||
const VertexIndexMap& vertex_index_map,
|
||||
const EdgeIndexMap& edge_index_map,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor t,
|
||||
// each inner vector corresponds to a pareto-optimal path
|
||||
std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >&
|
||||
pareto_optimal_solutions,
|
||||
std::vector<Resource_Container>& pareto_optimal_resource_containers,
|
||||
// to initialize the first label/resource container
|
||||
// and to carry the type information
|
||||
const Resource_Container& rc,
|
||||
const Resource_Extension_Function& ref,
|
||||
const Dominance_Function& dominance,
|
||||
// to specify the memory management strategy for the labels
|
||||
Label_Allocator la,
|
||||
Visitor vis )
|
||||
{
|
||||
r_c_shortest_paths_dispatch( g,
|
||||
vertex_index_map,
|
||||
edge_index_map,
|
||||
s,
|
||||
t,
|
||||
pareto_optimal_solutions,
|
||||
pareto_optimal_resource_containers,
|
||||
true,
|
||||
rc,
|
||||
ref,
|
||||
dominance,
|
||||
la,
|
||||
vis );
|
||||
}
|
||||
|
||||
// second overload:
|
||||
// - return only one pareto-optimal solution
|
||||
// - specify Label_Allocator and Visitor arguments
|
||||
template<class Graph,
|
||||
class VertexIndexMap,
|
||||
class EdgeIndexMap,
|
||||
class Resource_Container,
|
||||
class Resource_Extension_Function,
|
||||
class Dominance_Function,
|
||||
class Label_Allocator,
|
||||
class Visitor>
|
||||
void r_c_shortest_paths
|
||||
( const Graph& g,
|
||||
const VertexIndexMap& vertex_index_map,
|
||||
const EdgeIndexMap& edge_index_map,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor t,
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor>&
|
||||
pareto_optimal_solution,
|
||||
Resource_Container& pareto_optimal_resource_container,
|
||||
// to initialize the first label/resource container
|
||||
// and to carry the type information
|
||||
const Resource_Container& rc,
|
||||
const Resource_Extension_Function& ref,
|
||||
const Dominance_Function& dominance,
|
||||
// to specify the memory management strategy for the labels
|
||||
Label_Allocator la,
|
||||
Visitor vis )
|
||||
{
|
||||
// each inner vector corresponds to a pareto-optimal path
|
||||
std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >
|
||||
pareto_optimal_solutions;
|
||||
std::vector<Resource_Container> pareto_optimal_resource_containers;
|
||||
r_c_shortest_paths_dispatch( g,
|
||||
vertex_index_map,
|
||||
edge_index_map,
|
||||
s,
|
||||
t,
|
||||
pareto_optimal_solutions,
|
||||
pareto_optimal_resource_containers,
|
||||
false,
|
||||
rc,
|
||||
ref,
|
||||
dominance,
|
||||
la,
|
||||
vis );
|
||||
pareto_optimal_solution = pareto_optimal_solutions[0];
|
||||
pareto_optimal_resource_container = pareto_optimal_resource_containers[0];
|
||||
}
|
||||
|
||||
// third overload:
|
||||
// - return all pareto-optimal solutions
|
||||
// - use default Label_Allocator and Visitor
|
||||
template<class Graph,
|
||||
class VertexIndexMap,
|
||||
class EdgeIndexMap,
|
||||
class Resource_Container,
|
||||
class Resource_Extension_Function,
|
||||
class Dominance_Function>
|
||||
void r_c_shortest_paths
|
||||
( const Graph& g,
|
||||
const VertexIndexMap& vertex_index_map,
|
||||
const EdgeIndexMap& edge_index_map,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor t,
|
||||
// each inner vector corresponds to a pareto-optimal path
|
||||
std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >&
|
||||
pareto_optimal_solutions,
|
||||
std::vector<Resource_Container>& pareto_optimal_resource_containers,
|
||||
// to initialize the first label/resource container
|
||||
// and to carry the type information
|
||||
const Resource_Container& rc,
|
||||
const Resource_Extension_Function& ref,
|
||||
const Dominance_Function& dominance )
|
||||
{
|
||||
r_c_shortest_paths_dispatch( g,
|
||||
vertex_index_map,
|
||||
edge_index_map,
|
||||
s,
|
||||
t,
|
||||
pareto_optimal_solutions,
|
||||
pareto_optimal_resource_containers,
|
||||
true,
|
||||
rc,
|
||||
ref,
|
||||
dominance,
|
||||
default_r_c_shortest_paths_allocator(),
|
||||
default_r_c_shortest_paths_visitor() );
|
||||
}
|
||||
|
||||
// fourth overload:
|
||||
// - return only one pareto-optimal solution
|
||||
// - use default Label_Allocator and Visitor
|
||||
template<class Graph,
|
||||
class VertexIndexMap,
|
||||
class EdgeIndexMap,
|
||||
class Resource_Container,
|
||||
class Resource_Extension_Function,
|
||||
class Dominance_Function>
|
||||
void r_c_shortest_paths
|
||||
( const Graph& g,
|
||||
const VertexIndexMap& vertex_index_map,
|
||||
const EdgeIndexMap& edge_index_map,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor t,
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor>&
|
||||
pareto_optimal_solution,
|
||||
Resource_Container& pareto_optimal_resource_container,
|
||||
// to initialize the first label/resource container
|
||||
// and to carry the type information
|
||||
const Resource_Container& rc,
|
||||
const Resource_Extension_Function& ref,
|
||||
const Dominance_Function& dominance )
|
||||
{
|
||||
// each inner vector corresponds to a pareto-optimal path
|
||||
std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >
|
||||
pareto_optimal_solutions;
|
||||
std::vector<Resource_Container> pareto_optimal_resource_containers;
|
||||
r_c_shortest_paths_dispatch( g,
|
||||
vertex_index_map,
|
||||
edge_index_map,
|
||||
s,
|
||||
t,
|
||||
pareto_optimal_solutions,
|
||||
pareto_optimal_resource_containers,
|
||||
false,
|
||||
rc,
|
||||
ref,
|
||||
dominance,
|
||||
default_r_c_shortest_paths_allocator(),
|
||||
default_r_c_shortest_paths_visitor() );
|
||||
pareto_optimal_solution = pareto_optimal_solutions[0];
|
||||
pareto_optimal_resource_container = pareto_optimal_resource_containers[0];
|
||||
}
|
||||
// r_c_shortest_paths
|
||||
|
||||
|
||||
// check_r_c_path function
|
||||
template<class Graph,
|
||||
class Resource_Container,
|
||||
class Resource_Extension_Function>
|
||||
void check_r_c_path( const Graph& g,
|
||||
const std::vector
|
||||
<typename graph_traits
|
||||
<Graph>::edge_descriptor>& ed_vec_path,
|
||||
const Resource_Container& initial_resource_levels,
|
||||
// if true, computed accumulated final resource levels must
|
||||
// be equal to desired_final_resource_levels
|
||||
// if false, computed accumulated final resource levels must
|
||||
// be less than or equal to desired_final_resource_levels
|
||||
bool b_result_must_be_equal_to_desired_final_resource_levels,
|
||||
const Resource_Container& desired_final_resource_levels,
|
||||
Resource_Container& actual_final_resource_levels,
|
||||
const Resource_Extension_Function& ref,
|
||||
bool& b_is_a_path_at_all,
|
||||
bool& b_feasible,
|
||||
bool& b_correctly_extended,
|
||||
typename graph_traits<Graph>::edge_descriptor&
|
||||
ed_last_extended_arc )
|
||||
{
|
||||
int i_size_ed_vec_path = static_cast<int>( ed_vec_path.size() );
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor> buf_path;
|
||||
if( i_size_ed_vec_path == 0 )
|
||||
b_feasible = true;
|
||||
else
|
||||
{
|
||||
if( i_size_ed_vec_path == 1
|
||||
|| target( ed_vec_path[0], g ) == source( ed_vec_path[1], g ) )
|
||||
buf_path = ed_vec_path;
|
||||
else
|
||||
for( int i = i_size_ed_vec_path - 1; i >= 0; --i )
|
||||
buf_path.push_back( ed_vec_path[i] );
|
||||
for( int i = 0; i < i_size_ed_vec_path - 1; ++i )
|
||||
{
|
||||
if( target( buf_path[i], g ) != source( buf_path[i + 1], g ) )
|
||||
{
|
||||
b_is_a_path_at_all = false;
|
||||
b_feasible = false;
|
||||
b_correctly_extended = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
b_is_a_path_at_all = true;
|
||||
b_feasible = true;
|
||||
b_correctly_extended = false;
|
||||
Resource_Container current_resource_levels = initial_resource_levels;
|
||||
actual_final_resource_levels = current_resource_levels;
|
||||
for( int i = 0; i < i_size_ed_vec_path; ++i )
|
||||
{
|
||||
ed_last_extended_arc = buf_path[i];
|
||||
b_feasible = ref( g,
|
||||
actual_final_resource_levels,
|
||||
current_resource_levels,
|
||||
buf_path[i] );
|
||||
current_resource_levels = actual_final_resource_levels;
|
||||
if( !b_feasible )
|
||||
return;
|
||||
}
|
||||
if( b_result_must_be_equal_to_desired_final_resource_levels )
|
||||
b_correctly_extended =
|
||||
actual_final_resource_levels == desired_final_resource_levels ?
|
||||
true : false;
|
||||
else
|
||||
{
|
||||
if( actual_final_resource_levels < desired_final_resource_levels
|
||||
|| actual_final_resource_levels == desired_final_resource_levels )
|
||||
b_correctly_extended = true;
|
||||
}
|
||||
} // check_path
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP
|
||||
205
libraries/include/boost/graph/random.hpp
Normal file
205
libraries/include/boost/graph/random.hpp
Normal file
@@ -0,0 +1,205 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Copyright (C) Vladimir Prus 2003
|
||||
// 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_RANDOM_HPP
|
||||
#define BOOST_GRAPH_RANDOM_HPP
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/random/variate_generator.hpp>
|
||||
|
||||
#include <boost/pending/property.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/copy.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// grab a random vertex from the graph's vertex set
|
||||
template <class Graph, class RandomNumGen>
|
||||
typename graph_traits<Graph>::vertex_descriptor
|
||||
random_vertex(Graph& g, RandomNumGen& gen)
|
||||
{
|
||||
if (num_vertices(g) > 1) {
|
||||
#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581))
|
||||
std::size_t n = std::random( num_vertices(g) );
|
||||
#else
|
||||
uniform_int<> distrib(0, num_vertices(g)-1);
|
||||
variate_generator<RandomNumGen&, uniform_int<> > rand_gen(gen, distrib);
|
||||
std::size_t n = rand_gen();
|
||||
#endif
|
||||
typename graph_traits<Graph>::vertex_iterator
|
||||
i = vertices(g).first;
|
||||
while (n-- > 0) ++i; // std::advance not VC++ portable
|
||||
return *i;
|
||||
} else
|
||||
return *vertices(g).first;
|
||||
}
|
||||
|
||||
template <class Graph, class RandomNumGen>
|
||||
typename graph_traits<Graph>::edge_descriptor
|
||||
random_edge(Graph& g, RandomNumGen& gen) {
|
||||
if (num_edges(g) > 1) {
|
||||
#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581))
|
||||
typename graph_traits<Graph>::edges_size_type
|
||||
n = std::random( num_edges(g) );
|
||||
#else
|
||||
uniform_int<> distrib(0, num_edges(g)-1);
|
||||
variate_generator<RandomNumGen&, uniform_int<> > rand_gen(gen, distrib);
|
||||
typename graph_traits<Graph>::edges_size_type
|
||||
n = rand_gen();
|
||||
#endif
|
||||
typename graph_traits<Graph>::edge_iterator
|
||||
i = edges(g).first;
|
||||
while (n-- > 0) ++i; // std::advance not VC++ portable
|
||||
return *i;
|
||||
} else
|
||||
return *edges(g).first;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
class dummy_property_copier {
|
||||
public:
|
||||
template<class V1, class V2>
|
||||
void operator()(const V1&, const V2&) const {}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename MutableGraph, class RandNumGen>
|
||||
void generate_random_graph1
|
||||
(MutableGraph& g,
|
||||
typename graph_traits<MutableGraph>::vertices_size_type V,
|
||||
typename graph_traits<MutableGraph>::vertices_size_type E,
|
||||
RandNumGen& gen,
|
||||
bool allow_parallel = true,
|
||||
bool self_edges = false)
|
||||
{
|
||||
typedef graph_traits<MutableGraph> Traits;
|
||||
typedef typename Traits::vertices_size_type v_size_t;
|
||||
typedef typename Traits::edges_size_type e_size_t;
|
||||
typedef typename Traits::vertex_descriptor vertex_descriptor;
|
||||
|
||||
// When parallel edges are not allowed, we create a new graph which
|
||||
// does not allow parallel edges, construct it and copy back.
|
||||
// This is not efficient if 'g' already disallow parallel edges,
|
||||
// but that's task for later.
|
||||
if (!allow_parallel) {
|
||||
|
||||
typedef typename boost::graph_traits<MutableGraph>::directed_category dir;
|
||||
typedef typename mpl::if_<is_convertible<dir, directed_tag>,
|
||||
directedS, undirectedS>::type select;
|
||||
adjacency_list<setS, vecS, select> g2;
|
||||
generate_random_graph1(g2, V, E, gen, true, self_edges);
|
||||
|
||||
copy_graph(g2, g, vertex_copy(detail::dummy_property_copier()).
|
||||
edge_copy(detail::dummy_property_copier()));
|
||||
|
||||
} else {
|
||||
|
||||
for (v_size_t i = 0; i < V; ++i)
|
||||
add_vertex(g);
|
||||
|
||||
for (e_size_t j = 0; j < E; ++j) {
|
||||
vertex_descriptor a = random_vertex(g, gen), b;
|
||||
do {
|
||||
b = random_vertex(g, gen);
|
||||
} while (self_edges == false && a == b);
|
||||
add_edge(a, b, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MutableGraph, class RandNumGen>
|
||||
void generate_random_graph
|
||||
(MutableGraph& g,
|
||||
typename graph_traits<MutableGraph>::vertices_size_type V,
|
||||
typename graph_traits<MutableGraph>::vertices_size_type E,
|
||||
RandNumGen& gen,
|
||||
bool allow_parallel = true,
|
||||
bool self_edges = false)
|
||||
{
|
||||
generate_random_graph1(g, V, E, gen, allow_parallel, self_edges);
|
||||
}
|
||||
|
||||
template <typename MutableGraph, typename RandNumGen,
|
||||
typename VertexOutputIterator, typename EdgeOutputIterator>
|
||||
void generate_random_graph
|
||||
(MutableGraph& g,
|
||||
typename graph_traits<MutableGraph>::vertices_size_type V,
|
||||
typename graph_traits<MutableGraph>::vertices_size_type E,
|
||||
RandNumGen& gen,
|
||||
VertexOutputIterator vertex_out,
|
||||
EdgeOutputIterator edge_out,
|
||||
bool self_edges = false)
|
||||
{
|
||||
typedef graph_traits<MutableGraph> Traits;
|
||||
typedef typename Traits::vertices_size_type v_size_t;
|
||||
typedef typename Traits::edges_size_type e_size_t;
|
||||
typedef typename Traits::vertex_descriptor vertex_t;
|
||||
typedef typename Traits::edge_descriptor edge_t;
|
||||
|
||||
for (v_size_t i = 0; i < V; ++i)
|
||||
*vertex_out++ = add_vertex(g);
|
||||
|
||||
for (e_size_t j = 0; j < E; ++j) {
|
||||
vertex_t a = random_vertex(g, gen), b;
|
||||
do {
|
||||
b = random_vertex(g, gen);
|
||||
} while (self_edges == false && a == b);
|
||||
edge_t e; bool inserted;
|
||||
tie(e, inserted) = add_edge(a, b, g);
|
||||
if (inserted)
|
||||
*edge_out++ = std::make_pair(source(e, g), target(e, g));
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Property, class G, class RandomGenerator>
|
||||
void randomize_property(G& g, RandomGenerator& rg,
|
||||
Property, vertex_property_tag)
|
||||
{
|
||||
typename property_map<G, Property>::type pm = get(Property(), g);
|
||||
typename graph_traits<G>::vertex_iterator vi, ve;
|
||||
for (tie(vi, ve) = vertices(g); vi != ve; ++vi) {
|
||||
pm[*vi] = rg();
|
||||
}
|
||||
}
|
||||
|
||||
template<class Property, class G, class RandomGenerator>
|
||||
void randomize_property(G& g, RandomGenerator& rg,
|
||||
Property, edge_property_tag)
|
||||
{
|
||||
typename property_map<G, Property>::type pm = get(Property(), g);
|
||||
typename graph_traits<G>::edge_iterator ei, ee;
|
||||
for (tie(ei, ee) = edges(g); ei != ee; ++ei) {
|
||||
pm[*ei] = rg();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Property, class G, class RandomGenerator>
|
||||
void randomize_property(G& g, RandomGenerator& rg)
|
||||
{
|
||||
detail::randomize_property
|
||||
(g, rg, Property(), typename property_kind<Property>::type());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
49
libraries/include/boost/graph/random_layout.hpp
Normal file
49
libraries/include/boost/graph/random_layout.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2004 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: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_RANDOM_LAYOUT_HPP
|
||||
#define BOOST_GRAPH_RANDOM_LAYOUT_HPP
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/random/uniform_01.hpp>
|
||||
#include <boost/random/uniform_real.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename Graph, typename PositionMap, typename Dimension,
|
||||
typename RandomNumberGenerator>
|
||||
void
|
||||
random_graph_layout(const Graph& g, PositionMap position_map,
|
||||
Dimension minX, Dimension maxX,
|
||||
Dimension minY, Dimension maxY,
|
||||
RandomNumberGenerator& gen)
|
||||
{
|
||||
typedef typename mpl::if_<is_integral<Dimension>,
|
||||
uniform_int<Dimension>,
|
||||
uniform_real<Dimension> >::type distrib_t;
|
||||
typedef typename mpl::if_<is_integral<Dimension>,
|
||||
RandomNumberGenerator&,
|
||||
uniform_01<RandomNumberGenerator, Dimension> >
|
||||
::type gen_t;
|
||||
|
||||
gen_t my_gen(gen);
|
||||
distrib_t x(minX, maxX);
|
||||
distrib_t y(minY, maxY);
|
||||
typename graph_traits<Graph>::vertex_iterator vi, vi_end;
|
||||
for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
|
||||
position_map[*vi].x = x(my_gen);
|
||||
position_map[*vi].y = y(my_gen);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_RANDOM_LAYOUT_HPP
|
||||
280
libraries/include/boost/graph/read_dimacs.hpp
Normal file
280
libraries/include/boost/graph/read_dimacs.hpp
Normal file
@@ -0,0 +1,280 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
||||
//
|
||||
// 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)
|
||||
//=======================================================================
|
||||
|
||||
/*
|
||||
Reads maximal flow problem in extended DIMACS format.
|
||||
This works, but could use some polishing.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Graph, class CapacityMap, class ReverseEdgeMap>
|
||||
int read_dimacs_max_flow(Graph& g,
|
||||
CapacityMap capacity,
|
||||
ReverseEdgeMap reverse_edge,
|
||||
typename graph_traits<Graph>::vertex_descriptor& src,
|
||||
typename graph_traits<Graph>::vertex_descriptor& sink,
|
||||
std::istream& in = std::cin)
|
||||
{
|
||||
// const int MAXLINE = 100; /* max line length in the input file */
|
||||
const int ARC_FIELDS = 3; /* no of fields in arc line */
|
||||
const int NODE_FIELDS = 2; /* no of fields in node line */
|
||||
const int P_FIELDS = 3; /* no of fields in problem line */
|
||||
const char* PROBLEM_TYPE = "max"; /* name of problem type*/
|
||||
|
||||
typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
|
||||
std::vector<vertex_descriptor> verts;
|
||||
|
||||
long m, n, /* number of edges and nodes */
|
||||
i, head, tail, cap;
|
||||
|
||||
long no_lines=0, /* no of current input line */
|
||||
no_plines=0, /* no of problem-lines */
|
||||
no_nslines=0, /* no of node-source-lines */
|
||||
no_nklines=0, /* no of node-source-lines */
|
||||
no_alines=0; /* no of arc-lines */
|
||||
|
||||
std::string in_line; /* for reading input line */
|
||||
char pr_type[3]; /* for reading type of the problem */
|
||||
char nd; /* source (s) or sink (t) */
|
||||
|
||||
int k, /* temporary */
|
||||
err_no; /* no of detected error */
|
||||
|
||||
/* -------------- error numbers & error messages ---------------- */
|
||||
const int EN1 = 0;
|
||||
const int EN2 = 1;
|
||||
const int EN3 = 2;
|
||||
const int EN4 = 3;
|
||||
// const int EN6 = 4;
|
||||
// const int EN10 = 5;
|
||||
// const int EN7 = 6;
|
||||
const int EN8 = 7;
|
||||
const int EN9 = 8;
|
||||
const int EN11 = 9;
|
||||
const int EN12 = 10;
|
||||
// const int EN13 = 11;
|
||||
const int EN14 = 12;
|
||||
const int EN16 = 13;
|
||||
const int EN15 = 14;
|
||||
const int EN17 = 15;
|
||||
const int EN18 = 16;
|
||||
const int EN21 = 17;
|
||||
const int EN19 = 18;
|
||||
const int EN20 = 19;
|
||||
const int EN22 = 20;
|
||||
|
||||
static char *err_message[] =
|
||||
{
|
||||
/* 0*/ "more than one problem line.",
|
||||
/* 1*/ "wrong number of parameters in the problem line.",
|
||||
/* 2*/ "it is not a Max Flow problem line.",
|
||||
/* 3*/ "bad value of a parameter in the problem line.",
|
||||
/* 4*/ "can't obtain enough memory to solve this problem.",
|
||||
/* 5*/ "more than one line with the problem name.",
|
||||
/* 6*/ "can't read problem name.",
|
||||
/* 7*/ "problem description must be before node description.",
|
||||
/* 8*/ "this parser doesn't support multiply sources and sinks.",
|
||||
/* 9*/ "wrong number of parameters in the node line.",
|
||||
/*10*/ "wrong value of parameters in the node line.",
|
||||
/*11*/ " ",
|
||||
/*12*/ "source and sink descriptions must be before arc descriptions.",
|
||||
/*13*/ "too many arcs in the input.",
|
||||
/*14*/ "wrong number of parameters in the arc line.",
|
||||
/*15*/ "wrong value of parameters in the arc line.",
|
||||
/*16*/ "unknown line type in the input.",
|
||||
/*17*/ "reading error.",
|
||||
/*18*/ "not enough arcs in the input.",
|
||||
/*19*/ "source or sink doesn't have incident arcs.",
|
||||
/*20*/ "can't read anything from the input file."
|
||||
};
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
/* The main loop:
|
||||
- reads the line of the input,
|
||||
- analyses its type,
|
||||
- checks correctness of parameters,
|
||||
- puts data to the arrays,
|
||||
- does service functions
|
||||
*/
|
||||
|
||||
while (std::getline(in, in_line)) {
|
||||
++no_lines;
|
||||
|
||||
switch (in_line[0]) {
|
||||
case 'c': /* skip lines with comments */
|
||||
case '\n': /* skip empty lines */
|
||||
case '\0': /* skip empty lines at the end of file */
|
||||
break;
|
||||
|
||||
case 'p': /* problem description */
|
||||
if ( no_plines > 0 )
|
||||
/* more than one problem line */
|
||||
{ err_no = EN1 ; goto error; }
|
||||
|
||||
no_plines = 1;
|
||||
|
||||
if (
|
||||
/* reading problem line: type of problem, no of nodes, no of arcs */
|
||||
sscanf ( in_line.c_str(), "%*c %3s %ld %ld", pr_type, &n, &m )
|
||||
!= P_FIELDS
|
||||
)
|
||||
/*wrong number of parameters in the problem line*/
|
||||
{ err_no = EN2; goto error; }
|
||||
|
||||
if ( strcmp ( pr_type, PROBLEM_TYPE ) )
|
||||
/*wrong problem type*/
|
||||
{ err_no = EN3; goto error; }
|
||||
|
||||
if ( n <= 0 || m <= 0 )
|
||||
/*wrong value of no of arcs or nodes*/
|
||||
{ err_no = EN4; goto error; }
|
||||
|
||||
{
|
||||
for (long vi = 0; vi < n; ++vi)
|
||||
verts.push_back(add_vertex(g));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n': /* source(s) description */
|
||||
if ( no_plines == 0 )
|
||||
/* there was not problem line above */
|
||||
{ err_no = EN8; goto error; }
|
||||
|
||||
/* reading source or sink */
|
||||
k = sscanf ( in_line.c_str(),"%*c %ld %c", &i, &nd );
|
||||
--i; // index from 0
|
||||
if ( k < NODE_FIELDS )
|
||||
/* node line is incorrect */
|
||||
{ err_no = EN11; goto error; }
|
||||
|
||||
if ( i < 0 || i > n )
|
||||
/* wrong value of node */
|
||||
{ err_no = EN12; goto error; }
|
||||
|
||||
switch (nd) {
|
||||
case 's': /* source line */
|
||||
|
||||
if ( no_nslines != 0)
|
||||
/* more than one source line */
|
||||
{ err_no = EN9; goto error; }
|
||||
|
||||
no_nslines = 1;
|
||||
src = verts[i];
|
||||
break;
|
||||
|
||||
case 't': /* sink line */
|
||||
|
||||
if ( no_nklines != 0)
|
||||
/* more than one sink line */
|
||||
{ err_no = EN9; goto error; }
|
||||
|
||||
no_nklines = 1;
|
||||
sink = verts[i];
|
||||
break;
|
||||
|
||||
default:
|
||||
/* wrong type of node-line */
|
||||
err_no = EN12; goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a': /* arc description */
|
||||
if ( no_nslines == 0 || no_nklines == 0 )
|
||||
/* there was not source and sink description above */
|
||||
{ err_no = EN14; goto error; }
|
||||
|
||||
if ( no_alines >= m )
|
||||
/*too many arcs on input*/
|
||||
{ err_no = EN16; goto error; }
|
||||
|
||||
if (
|
||||
/* reading an arc description */
|
||||
sscanf ( in_line.c_str(),"%*c %ld %ld %ld",
|
||||
&tail, &head, &cap )
|
||||
!= ARC_FIELDS
|
||||
)
|
||||
/* arc description is not correct */
|
||||
{ err_no = EN15; goto error; }
|
||||
|
||||
--tail; // index from 0, not 1
|
||||
--head;
|
||||
if ( tail < 0 || tail > n ||
|
||||
head < 0 || head > n
|
||||
)
|
||||
/* wrong value of nodes */
|
||||
{ err_no = EN17; goto error; }
|
||||
|
||||
{
|
||||
edge_descriptor e1, e2;
|
||||
bool in1, in2;
|
||||
tie(e1, in1) = add_edge(verts[tail], verts[head], g);
|
||||
tie(e2, in2) = add_edge(verts[head], verts[tail], g);
|
||||
if (!in1 || !in2) {
|
||||
std::cerr << "unable to add edge (" << head << "," << tail << ")"
|
||||
<< std::endl;
|
||||
return -1;
|
||||
}
|
||||
capacity[e1] = cap;
|
||||
capacity[e2] = 0;
|
||||
reverse_edge[e1] = e2;
|
||||
reverse_edge[e2] = e1;
|
||||
}
|
||||
++no_alines;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown type of line */
|
||||
err_no = EN18; goto error;
|
||||
|
||||
} /* end of switch */
|
||||
} /* end of input loop */
|
||||
|
||||
/* ----- all is red or error while reading ----- */
|
||||
|
||||
if ( in.eof() == 0 ) /* reading error */
|
||||
{ err_no=EN21; goto error; }
|
||||
|
||||
if ( no_lines == 0 ) /* empty input */
|
||||
{ err_no = EN22; goto error; }
|
||||
|
||||
if ( no_alines < m ) /* not enough arcs */
|
||||
{ err_no = EN19; goto error; }
|
||||
|
||||
if ( out_degree(src, g) == 0 || out_degree(sink, g) == 0 )
|
||||
/* no arc goes out of the source */
|
||||
{ err_no = EN20; goto error; }
|
||||
|
||||
/* Thanks God! all is done */
|
||||
return (0);
|
||||
|
||||
/* ---------------------------------- */
|
||||
error: /* error found reading input */
|
||||
|
||||
printf ( "\nline %ld of input - %s\n",
|
||||
no_lines, err_message[err_no] );
|
||||
|
||||
exit (1);
|
||||
return (0); /* to avoid warning */
|
||||
}
|
||||
/* -------------------- end of parser -------------------*/
|
||||
|
||||
} // namespace boost
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user