Imported existing code

This commit is contained in:
Hazim Gazov
2010-04-02 02:48:44 -03:00
parent 48fbc5ae91
commit 7a86d01598
13996 changed files with 2468699 additions and 0 deletions

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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

View 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

View 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 */

View 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__

View 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

View 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__

View 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

View 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 &current_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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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 */

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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*/

View 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

View 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

View 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

View 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

View 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

View 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

View 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 */

View 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

View 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

View 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 &current; }
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 &current; }
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

View 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

View 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

View 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

View 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

View 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

View 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

View 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 */

View File

@@ -0,0 +1,38 @@
//=======================================================================
// Copyright 2002 Indiana University.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef BOOST_GRAPH_SELECTORS_HPP
#define BOOST_GRAPH_SELECTORS_HPP
#include <boost/mpl/bool.hpp>
namespace boost {
//===========================================================================
// Selectors for the Directed template parameter of adjacency_list
// and adjacency_matrix.
struct directedS { enum { is_directed = true, is_bidir = false };
typedef mpl::true_ is_directed_t;
typedef mpl::false_ is_bidir_t;
};
struct undirectedS {
enum { is_directed = false, is_bidir = false };
typedef mpl::false_ is_directed_t;
typedef mpl::false_ is_bidir_t;
};
struct bidirectionalS {
enum { is_directed = true, is_bidir = true };
typedef mpl::true_ is_directed_t;
typedef mpl::true_ is_bidir_t;
};
} // namespace boost
#endif // BOOST_GRAPH_SELECTORS_HPP

View 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

View 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

View 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*/

View 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

View 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

View 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

View 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

View 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

View 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__

View 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__

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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__

View 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__

View 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__

View 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*/

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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__

View File

@@ -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__

File diff suppressed because it is too large Load Diff

View 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__

View 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__

View 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__

View 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__

View 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 &current; }
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

View 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

View 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

View 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 */

View 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

View 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

View 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

View 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

View 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

View 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