mirror of
https://github.com/boostorg/graph.git
synced 2026-01-19 04:12:11 +00:00
This commit was manufactured by cvs2svn to create tag 'boost++graph'.
[SVN r24506]
This commit is contained in:
@@ -332,26 +332,6 @@ Automata, Languages and Programming, 376-386, 1986
|
||||
<EM>A Transitive Closure Algorithm</EM><br>
|
||||
BIT, 10, 1970, pp. 76-94.
|
||||
|
||||
<p></p><dt><a name="brandes01">54</a>
|
||||
<dd>Ulrik Brandes<br>
|
||||
<em><a href="http://ella.slis.indiana.edu/~katy/L579/brandes.pdf">A
|
||||
Faster Algorithm for Betweenness Centrality</a></em><br>
|
||||
Journal of Mathematical Sociology 25 (2):163-177, 2001.
|
||||
|
||||
<p></p><dt><a name="freeman77">55</a>
|
||||
<dd>Lindon C. Freeman<br>
|
||||
<em>A Set of Measures of Centrality Based on Betweenness</em><br>
|
||||
Sociometry 40, pp. 35-41, 1977.
|
||||
|
||||
<p></p><dt><a name="anthonisse71">56</a>
|
||||
<dd>J.M. Anthonisse<br>
|
||||
<em>The rush in a directed graph.</em><br>
|
||||
Technical Report BN9/71, Stichting Mahtematisch Centrum, Amsterdam, 1971.
|
||||
|
||||
<p></p><dt><a name="kamada89">57</a>
|
||||
<dd>T. Kamada and S. Kawai<br>
|
||||
<em>An algorithm for drawing general undirected graphs.</em><br>
|
||||
Information Processing Letters, 31, pp. 7-15, 1989.
|
||||
</DL>
|
||||
|
||||
<br>
|
||||
|
||||
@@ -132,21 +132,21 @@
|
||||
</OL>
|
||||
<LI>Graph Algorithms
|
||||
<OL>
|
||||
<LI>Shortest Paths Algorithms
|
||||
<LI>Shortest Paths Algorithms
|
||||
<OL>
|
||||
<LI><A href="./dijkstra_shortest_paths.html"><tt>dijkstra_shortest_paths</tt></A>
|
||||
<LI><A href="./bellman_ford_shortest.html"><tt>bellman_ford_shortest_paths</tt></A>
|
||||
<LI><A href="./dag_shortest_paths.html"><tt>dag_shortest_paths</tt></A>
|
||||
<LI><A
|
||||
href="./johnson_all_pairs_shortest.html"><tt>johnson_all_pairs_shortest_paths</tt></A>
|
||||
<LI><A href="./dijkstra_shortest_paths.html"><tt>dijkstra_shortest_paths</tt></A>
|
||||
<LI><A href="./bellman_ford_shortest.html"><tt>bellman_ford_shortest_paths</tt></A>
|
||||
<LI><A href="./dag_shortest_paths.html"><tt>dag_shortest_paths</tt></A>
|
||||
<LI><A
|
||||
href="./johnson_all_pairs_shortest.html"><tt>johnson_all_pairs_shortest_paths</tt></A>
|
||||
</OL>
|
||||
<LI>Minimum Spanning Tree Algorithms
|
||||
<OL>
|
||||
<LI><A
|
||||
href="./kruskal_min_spanning_tree.html"><tt>kruskal_minimum_spanning_tree</tt></A>
|
||||
<LI><A
|
||||
href="./prim_minimum_spanning_tree.html"><tt>prim_minimum_spanning_tree</tt></A>
|
||||
</OL>
|
||||
<OL>
|
||||
<LI><A
|
||||
href="./kruskal_min_spanning_tree.html"><tt>kruskal_minimum_spanning_tree</tt></A>
|
||||
<LI><A
|
||||
href="./prim_minimum_spanning_tree.html"><tt>prim_minimum_spanning_tree</tt></A>
|
||||
</OL>
|
||||
<LI><A href="./connected_components.html"><tt>connected_components</tt></A>
|
||||
<LI><A href="./strong_components.html"><tt>strong_components</tt></A>
|
||||
|
||||
@@ -175,29 +175,17 @@
|
||||
<LI><A
|
||||
href="../../../boost/graph/sequential_vertex_coloring.hpp"><tt>sequential_vertex_coloring</tt></A><a
|
||||
href="#*">*</a>
|
||||
<LI><a href="./minimum_degree_ordering.html"><tt>minimum_degree_ordering</tt></a>
|
||||
<LI><a href="./minimum_degree_ordering.html"><tt>minimum_degree_ordering</tt></a>
|
||||
<li><a href="./sloan_ordering.htm"><tt>sloan_ordering</tt></a></li>
|
||||
<LI><A href="./wavefront.htm"><tt>ith_wavefront</tt>, <tt>max_wavefront</tt>, <tt>aver_wavefront</tt>, and <tt>rms_wavefront</tt></A></LI>
|
||||
<LI><A href="brandes_betweenness_centrality.html"><tt>brandes_betweenness_centrality</tt></A></LI>
|
||||
<li>Layout algorithms
|
||||
<ol>
|
||||
<li><a href="circle_layout.html"><tt>circle_layout</tt></a></li>
|
||||
<li><a href="kamada_kawai_spring_layout.html"><tt>kamada_kawai_spring_layout</tt></a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>Clustering algorithms
|
||||
<ol>
|
||||
<li><a href="betweenness_centrality_clustering.html"><tt>betweenness_centrality_clustering</tt></li>
|
||||
</ol>
|
||||
</li>
|
||||
</OL>
|
||||
</OL>
|
||||
|
||||
<LI>AT&T Graphviz Read/Write Utilities
|
||||
<OL>
|
||||
<LI><a href="./write-graphviz.html">write_graphviz</a>
|
||||
<LI><a href="./read-graphviz.html">read_graphviz</a>
|
||||
</OL>
|
||||
<LI><a href="./write-graphviz.html">write_graphviz</a>
|
||||
<LI><a href="./read-graphviz.html">read_graphviz</a>
|
||||
</OL>
|
||||
|
||||
<LI>Auxiliary Concepts, Classes, and Functions
|
||||
<OL>
|
||||
@@ -207,8 +195,8 @@
|
||||
<LI><a href="./BasicMatrix.html">BasicMatrix</a>
|
||||
<LI><a href="./incident.html"><tt>incident</tt></a>
|
||||
<LI><a href="./opposite.html"><tt>opposite</tt></a>
|
||||
<LI><a href="./bandwidth.html#sec:bandwidth"><tt>bandwidth</tt></a>
|
||||
<LI><a href="./bandwidth.html#sec:ith-bandwidth"><tt>ith_bandwidth</tt></a>
|
||||
<LI><a href="./bandwidth.html#sec:bandwidth"><tt>bandwidth</tt></a>
|
||||
<LI><a href="./bandwidth.html#sec:ith-bandwidth"><tt>ith_bandwidth</tt></a>
|
||||
<LI><a href="./random.html">Tools for random graphs</a>
|
||||
<OL>
|
||||
<LI><a href="./random.html#random_vertex">random_vertex</a>
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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
|
||||
@@ -1,548 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_GRAPH_ADJACENCY_LIST_HPP
|
||||
#define BOOST_GRAPH_ADJACENCY_LIST_HPP
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#if !defined BOOST_NO_HASH
|
||||
#include <hash_set>
|
||||
#endif
|
||||
|
||||
#if !defined BOOST_NO_SLIST
|
||||
#include <slist>
|
||||
#endif
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/graph_selectors.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/pending/ct_if.hpp>
|
||||
#include <boost/graph/detail/edge.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/graph/properties.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 std::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 false_type type;
|
||||
};
|
||||
template <>
|
||||
struct is_random_access<vecS> {
|
||||
enum { value = true };
|
||||
typedef true_type 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>
|
||||
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 boost::ct_if_t<is_bidir,
|
||||
bidirectional_tag,
|
||||
typename boost::ct_if_t<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 boost::ct_if_t<is_rand_access,
|
||||
std::size_t, vertex_ptr>::type vertex_descriptor;
|
||||
typedef detail::edge_desc_impl<directed_category, vertex_descriptor>
|
||||
edge_descriptor;
|
||||
};
|
||||
|
||||
} // 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
|
||||
{
|
||||
#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
|
||||
|
||||
struct no_vertex_bundle {};
|
||||
struct no_edge_bundle {};
|
||||
|
||||
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 ct_if<(is_same<maybe_vertex_bundled, no_property>::value),
|
||||
no_vertex_bundle,
|
||||
maybe_vertex_bundled>::type vertex_bundled;
|
||||
typedef typename ct_if<(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 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) {
|
||||
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 m = 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 m = 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;
|
||||
}
|
||||
|
||||
#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 DS, class VP,class EP, class GP,
|
||||
class EL, class Tag, class Value>
|
||||
inline void
|
||||
set_property(adjacency_list<OEL,VL,DS,VP,EP,GP,EL>& g, Tag,
|
||||
const Value& value) {
|
||||
get_property_value(g.m_property, Tag()) = value;;
|
||||
}
|
||||
|
||||
template <class OEL, class VL, class DS, class VP, class EP, class GP,
|
||||
class Tag, class EL>
|
||||
inline
|
||||
typename graph_property<adjacency_list<OEL,VL,DS,VP,EP,GP,EL>, Tag>::type&
|
||||
get_property(adjacency_list<OEL,VL,DS,VP,EP,GP,EL>& g, Tag) {
|
||||
return get_property_value(g.m_property, Tag());
|
||||
}
|
||||
|
||||
template <class OEL, class VL, class DS, class VP, class EP, class GP,
|
||||
class Tag, class EL>
|
||||
inline
|
||||
const
|
||||
typename graph_property<adjacency_list<OEL,VL,DS,VP,EP,GP,EL>, Tag>::type&
|
||||
get_property(const adjacency_list<OEL,VL,DS,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
|
||||
@@ -1,375 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2001 Universite Joseph Fourier, Grenoble.
|
||||
// Author: François Faure
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
|
||||
#ifndef ______adj_list_io_______
|
||||
#define ______adj_list_io_______
|
||||
|
||||
#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 )
|
||||
{
|
||||
}
|
||||
|
||||
// get property subset
|
||||
//===========================================================================
|
||||
// graph parser
|
||||
|
||||
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;
|
||||
|
||||
typedef enum{ PARSE_NUM_NODES, PARSE_VERTEX, PARSE_EDGE } State;
|
||||
State 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
|
||||
|
||||
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( 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:
|
||||
Graph* graph;
|
||||
};
|
||||
template<class Graph>
|
||||
struct PropertyPrinter<Graph, no_property>
|
||||
{
|
||||
PropertyPrinter( 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( 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:
|
||||
|
||||
Graph& graph;
|
||||
|
||||
};
|
||||
|
||||
template<class Graph, class V, class E>
|
||||
struct GraphPrinter: public EdgePrinter<Graph,E>
|
||||
{
|
||||
GraphPrinter( 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( 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( 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( 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
@@ -1,83 +0,0 @@
|
||||
// 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
|
||||
@@ -1,199 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
/*
|
||||
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 <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)
|
||||
{
|
||||
typedef typename property_traits<DistanceMap>::value_type D;
|
||||
bellman_visitor<> null_vis;
|
||||
dummy_property_map dummy_pred;
|
||||
return bellman_ford_shortest_paths
|
||||
(g, N, weight,
|
||||
choose_param(get_param(params, vertex_predecessor), dummy_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)
|
||||
);
|
||||
}
|
||||
|
||||
} // 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);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP
|
||||
@@ -1,165 +0,0 @@
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Authors: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP
|
||||
#define BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP
|
||||
|
||||
#include <boost/graph/brandes_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);
|
||||
centrality_type max_centrality = get(edge_centrality, e);
|
||||
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
|
||||
@@ -1,111 +0,0 @@
|
||||
// Copyright (c) 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)
|
||||
|
||||
// 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 <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>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template < typename Graph, typename ComponentMap,
|
||||
typename DiscoverTimeMap, typename LowPointMap, typename Stack >
|
||||
void biconnect(typename graph_traits < Graph >::vertex_descriptor v,
|
||||
typename graph_traits < Graph >::vertex_descriptor u,
|
||||
bool at_top,
|
||||
const Graph & g,
|
||||
ComponentMap comp,
|
||||
std::size_t & c,
|
||||
DiscoverTimeMap d,
|
||||
std::size_t & dfs_time, LowPointMap lowpt, Stack & S)
|
||||
{
|
||||
BOOST_USING_STD_MIN();
|
||||
typedef typename graph_traits < Graph >::vertex_descriptor vertex_t;
|
||||
typedef typename property_traits < DiscoverTimeMap >::value_type D;
|
||||
D infinity = (std::numeric_limits < D >::max)();
|
||||
put(d, v, ++dfs_time);
|
||||
put(lowpt, v, get(d, v));
|
||||
typename graph_traits < Graph >::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei)
|
||||
{
|
||||
vertex_t w = target(*ei, g);
|
||||
if (get(d, w) == infinity)
|
||||
{
|
||||
S.push(*ei);
|
||||
biconnect(w, v, false, g, comp, c, d, dfs_time, lowpt, S);
|
||||
put(lowpt, v, min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, v), get(lowpt, w)));
|
||||
if (get(lowpt, w) >= get(d, v))
|
||||
{
|
||||
while (d[source(S.top(), g)] >= d[w]) {
|
||||
put(comp, S.top(), c);
|
||||
S.pop();
|
||||
}
|
||||
put(comp, S.top(), c);
|
||||
S.pop();
|
||||
++c;
|
||||
|
||||
}
|
||||
} else if (get(d, w) < get(d, v) && (!at_top && w != u))
|
||||
{
|
||||
S.push(*ei);
|
||||
put(lowpt, v, min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, v), get(d, w)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template < typename Graph, typename ComponentMap,
|
||||
typename DiscoverTimeMap, typename LowPointMap >
|
||||
void biconnected_components
|
||||
(typename graph_traits < Graph >::vertex_descriptor v,
|
||||
typename graph_traits < Graph >::vertex_descriptor u,
|
||||
const Graph & g,
|
||||
ComponentMap comp,
|
||||
std::size_t & num_components,
|
||||
DiscoverTimeMap discover_time, LowPointMap lowpt)
|
||||
{
|
||||
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 > >();
|
||||
|
||||
typedef typename property_traits < DiscoverTimeMap >::value_type D;
|
||||
num_components = 0;
|
||||
std::size_t dfs_time = 0;
|
||||
std::stack < edge_t > S;
|
||||
typename graph_traits < Graph >::vertex_iterator wi, wi_end;
|
||||
std::size_t infinity = (std::numeric_limits < std::size_t >::max)();
|
||||
for (tie(wi, wi_end) = vertices(g); wi != wi_end; ++wi)
|
||||
put(discover_time, *wi, infinity);
|
||||
|
||||
for (tie(wi, wi_end) = vertices(g); wi != wi_end; ++wi)
|
||||
if (get(discover_time, *wi) == (std::numeric_limits < D >::max)())
|
||||
detail::biconnect(*wi, *wi, true,
|
||||
g, comp, num_components,
|
||||
discover_time, dfs_time, lowpt, S);
|
||||
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif /* BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP */
|
||||
@@ -1,599 +0,0 @@
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Authors: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_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>::degree_size_type degree_size_type;
|
||||
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<degree_size_type> 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>::degree_size_type degree_size_type;
|
||||
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<degree_size_type> 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
|
||||
@@ -1,309 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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) {
|
||||
put(color, *i, Color::white());
|
||||
vis.initialize_vertex(*i, g);
|
||||
}
|
||||
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
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Authors: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_CIRCLE_LAYOUT_HPP
|
||||
#define BOOST_GRAPH_CIRCLE_LAYOUT_HPP
|
||||
#include <cmath>
|
||||
#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;
|
||||
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
|
||||
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
|
||||
@@ -1,113 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
@@ -1,466 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Lie-Quan Lee, Andrew Lumsdaine
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
/*
|
||||
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
|
||||
@@ -1,97 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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
|
||||
@@ -1,242 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#ifndef BOOST_GRAPH_CUTHILL_MCKEE_HPP
|
||||
#define BOOST_GRAPH_CUTHILL_MCKEE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <boost/pending/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>
|
||||
|
||||
/*
|
||||
(Reverse) Cuthill-McKee Algorithm for matrix reordering
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// rcm_queue
|
||||
//
|
||||
// This is a custom queue type used in the
|
||||
// reverse_cuthill_mckee_ordering algorithm.
|
||||
// In addition to the normal queue operations, the
|
||||
// rcm_queue provides:
|
||||
//
|
||||
// int eccentricity() const;
|
||||
// value_type spouse() const;
|
||||
//
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Compute Pseudo peripheral
|
||||
//
|
||||
// To compute an approximated peripheral for a given vertex.
|
||||
// Used in <tt>reverse_cuthill_mckee_ordering</tt> algorithm.
|
||||
//
|
||||
template <class Graph, class Vertex, class ColorMap, class DegreeMap>
|
||||
Vertex
|
||||
pseudo_peripheral_pair(Graph& G, const Vertex& u, int& ecc,
|
||||
ColorMap color, DegreeMap degree)
|
||||
{
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
detail::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)
|
||||
put(color, *ui, Color::white());
|
||||
breadth_first_search(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
|
||||
// reverse_cuthill_mckee_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& 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;
|
||||
}
|
||||
|
||||
|
||||
// Reverse Cuthill-McKee algorithm with a given starting Vertex.
|
||||
//
|
||||
// This algorithm requires user to provide a starting vertex to
|
||||
// compute RCM ordering.
|
||||
|
||||
template <class Graph, class OutputIterator,
|
||||
class ColorMap, class DegreeMap>
|
||||
OutputIterator
|
||||
cuthill_mckee_ordering(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
OutputIterator inverse_permutation,
|
||||
ColorMap color, DegreeMap degree)
|
||||
{
|
||||
typedef typename property_traits<DegreeMap>::value_type DS;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
|
||||
put(color, *ui, Color::white());
|
||||
|
||||
typedef indirect_cmp<DegreeMap, std::greater<DS> > Compare;
|
||||
Compare comp(degree);
|
||||
|
||||
boost::queue<Vertex> bfs_queue;
|
||||
std::priority_queue<Vertex, std::vector<Vertex>, Compare>
|
||||
degree_queue(comp);
|
||||
Vertex u, v;
|
||||
|
||||
// Like BFS, except the adjacent vertices are visited
|
||||
// in increasing order of degree.
|
||||
|
||||
put(color, s, Color::gray());
|
||||
bfs_queue.push(s);
|
||||
while (! bfs_queue.empty()) {
|
||||
u = bfs_queue.top(); bfs_queue.pop();
|
||||
*inverse_permutation++ = u;
|
||||
typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
|
||||
v = target(*ei, g);
|
||||
if (get(color, v) == Color::white()) {
|
||||
put(color, v, Color::gray());
|
||||
degree_queue.push(v);
|
||||
}
|
||||
}
|
||||
while (!degree_queue.empty()) {
|
||||
v = degree_queue.top(); degree_queue.pop();
|
||||
bfs_queue.push(v);
|
||||
}
|
||||
put(color, u, Color::black());
|
||||
} // while
|
||||
return inverse_permutation;
|
||||
}
|
||||
|
||||
template < class Graph, class OutputIterator,
|
||||
class Color, class Degree >
|
||||
inline OutputIterator
|
||||
cuthill_mckee_ordering(Graph& G, OutputIterator inverse_permutation,
|
||||
Color color, Degree degree)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename boost::graph_traits<Graph>::vertex_iterator VerIter;
|
||||
VerIter ri = vertices(G).first;
|
||||
Vertex r = *ri;
|
||||
|
||||
//if G has several forests, how to let is cover all. ??
|
||||
|
||||
Vertex s = find_starting_node(G, r, color, degree);
|
||||
return cuthill_mckee_ordering(G, s, inverse_permutation, color, degree);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_CUTHILL_MCKEE_HPP
|
||||
@@ -1,163 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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));
|
||||
topological_sort(g, std::back_inserter(rev_topo_order));
|
||||
|
||||
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
|
||||
@@ -1,386 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
// Nonrecursive implementation of depth_first_visit_impl submitted by
|
||||
// Bruce Barr, schmoost <at> yahoo.com, May/June 2003.
|
||||
//
|
||||
// (C) Copyright Bruce Barr, 2003
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
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
|
||||
@@ -1,107 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#ifndef BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP
|
||||
#define BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
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),
|
||||
eCurr(x.eCurr), eEnd(x.eEnd), 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 )
|
||||
tie(eCurr, eEnd) = 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++() {
|
||||
++eCurr;
|
||||
if ( eCurr == eEnd ) {
|
||||
++vCurr;
|
||||
while ( vCurr != vEnd && out_degree(*vCurr, *m_g) == 0 )
|
||||
++vCurr;
|
||||
if ( vCurr != vEnd )
|
||||
tie(eCurr, eEnd) = out_edges(*vCurr, *m_g);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline self operator++(int) {
|
||||
self tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
inline value_type operator*() const { return *eCurr; }
|
||||
inline bool operator==(const self& x) const {
|
||||
return vCurr == x.vCurr && (vCurr == vEnd || eCurr == x.eCurr);
|
||||
}
|
||||
inline bool operator!=(const self& x) const {
|
||||
return vCurr != x.vCurr || (vCurr != vEnd && eCurr != x.eCurr);
|
||||
}
|
||||
protected:
|
||||
VertexIterator vBegin;
|
||||
VertexIterator vCurr;
|
||||
VertexIterator vEnd;
|
||||
OutEdgeIterator eCurr;
|
||||
OutEdgeIterator eEnd;
|
||||
const Graph* m_g;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,196 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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 ) {
|
||||
value_type tmp = x.value();
|
||||
|
||||
/*swap external data*/
|
||||
edata[ boost::get(id, tmp) ] = i;
|
||||
edata[ boost::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 */
|
||||
@@ -1,907 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/pending/ct_if.hpp>
|
||||
#include <boost/graph/detail/bitset_adaptor.hpp>
|
||||
|
||||
// This provides versions of std::bitset with both static and dynamic size.
|
||||
|
||||
// UNDER CONSTRUCTION
|
||||
|
||||
|
||||
// replace this later
|
||||
#include <cassert>
|
||||
#define BOOST_ASSERT_THROW(expr, except) assert(expr)
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// structure to aid in counting bits
|
||||
template<bool dummy = true>
|
||||
struct bit_count {
|
||||
static unsigned char value[256];
|
||||
};
|
||||
|
||||
// Mapping from 8 bit unsigned integers to the index of the first bit
|
||||
template<bool dummy = true>
|
||||
struct first_bit_location {
|
||||
static unsigned char value[256];
|
||||
};
|
||||
|
||||
template <typename WordType> // this size is in bits
|
||||
struct word_traits {
|
||||
typedef WordType word_type;
|
||||
static const std::size_t word_size = CHAR_BIT * sizeof(word_type);
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
template <class WordTraits, class SizeType, class Derived>
|
||||
class bitset_base
|
||||
: public bitset_adaptor< SizeType,
|
||||
bitset_base<WordTraits, SizeType, Derived> >
|
||||
{
|
||||
// private:
|
||||
public:
|
||||
typedef SizeType size_type;
|
||||
typedef typename WordTraits::word_type word_type;
|
||||
|
||||
static size_type s_which_word(size_type pos) {
|
||||
return pos / WordTraits::word_size;
|
||||
}
|
||||
static size_type s_which_byte(size_type pos) {
|
||||
return (pos % WordTraits::word_size) / CHAR_BIT;
|
||||
}
|
||||
static size_type s_which_bit(size_type pos) {
|
||||
return pos % WordTraits::word_size;
|
||||
}
|
||||
static word_type s_mask_bit(size_type pos) {
|
||||
return (static_cast<word_type>(1)) << s_which_bit(pos);
|
||||
}
|
||||
word_type& m_get_word(size_type pos) {
|
||||
return data()[s_which_word(pos)];
|
||||
}
|
||||
word_type m_get_word(size_type pos) const {
|
||||
return data()[s_which_word(pos)];
|
||||
}
|
||||
word_type& m_hi_word() { return data()[num_words() - 1]; }
|
||||
word_type m_hi_word() const { return data()[num_words() - 1]; }
|
||||
|
||||
void m_sanitize_highest() {
|
||||
size_type extra_bits = size() % WordTraits::word_size;
|
||||
if (extra_bits)
|
||||
m_hi_word() &= ~((~static_cast<word_type>(0)) << extra_bits);
|
||||
}
|
||||
public:
|
||||
|
||||
class reference {
|
||||
friend class bitset_base;
|
||||
|
||||
word_type *m_word_ptr;
|
||||
size_type m_bit_pos;
|
||||
|
||||
// left undefined
|
||||
reference();
|
||||
|
||||
reference(bitset_base& b, size_type pos ) {
|
||||
m_word_ptr = &b.m_get_word(pos);
|
||||
m_bit_pos = s_which_bit(pos);
|
||||
}
|
||||
|
||||
public:
|
||||
~reference() {}
|
||||
|
||||
// for b[i] = x;
|
||||
reference& operator=(bool x) {
|
||||
if ( x )
|
||||
*m_word_ptr |= s_mask_bit(m_bit_pos);
|
||||
else
|
||||
*m_word_ptr &= ~s_mask_bit(m_bit_pos);
|
||||
|
||||
return *this;
|
||||
}
|
||||
// for b[i] = b[j];
|
||||
reference& operator=(const reference& j) {
|
||||
if ( (*(j.m_word_ptr) & s_mask_bit(j.m_bit_pos)) )
|
||||
*m_word_ptr |= s_mask_bit(m_bit_pos);
|
||||
else
|
||||
*m_word_ptr &= ~s_mask_bit(m_bit_pos);
|
||||
|
||||
return *this;
|
||||
}
|
||||
// flips the bit
|
||||
bool operator~() const {
|
||||
return (*(m_word_ptr) & s_mask_bit(m_bit_pos)) == 0;
|
||||
}
|
||||
// for x = b[i];
|
||||
operator bool() const {
|
||||
return (*(m_word_ptr) & s_mask_bit(m_bit_pos)) != 0;
|
||||
}
|
||||
// for b[i].flip();
|
||||
reference& flip() {
|
||||
*m_word_ptr ^= s_mask_bit(m_bit_pos);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
void init_from_ulong(unsigned long val) {
|
||||
reset();
|
||||
const size_type n = (std::min)(sizeof(unsigned long) * CHAR_BIT,
|
||||
WordTraits::word_size * num_words());
|
||||
for(size_type i = 0; i < n; ++i, val >>= 1)
|
||||
if ( val & 0x1 )
|
||||
m_get_word(i) |= s_mask_bit(i);
|
||||
}
|
||||
|
||||
// intersection: this = this & x
|
||||
Derived& operator&=(const Derived& x) {
|
||||
for (size_type i = 0; i < num_words(); ++i)
|
||||
data()[i] &= x.data()[i];
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
// union: this = this | x
|
||||
Derived& operator|=(const Derived& x) {
|
||||
for (size_type i = 0; i < num_words(); ++i)
|
||||
data()[i] |= x.data()[i];
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
// exclusive or: this = this ^ x
|
||||
Derived& operator^=(const Derived& x) {
|
||||
for (size_type i = 0; i < num_words(); ++i)
|
||||
data()[i] ^= x.data()[i];
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
// left shift
|
||||
Derived& operator<<=(size_type pos);
|
||||
|
||||
// right shift
|
||||
Derived& operator>>=(size_type pos);
|
||||
|
||||
Derived& set() {
|
||||
for (size_type i = 0; i < num_words(); ++i)
|
||||
data()[i] = ~static_cast<word_type>(0);
|
||||
m_sanitize_highest();
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
|
||||
Derived& set(size_type pos, int val = true)
|
||||
{
|
||||
BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::set(pos,value)"));
|
||||
if (val)
|
||||
m_get_word(pos) |= s_mask_bit(pos);
|
||||
else
|
||||
m_get_word(pos) &= ~s_mask_bit(pos);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
|
||||
Derived& reset() {
|
||||
for (size_type i = 0; i < num_words(); ++i)
|
||||
data()[i] = 0;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
|
||||
Derived& reset(size_type pos) {
|
||||
BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::reset(pos)"));
|
||||
m_get_word(pos) &= ~s_mask_bit(pos);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
|
||||
// compliment
|
||||
Derived operator~() const {
|
||||
return Derived(static_cast<const Derived&>(*this)).flip();
|
||||
}
|
||||
|
||||
Derived& flip() {
|
||||
for (size_type i = 0; i < num_words(); ++i)
|
||||
data()[i] = ~data()[i];
|
||||
m_sanitize_highest();
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived& flip(size_type pos) {
|
||||
BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::flip(pos)"));
|
||||
m_get_word(pos) ^= s_mask_bit(pos);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
|
||||
// element access
|
||||
reference operator[](size_type pos) { return reference(*this, pos); }
|
||||
bool operator[](size_type pos) const { return test(pos); }
|
||||
|
||||
unsigned long to_ulong() const;
|
||||
|
||||
// to_string
|
||||
|
||||
|
||||
size_type count() const {
|
||||
size_type result = 0;
|
||||
const unsigned char* byte_ptr = (const unsigned char*)data();
|
||||
const unsigned char* end_ptr =
|
||||
(const unsigned char*)(data() + num_words());
|
||||
while ( byte_ptr < end_ptr ) {
|
||||
result += bit_count<>::value[*byte_ptr];
|
||||
byte_ptr++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// size() must be provided by Derived class
|
||||
|
||||
bool operator==(const Derived& x) const {
|
||||
return std::equal(data(), data() + num_words(), x.data());
|
||||
}
|
||||
|
||||
bool operator!=(const Derived& x) const {
|
||||
return ! this->operator==(x);
|
||||
}
|
||||
|
||||
bool test(size_type pos) const {
|
||||
BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::test(pos)"));
|
||||
return (m_get_word(pos) & s_mask_bit(pos))
|
||||
!= static_cast<word_type>(0);
|
||||
}
|
||||
|
||||
bool any() const {
|
||||
for (size_type i = 0; i < num_words(); ++i) {
|
||||
if ( data()[i] != static_cast<word_type>(0) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool none() const {
|
||||
return !any();
|
||||
}
|
||||
|
||||
Derived operator<<(size_type pos) const
|
||||
{ return Derived(static_cast<const Derived&>(*this)) <<= pos; }
|
||||
|
||||
Derived operator>>(size_type pos) const
|
||||
{ return Derived(static_cast<const Derived&>(*this)) >>= pos; }
|
||||
|
||||
template <class CharT, class Traits, class Alloc>
|
||||
void m_copy_from_string(const basic_string<CharT,Traits,Alloc>& s,
|
||||
size_type pos, size_type n)
|
||||
{
|
||||
reset();
|
||||
const size_type nbits = (std::min)(size(), (std::min)(n, s.size() - pos));
|
||||
for (size_type i = 0; i < nbits; ++i) {
|
||||
switch(s[pos + nbits - i - 1]) {
|
||||
case '0':
|
||||
break;
|
||||
case '1':
|
||||
this->set(i);
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument
|
||||
("boost::bitset_base::m_copy_from_string(s, pos, n)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT, class Traits, class Alloc>
|
||||
void m_copy_to_string(basic_string<CharT, Traits, Alloc>& s) const
|
||||
{
|
||||
s.assign(size(), '0');
|
||||
|
||||
for (size_type i = 0; i < size(); ++i)
|
||||
if (test(i))
|
||||
s[size() - 1 - i] = '1';
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Stuff not in std::bitset
|
||||
|
||||
// difference: this = this - x
|
||||
Derived& operator-=(const Derived& x) {
|
||||
for (size_type i = 0; i < num_words(); ++i)
|
||||
data()[i] &= ~x.data()[i];
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
|
||||
// this wasn't working, why?
|
||||
int compare_3way(const Derived& x) const {
|
||||
return std::lexicographical_compare_3way
|
||||
(data(), data() + num_words(), x.data(), x.data() + x.num_words());
|
||||
}
|
||||
|
||||
// less-than compare
|
||||
bool operator<(const Derived& x) const {
|
||||
return std::lexicographical_compare
|
||||
(data(), data() + num_words(), x.data(), x.data() + x.num_words());
|
||||
}
|
||||
|
||||
// find the index of the first "on" bit
|
||||
size_type find_first() const;
|
||||
|
||||
// find the index of the next "on" bit after prev
|
||||
size_type find_next(size_type prev) const;
|
||||
|
||||
|
||||
size_type _Find_first() const { return find_first(); }
|
||||
|
||||
// find the index of the next "on" bit after prev
|
||||
size_type _Find_next(size_type prev) const { return find_next(prev); }
|
||||
|
||||
// private:
|
||||
word_type* data()
|
||||
{ return static_cast<Derived*>(this)->data(); }
|
||||
|
||||
const word_type* data() const
|
||||
{ return static_cast<const Derived*>(this)->data(); }
|
||||
|
||||
size_type num_words() const
|
||||
{ return static_cast<const Derived*>(this)->num_words(); }
|
||||
|
||||
size_type size() const
|
||||
{ return static_cast<const Derived*>(this)->size(); }
|
||||
};
|
||||
|
||||
// 23.3.5.3 bitset operations:
|
||||
template <class W, class S, class D>
|
||||
inline D operator&(const bitset_base<W,S,D>& x,
|
||||
const bitset_base<W,S,D>& y) {
|
||||
D result(static_cast<const D&>(x));
|
||||
result &= static_cast<const D&>(y);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class W, class S, class D>
|
||||
inline D operator|(const bitset_base<W,S,D>& x,
|
||||
const bitset_base<W,S,D>& y) {
|
||||
D result(static_cast<const D&>(x));
|
||||
result |= static_cast<const D&>(y);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class W, class S, class D>
|
||||
inline D operator^(const bitset_base<W,S,D>& x,
|
||||
const bitset_base<W,S,D>& y) {
|
||||
D result(static_cast<const D&>(x));
|
||||
result ^= static_cast<const D&>(y);
|
||||
return result;
|
||||
}
|
||||
|
||||
// this one is an extension
|
||||
template <class W, class S, class D>
|
||||
inline D operator-(const bitset_base<W,S,D>& x,
|
||||
const bitset_base<W,S,D>& y) {
|
||||
D result(static_cast<const D&>(x));
|
||||
result -= static_cast<const D&>(y);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class W, class S, class D>
|
||||
inline int compare_3way(const bitset_base<W,S,D>& x,
|
||||
const bitset_base<W,S,D>& y) {
|
||||
return std::lexicographical_compare_3way
|
||||
(x.data(), x.data() + x.num_words(),
|
||||
y.data(), y.data() + y.num_words());
|
||||
}
|
||||
|
||||
|
||||
template <class W, class S, class D>
|
||||
std::istream&
|
||||
operator>>(std::istream& is, bitset_base<W,S,D>& x) {
|
||||
std::string tmp;
|
||||
tmp.reserve(x.size());
|
||||
|
||||
// In new templatized iostreams, use istream::sentry
|
||||
if (is.flags() & ios::skipws) {
|
||||
char c;
|
||||
do
|
||||
is.get(c);
|
||||
while (is && isspace(c));
|
||||
if (is)
|
||||
is.putback(c);
|
||||
}
|
||||
|
||||
for (S i = 0; i < x.size(); ++i) {
|
||||
char c;
|
||||
is.get(c);
|
||||
|
||||
if (!is)
|
||||
break;
|
||||
else if (c != '0' && c != '1') {
|
||||
is.putback(c);
|
||||
break;
|
||||
}
|
||||
else
|
||||
// tmp.push_back(c);
|
||||
tmp += c;
|
||||
}
|
||||
|
||||
if (tmp.empty())
|
||||
is.clear(is.rdstate() | ios::failbit);
|
||||
else
|
||||
x.m_copy_from_string(tmp, static_cast<S>(0), x.size());
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
template <class W, class S, class D>
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
const bitset_base<W,S,D>& x) {
|
||||
std::string tmp;
|
||||
x.m_copy_to_string(tmp);
|
||||
return os << tmp;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
template <typename WordType = unsigned long,
|
||||
typename SizeType = std::size_t,
|
||||
typename Allocator = std::allocator<WordType>
|
||||
>
|
||||
class dyn_size_bitset
|
||||
: public bitset_base<word_traits<WordType>, SizeType,
|
||||
dyn_size_bitset<WordType,SizeType,Allocator> >
|
||||
{
|
||||
typedef dyn_size_bitset self;
|
||||
public:
|
||||
typedef SizeType size_type;
|
||||
private:
|
||||
typedef word_traits<WordType> WordTraits;
|
||||
static const size_type word_size = WordTraits::word_size;
|
||||
|
||||
public:
|
||||
dyn_size_bitset(unsigned long val,
|
||||
size_type n,
|
||||
const Allocator& alloc = Allocator())
|
||||
: m_data(alloc.allocate((n + word_size - 1) / word_size)),
|
||||
m_size(n),
|
||||
m_num_words((n + word_size - 1) / word_size),
|
||||
m_alloc(alloc)
|
||||
{
|
||||
init_from_ulong(val);
|
||||
}
|
||||
|
||||
dyn_size_bitset(size_type n, // size of the set's "universe"
|
||||
const Allocator& alloc = Allocator())
|
||||
: m_data(alloc.allocate((n + word_size - 1) / word_size)),
|
||||
m_size(n), m_num_words((n + word_size - 1) / word_size),
|
||||
m_alloc(alloc)
|
||||
{ }
|
||||
|
||||
template<class CharT, class Traits, class Alloc>
|
||||
explicit dyn_size_bitset
|
||||
(const basic_string<CharT,Traits,Alloc>& s,
|
||||
std::size_t pos = 0,
|
||||
std::size_t n = std::size_t(basic_string<CharT,Traits,Alloc>::npos),
|
||||
const Allocator& alloc = Allocator())
|
||||
: m_data(alloc.allocate((n + word_size - 1) / word_size)),
|
||||
m_size(n), m_num_words((n + word_size - 1) / word_size),
|
||||
m_alloc(alloc)
|
||||
{
|
||||
BOOST_ASSERT_THROW(pos < s.size(), std::out_of_range("dyn_size_bitset::dyn_size_bitset(s,pos,n,alloc)"));
|
||||
m_copy_from_string(s, pos, n);
|
||||
}
|
||||
|
||||
template <typename InputIterator>
|
||||
explicit dyn_size_bitset
|
||||
(InputIterator first, InputIterator last,
|
||||
size_type n, // size of the set's "universe"
|
||||
const Allocator& alloc = Allocator())
|
||||
: m_data(alloc.allocate((n + word_size - 1) / word_size)),
|
||||
m_size(N), m_num_words((n + word_size - 1) / word_size),
|
||||
m_alloc(alloc)
|
||||
{
|
||||
while (first != last)
|
||||
this->set(*first++);
|
||||
}
|
||||
|
||||
~dyn_size_bitset() {
|
||||
m_alloc.deallocate(m_data, m_num_words);
|
||||
}
|
||||
|
||||
size_type size() const { return m_size; }
|
||||
|
||||
// protected:
|
||||
size_type num_words() const { return m_num_words; }
|
||||
|
||||
word_type* data() { return m_data; }
|
||||
const word_type* data() const { return m_data; }
|
||||
|
||||
protected:
|
||||
word_type* m_data;
|
||||
SizeType m_size;
|
||||
SizeType m_num_words;
|
||||
Allocator m_alloc;
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
template <std::size_t N, typename WordType = unsigned long,
|
||||
typename SizeType = std::size_t>
|
||||
class bitset
|
||||
: public bitset_base<word_traits<WordType>, SizeType,
|
||||
bitset<N, WordType, SizeType> >
|
||||
{
|
||||
typedef bitset self;
|
||||
static const std::size_t word_size = word_traits<WordType>::word_size;
|
||||
public:
|
||||
// 23.3.5.1 constructors:
|
||||
bitset() {
|
||||
#if defined(__GNUC__)
|
||||
for (size_type i = 0; i < num_words(); ++i)
|
||||
m_data[i] = static_cast<WordType>(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bitset(unsigned long val) {
|
||||
init_from_ulong(val);
|
||||
}
|
||||
|
||||
template<class CharT, class Traits, class Alloc>
|
||||
explicit bitset
|
||||
(const basic_string<CharT,Traits,Alloc>& s,
|
||||
std::size_t pos = 0,
|
||||
std::size_t n = std::size_t(basic_string<CharT,Traits,Alloc>::npos))
|
||||
{
|
||||
BOOST_ASSERT_THROW
|
||||
(pos < s.size(), std::out_of_range("bitset::bitset(s,pos,n)"));
|
||||
m_copy_from_string(s, pos, n);
|
||||
}
|
||||
|
||||
size_type size() const { return N; }
|
||||
|
||||
// protected:
|
||||
size_type num_words() const { return (N + word_size - 1) / word_size; }
|
||||
|
||||
word_type* data() { return m_data; }
|
||||
const word_type* data() const { return m_data; }
|
||||
protected:
|
||||
word_type m_data[(N + word_size - 1) / word_size];
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
struct select_static_bitset {
|
||||
template <std::size_t N, typename WordT, typename SizeT, typename Alloc>
|
||||
struct bind_ {
|
||||
typedef bitset<N, WordT, SizeT> type;
|
||||
};
|
||||
};
|
||||
struct select_dyn_size_bitset {
|
||||
template <std::size_t N, typename WordT, typename SizeT, typename Alloc>
|
||||
struct bind_ {
|
||||
typedef dyn_size_bitset<WordT, SizeT, Alloc> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <std::size_t N = 0, // 0 means use dynamic
|
||||
typename WordType = unsigned long,
|
||||
typename Size_type = std::size_t,
|
||||
typename Allocator = std::allocator<WordType>
|
||||
>
|
||||
class bitset_generator {
|
||||
typedef typename ct_if<N, select_dyn_size_bitset,
|
||||
select_static_bitset>::type selector;
|
||||
public:
|
||||
typedef typename selector
|
||||
::template bind_<N, WordType, SizeType, Allocator>::type type;
|
||||
};
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// bitset_base non-inline member function implementations
|
||||
|
||||
template <class WordTraits, class SizeType, class Derived>
|
||||
Derived&
|
||||
bitset_base<WordTraits, SizeType, Derived>::
|
||||
operator<<=(size_type shift)
|
||||
{
|
||||
typedef typename WordTraits::word_type word_type;
|
||||
typedef SizeType size_type;
|
||||
if (shift != 0) {
|
||||
const size_type wshift = shift / WordTraits::word_size;
|
||||
const size_type offset = shift % WordTraits::word_size;
|
||||
const size_type sub_offset = WordTraits::word_size - offset;
|
||||
size_type n = num_words() - 1;
|
||||
for ( ; n > wshift; --n)
|
||||
data()[n] = (data()[n - wshift] << offset) |
|
||||
(data()[n - wshift - 1] >> sub_offset);
|
||||
if (n == wshift)
|
||||
data()[n] = data()[0] << offset;
|
||||
for (size_type n1 = 0; n1 < n; ++n1)
|
||||
data()[n1] = static_cast<word_type>(0);
|
||||
}
|
||||
m_sanitize_highest();
|
||||
return static_cast<Derived&>(*this);
|
||||
} // end operator<<=
|
||||
|
||||
|
||||
template <class WordTraits, class SizeType, class Derived>
|
||||
Derived&
|
||||
bitset_base<WordTraits, SizeType, Derived>::
|
||||
operator>>=(size_type shift)
|
||||
{
|
||||
typedef typename WordTraits::word_type word_type;
|
||||
typedef SizeType size_type;
|
||||
if (shift != 0) {
|
||||
const size_type wshift = shift / WordTraits::word_size;
|
||||
const size_type offset = shift % WordTraits::word_size;
|
||||
const size_type sub_offset = WordTraits::word_size - offset;
|
||||
const size_type limit = num_words() - wshift - 1;
|
||||
size_type n = 0;
|
||||
for ( ; n < limit; ++n)
|
||||
data()[n] = (data()[n + wshift] >> offset) |
|
||||
(data()[n + wshift + 1] << sub_offset);
|
||||
data()[limit] = data()[num_words()-1] >> offset;
|
||||
for (size_type n1 = limit + 1; n1 < num_words(); ++n1)
|
||||
data()[n1] = static_cast<word_type>(0);
|
||||
}
|
||||
m_sanitize_highest();
|
||||
return static_cast<Derived&>(*this);
|
||||
} // end operator>>=
|
||||
|
||||
|
||||
template <class WordTraits, class SizeType, class Derived>
|
||||
unsigned long bitset_base<WordTraits, SizeType, Derived>::
|
||||
to_ulong() const
|
||||
{
|
||||
typedef typename WordTraits::word_type word_type;
|
||||
typedef SizeType size_type;
|
||||
const std::overflow_error
|
||||
overflow("boost::bit_set::operator unsigned long()");
|
||||
|
||||
if (sizeof(word_type) >= sizeof(unsigned long)) {
|
||||
for (size_type i = 1; i < num_words(); ++i)
|
||||
BOOST_ASSERT_THROW(! data()[i], overflow);
|
||||
|
||||
const word_type mask
|
||||
= static_cast<word_type>(static_cast<unsigned long>(-1));
|
||||
BOOST_ASSERT_THROW(! (data()[0] & ~mask), overflow);
|
||||
|
||||
return static_cast<unsigned long>(data()[0] & mask);
|
||||
}
|
||||
else { // sizeof(word_type) < sizeof(unsigned long).
|
||||
const size_type nwords =
|
||||
(sizeof(unsigned long) + sizeof(word_type) - 1) / sizeof(word_type);
|
||||
|
||||
size_type min_nwords = nwords;
|
||||
if (num_words() > nwords) {
|
||||
for (size_type i = nwords; i < num_words(); ++i)
|
||||
BOOST_ASSERT_THROW(!data()[i], overflow);
|
||||
}
|
||||
else
|
||||
min_nwords = num_words();
|
||||
|
||||
// If unsigned long is 8 bytes and word_type is 6 bytes, then
|
||||
// an unsigned long consists of all of one word plus 2 bytes
|
||||
// from another word.
|
||||
const size_type part = sizeof(unsigned long) % sizeof(word_type);
|
||||
|
||||
#if 0
|
||||
// bug in here?
|
||||
// >> to far?
|
||||
BOOST_ASSERT_THROW((part != 0
|
||||
&& nwords <= num_words()
|
||||
&& (data()[min_nwords - 1] >>
|
||||
((sizeof(word_type) - part) * CHAR_BIT)) != 0),
|
||||
overflow);
|
||||
#endif
|
||||
|
||||
unsigned long result = 0;
|
||||
for (size_type i = 0; i < min_nwords; ++i) {
|
||||
result |= static_cast<unsigned long>(
|
||||
data()[i]) << (i * sizeof(word_type) * CHAR_BIT);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}// end operator unsigned long()
|
||||
|
||||
|
||||
template <class WordTraits, class SizeType, class Derived>
|
||||
SizeType bitset_base<WordTraits,SizeType,Derived>::
|
||||
find_first() const
|
||||
{
|
||||
SizeType not_found = size();
|
||||
for (size_type i = 0; i < num_words(); i++ ) {
|
||||
word_type thisword = data()[i];
|
||||
if ( thisword != static_cast<word_type>(0) ) {
|
||||
// find byte within word
|
||||
for ( std::size_t j = 0; j < sizeof(word_type); j++ ) {
|
||||
unsigned char this_byte
|
||||
= static_cast<unsigned char>(thisword & (~(unsigned char)0));
|
||||
if ( this_byte )
|
||||
return i * WordTraits::word_size + j * CHAR_BIT +
|
||||
first_bit_location<>::value[this_byte];
|
||||
|
||||
thisword >>= CHAR_BIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
// not found, so return an indication of failure.
|
||||
return not_found;
|
||||
}
|
||||
|
||||
template <class WordTraits, class SizeType, class Derived>
|
||||
SizeType bitset_base<WordTraits, SizeType, Derived>::
|
||||
bitset_base<WordTraits,SizeType,Derived>::
|
||||
find_next(size_type prev) const
|
||||
{
|
||||
SizeType not_found = size();
|
||||
// make bound inclusive
|
||||
++prev;
|
||||
|
||||
// check out of bounds
|
||||
if ( prev >= num_words() * WordTraits::word_size )
|
||||
return not_found;
|
||||
|
||||
// search first word
|
||||
size_type i = s_which_word(prev);
|
||||
word_type thisword = data()[i];
|
||||
|
||||
// mask off bits below bound
|
||||
thisword &= (~static_cast<word_type>(0)) << s_which_bit(prev);
|
||||
|
||||
if ( thisword != static_cast<word_type>(0) ) {
|
||||
// find byte within word
|
||||
// get first byte into place
|
||||
thisword >>= s_which_byte(prev) * CHAR_BIT;
|
||||
for ( size_type j = s_which_byte(prev); j < sizeof(word_type); j++ ) {
|
||||
unsigned char this_byte
|
||||
= static_cast<unsigned char>(thisword & (~(unsigned char)0));
|
||||
if ( this_byte )
|
||||
return i * WordTraits::word_size + j * CHAR_BIT +
|
||||
first_bit_location<>::value[this_byte];
|
||||
|
||||
thisword >>= CHAR_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
// check subsequent words
|
||||
i++;
|
||||
for ( ; i < num_words(); i++ ) {
|
||||
word_type thisword = data()[i];
|
||||
if ( thisword != static_cast<word_type>(0) ) {
|
||||
// find byte within word
|
||||
for ( size_type j = 0; j < sizeof(word_type); j++ ) {
|
||||
unsigned char this_byte
|
||||
= static_cast<unsigned char>(thisword & (~(unsigned char)0));
|
||||
if ( this_byte )
|
||||
return i * WordTraits::word_size + j * CHAR_BIT +
|
||||
first_bit_location<>::value[this_byte];
|
||||
|
||||
thisword >>= CHAR_BIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not found, so return an indication of failure.
|
||||
return not_found;
|
||||
} // end find_next
|
||||
|
||||
|
||||
template <bool dummy>
|
||||
unsigned char bit_count<dummy>::value[] = {
|
||||
0, /* 0 */ 1, /* 1 */ 1, /* 2 */ 2, /* 3 */ 1, /* 4 */
|
||||
2, /* 5 */ 2, /* 6 */ 3, /* 7 */ 1, /* 8 */ 2, /* 9 */
|
||||
2, /* 10 */ 3, /* 11 */ 2, /* 12 */ 3, /* 13 */ 3, /* 14 */
|
||||
4, /* 15 */ 1, /* 16 */ 2, /* 17 */ 2, /* 18 */ 3, /* 19 */
|
||||
2, /* 20 */ 3, /* 21 */ 3, /* 22 */ 4, /* 23 */ 2, /* 24 */
|
||||
3, /* 25 */ 3, /* 26 */ 4, /* 27 */ 3, /* 28 */ 4, /* 29 */
|
||||
4, /* 30 */ 5, /* 31 */ 1, /* 32 */ 2, /* 33 */ 2, /* 34 */
|
||||
3, /* 35 */ 2, /* 36 */ 3, /* 37 */ 3, /* 38 */ 4, /* 39 */
|
||||
2, /* 40 */ 3, /* 41 */ 3, /* 42 */ 4, /* 43 */ 3, /* 44 */
|
||||
4, /* 45 */ 4, /* 46 */ 5, /* 47 */ 2, /* 48 */ 3, /* 49 */
|
||||
3, /* 50 */ 4, /* 51 */ 3, /* 52 */ 4, /* 53 */ 4, /* 54 */
|
||||
5, /* 55 */ 3, /* 56 */ 4, /* 57 */ 4, /* 58 */ 5, /* 59 */
|
||||
4, /* 60 */ 5, /* 61 */ 5, /* 62 */ 6, /* 63 */ 1, /* 64 */
|
||||
2, /* 65 */ 2, /* 66 */ 3, /* 67 */ 2, /* 68 */ 3, /* 69 */
|
||||
3, /* 70 */ 4, /* 71 */ 2, /* 72 */ 3, /* 73 */ 3, /* 74 */
|
||||
4, /* 75 */ 3, /* 76 */ 4, /* 77 */ 4, /* 78 */ 5, /* 79 */
|
||||
2, /* 80 */ 3, /* 81 */ 3, /* 82 */ 4, /* 83 */ 3, /* 84 */
|
||||
4, /* 85 */ 4, /* 86 */ 5, /* 87 */ 3, /* 88 */ 4, /* 89 */
|
||||
4, /* 90 */ 5, /* 91 */ 4, /* 92 */ 5, /* 93 */ 5, /* 94 */
|
||||
6, /* 95 */ 2, /* 96 */ 3, /* 97 */ 3, /* 98 */ 4, /* 99 */
|
||||
3, /* 100 */ 4, /* 101 */ 4, /* 102 */ 5, /* 103 */ 3, /* 104 */
|
||||
4, /* 105 */ 4, /* 106 */ 5, /* 107 */ 4, /* 108 */ 5, /* 109 */
|
||||
5, /* 110 */ 6, /* 111 */ 3, /* 112 */ 4, /* 113 */ 4, /* 114 */
|
||||
5, /* 115 */ 4, /* 116 */ 5, /* 117 */ 5, /* 118 */ 6, /* 119 */
|
||||
4, /* 120 */ 5, /* 121 */ 5, /* 122 */ 6, /* 123 */ 5, /* 124 */
|
||||
6, /* 125 */ 6, /* 126 */ 7, /* 127 */ 1, /* 128 */ 2, /* 129 */
|
||||
2, /* 130 */ 3, /* 131 */ 2, /* 132 */ 3, /* 133 */ 3, /* 134 */
|
||||
4, /* 135 */ 2, /* 136 */ 3, /* 137 */ 3, /* 138 */ 4, /* 139 */
|
||||
3, /* 140 */ 4, /* 141 */ 4, /* 142 */ 5, /* 143 */ 2, /* 144 */
|
||||
3, /* 145 */ 3, /* 146 */ 4, /* 147 */ 3, /* 148 */ 4, /* 149 */
|
||||
4, /* 150 */ 5, /* 151 */ 3, /* 152 */ 4, /* 153 */ 4, /* 154 */
|
||||
5, /* 155 */ 4, /* 156 */ 5, /* 157 */ 5, /* 158 */ 6, /* 159 */
|
||||
2, /* 160 */ 3, /* 161 */ 3, /* 162 */ 4, /* 163 */ 3, /* 164 */
|
||||
4, /* 165 */ 4, /* 166 */ 5, /* 167 */ 3, /* 168 */ 4, /* 169 */
|
||||
4, /* 170 */ 5, /* 171 */ 4, /* 172 */ 5, /* 173 */ 5, /* 174 */
|
||||
6, /* 175 */ 3, /* 176 */ 4, /* 177 */ 4, /* 178 */ 5, /* 179 */
|
||||
4, /* 180 */ 5, /* 181 */ 5, /* 182 */ 6, /* 183 */ 4, /* 184 */
|
||||
5, /* 185 */ 5, /* 186 */ 6, /* 187 */ 5, /* 188 */ 6, /* 189 */
|
||||
6, /* 190 */ 7, /* 191 */ 2, /* 192 */ 3, /* 193 */ 3, /* 194 */
|
||||
4, /* 195 */ 3, /* 196 */ 4, /* 197 */ 4, /* 198 */ 5, /* 199 */
|
||||
3, /* 200 */ 4, /* 201 */ 4, /* 202 */ 5, /* 203 */ 4, /* 204 */
|
||||
5, /* 205 */ 5, /* 206 */ 6, /* 207 */ 3, /* 208 */ 4, /* 209 */
|
||||
4, /* 210 */ 5, /* 211 */ 4, /* 212 */ 5, /* 213 */ 5, /* 214 */
|
||||
6, /* 215 */ 4, /* 216 */ 5, /* 217 */ 5, /* 218 */ 6, /* 219 */
|
||||
5, /* 220 */ 6, /* 221 */ 6, /* 222 */ 7, /* 223 */ 3, /* 224 */
|
||||
4, /* 225 */ 4, /* 226 */ 5, /* 227 */ 4, /* 228 */ 5, /* 229 */
|
||||
5, /* 230 */ 6, /* 231 */ 4, /* 232 */ 5, /* 233 */ 5, /* 234 */
|
||||
6, /* 235 */ 5, /* 236 */ 6, /* 237 */ 6, /* 238 */ 7, /* 239 */
|
||||
4, /* 240 */ 5, /* 241 */ 5, /* 242 */ 6, /* 243 */ 5, /* 244 */
|
||||
6, /* 245 */ 6, /* 246 */ 7, /* 247 */ 5, /* 248 */ 6, /* 249 */
|
||||
6, /* 250 */ 7, /* 251 */ 6, /* 252 */ 7, /* 253 */ 7, /* 254 */
|
||||
8 /* 255 */
|
||||
}; // end _Bit_count
|
||||
|
||||
template <bool dummy>
|
||||
unsigned char first_bit_location<dummy>::value[] = {
|
||||
0, /* 0 */ 0, /* 1 */ 1, /* 2 */ 0, /* 3 */ 2, /* 4 */
|
||||
0, /* 5 */ 1, /* 6 */ 0, /* 7 */ 3, /* 8 */ 0, /* 9 */
|
||||
1, /* 10 */ 0, /* 11 */ 2, /* 12 */ 0, /* 13 */ 1, /* 14 */
|
||||
0, /* 15 */ 4, /* 16 */ 0, /* 17 */ 1, /* 18 */ 0, /* 19 */
|
||||
2, /* 20 */ 0, /* 21 */ 1, /* 22 */ 0, /* 23 */ 3, /* 24 */
|
||||
0, /* 25 */ 1, /* 26 */ 0, /* 27 */ 2, /* 28 */ 0, /* 29 */
|
||||
1, /* 30 */ 0, /* 31 */ 5, /* 32 */ 0, /* 33 */ 1, /* 34 */
|
||||
0, /* 35 */ 2, /* 36 */ 0, /* 37 */ 1, /* 38 */ 0, /* 39 */
|
||||
3, /* 40 */ 0, /* 41 */ 1, /* 42 */ 0, /* 43 */ 2, /* 44 */
|
||||
0, /* 45 */ 1, /* 46 */ 0, /* 47 */ 4, /* 48 */ 0, /* 49 */
|
||||
1, /* 50 */ 0, /* 51 */ 2, /* 52 */ 0, /* 53 */ 1, /* 54 */
|
||||
0, /* 55 */ 3, /* 56 */ 0, /* 57 */ 1, /* 58 */ 0, /* 59 */
|
||||
2, /* 60 */ 0, /* 61 */ 1, /* 62 */ 0, /* 63 */ 6, /* 64 */
|
||||
0, /* 65 */ 1, /* 66 */ 0, /* 67 */ 2, /* 68 */ 0, /* 69 */
|
||||
1, /* 70 */ 0, /* 71 */ 3, /* 72 */ 0, /* 73 */ 1, /* 74 */
|
||||
0, /* 75 */ 2, /* 76 */ 0, /* 77 */ 1, /* 78 */ 0, /* 79 */
|
||||
4, /* 80 */ 0, /* 81 */ 1, /* 82 */ 0, /* 83 */ 2, /* 84 */
|
||||
0, /* 85 */ 1, /* 86 */ 0, /* 87 */ 3, /* 88 */ 0, /* 89 */
|
||||
1, /* 90 */ 0, /* 91 */ 2, /* 92 */ 0, /* 93 */ 1, /* 94 */
|
||||
0, /* 95 */ 5, /* 96 */ 0, /* 97 */ 1, /* 98 */ 0, /* 99 */
|
||||
2, /* 100 */ 0, /* 101 */ 1, /* 102 */ 0, /* 103 */ 3, /* 104 */
|
||||
0, /* 105 */ 1, /* 106 */ 0, /* 107 */ 2, /* 108 */ 0, /* 109 */
|
||||
1, /* 110 */ 0, /* 111 */ 4, /* 112 */ 0, /* 113 */ 1, /* 114 */
|
||||
0, /* 115 */ 2, /* 116 */ 0, /* 117 */ 1, /* 118 */ 0, /* 119 */
|
||||
3, /* 120 */ 0, /* 121 */ 1, /* 122 */ 0, /* 123 */ 2, /* 124 */
|
||||
0, /* 125 */ 1, /* 126 */ 0, /* 127 */ 7, /* 128 */ 0, /* 129 */
|
||||
1, /* 130 */ 0, /* 131 */ 2, /* 132 */ 0, /* 133 */ 1, /* 134 */
|
||||
0, /* 135 */ 3, /* 136 */ 0, /* 137 */ 1, /* 138 */ 0, /* 139 */
|
||||
2, /* 140 */ 0, /* 141 */ 1, /* 142 */ 0, /* 143 */ 4, /* 144 */
|
||||
0, /* 145 */ 1, /* 146 */ 0, /* 147 */ 2, /* 148 */ 0, /* 149 */
|
||||
1, /* 150 */ 0, /* 151 */ 3, /* 152 */ 0, /* 153 */ 1, /* 154 */
|
||||
0, /* 155 */ 2, /* 156 */ 0, /* 157 */ 1, /* 158 */ 0, /* 159 */
|
||||
5, /* 160 */ 0, /* 161 */ 1, /* 162 */ 0, /* 163 */ 2, /* 164 */
|
||||
0, /* 165 */ 1, /* 166 */ 0, /* 167 */ 3, /* 168 */ 0, /* 169 */
|
||||
1, /* 170 */ 0, /* 171 */ 2, /* 172 */ 0, /* 173 */ 1, /* 174 */
|
||||
0, /* 175 */ 4, /* 176 */ 0, /* 177 */ 1, /* 178 */ 0, /* 179 */
|
||||
2, /* 180 */ 0, /* 181 */ 1, /* 182 */ 0, /* 183 */ 3, /* 184 */
|
||||
0, /* 185 */ 1, /* 186 */ 0, /* 187 */ 2, /* 188 */ 0, /* 189 */
|
||||
1, /* 190 */ 0, /* 191 */ 6, /* 192 */ 0, /* 193 */ 1, /* 194 */
|
||||
0, /* 195 */ 2, /* 196 */ 0, /* 197 */ 1, /* 198 */ 0, /* 199 */
|
||||
3, /* 200 */ 0, /* 201 */ 1, /* 202 */ 0, /* 203 */ 2, /* 204 */
|
||||
0, /* 205 */ 1, /* 206 */ 0, /* 207 */ 4, /* 208 */ 0, /* 209 */
|
||||
1, /* 210 */ 0, /* 211 */ 2, /* 212 */ 0, /* 213 */ 1, /* 214 */
|
||||
0, /* 215 */ 3, /* 216 */ 0, /* 217 */ 1, /* 218 */ 0, /* 219 */
|
||||
2, /* 220 */ 0, /* 221 */ 1, /* 222 */ 0, /* 223 */ 5, /* 224 */
|
||||
0, /* 225 */ 1, /* 226 */ 0, /* 227 */ 2, /* 228 */ 0, /* 229 */
|
||||
1, /* 230 */ 0, /* 231 */ 3, /* 232 */ 0, /* 233 */ 1, /* 234 */
|
||||
0, /* 235 */ 2, /* 236 */ 0, /* 237 */ 1, /* 238 */ 0, /* 239 */
|
||||
4, /* 240 */ 0, /* 241 */ 1, /* 242 */ 0, /* 243 */ 2, /* 244 */
|
||||
0, /* 245 */ 1, /* 246 */ 0, /* 247 */ 3, /* 248 */ 0, /* 249 */
|
||||
1, /* 250 */ 0, /* 251 */ 2, /* 252 */ 0, /* 253 */ 1, /* 254 */
|
||||
0, /* 255 */
|
||||
}; // end _First_one
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
@@ -1,104 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_BITSET_ADAPTOR_HPP
|
||||
#define BOOST_BITSET_ADAPTOR_HPP
|
||||
|
||||
template <class T, class Derived>
|
||||
struct bitset_adaptor {
|
||||
Derived& derived() { return static_cast<Derived&>(*this); }
|
||||
const Derived& derived() const {
|
||||
return static_cast<const Derived&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class D, class V>
|
||||
bool set_contains(const bitset_adaptor<T,D>& s, const V& x) {
|
||||
return s.derived().test(x);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool set_equal(const bitset_adaptor<T,D>& x,
|
||||
const bitset_adaptor<T,D>& y) {
|
||||
return x.derived() == y.derived();
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
int set_lex_order(const bitset_adaptor<T,D>& x,
|
||||
const bitset_adaptor<T,D>& y) {
|
||||
return compare_3way(x.derived(), y.derived());
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
void set_clear(bitset_adaptor<T,D>& x) {
|
||||
x.derived().reset();
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool set_empty(const bitset_adaptor<T,D>& x) {
|
||||
return x.derived().none();
|
||||
}
|
||||
|
||||
template <class T, class D, class V>
|
||||
void set_insert(bitset_adaptor<T,D>& x, const V& a) {
|
||||
x.derived().set(a);
|
||||
}
|
||||
|
||||
template <class T, class D, class V>
|
||||
void set_remove(bitset_adaptor<T,D>& x, const V& a) {
|
||||
x.derived().set(a, false);
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
void set_intersect(const bitset_adaptor<T,D>& x,
|
||||
const bitset_adaptor<T,D>& y,
|
||||
bitset_adaptor<T,D>& z)
|
||||
{
|
||||
z.derived() = x.derived() & y.derived();
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
void set_union(const bitset_adaptor<T,D>& x,
|
||||
const bitset_adaptor<T,D>& y,
|
||||
bitset_adaptor<T,D>& z)
|
||||
{
|
||||
z.derived() = x.derived() | y.derived();
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
void set_difference(const bitset_adaptor<T,D>& x,
|
||||
const bitset_adaptor<T,D>& y,
|
||||
bitset_adaptor<T,D>& z)
|
||||
{
|
||||
z.derived() = x.derived() - y.derived();
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
void set_compliment(const bitset_adaptor<T,D>& x,
|
||||
bitset_adaptor<T,D>& z)
|
||||
{
|
||||
z.derived() = x.derived();
|
||||
z.derived().flip();
|
||||
}
|
||||
|
||||
#endif // BOOST_BITSET_ADAPTOR_HPP
|
||||
@@ -1,224 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#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
|
||||
@@ -1,110 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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());
|
||||
}
|
||||
|
||||
} //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
|
||||
@@ -1,95 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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
|
||||
@@ -1,154 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP
|
||||
#define BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP
|
||||
|
||||
#include <boost/operators.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
|
||||
@@ -1,56 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#ifndef BOOST_GRAPH_DETAIL_IS_SAME_HPP
|
||||
#define BOOST_GRAPH_DETAIL_IS_SAME_HPP
|
||||
|
||||
#include <boost/pending/ct_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 boost::ct_if< (Unum == Vnum),
|
||||
boost::true_tag, boost::false_tag>::type is_same_tag;
|
||||
};
|
||||
#endif
|
||||
} // namespace graph_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -1,234 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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
|
||||
@@ -1,205 +0,0 @@
|
||||
// (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
|
||||
@@ -1,434 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#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*/
|
||||
@@ -1,117 +0,0 @@
|
||||
// (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
|
||||
@@ -1,139 +0,0 @@
|
||||
// (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
|
||||
@@ -1,293 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
//
|
||||
// Revision History:
|
||||
// 04 April 2001: Added named parameter variant. (Jeremy Siek)
|
||||
// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)
|
||||
//
|
||||
#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/pending/mutable_queue.hpp>
|
||||
#include <boost/graph/relax.hpp>
|
||||
#include <boost/pending/indirect_cmp.hpp>
|
||||
#include <boost/graph/exception.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Visitor, class Graph>
|
||||
struct DijkstraVisitorConcept {
|
||||
void constraints() {
|
||||
function_requires< CopyConstructibleConcept<Visitor> >();
|
||||
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)
|
||||
{ m_vis.initialize_vertex(u, 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
|
||||
|
||||
// Initalize distances and call breadth first search
|
||||
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)
|
||||
{
|
||||
typedef indirect_cmp<DistanceMap, Compare> IndirectCmp;
|
||||
IndirectCmp icmp(distance, compare);
|
||||
|
||||
typedef typename graph_traits<VertexListGraph>::vertex_descriptor Vertex;
|
||||
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);
|
||||
|
||||
std::vector<default_color_type> color(num_vertices(g));
|
||||
default_color_type c = white_color;
|
||||
breadth_first_visit(g, s, Q, bfs_vis,
|
||||
make_iterator_property_map(&color[0], index_map, c));
|
||||
}
|
||||
|
||||
|
||||
// Initalize 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>
|
||||
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)
|
||||
{
|
||||
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(predecessor, *ui, *ui);
|
||||
}
|
||||
put(distance, s, zero);
|
||||
|
||||
dijkstra_shortest_paths_no_init(g, s, predecessor, distance, weight,
|
||||
index_map, compare, combine, zero, vis);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Handle defaults for PredecessorMap and
|
||||
// Distance Compare, Combine, Inf and Zero
|
||||
template <class VertexListGraph, class DistanceMap, class WeightMap,
|
||||
class IndexMap, class Params>
|
||||
inline void
|
||||
dijkstra_dispatch2
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
DistanceMap distance, WeightMap weight, IndexMap index_map,
|
||||
const Params& params)
|
||||
{
|
||||
// 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())));
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class DistanceMap, class WeightMap,
|
||||
class IndexMap, class Params>
|
||||
inline void
|
||||
dijkstra_dispatch1
|
||||
(const VertexListGraph& g,
|
||||
typename graph_traits<VertexListGraph>::vertex_descriptor s,
|
||||
DistanceMap distance, WeightMap weight, IndexMap index_map,
|
||||
const Params& params)
|
||||
{
|
||||
// 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);
|
||||
|
||||
detail::dijkstra_dispatch2
|
||||
(g, s, choose_param(distance, make_iterator_property_map
|
||||
(distance_map.begin(), index_map,
|
||||
distance_map[0])),
|
||||
weight, index_map, params);
|
||||
}
|
||||
} // 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);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_DIJKSTRA_HPP
|
||||
@@ -1,197 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2000 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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/edmunds_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 = edmunds_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
|
||||
@@ -1,319 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
#ifndef BOOST_GRAPH_EDGE_LIST_HPP
|
||||
#define BOOST_GRAPH_EDGE_LIST_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/pending/ct_if.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 false_type type;
|
||||
};
|
||||
template <>
|
||||
struct is_random<std::random_access_iterator_tag> {
|
||||
enum { RET = true }; typedef true_type 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 ct_if_t< 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 */
|
||||
@@ -1,266 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2000 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#ifndef EDMUNDS_KARP_MAX_FLOW_HPP
|
||||
#define EDMUNDS_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
|
||||
// Edmunds-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
|
||||
edmunds_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;
|
||||
} // edmunds_karp_max_flow()
|
||||
|
||||
namespace detail {
|
||||
//-------------------------------------------------------------------------
|
||||
// Handle default for color property map
|
||||
|
||||
// use of class here is a VC++ workaround
|
||||
template <class ColorMap>
|
||||
struct edmunds_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 edmunds_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 edmunds_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 edmunds_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 edmunds_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 edmunds_karp_dispatch2<C>::apply
|
||||
(g, src, sink, pred, params, get_param(params, vertex_color));
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct edmunds_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 edmunds_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
|
||||
edmunds_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::edmunds_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
|
||||
edmunds_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 edmunds_karp_max_flow(g, src, sink, params);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // EDMUNDS_KARP_MAX_FLOW_HPP
|
||||
@@ -1,58 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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.") { }
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_EXCEPTION_HPP
|
||||
@@ -1,482 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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;
|
||||
|
||||
//private:
|
||||
EdgePredicate m_edge_pred;
|
||||
VertexPredicate m_vertex_pred;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// 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 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
|
||||
@@ -1,304 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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
|
||||
@@ -1,170 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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
|
||||
@@ -1,508 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class T>
|
||||
struct MultiPassInputIteratorConcept {
|
||||
void constraints() {
|
||||
function_requires< InputIteratorConcept<T> >();
|
||||
}
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct GraphConcept
|
||||
{
|
||||
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;
|
||||
void constraints() {
|
||||
function_requires< DefaultConstructibleConcept<vertex_descriptor> >();
|
||||
function_requires< EqualityComparableConcept<vertex_descriptor> >();
|
||||
function_requires< AssignableConcept<vertex_descriptor> >();
|
||||
}
|
||||
G g;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct IncidenceGraphConcept
|
||||
{
|
||||
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;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
function_requires< MultiPassInputIteratorConcept<out_edge_iterator> >();
|
||||
function_requires< DefaultConstructibleConcept<edge_descriptor> >();
|
||||
function_requires< EqualityComparableConcept<edge_descriptor> >();
|
||||
function_requires< AssignableConcept<edge_descriptor> >();
|
||||
function_requires< ConvertibleConcept<traversal_category,
|
||||
incidence_graph_tag> >();
|
||||
|
||||
p = out_edges(v, g);
|
||||
n = out_degree(v, g);
|
||||
e = *p.first;
|
||||
u = source(e, g);
|
||||
v = target(e, g);
|
||||
const_constraints(g);
|
||||
}
|
||||
void const_constraints(const G& g) {
|
||||
p = out_edges(v, g);
|
||||
n = out_degree(v, g);
|
||||
e = *p.first;
|
||||
u = source(e, g);
|
||||
v = target(e, g);
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct BidirectionalGraphConcept
|
||||
{
|
||||
typedef typename graph_traits<G>::in_edge_iterator
|
||||
in_edge_iterator;
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
void constraints() {
|
||||
function_requires< IncidenceGraphConcept<G> >();
|
||||
function_requires< MultiPassInputIteratorConcept<in_edge_iterator> >();
|
||||
function_requires< ConvertibleConcept<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& g) {
|
||||
p = in_edges(v, g);
|
||||
n = in_degree(v, g);
|
||||
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;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct AdjacencyGraphConcept
|
||||
{
|
||||
typedef typename graph_traits<G>::adjacency_iterator
|
||||
adjacency_iterator;
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
function_requires< MultiPassInputIteratorConcept<adjacency_iterator> >();
|
||||
function_requires< ConvertibleConcept<traversal_category,
|
||||
adjacency_graph_tag> >();
|
||||
|
||||
p = adjacent_vertices(v, g);
|
||||
v = *p.first;
|
||||
const_constraints(g);
|
||||
}
|
||||
void const_constraints(const G& g) {
|
||||
p = adjacent_vertices(v, g);
|
||||
}
|
||||
std::pair<adjacency_iterator,adjacency_iterator> p;
|
||||
typename graph_traits<G>::vertex_descriptor v;
|
||||
G g;
|
||||
};
|
||||
|
||||
// dwa 2003/7/11 -- This clearly shouldn't be neccessary, 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
|
||||
|
||||
template <class G>
|
||||
struct VertexListGraphConcept
|
||||
{
|
||||
typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
|
||||
typedef typename graph_traits<G>::vertices_size_type vertices_size_type;
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
function_requires< MultiPassInputIteratorConcept<vertex_iterator> >();
|
||||
function_requires< ConvertibleConcept<traversal_category,
|
||||
vertex_list_graph_tag> >();
|
||||
|
||||
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
|
||||
// dwa 2003/7/11 -- This clearly shouldn't be neccessary, 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& g) {
|
||||
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
|
||||
// dwa 2003/7/11 -- This clearly shouldn't be neccessary, 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;
|
||||
V = num_vertices(g);
|
||||
}
|
||||
std::pair<vertex_iterator,vertex_iterator> p;
|
||||
typename graph_traits<G>::vertex_descriptor v;
|
||||
G g;
|
||||
vertices_size_type V;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct EdgeListGraphConcept
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<G>::edge_iterator edge_iterator;
|
||||
typedef typename graph_traits<G>::edges_size_type edges_size_type;
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
function_requires< MultiPassInputIteratorConcept<edge_iterator> >();
|
||||
function_requires< DefaultConstructibleConcept<edge_descriptor> >();
|
||||
function_requires< EqualityComparableConcept<edge_descriptor> >();
|
||||
function_requires< AssignableConcept<edge_descriptor> >();
|
||||
function_requires< ConvertibleConcept<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& g) {
|
||||
p = edges(g);
|
||||
E = num_edges(g);
|
||||
e = *p.first;
|
||||
u = source(e, g);
|
||||
v = target(e, g);
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct VertexAndEdgeListGraphConcept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< VertexListGraphConcept<G> >();
|
||||
function_requires< EdgeListGraphConcept<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.
|
||||
|
||||
template <class G>
|
||||
struct EdgeMutableGraphConcept
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
void constraints() {
|
||||
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;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct VertexMutableGraphConcept
|
||||
{
|
||||
void constraints() {
|
||||
v = add_vertex(g);
|
||||
remove_vertex(v, g);
|
||||
}
|
||||
G g;
|
||||
typename graph_traits<G>::vertex_descriptor u, v;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct MutableGraphConcept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< EdgeMutableGraphConcept<G> >();
|
||||
function_requires< VertexMutableGraphConcept<G> >();
|
||||
}
|
||||
};
|
||||
|
||||
template <class edge_descriptor>
|
||||
struct dummy_edge_predicate {
|
||||
bool operator()(const edge_descriptor&) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct MutableIncidenceGraphConcept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< MutableGraphConcept<G> >();
|
||||
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;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct MutableBidirectionalGraphConcept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< MutableIncidenceGraphConcept<G> >();
|
||||
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;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct MutableEdgeListGraphConcept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< EdgeMutableGraphConcept<G> >();
|
||||
remove_edge_if(p, g);
|
||||
}
|
||||
G g;
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
dummy_edge_predicate<edge_descriptor> p;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct VertexMutablePropertyGraphConcept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< VertexMutableGraphConcept<G> >();
|
||||
v = add_vertex(vp, g);
|
||||
}
|
||||
G g;
|
||||
typename graph_traits<G>::vertex_descriptor v;
|
||||
typename vertex_property<G>::type vp;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct EdgeMutablePropertyGraphConcept
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
void constraints() {
|
||||
function_requires< EdgeMutableGraphConcept<G> >();
|
||||
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;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct AdjacencyMatrixConcept
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
|
||||
p = edge(u, v, g);
|
||||
const_constraints(g);
|
||||
}
|
||||
void const_constraints(const G& g) {
|
||||
p = edge(u, v, g);
|
||||
}
|
||||
typename graph_traits<G>::vertex_descriptor u, v;
|
||||
std::pair<edge_descriptor, bool> p;
|
||||
G g;
|
||||
};
|
||||
|
||||
template <class G, class X, class Property>
|
||||
struct ReadablePropertyGraphConcept
|
||||
{
|
||||
typedef typename property_map<G, Property>::const_type const_Map;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
function_requires< ReadablePropertyMapConcept<const_Map, X> >();
|
||||
|
||||
const_constraints(g);
|
||||
}
|
||||
void const_constraints(const G& g) {
|
||||
const_Map pmap = get(Property(), g);
|
||||
pval = get(Property(), g, x);
|
||||
ignore_unused_variable_warning(pmap);
|
||||
}
|
||||
G g;
|
||||
X x;
|
||||
typename property_traits<const_Map>::value_type pval;
|
||||
};
|
||||
|
||||
template <class G, class X, class Property>
|
||||
struct PropertyGraphConcept
|
||||
{
|
||||
typedef typename property_map<G, Property>::type Map;
|
||||
void constraints() {
|
||||
function_requires< ReadablePropertyGraphConcept<G, X, Property> >();
|
||||
function_requires< 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;
|
||||
};
|
||||
|
||||
template <class G, class X, class Property>
|
||||
struct LvaluePropertyGraphConcept
|
||||
{
|
||||
typedef typename property_map<G, Property>::type Map;
|
||||
typedef typename property_map<G, Property>::const_type const_Map;
|
||||
void constraints() {
|
||||
function_requires< ReadablePropertyGraphConcept<G, X, Property> >();
|
||||
function_requires< 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
|
||||
template <class B>
|
||||
struct BufferConcept
|
||||
{
|
||||
void constraints() {
|
||||
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& b) {
|
||||
const typename B::value_type& v = b.top();
|
||||
n = b.size();
|
||||
bool e = b.empty();
|
||||
ignore_unused_variable_warning(v);
|
||||
ignore_unused_variable_warning(e);
|
||||
}
|
||||
typename B::size_type n;
|
||||
typename B::value_type t;
|
||||
B b;
|
||||
};
|
||||
|
||||
template <class C>
|
||||
struct ColorValueConcept
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< EqualityComparableConcept<C> >();
|
||||
function_requires< DefaultConstructibleConcept<C> >();
|
||||
|
||||
c = color_traits<C>::white();
|
||||
c = color_traits<C>::gray();
|
||||
c = color_traits<C>::black();
|
||||
}
|
||||
C c;
|
||||
};
|
||||
|
||||
template <class M, class I, class V>
|
||||
struct BasicMatrixConcept
|
||||
{
|
||||
void constraints() {
|
||||
V& elt = A[i][j];
|
||||
const_constraints(A);
|
||||
ignore_unused_variable_warning(elt);
|
||||
}
|
||||
void const_constraints(const M& A) {
|
||||
const V& elt = A[i][j];
|
||||
ignore_unused_variable_warning(elt);
|
||||
}
|
||||
M A;
|
||||
I i, j;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif /* BOOST_GRAPH_CONCEPTS_H */
|
||||
@@ -1,50 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_GRAPH_SELECTORS_HPP
|
||||
#define BOOST_GRAPH_SELECTORS_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 true_type is_directed_t;
|
||||
typedef false_type is_bidir_t;
|
||||
};
|
||||
struct undirectedS {
|
||||
enum { is_directed = false, is_bidir = false };
|
||||
typedef false_type is_directed_t;
|
||||
typedef false_type is_bidir_t;
|
||||
};
|
||||
struct bidirectionalS {
|
||||
enum { is_directed = true, is_bidir = true };
|
||||
typedef true_type is_directed_t;
|
||||
typedef true_type is_bidir_t;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_SELECTORS_HPP
|
||||
@@ -1,396 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_GRAPH_TEST_HPP
|
||||
#define BOOST_GRAPH_TEST_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <boost/test/test_tools.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_TEST(out_degree(u, g) == adj.size());
|
||||
BOOST_TEST(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_TEST(source(e, g) == u);
|
||||
BOOST_TEST(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_TEST(in_degree(v, g) == inv_adj.size());
|
||||
BOOST_TEST(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_TEST(target(e, g) == v);
|
||||
BOOST_TEST(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_TEST(deg_size_t(std::distance(p.first, p.second)) == adj.size());
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
vertex_t v = *p.first;
|
||||
BOOST_TEST(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_TEST(num_vertices(g) == vertex_set.size());
|
||||
v_size_t n = std::distance(p.first, p.second);
|
||||
BOOST_TEST(n == num_vertices(g));
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
vertex_t v = *p.first;
|
||||
BOOST_TEST(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_TEST(num_edges(g) == edge_set.size());
|
||||
e_size_t m = std::distance(p.first, p.second);
|
||||
BOOST_TEST(m == num_edges(g));
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
edge_t e = *p.first;
|
||||
BOOST_TEST(any_if(edge_set, connects(source(e, g), target(e, g), g)));
|
||||
BOOST_TEST(contains(vertex_set, source(e, g)) == true);
|
||||
BOOST_TEST(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_TEST(p.second == true);
|
||||
BOOST_TEST(source(p.first, g) == i->first);
|
||||
BOOST_TEST(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_TEST(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_TEST(num_vertices(g) == num_vertices(cpy) + 1);
|
||||
|
||||
BOOST_TEST(out_degree(v, g) == 0);
|
||||
|
||||
// Make sure the rest of the graph stayed the same
|
||||
BOOST_TEST((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 = 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_TEST(added == false);
|
||||
else if (parallel_edge_exists)
|
||||
BOOST_TEST(allows_parallel_edges(g) && added == true
|
||||
|| !allows_parallel_edges(g) && added == false);
|
||||
else
|
||||
BOOST_TEST(added == true);
|
||||
|
||||
if (p.second == true) { // edge added
|
||||
BOOST_TEST(num_edges(g) == num_edges(cpy) + 1);
|
||||
|
||||
BOOST_TEST(contains(out_edges(u, g), e) == true);
|
||||
|
||||
BOOST_TEST((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_TEST(source(e, g) == u);
|
||||
BOOST_TEST(target(e, g) == v);
|
||||
}
|
||||
// The graph should not be changed.
|
||||
BOOST_TEST((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_TEST(num_edges(g) + occurances == num_edges(cpy));
|
||||
BOOST_TEST((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_TEST(num_edges(g) + 1 == num_edges(cpy));
|
||||
BOOST_TEST(count(adjacent_vertices(u, g), v) + 1 == occurances);
|
||||
BOOST_TEST((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_TEST(out_degree(v, g) == 0);
|
||||
BOOST_TEST(num_vertices(g) == num_vertices(cpy));
|
||||
BOOST_TEST((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_TEST(pval1 == pval2);
|
||||
BOOST_TEST(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
|
||||
@@ -1,155 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_GRAPH_TRAITS_HPP
|
||||
#define BOOST_GRAPH_TRAITS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/pending/ct_if.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;
|
||||
};
|
||||
|
||||
} // 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
|
||||
@@ -1,435 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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>
|
||||
#ifndef BOOST_NO_SLIST
|
||||
# include <slist> // shouldn't have to include this... -JGS
|
||||
#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, 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*/
|
||||
@@ -1,462 +0,0 @@
|
||||
//=======================================================================
|
||||
// (C) Copyright Jeremy Siek 2003.
|
||||
// Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
//=======================================================================
|
||||
// Copyright 2001 University of Notre Dame.
|
||||
// Author: Lie-Quan Lee
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#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>
|
||||
|
||||
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=\"" << 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>
|
||||
|
||||
inline void write_graphviz(std::ostream& out, const Graph& g,
|
||||
VertexPropertiesWriter vpw,
|
||||
EdgePropertiesWriter epw,
|
||||
GraphPropertiesWriter gpw)
|
||||
{
|
||||
typedef typename property_map<Graph, vertex_index_t>::const_type vimap_t;
|
||||
vimap_t vertex_index = get(vertex_index_t(), g);
|
||||
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_index, *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_index, source(*ei, g)) << Traits::delimiter() << get(vertex_index, target(*ei, g)) << " ";
|
||||
epw(out, *ei); //print edge attributes
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
#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>
|
||||
void write_graphviz_subgraph (std::ostream& out,
|
||||
const subgraph<Graph_>& g,
|
||||
RandomAccessIterator vertex_marker,
|
||||
RandomAccessIterator edge_marker)
|
||||
{
|
||||
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);
|
||||
|
||||
// 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;
|
||||
|
||||
typename property_map<Graph, vertex_index_t>::const_type
|
||||
indexmap = get(vertex_index, g.root());
|
||||
|
||||
for(tie(i,end) = vertices(g); i != end; ++i) {
|
||||
Vertex v = g.local_to_global(*i);
|
||||
int pos = get(indexmap, 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(indexmap, u) << " " << Traits::delimiter()
|
||||
<< " " << get(indexmap, 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());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPHVIZ_HPP
|
||||
@@ -1,186 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
#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.link(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
|
||||
@@ -1,472 +0,0 @@
|
||||
// Copyright (C) 2001 Jeremy Siek, Douglas Gregor, Brian Osman
|
||||
//
|
||||
// Permission to copy, use, sell and distribute this software is granted
|
||||
// provided this copyright notice appears in all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted
|
||||
// provided this copyright notice appears in all copies, and a notice
|
||||
// that the code was modified is included with the copyright notice.
|
||||
//
|
||||
// This software is provided "as is" without express or implied warranty,
|
||||
// and with no claim as to its suitability for any purpose.
|
||||
#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 make_pair(m1, make_pair(u1, v1))
|
||||
< make_pair(m2, 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 (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
|
||||
@@ -1,143 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2001 Indiana University
|
||||
// Author: Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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
|
||||
@@ -1,36 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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
|
||||
@@ -1,200 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
/*
|
||||
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/pending/ct_if.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
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 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, id1[*v] + 1, g2);
|
||||
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(id1[source(*e, g1)] + 1,
|
||||
id1[target(*e, g1)] + 1, g2);
|
||||
w[e2] = get(w1, *e);
|
||||
if (is_undirected) {
|
||||
tie(e2, z) = add_edge(id1[target(*e, g1)] + 1,
|
||||
id1[source(*e, g1)] + 1, g2);
|
||||
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);
|
||||
|
||||
DT inf = (std::numeric_limits<DT>::max)();
|
||||
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; closed_plus<DT> combine;
|
||||
std::less<DT> compare; 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, 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] = get(d, *v) + get(h, *v) - get(h, *u);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
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_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
|
||||
|
||||
|
||||
@@ -1,501 +0,0 @@
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Authors: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_GRAPH_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 <limits>
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
using std::sqrt;
|
||||
|
||||
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()
|
||||
{
|
||||
// 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)];
|
||||
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;
|
||||
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 tolerance.
|
||||
*
|
||||
* For local movements, where a single vertex is being moved toward
|
||||
* a local minima the tolerance is taken as an absolute tolerance;
|
||||
* for global movements, layout terminates when moving individual
|
||||
* particles results in changes in the maximum vertex energy less
|
||||
* than the tolerance.
|
||||
*/
|
||||
template<typename T = double>
|
||||
struct layout_tolerance
|
||||
{
|
||||
layout_tolerance(const T& tolerance = T(0.01))
|
||||
: tolerance(tolerance), last_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) {
|
||||
double diff = fabs(last_energy - delta_p);
|
||||
if (diff < T(0)) diff = -diff;
|
||||
last_energy = delta_p;
|
||||
return diff < tolerance;
|
||||
} else {
|
||||
return delta_p < tolerance;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T tolerance;
|
||||
T last_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));
|
||||
}
|
||||
|
||||
/**
|
||||
* \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 =
|
||||
typename property_traits<WeightMap>::value_type(1))
|
||||
{
|
||||
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>
|
||||
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
|
||||
@@ -1,168 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
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
|
||||
|
||||
@@ -1,587 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#ifndef BOOST_GRAPH_LEDA_HPP
|
||||
#define BOOST_GRAPH_LEDA_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator_adaptors.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.
|
||||
|
||||
// Remember to define LEDA_PREFIX so that LEDA types such as
|
||||
// leda_edge show up as "leda_edge" and not just "edge".
|
||||
|
||||
// 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
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct leda_out_edge_iterator_policies
|
||||
{
|
||||
static void initialize(leda_edge& ) { }
|
||||
|
||||
template <typename Iter>
|
||||
static void increment(Iter& i)
|
||||
{ i.base() = Succ_Adj_Edge(i.base(), 0); }
|
||||
|
||||
template <typename Iter>
|
||||
static void decrement(Iter& i)
|
||||
{ i.base() = Pred_Adj_Edge(i.base(), 0); }
|
||||
|
||||
template <typename Iter>
|
||||
static leda_edge dereference(const Iter& i)
|
||||
{ return i.base(); }
|
||||
|
||||
template <typename Iter>
|
||||
static bool equal(const Iter& x, const Iter& y)
|
||||
{ return x.base() == y.base(); }
|
||||
};
|
||||
|
||||
struct leda_in_edge_iterator_policies
|
||||
{
|
||||
static void initialize(leda_edge& ) { }
|
||||
|
||||
template <typename Iter>
|
||||
static void increment(Iter& i)
|
||||
{ i.base() = Succ_Adj_Edge(i.base(), 1); }
|
||||
|
||||
template <typename Iter>
|
||||
static void decrement(Iter& i)
|
||||
{ i.bae() = Pred_Adj_Edge(i.base(), 1); }
|
||||
|
||||
template <typename Iter>
|
||||
static leda_edge dereference(const Iter& i)
|
||||
{ return i.base(); }
|
||||
|
||||
template <typename Iter>
|
||||
static bool equal(const Iter& x, const Iter& y)
|
||||
{ return x.base() == y.base(); }
|
||||
};
|
||||
|
||||
struct leda_adjacency_iterator_policies
|
||||
{
|
||||
static void initialize(leda_edge& ) { }
|
||||
|
||||
template <typename Iter>
|
||||
static void increment(Iter& i)
|
||||
{ i.base() = Succ_Adj_Edge(i.base(), 0); }
|
||||
|
||||
template <typename Iter>
|
||||
static void decrement(Iter& i)
|
||||
{ i.base() = Pred_Adj_Edge(i.base(), 0); }
|
||||
|
||||
template <typename Iter>
|
||||
static leda_node dereference(const Iter& i)
|
||||
{ return ::target(i.base()); }
|
||||
|
||||
template <typename Iter>
|
||||
static bool equal(const Iter& x, const Iter& y)
|
||||
{ return x.base() == y.base(); }
|
||||
};
|
||||
|
||||
template <class LedaGraph>
|
||||
struct leda_vertex_iterator_policies
|
||||
{
|
||||
leda_vertex_iterator_policies() { }
|
||||
leda_vertex_iterator_policies(const LedaGraph* g) : m_g(g) { }
|
||||
|
||||
void initialize(leda_node& v) const { }
|
||||
|
||||
template <typename Iter>
|
||||
void increment(Iter& i) const
|
||||
{ i.base() = m_g->succ_node(i.base()); }
|
||||
|
||||
template <typename Iter>
|
||||
void decrement(Iter& i) const
|
||||
{ i.base() = m_g->pred_node(i.base()); }
|
||||
|
||||
template <typename Iter>
|
||||
leda_node dereference(const Iter& i) const
|
||||
{ return i.base(); }
|
||||
|
||||
template <typename Iter>
|
||||
static bool equal(const Iter& x, const Iter& y)
|
||||
{ return x.base() == y.base(); }
|
||||
|
||||
const LedaGraph* m_g;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#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< GRAPH<vtype,etype> > {
|
||||
typedef leda_node vertex_descriptor;
|
||||
typedef leda_edge edge_descriptor;
|
||||
|
||||
typedef boost::iterator_adaptor<leda_edge,
|
||||
boost::leda_adjacency_iterator_policies,
|
||||
leda_node, leda_node, const leda_node*,
|
||||
boost::multi_pass_input_iterator_tag,
|
||||
std::ptrdiff_t
|
||||
> adjacency_iterator;
|
||||
|
||||
typedef boost::iterator_adaptor<leda_edge,
|
||||
boost::leda_out_edge_iterator_policies,
|
||||
leda_edge, const leda_edge&, const leda_edge*,
|
||||
std::forward_iterator_tag,
|
||||
std::ptrdiff_t
|
||||
> out_edge_iterator;
|
||||
|
||||
typedef boost::iterator_adaptor<leda_edge,
|
||||
boost::leda_in_edge_iterator_policies,
|
||||
leda_edge, const leda_edge&, const leda_edge*,
|
||||
std::forward_iterator_tag,
|
||||
std::ptrdiff_t
|
||||
> in_edge_iterator;
|
||||
|
||||
typedef boost::iterator_adaptor<leda_node,
|
||||
boost::leda_vertex_iterator_policies< GRAPH<vtype,etype> >,
|
||||
leda_node, leda_node, const leda_node*,
|
||||
boost::multi_pass_input_iterator_tag,
|
||||
std::ptrdiff_t
|
||||
> vertex_iterator;
|
||||
|
||||
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 <class vtype, class etype>
|
||||
struct vertex_property< GRAPH<vtype,etype> > {
|
||||
typedef vtype type;
|
||||
};
|
||||
|
||||
template <class vtype, class etype>
|
||||
struct edge_property< GRAPH<vtype,etype> > {
|
||||
typedef etype type;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor
|
||||
source(typename graph_traits< GRAPH<vtype,etype> >::edge_descriptor e,
|
||||
const GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return source(e);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor
|
||||
target(typename graph_traits< GRAPH<vtype,etype> >::edge_descriptor e,
|
||||
const GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return target(e);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_iterator,
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_iterator >
|
||||
vertices(const GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< GRAPH<vtype,etype> >::vertex_iterator
|
||||
Iter;
|
||||
return std::make_pair( Iter(g.first_node(),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
// no edges(g) function
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< GRAPH<vtype,etype> >::out_edge_iterator,
|
||||
typename graph_traits< GRAPH<vtype,etype> >::out_edge_iterator >
|
||||
out_edges(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< GRAPH<vtype,etype> >
|
||||
::out_edge_iterator Iter;
|
||||
return std::make_pair( Iter(First_Adj_Edge(u,0)), Iter(0) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< GRAPH<vtype,etype> >::in_edge_iterator,
|
||||
typename graph_traits< GRAPH<vtype,etype> >::in_edge_iterator >
|
||||
in_edges(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< GRAPH<vtype,etype> >
|
||||
::in_edge_iterator Iter;
|
||||
return std::make_pair( Iter(First_Adj_Edge(u,1)), Iter(0) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
typename graph_traits< GRAPH<vtype,etype> >::adjacency_iterator,
|
||||
typename graph_traits< GRAPH<vtype,etype> >::adjacency_iterator >
|
||||
adjacent_vertices(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< GRAPH<vtype,etype> >
|
||||
::adjacency_iterator Iter;
|
||||
return std::make_pair( Iter(First_Adj_Edge(u,0)), Iter(0) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertices_size_type
|
||||
num_vertices(const GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.number_of_nodes();
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::edges_size_type
|
||||
num_edges(const GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.number_of_edges();
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::degree_size_type
|
||||
out_degree(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const GRAPH<vtype,etype>&)
|
||||
{
|
||||
return outdeg(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::degree_size_type
|
||||
in_degree(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const GRAPH<vtype,etype>&)
|
||||
{
|
||||
return indeg(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::degree_size_type
|
||||
degree(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const GRAPH<vtype,etype>&)
|
||||
{
|
||||
return outdeg(u) + indeg(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor
|
||||
add_vertex(GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.new_node();
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor
|
||||
add_vertex(const vtype& vp, GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return g.new_node(vp);
|
||||
}
|
||||
|
||||
// Hmm, LEDA doesn't have the equivalent of clear_vertex() -JGS
|
||||
// need to write an implementation
|
||||
template <class vtype, class etype>
|
||||
void clear_vertex(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
GRAPH<vtype,etype>& g)
|
||||
{
|
||||
g.del_node(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
void remove_vertex(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
GRAPH<vtype,etype>& g)
|
||||
{
|
||||
g.del_node(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
std::pair<
|
||||
typename graph_traits< GRAPH<vtype,etype> >::edge_descriptor,
|
||||
bool>
|
||||
add_edge(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor v,
|
||||
GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return std::make_pair(g.new_edge(u, v), true);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
std::pair<
|
||||
typename graph_traits< GRAPH<vtype,etype> >::edge_descriptor,
|
||||
bool>
|
||||
add_edge(
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor v,
|
||||
const etype& et,
|
||||
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< GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
typename graph_traits< GRAPH<vtype,etype> >::vertex_descriptor v,
|
||||
GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typename graph_traits< 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< GRAPH<vtype,etype> >::edge_descriptor e,
|
||||
GRAPH<vtype,etype>& g)
|
||||
{
|
||||
g.del_edge(e);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// property maps
|
||||
|
||||
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 GRAPH<vtype, etype>& g) {
|
||||
return leda_graph_id_map();
|
||||
}
|
||||
template <class vtype, class etype>
|
||||
inline leda_graph_id_map
|
||||
get(edge_index_t, const 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&, GRAPH<vtype, etype>*> type;
|
||||
typedef leda_graph_data_map<vtype, const vtype&,
|
||||
const GRAPH<vtype, etype>*> const_type;
|
||||
};
|
||||
};
|
||||
template <class vtype, class etype >
|
||||
inline typename property_map< GRAPH<vtype, etype>, vertex_all_t>::type
|
||||
get(vertex_all_t, GRAPH<vtype, etype>& g) {
|
||||
typedef typename property_map< GRAPH<vtype, etype>, vertex_all_t>::type
|
||||
pmap_type;
|
||||
return pmap_type(&g);
|
||||
}
|
||||
template <class vtype, class etype >
|
||||
inline typename property_map< GRAPH<vtype, etype>, vertex_all_t>::const_type
|
||||
get(vertex_all_t, const GRAPH<vtype, etype>& g) {
|
||||
typedef typename property_map< 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&, GRAPH<vtype, etype>*> type;
|
||||
typedef leda_graph_data_map<etype, const etype&,
|
||||
const GRAPH<vtype, etype>*> const_type;
|
||||
};
|
||||
};
|
||||
template <class vtype, class etype >
|
||||
inline typename property_map< GRAPH<vtype, etype>, edge_all_t>::type
|
||||
get(edge_all_t, GRAPH<vtype, etype>& g) {
|
||||
typedef typename property_map< GRAPH<vtype, etype>, edge_all_t>::type
|
||||
pmap_type;
|
||||
return pmap_type(&g);
|
||||
}
|
||||
template <class vtype, class etype >
|
||||
inline typename property_map< GRAPH<vtype, etype>, edge_all_t>::const_type
|
||||
get(edge_all_t, const GRAPH<vtype, etype>& g) {
|
||||
typedef typename property_map< 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<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<GRAPH<vtype, etype>,PropertyTag>::const_type
|
||||
>::value_type
|
||||
get(PropertyTag p, const 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, GRAPH<vtype, etype>& g,
|
||||
const Key& key, const Value& value)
|
||||
{
|
||||
typedef typename property_map<GRAPH<vtype, etype>, PropertyTag>::type Map;
|
||||
Map pmap = get(p, g);
|
||||
put(pmap, key, value);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_LEDA_HPP
|
||||
@@ -1,143 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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*/
|
||||
@@ -1,669 +0,0 @@
|
||||
//-*-c++-*-
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 University of Notre Dame.
|
||||
// Authors: Lie-Quan Lee, Jeremy Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Generic Graph Component Library along with the software; see the
|
||||
// file LICENSE. If not, contact Office of Research, University of Notre
|
||||
// Dame, Notre Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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
|
||||
|
||||
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[id[node]] = done(); }
|
||||
|
||||
bool is_done(Vertex node) { return data[id[node]] == done(); }
|
||||
|
||||
void mark_tagged(Vertex node) { data[id[node]] = tag; }
|
||||
|
||||
void mark_multiple_tagged(Vertex node) { data[id[node]] = multiple_tag; }
|
||||
|
||||
bool is_tagged(Vertex node) const { return data[id[node]] >= tag; }
|
||||
|
||||
bool is_not_tagged(Vertex node) const { return data[id[node]] < tag; }
|
||||
|
||||
bool is_multiple_tagged(Vertex node) const
|
||||
{ return data[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[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[id[node]] < 0;
|
||||
}
|
||||
void indistinguishable(Vertex i, Vertex j) {
|
||||
data[id[i]] = - (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[id[i]] = 1; }
|
||||
bool need_update(Vertex i) { return marks[id[i]] == 1; }
|
||||
bool outmatched_or_done (Vertex i) { return marks[id[i]] == -1; }
|
||||
void mark(Vertex i) { marks[id[i]] = -1; }
|
||||
void unmark(Vertex i) { marks[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(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 = 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 = 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 = 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 = 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 = 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 = 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[index_vertex_map[i]];
|
||||
if ( size <= 0 ) {
|
||||
prev[i] = next[i];
|
||||
supernode_size[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
|
||||
@@ -1,633 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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 { };
|
||||
|
||||
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 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 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 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);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// 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
|
||||
@@ -1,339 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#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
|
||||
@@ -1,60 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 2002 Marc Wintermantel (wintermantel@imes.mavt.ethz.ch)
|
||||
// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st)
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
#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
|
||||
@@ -1,384 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#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>
|
||||
|
||||
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(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(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<Bundle*, VertexBundle*> {};
|
||||
}
|
||||
|
||||
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 ct_if<(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<Graph, descriptor, Bundle, T> type;
|
||||
typedef bundle_property_map<const Graph, descriptor, Bundle, const T> const_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif /* BOOST_GRAPH_PROPERTIES_HPPA */
|
||||
@@ -1,118 +0,0 @@
|
||||
|
||||
// (C) Copyright François Faure, iMAGIS-GRAVIR / UJF, 2001. Permission
|
||||
// to copy, use, modify, sell and distribute this software is granted
|
||||
// provided this copyright notice appears in all copies. This software
|
||||
// is provided "as is" without express or implied warranty, and with
|
||||
// no claim as to its suitability for any purpose.
|
||||
|
||||
// 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ç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/pending/ct_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 ct_if<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
|
||||
@@ -1,742 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2000 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#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_)),
|
||||
layer_list_ptr(num_vertices(g_)),
|
||||
current(num_vertices(g_)),
|
||||
distance(num_vertices(g_)),
|
||||
color(num_vertices(g_)),
|
||||
reverse_edge(rev),
|
||||
residual_capacity(res),
|
||||
layers(num_vertices(g_)),
|
||||
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< list_iterator > layer_list_ptr;
|
||||
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;
|
||||
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
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
// Copyright (C) Vladimir Prus 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#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) {
|
||||
uniform_int<> distrib(0, num_vertices(g)-1);
|
||||
variate_generator<RandomNumGen&, uniform_int<> > rand_gen(gen, distrib);
|
||||
std::size_t n = rand_gen();
|
||||
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) {
|
||||
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();
|
||||
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
|
||||
@@ -1,294 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
/*
|
||||
Reads maximal flow problem in extended DIMACS format.
|
||||
|
||||
Reads from stdin.
|
||||
|
||||
This works, but could use some polishing.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
|
||||
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)
|
||||
{
|
||||
// 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(std::cin, 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 ( feof (stdin) == 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
|
||||
@@ -1,99 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
#ifndef BOOST_GRAPH_RELAX_HPP
|
||||
#define BOOST_GRAPH_RELAX_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <boost/limits.hpp> // for numeric limits
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// The following version of the plus functor prevents
|
||||
// problems due to overflow at positive infinity.
|
||||
|
||||
template <class T>
|
||||
struct closed_plus
|
||||
{
|
||||
// std::abs just isn't portable :(
|
||||
template <class X>
|
||||
inline X my_abs(const X& x) const { return x < 0 ? -x : x; }
|
||||
|
||||
T operator()(const T& a, const T& b) const {
|
||||
using namespace std;
|
||||
T inf = (numeric_limits<T>::max)();
|
||||
if (b > 0 && my_abs(inf - a) < b)
|
||||
return inf;
|
||||
return a + b;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Graph, class WeightMap,
|
||||
class PredecessorMap, class DistanceMap,
|
||||
class BinaryFunction, class BinaryPredicate>
|
||||
bool relax(typename graph_traits<Graph>::edge_descriptor e,
|
||||
const Graph& g, const WeightMap& w,
|
||||
PredecessorMap& p, DistanceMap& d,
|
||||
const BinaryFunction& combine, const BinaryPredicate& compare)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category DirCat;
|
||||
bool is_undirected = is_same<DirCat, undirected_tag>::value;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
Vertex u = source(e, g), v = target(e, g);
|
||||
typedef typename property_traits<DistanceMap>::value_type D;
|
||||
typedef typename property_traits<WeightMap>::value_type W;
|
||||
D d_u = get(d, u), d_v = get(d, v);
|
||||
W w_e = get(w, e);
|
||||
|
||||
if ( compare(combine(d_u, w_e), d_v) ) {
|
||||
put(d, v, combine(d_u, w_e));
|
||||
put(p, v, u);
|
||||
return true;
|
||||
} else if (is_undirected && compare(combine(d_v, w_e), d_u)) {
|
||||
put(d, u, combine(d_v, w_e));
|
||||
put(p, u, v);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class Graph, class WeightMap,
|
||||
class PredecessorMap, class DistanceMap>
|
||||
bool relax(typename graph_traits<Graph>::edge_descriptor e,
|
||||
const Graph& g, WeightMap w, PredecessorMap p, DistanceMap d)
|
||||
{
|
||||
typedef typename property_traits<DistanceMap>::value_type D;
|
||||
typedef closed_plus<D> Combine;
|
||||
typedef std::less<D> Compare;
|
||||
return relax(e, g, w, p, d, Combine(), Compare());
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif /* BOOST_GRAPH_RELAX_HPP */
|
||||
@@ -1,273 +0,0 @@
|
||||
// (C) Copyright David Abrahams 2000.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef REVERSE_GRAPH_DWA092300_H_
|
||||
# define REVERSE_GRAPH_DWA092300_H_
|
||||
|
||||
#include <boost/graph/adjacency_iterator.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct reverse_graph_tag { };
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <bool isEdgeList> struct choose_rev_edge_iter { };
|
||||
template <> struct choose_rev_edge_iter<true> {
|
||||
template <class G> struct bind_ {
|
||||
typedef typename graph_traits<G>::edge_iterator type;
|
||||
};
|
||||
};
|
||||
template <> struct choose_rev_edge_iter<false> {
|
||||
template <class G> struct bind_ {
|
||||
typedef void type;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class BidirectionalGraph, class GraphRef = const BidirectionalGraph&>
|
||||
class reverse_graph {
|
||||
typedef reverse_graph<BidirectionalGraph, GraphRef> Self;
|
||||
typedef graph_traits<BidirectionalGraph> Traits;
|
||||
public:
|
||||
typedef BidirectionalGraph base_type;
|
||||
|
||||
// Constructor
|
||||
reverse_graph(GraphRef g) : m_g(g) {}
|
||||
|
||||
// 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 typename Traits::in_edge_iterator out_edge_iterator;
|
||||
typedef typename Traits::degree_size_type degree_size_type;
|
||||
|
||||
// BidirectionalGraph requirements
|
||||
typedef typename Traits::out_edge_iterator in_edge_iterator;
|
||||
|
||||
// AdjacencyGraph requirements
|
||||
typedef typename adjacency_iterator_generator<Self,
|
||||
vertex_descriptor, out_edge_iterator>::type adjacency_iterator;
|
||||
|
||||
// VertexListGraph requirements
|
||||
typedef typename Traits::vertex_iterator vertex_iterator;
|
||||
|
||||
// EdgeListGraph requirements
|
||||
enum { is_edge_list = is_convertible<traversal_category,
|
||||
edge_list_graph_tag>::value };
|
||||
typedef detail::choose_rev_edge_iter<is_edge_list> ChooseEdgeIter;
|
||||
typedef typename ChooseEdgeIter::
|
||||
template bind_<BidirectionalGraph>::type edge_iterator;
|
||||
typedef typename Traits::vertices_size_type vertices_size_type;
|
||||
typedef typename Traits::edges_size_type edges_size_type;
|
||||
|
||||
// More typedefs used by detail::edge_property_map, vertex_property_map
|
||||
typedef typename BidirectionalGraph::edge_property_type
|
||||
edge_property_type;
|
||||
typedef typename BidirectionalGraph::vertex_property_type
|
||||
vertex_property_type;
|
||||
typedef reverse_graph_tag graph_tag;
|
||||
|
||||
static vertex_descriptor null_vertex()
|
||||
{ return Traits::null_vertex(); }
|
||||
|
||||
// would be private, but template friends aren't portable enough.
|
||||
// private:
|
||||
GraphRef m_g;
|
||||
};
|
||||
|
||||
template <class BidirectionalGraph>
|
||||
inline reverse_graph<BidirectionalGraph>
|
||||
make_reverse_graph(const BidirectionalGraph& g)
|
||||
{
|
||||
return reverse_graph<BidirectionalGraph>(g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph>
|
||||
inline reverse_graph<BidirectionalGraph, BidirectionalGraph&>
|
||||
make_reverse_graph(BidirectionalGraph& g)
|
||||
{
|
||||
return reverse_graph<BidirectionalGraph, BidirectionalGraph&>(g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
std::pair<typename reverse_graph<BidirectionalGraph>::vertex_iterator,
|
||||
typename reverse_graph<BidirectionalGraph>::vertex_iterator>
|
||||
vertices(const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return vertices(g.m_g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
std::pair<typename reverse_graph<BidirectionalGraph>::edge_iterator,
|
||||
typename reverse_graph<BidirectionalGraph>::edge_iterator>
|
||||
edges(const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return edges(g.m_g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
inline std::pair<typename BidirectionalGraph::in_edge_iterator,
|
||||
typename BidirectionalGraph::in_edge_iterator>
|
||||
out_edges(const typename BidirectionalGraph::vertex_descriptor u,
|
||||
const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return in_edges(u, g.m_g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
inline typename BidirectionalGraph::vertices_size_type
|
||||
num_vertices(const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return num_vertices(g.m_g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
inline typename reverse_graph<BidirectionalGraph>::edges_size_type
|
||||
num_edges(const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return num_edges(g.m_g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
inline typename BidirectionalGraph::degree_size_type
|
||||
out_degree(const typename BidirectionalGraph::vertex_descriptor u,
|
||||
const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return in_degree(u, g.m_g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
inline std::pair<typename BidirectionalGraph::edge_descriptor, bool>
|
||||
edge(const typename BidirectionalGraph::vertex_descriptor u,
|
||||
const typename BidirectionalGraph::vertex_descriptor v,
|
||||
const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return edge(v, u, g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
inline std::pair<typename BidirectionalGraph::out_edge_iterator,
|
||||
typename BidirectionalGraph::out_edge_iterator>
|
||||
in_edges(const typename BidirectionalGraph::vertex_descriptor u,
|
||||
const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return out_edges(u, g.m_g);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
inline std::pair<typename reverse_graph<BidirectionalGraph,GRef>::adjacency_iterator,
|
||||
typename reverse_graph<BidirectionalGraph,GRef>::adjacency_iterator>
|
||||
adjacent_vertices(const typename BidirectionalGraph::vertex_descriptor u,
|
||||
const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
typedef reverse_graph<BidirectionalGraph,GRef> Graph;
|
||||
typename Graph::out_edge_iterator first, last;
|
||||
tie(first, last) = out_edges(u, g);
|
||||
typedef typename Graph::adjacency_iterator adjacency_iterator;
|
||||
return std::make_pair(adjacency_iterator(first, const_cast<Graph*>(&g)),
|
||||
adjacency_iterator(last, const_cast<Graph*>(&g)));
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef>
|
||||
inline typename BidirectionalGraph::degree_size_type
|
||||
in_degree(const typename BidirectionalGraph::vertex_descriptor u,
|
||||
const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return out_degree(u, g.m_g);
|
||||
}
|
||||
|
||||
template <class Edge, class BidirectionalGraph, class GRef>
|
||||
inline typename graph_traits<BidirectionalGraph>::vertex_descriptor
|
||||
source(const Edge& e, const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return target(e, g.m_g);
|
||||
}
|
||||
|
||||
template <class Edge, class BidirectionalGraph, class GRef>
|
||||
inline typename graph_traits<BidirectionalGraph>::vertex_descriptor
|
||||
target(const Edge& e, const reverse_graph<BidirectionalGraph,GRef>& g)
|
||||
{
|
||||
return source(e, g.m_g);
|
||||
}
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct reverse_graph_vertex_property_selector {
|
||||
template <class ReverseGraph, class Property, class Tag>
|
||||
struct bind_ {
|
||||
typedef typename ReverseGraph::base_type Graph;
|
||||
typedef property_map<Graph, Tag> PMap;
|
||||
typedef typename PMap::type type;
|
||||
typedef typename PMap::const_type const_type;
|
||||
};
|
||||
};
|
||||
|
||||
struct reverse_graph_edge_property_selector {
|
||||
template <class ReverseGraph, class Property, class Tag>
|
||||
struct bind_ {
|
||||
typedef typename ReverseGraph::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<reverse_graph_tag> {
|
||||
typedef detail::reverse_graph_vertex_property_selector type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct edge_property_selector<reverse_graph_tag> {
|
||||
typedef detail::reverse_graph_edge_property_selector type;
|
||||
};
|
||||
|
||||
template <class BidirGraph, class GRef, class Property>
|
||||
typename property_map<BidirGraph, Property>::type
|
||||
get(Property p, reverse_graph<BidirGraph,GRef>& g)
|
||||
{
|
||||
return get(p, g.m_g);
|
||||
}
|
||||
|
||||
template <class BidirGraph, class GRef, class Property>
|
||||
typename property_map<BidirGraph, Property>::const_type
|
||||
get(Property p, const reverse_graph<BidirGraph,GRef>& g)
|
||||
{
|
||||
const BidirGraph& gref = g.m_g; // in case GRef is non-const
|
||||
return get(p, gref);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef, class Property, class Key>
|
||||
typename property_traits<
|
||||
typename property_map<BidirectionalGraph, Property>::const_type
|
||||
>::value_type
|
||||
get(Property p, const reverse_graph<BidirectionalGraph,GRef>& g, const Key& k)
|
||||
{
|
||||
return get(p, g.m_g, k);
|
||||
}
|
||||
|
||||
template <class BidirectionalGraph, class GRef, class Property, class Key, class Value>
|
||||
void
|
||||
put(Property p, const reverse_graph<BidirectionalGraph,GRef>& g, const Key& k,
|
||||
const Value& val)
|
||||
{
|
||||
put(p, g.m_g, k, val);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -1,109 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#ifndef BOOST_GRAPH_SEQUENTIAL_VERTEX_COLORING_HPP
|
||||
#define BOOST_GRAPH_SEQUENTIAL_VERTEX_COLORING_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
/* This algorithm is to find coloring of a graph
|
||||
|
||||
Algorithm:
|
||||
Let G = (V,E) be a graph with vertices (somehow) ordered v_1, v_2, ...,
|
||||
v_n. For k = 1, 2, ..., n the sequential algorithm assigns v_k to the
|
||||
smallest possible color.
|
||||
|
||||
Reference:
|
||||
|
||||
Thomas F. Coleman and Jorge J. More, Estimation of sparse Jacobian
|
||||
matrices and graph coloring problems. J. Numer. Anal. V20, P187-209, 1983
|
||||
|
||||
v_k is stored as o[k] here.
|
||||
|
||||
The color of the vertex v will be stored in color[v].
|
||||
i.e., vertex v belongs to coloring color[v] */
|
||||
|
||||
namespace boost {
|
||||
template <class VertexListGraph, class OrderPA, class ColorMap>
|
||||
typename graph_traits<VertexListGraph>::size_type
|
||||
sequential_vertex_coloring(const VertexListGraph& G, OrderPA order,
|
||||
ColorMap color)
|
||||
{
|
||||
using graph_traits;
|
||||
using boost::tie;
|
||||
typedef graph_traits<VertexListGraph> GraphTraits;
|
||||
typedef typename GraphTraits::vertex_descriptor Vertex;
|
||||
typedef typename GraphTraits::size_type size_type;
|
||||
|
||||
size_type max_color = 0;
|
||||
const size_type V = num_vertices(G);
|
||||
|
||||
// We need to keep track of which colors are used by
|
||||
// adjacent vertices. We do this by marking the colors
|
||||
// that are used. The mark array contains the mark
|
||||
// for each color. The length of mark is the
|
||||
// number of vertices since the maximum possible number of colors
|
||||
// is the number of vertices.
|
||||
std::vector<size_type> mark(V, numeric_limits_max(max_color));
|
||||
|
||||
//Initialize colors
|
||||
typename GraphTraits::vertex_iterator v, vend;
|
||||
for (tie(v, vend) = vertices(G); v != vend; ++v)
|
||||
put(color, *v, V-1);
|
||||
|
||||
//Determine the color for every vertex one by one
|
||||
for ( size_type i = 0; i < V; i++) {
|
||||
Vertex current = get(order,i);
|
||||
typename GraphTraits::adjacency_iterator v, vend;
|
||||
|
||||
//Mark the colors of vertices adjacent to current.
|
||||
//i can be the value for marking since i increases successively
|
||||
for (tie(v,vend) = adjacent_vertices(current, G); v != vend; ++v)
|
||||
mark[get(color,*v)] = i;
|
||||
|
||||
//Next step is to assign the smallest un-marked color
|
||||
//to the current vertex.
|
||||
size_type j = 0;
|
||||
|
||||
//Scan through all useable colors, find the smallest possible
|
||||
//color which is not used by neighbors. Note that if mark[j]
|
||||
//is equal to i, color j is used by one of the current vertex's
|
||||
//neighbors.
|
||||
while ( j < max_color && mark[j] == i )
|
||||
++j;
|
||||
|
||||
if ( j == max_color ) //All colors are used up. Add one more color
|
||||
++max_color;
|
||||
|
||||
//At this point, j is the smallest possible color
|
||||
put(color, current, j); //Save the color of vertex current
|
||||
|
||||
}
|
||||
|
||||
return max_color;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,464 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 2002 Marc Wintermantel (wintermantel@imes.mavt.ethz.ch)
|
||||
// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st)
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
#ifndef BOOST_GRAPH_SLOAN_HPP
|
||||
#define BOOST_GRAPH_SLOAN_HPP
|
||||
|
||||
#define WEIGHT1 1 //default weight for the distance in the Sloan algorithm
|
||||
#define WEIGHT2 2 //default weight for the degree in the Sloan algorithm
|
||||
#define MAXINT 2147483647 //Maximum value for a 32bit integer
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <boost/pending/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 <algorithm>
|
||||
#include <utility>
|
||||
#include <boost/graph/visitors.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/cuthill_mckee_ordering.hpp>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
//Sloan-Algorithm for graph reordering
|
||||
//(optimzes profile and wavefront, not primiraly bandwidth
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Function that returns the maximum depth of
|
||||
// a rooted level strucutre (RLS)
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
template<class Distance>
|
||||
unsigned RLS_depth(Distance& d)
|
||||
{
|
||||
unsigned h_s = 0;
|
||||
typename Distance::iterator iter;
|
||||
|
||||
for (iter = d.begin(); iter != d.end(); ++iter)
|
||||
{
|
||||
if(*iter > h_s)
|
||||
{
|
||||
h_s = *iter;
|
||||
}
|
||||
}
|
||||
|
||||
return h_s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Function that returns the width of the largest level of
|
||||
// a rooted level strucutre (RLS)
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
template<class Distance, class my_int>
|
||||
unsigned RLS_max_width(Distance& d, my_int depth)
|
||||
{
|
||||
|
||||
//Searching for the maximum width of a level
|
||||
std::vector<unsigned> dummy_width(depth+1, 0);
|
||||
std::vector<unsigned>::iterator my_it;
|
||||
typename Distance::iterator iter;
|
||||
unsigned w_max = 0;
|
||||
|
||||
for (iter = d.begin(); iter != d.end(); ++iter)
|
||||
{
|
||||
dummy_width[*iter]++;
|
||||
}
|
||||
|
||||
for(my_it = dummy_width.begin(); my_it != dummy_width.end(); ++my_it)
|
||||
{
|
||||
if(*my_it > w_max) w_max = *my_it;
|
||||
}
|
||||
|
||||
return w_max;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Function for finding a good starting node for Sloan algorithm
|
||||
//
|
||||
// This is to find a good starting node. "good" is in the sense
|
||||
// of the ordering generated.
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
template <class Graph, class ColorMap, class DegreeMap>
|
||||
typename graph_traits<Graph>::vertex_descriptor
|
||||
sloan_start_end_vertices(Graph& G,
|
||||
typename graph_traits<Graph>::vertex_descriptor &s,
|
||||
ColorMap color,
|
||||
DegreeMap degree)
|
||||
{
|
||||
typedef typename property_traits<DegreeMap>::value_type DS;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename std::vector< typename graph_traits<Graph>::vertices_size_type>::iterator vec_iter;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
|
||||
typedef typename property_map<Graph, vertex_index_t>::const_type VertexID;
|
||||
|
||||
s = *(vertices(G).first);
|
||||
Vertex e = s;
|
||||
Vertex i;
|
||||
unsigned my_degree = get(degree, s );
|
||||
unsigned dummy, h_i, h_s, w_i, w_e;
|
||||
bool new_start = true;
|
||||
unsigned maximum_degree = 0;
|
||||
|
||||
//Creating a std-vector for storing the distance from the start vertex in dist
|
||||
std::vector<typename graph_traits<Graph>::vertices_size_type> dist(num_vertices(G), 0);
|
||||
|
||||
//Wrap a property_map_iterator around the std::iterator
|
||||
boost::iterator_property_map<vec_iter, VertexID, size_type, size_type&> dist_pmap(dist.begin(), get(vertex_index, G));
|
||||
|
||||
//Creating a property_map for the indices of a vertex
|
||||
typename property_map<Graph, vertex_index_t>::type index_map = get(vertex_index, G);
|
||||
|
||||
//Creating a priority queue
|
||||
typedef indirect_cmp<DegreeMap, std::greater<DS> > Compare;
|
||||
Compare comp(degree);
|
||||
std::priority_queue<Vertex, std::vector<Vertex>, Compare> degree_queue(comp);
|
||||
|
||||
//step 1
|
||||
//Scan for the vertex with the smallest degree and the maximum degree
|
||||
typename graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
|
||||
{
|
||||
dummy = get(degree, *ui);
|
||||
|
||||
if(dummy < my_degree)
|
||||
{
|
||||
my_degree = dummy;
|
||||
s = *ui;
|
||||
}
|
||||
|
||||
if(dummy > maximum_degree)
|
||||
{
|
||||
maximum_degree = dummy;
|
||||
}
|
||||
}
|
||||
//end 1
|
||||
|
||||
do{
|
||||
new_start = false; //Setting the loop repetition status to false
|
||||
|
||||
//step 2
|
||||
//initialize the the disance std-vector with 0
|
||||
for(typename std::vector<typename graph_traits<Graph>::vertices_size_type>::iterator iter = dist.begin(); iter != dist.end(); ++iter) *iter = 0;
|
||||
|
||||
//generating the RLS (rooted level structure)
|
||||
breadth_first_search
|
||||
(G, s, visitor
|
||||
(
|
||||
make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) )
|
||||
)
|
||||
);
|
||||
|
||||
//end 2
|
||||
|
||||
//step 3
|
||||
//calculating the depth of the RLS
|
||||
h_s = RLS_depth(dist);
|
||||
|
||||
//step 4
|
||||
//pushing one node of each degree in an ascending manner into degree_queue
|
||||
std::vector<bool> shrink_trace(maximum_degree, false);
|
||||
for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
|
||||
{
|
||||
dummy = get(degree, *ui);
|
||||
|
||||
if( (dist[index_map[*ui]] == h_s ) && ( !shrink_trace[ dummy ] ) )
|
||||
{
|
||||
degree_queue.push(*ui);
|
||||
shrink_trace[ dummy ] = true;
|
||||
}
|
||||
}
|
||||
|
||||
//end 3 & 4
|
||||
|
||||
|
||||
//step 5
|
||||
//Initializing w
|
||||
w_e = MAXINT;
|
||||
//end 5
|
||||
|
||||
|
||||
//step 6
|
||||
//Testing for termination
|
||||
while( !degree_queue.empty() )
|
||||
{
|
||||
i = degree_queue.top(); //getting the node with the lowest degree from the degree queue
|
||||
degree_queue.pop(); //ereasing the node with the lowest degree from the degree queue
|
||||
|
||||
//generating a RLS
|
||||
for(typename std::vector<typename graph_traits<Graph>::vertices_size_type>::iterator iter = dist.begin(); iter != dist.end(); ++iter) *iter = 0;
|
||||
|
||||
breadth_first_search
|
||||
(G, i, boost::visitor
|
||||
(
|
||||
make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) )
|
||||
)
|
||||
);
|
||||
|
||||
//Calculating depth and width of the rooted level
|
||||
h_i = RLS_depth(dist);
|
||||
w_i = RLS_max_width(dist, h_i);
|
||||
|
||||
//Testing for termination
|
||||
if( (h_i > h_s) && (w_i < w_e) )
|
||||
{
|
||||
h_s = h_i;
|
||||
s = i;
|
||||
while(!degree_queue.empty()) degree_queue.pop();
|
||||
new_start = true;
|
||||
}
|
||||
else if(w_i < w_e)
|
||||
{
|
||||
w_e = w_i;
|
||||
e = i;
|
||||
}
|
||||
}
|
||||
//end 6
|
||||
|
||||
}while(new_start);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sloan algorithm with a given starting Vertex.
|
||||
//
|
||||
// This algorithm requires user to provide a starting vertex to
|
||||
// compute Sloan ordering.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Graph, class OutputIterator,
|
||||
class ColorMap, class DegreeMap,
|
||||
class PriorityMap, class Weight>
|
||||
OutputIterator
|
||||
sloan_ordering(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor e,
|
||||
OutputIterator permutation,
|
||||
ColorMap color,
|
||||
DegreeMap degree,
|
||||
PriorityMap priority,
|
||||
Weight W1,
|
||||
Weight W2)
|
||||
{
|
||||
//typedef typename property_traits<DegreeMap>::value_type DS;
|
||||
typedef typename property_traits<PriorityMap>::value_type DS;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename std::vector<typename graph_traits<Graph>::vertices_size_type>::iterator vec_iter;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
|
||||
typedef typename property_map<Graph, vertex_index_t>::const_type VertexID;
|
||||
|
||||
|
||||
//Creating a std-vector for storing the distance from the end vertex in it
|
||||
typename std::vector<typename graph_traits<Graph>::vertices_size_type> dist(num_vertices(g), 0);
|
||||
|
||||
//Wrap a property_map_iterator around the std::iterator
|
||||
boost::iterator_property_map<vec_iter, VertexID, size_type, size_type&> dist_pmap(dist.begin(), get(vertex_index, g));
|
||||
|
||||
breadth_first_search
|
||||
(g, e, visitor
|
||||
(
|
||||
make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) )
|
||||
)
|
||||
);
|
||||
|
||||
//Creating a property_map for the indices of a vertex
|
||||
typename property_map<Graph, vertex_index_t>::type index_map = get(vertex_index, g);
|
||||
|
||||
//Sets the color and priority to their initial status
|
||||
unsigned cdeg;
|
||||
typename graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
|
||||
{
|
||||
put(color, *ui, Color::white());
|
||||
cdeg=get(degree, *ui)+1;
|
||||
put(priority, *ui, W1*dist[index_map[*ui]]-W2*cdeg );
|
||||
}
|
||||
|
||||
//Priority list
|
||||
typedef indirect_cmp<PriorityMap, std::greater<DS> > Compare;
|
||||
Compare comp(priority);
|
||||
std::list<Vertex> priority_list;
|
||||
|
||||
//Some more declarations
|
||||
typename graph_traits<Graph>::out_edge_iterator ei, ei_end, ei2, ei2_end;
|
||||
Vertex u, v, w;
|
||||
|
||||
put(color, s, Color::green()); //Sets the color of the starting vertex to gray
|
||||
priority_list.push_front(s); //Puts s into the priority_list
|
||||
|
||||
while ( !priority_list.empty() )
|
||||
{
|
||||
priority_list.sort(comp); //Orders the elements in the priority list in an ascending manner
|
||||
|
||||
u = priority_list.front(); //Accesses the last element in the priority list
|
||||
priority_list.pop_front(); //Removes the last element in the priority list
|
||||
|
||||
if(get(color, u) == Color::green() )
|
||||
{
|
||||
//for-loop over all out-edges of vertex u
|
||||
for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei)
|
||||
{
|
||||
v = target(*ei, g);
|
||||
|
||||
put( priority, v, get(priority, v) + W2 ); //updates the priority
|
||||
|
||||
if (get(color, v) == Color::white() ) //test if the vertex is inactive
|
||||
{
|
||||
put(color, v, Color::green() ); //giving the vertex a preactive status
|
||||
priority_list.push_front(v); //writing the vertex in the priority_queue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Here starts step 8
|
||||
*permutation++ = u; //Puts u to the first position in the permutation-vector
|
||||
put(color, u, Color::black() ); //Gives u an inactive status
|
||||
|
||||
//for loop over all the adjacent vertices of u
|
||||
for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
|
||||
|
||||
v = target(*ei, g);
|
||||
|
||||
if (get(color, v) == Color::green() ) { //tests if the vertex is inactive
|
||||
|
||||
put(color, v, Color::red() ); //giving the vertex an active status
|
||||
put(priority, v, get(priority, v)+W2); //updates the priority
|
||||
|
||||
//for loop over alll adjacent vertices of v
|
||||
for (tie(ei2, ei2_end) = out_edges(v, g); ei2 != ei2_end; ++ei2) {
|
||||
w = target(*ei2, g);
|
||||
|
||||
if(get(color, w) != Color::black() ) { //tests if vertex is postactive
|
||||
|
||||
put(priority, w, get(priority, w)+W2); //updates the priority
|
||||
|
||||
if(get(color, w) == Color::white() ){
|
||||
|
||||
put(color, w, Color::green() ); // gives the vertex a preactive status
|
||||
priority_list.push_front(w); // puts the vertex into the priority queue
|
||||
|
||||
} //end if
|
||||
|
||||
} //end if
|
||||
|
||||
} //end for
|
||||
|
||||
} //end if
|
||||
|
||||
} //end for
|
||||
|
||||
} //end while
|
||||
|
||||
|
||||
return permutation;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Same algorithm as before, but without the weights given (taking default weights
|
||||
template <class Graph, class OutputIterator,
|
||||
class ColorMap, class DegreeMap,
|
||||
class PriorityMap>
|
||||
OutputIterator
|
||||
sloan_ordering(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor e,
|
||||
OutputIterator permutation,
|
||||
ColorMap color,
|
||||
DegreeMap degree,
|
||||
PriorityMap priority)
|
||||
{
|
||||
return sloan_ordering(g, s, e, permutation, color, degree, priority, WEIGHT1, WEIGHT2);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sloan algorithm without a given starting Vertex.
|
||||
//
|
||||
// This algorithm finds a good starting vertex itself to
|
||||
// compute Sloan-ordering.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
template < class Graph, class OutputIterator,
|
||||
class Color, class Degree,
|
||||
class Priority, class Weight>
|
||||
inline OutputIterator
|
||||
sloan_ordering(Graph& G,
|
||||
OutputIterator permutation,
|
||||
Color color,
|
||||
Degree degree,
|
||||
Priority priority,
|
||||
Weight W1,
|
||||
Weight W2 )
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
|
||||
Vertex s, e;
|
||||
e = sloan_start_end_vertices(G, s, color, degree);
|
||||
|
||||
return sloan_ordering(G, s, e, permutation, color, degree, priority, W1, W2);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Same as before, but without given weights (default weights are taken instead)
|
||||
template < class Graph, class OutputIterator,
|
||||
class Color, class Degree,
|
||||
class Priority >
|
||||
inline OutputIterator
|
||||
sloan_ordering(Graph& G,
|
||||
OutputIterator permutation,
|
||||
Color color,
|
||||
Degree degree,
|
||||
Priority priority)
|
||||
{
|
||||
return sloan_ordering(G, permutation, color, degree, priority, WEIGHT1, WEIGHT2);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_SLOAN_HPP
|
||||
@@ -1,127 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#ifndef BOOST_SMALLEST_LAST_VERTEX_ORDERING_HPP
|
||||
#define BOOST_SMALLEST_LAST_VERTEX_ORDERING_HPP
|
||||
/*
|
||||
The smallest-last ordering is defined for the loopless graph G with
|
||||
vertices a(j), j = 1,2,...,n where a(j) is the j-th column of A and
|
||||
with edge (a(i),a(j)) if and only if columns i and j have a
|
||||
non-zero in the same row position. The smallest-last ordering is
|
||||
determined recursively by letting list(k), k = n,...,1 be a column
|
||||
with least degree in the subgraph spanned by the un-ordered
|
||||
columns.
|
||||
*/
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/pending/bucket_sorter.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class VertexListGraph, class Order, class Degree, class Marker>
|
||||
void
|
||||
smallest_last_vertex_ordering(const VertexListGraph& G, Order order,
|
||||
Degree degree, Marker marker) {
|
||||
typedef typename graph_traits<VertexListGraph> GraphTraits;
|
||||
typedef typename GraphTraits::vertex_descriptor Vertex;
|
||||
//typedef typename GraphTraits::size_type size_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
const size_type num = num_vertices(G);
|
||||
|
||||
typedef typename vertex_property_map<VertexListGraph, vertex_index_t>::type ID;
|
||||
typedef bucket_sorter<size_type, Vertex, Degree, ID> BucketSorter;
|
||||
|
||||
BucketSorter degree_bucket_sorter(num, num, degree,
|
||||
get_vertex_property(G, vertex_index));
|
||||
|
||||
smallest_last_vertex_ordering(G, order, degree, marker, degree_bucket_sorter);
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class Order, class Degree,
|
||||
class Marker, class BucketSorter>
|
||||
void
|
||||
smallest_last_vertex_ordering(const VertexListGraph& G, Order order,
|
||||
Degree degree, Marker marker,
|
||||
BucketSorter& degree_buckets) {
|
||||
typedef typename graph_traits<VertexListGraph> GraphTraits;
|
||||
typedef typename GraphTraits::vertex_descriptor Vertex;
|
||||
//typedef typename GraphTraits::size_type size_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
const size_type num = num_vertices(G);
|
||||
|
||||
typename GraphTraits::vertex_iterator v, vend;
|
||||
for (boost::tie(v, vend) = vertices(G); v != vend; ++v) {
|
||||
put(marker, *v, num);
|
||||
put(degree, *v, out_degree(*v, G));
|
||||
degree_buckets.push(*v);
|
||||
}
|
||||
|
||||
size_type minimum_degree = 1;
|
||||
size_type current_order = num - 1;
|
||||
|
||||
while ( 1 ) {
|
||||
typedef typename BucketSorter::stack MDStack;
|
||||
MDStack minimum_degree_stack = degree_buckets[minimum_degree];
|
||||
while (minimum_degree_stack.empty())
|
||||
minimum_degree_stack = degree_buckets[++minimum_degree];
|
||||
|
||||
Vertex node = minimum_degree_stack.top();
|
||||
put(order, current_order, node);
|
||||
|
||||
if ( current_order == 0 ) //find all vertices
|
||||
break;
|
||||
|
||||
minimum_degree_stack.pop();
|
||||
put(marker, node, 0); //node has been ordered.
|
||||
|
||||
typename GraphTraits::adjacency_iterator v, vend;
|
||||
for (boost::tie(v,vend) = adjacent_vertices(node, G); v != vend; ++v)
|
||||
|
||||
if ( get(marker,*v) > current_order ) { //*v is unordered vertex
|
||||
put(marker, *v, current_order); //mark the columns adjacent to node
|
||||
|
||||
//It is possible minimum degree goes down
|
||||
//Here we keep tracking it.
|
||||
put(degree, *v, get(degree, *v) - 1);
|
||||
BOOST_USING_STD_MIN();
|
||||
minimum_degree = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_degree, get(degree, *v));
|
||||
|
||||
//update the position of *v in the bucket sorter
|
||||
degree_buckets.update(*v);
|
||||
}
|
||||
|
||||
current_order--;
|
||||
}
|
||||
|
||||
//at this point, order[i] = v_i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,581 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997-2001 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
#ifndef BOOST_GRAPH_SGB_GRAPH_HPP
|
||||
#define BOOST_GRAPH_SGB_GRAPH_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
|
||||
// Thanks to Andreas Scherer for numerous suggestions and fixes!
|
||||
|
||||
// This file adapts a Stanford GraphBase (SGB) Graph pointer into a
|
||||
// VertexListGraph. Note that a graph adaptor class is not needed,
|
||||
// SGB's Graph* is used as is. The VertexListGraph concept is fulfilled by
|
||||
// defining the appropriate non-member functions for Graph*.
|
||||
//
|
||||
// The PROTOTYPES change file extensions to SGB must be applied so
|
||||
// that the SGB functions have real prototypes which are necessary for
|
||||
// the C++ compiler. To apply the PROTOTYPES extensions, before you do
|
||||
// "make tests install" for SGB do "ln -s PROTOTYPES/* ." to the SGB
|
||||
// root directory (or just copy all the files from the PROTOTYPES
|
||||
// directory to the SGB root directory).
|
||||
//
|
||||
extern "C" {
|
||||
// We include all global definitions for the general stuff
|
||||
// of The Stanford GraphBase and its various graph generator
|
||||
// functions by reading all SGB headerfiles as in section 2 of
|
||||
// the "test_sample" program.
|
||||
#include <gb_graph.h> /* SGB data structures */
|
||||
#include <gb_io.h> /* SGB input/output routines */
|
||||
#include <gb_flip.h> /* random number generator */
|
||||
#include <gb_dijk.h> /* routines for shortest paths */
|
||||
#include <gb_basic.h> /* the basic graph operations */
|
||||
#undef empty /* avoid name clash with C++ standard library */
|
||||
inline Graph* empty( long n ) /* and provide workaround */
|
||||
{ return board(n,0L,0L,0L,2L,0L,0L); }
|
||||
#include <gb_books.h> /* graphs based on literature */
|
||||
#include <gb_econ.h> /* graphs based on economic data */
|
||||
#include <gb_games.h> /* graphs based on football scores */
|
||||
#include <gb_gates.h> /* graphs based on logic circuits */
|
||||
#undef val /* avoid name clash with g++ headerfile stl_tempbuf.h */
|
||||
// val ==> Vertex::x.I
|
||||
#include <gb_lisa.h> /* graphs based on Mona Lisa */
|
||||
#include <gb_miles.h> /* graphs based on mileage data */
|
||||
#include <gb_plane.h> /* planar graphs */
|
||||
#include <gb_raman.h> /* Ramanujan graphs */
|
||||
#include <gb_rand.h> /* random graphs */
|
||||
#include <gb_roget.h> /* graphs based on Roget's Thesaurus */
|
||||
#include <gb_save.h> /* we save results in ASCII format */
|
||||
#include <gb_words.h> /* five-letter-word graphs */
|
||||
#undef weight /* avoid name clash with BGL parameter */
|
||||
// weight ==> Vertex::u.I
|
||||
}
|
||||
|
||||
namespace boost {
|
||||
class sgb_edge;
|
||||
}
|
||||
|
||||
class sgb_out_edge_iterator;
|
||||
class sgb_adj_iterator;
|
||||
class sgb_vertex_iterator;
|
||||
|
||||
namespace boost {
|
||||
typedef Graph* sgb_graph_ptr;
|
||||
typedef const Graph* sgb_const_graph_ptr;
|
||||
|
||||
struct sgb_traversal_tag :
|
||||
public virtual vertex_list_graph_tag,
|
||||
public virtual incidence_graph_tag,
|
||||
public virtual adjacency_graph_tag { };
|
||||
|
||||
template <> struct graph_traits<sgb_graph_ptr> {
|
||||
typedef Vertex* vertex_descriptor;
|
||||
typedef boost::sgb_edge edge_descriptor;
|
||||
typedef sgb_out_edge_iterator out_edge_iterator;
|
||||
typedef void in_edge_iterator;
|
||||
typedef sgb_adj_iterator adjacency_iterator;
|
||||
typedef sgb_vertex_iterator vertex_iterator;
|
||||
typedef void edge_iterator;
|
||||
typedef long vertices_size_type;
|
||||
typedef long edge_size_type;
|
||||
typedef long degree_size_type;
|
||||
typedef directed_tag directed_category;
|
||||
typedef sgb_traversal_tag traversal_category;
|
||||
typedef allow_parallel_edge_tag edge_parallel_category;
|
||||
};
|
||||
template <> struct graph_traits<sgb_const_graph_ptr> {
|
||||
typedef Vertex* vertex_descriptor;
|
||||
typedef boost::sgb_edge edge_descriptor;
|
||||
typedef sgb_out_edge_iterator out_edge_iterator;
|
||||
typedef void in_edge_iterator;
|
||||
typedef sgb_adj_iterator adjacency_iterator;
|
||||
typedef sgb_vertex_iterator vertex_iterator;
|
||||
typedef void edge_iterator;
|
||||
typedef long vertices_size_type;
|
||||
typedef long edge_size_type;
|
||||
typedef long degree_size_type;
|
||||
typedef directed_tag directed_category;
|
||||
typedef sgb_traversal_tag traversal_category;
|
||||
typedef allow_parallel_edge_tag edge_parallel_category;
|
||||
};
|
||||
}
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct edge_length_t {
|
||||
typedef edge_property_tag kind;
|
||||
};
|
||||
|
||||
// We could just use Arc* as the edge descriptor type, but
|
||||
// we want to add the source(e,g) function which requires
|
||||
// that we carry along a pointer to the source vertex.
|
||||
class sgb_edge {
|
||||
typedef sgb_edge self;
|
||||
public:
|
||||
sgb_edge() : _arc(0), _src(0) { }
|
||||
sgb_edge(Arc* a, Vertex* s) : _arc(a), _src(s) { }
|
||||
friend Vertex* source(self e, sgb_const_graph_ptr) { return e._src; }
|
||||
friend Vertex* target(self e, sgb_const_graph_ptr) { return e._arc->tip; }
|
||||
friend bool operator==(const self& a, const self& b) {
|
||||
return a._arc == b._arc; }
|
||||
friend bool operator!=(const self& a, const self& b) {
|
||||
return a._arc != b._arc; }
|
||||
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
||||
template <class Ref> friend class sgb_edge_length_map;
|
||||
template <class Tag, class Ref> friend class sgb_edge_util_map;
|
||||
friend long get(edge_length_t, const sgb_graph_ptr&, const sgb_edge& key);
|
||||
friend long get(edge_length_t, const sgb_const_graph_ptr&, const sgb_edge& key);
|
||||
friend void put(edge_length_t, sgb_graph_ptr&, const sgb_edge& key, long value);
|
||||
protected:
|
||||
#endif
|
||||
Arc* _arc;
|
||||
Vertex* _src;
|
||||
};
|
||||
} // namespace boost
|
||||
|
||||
class sgb_out_edge_iterator
|
||||
: public boost::forward_iterator_helper<
|
||||
sgb_out_edge_iterator, boost::sgb_edge,
|
||||
std::ptrdiff_t, boost::sgb_edge*, boost::sgb_edge>
|
||||
{
|
||||
typedef sgb_out_edge_iterator self;
|
||||
public:
|
||||
sgb_out_edge_iterator() : _src(0), _arc(0) {}
|
||||
sgb_out_edge_iterator(Vertex* s, Arc* d) : _src(s), _arc(d) {}
|
||||
boost::sgb_edge operator*() { return boost::sgb_edge(_arc, _src); }
|
||||
self& operator++() { _arc = _arc->next; return *this; }
|
||||
friend bool operator==(const self& x, const self& y) {
|
||||
return x._arc == y._arc; }
|
||||
protected:
|
||||
Vertex* _src;
|
||||
Arc* _arc;
|
||||
};
|
||||
|
||||
class sgb_adj_iterator
|
||||
: public boost::forward_iterator_helper<
|
||||
sgb_adj_iterator, Vertex*, std::ptrdiff_t, Vertex**,Vertex*>
|
||||
{
|
||||
typedef sgb_adj_iterator self;
|
||||
public:
|
||||
sgb_adj_iterator() : _arc(0) {}
|
||||
sgb_adj_iterator(Arc* d) : _arc(d) {}
|
||||
Vertex* operator*() { return _arc->tip; }
|
||||
self& operator++() { _arc = _arc->next; return *this; }
|
||||
friend bool operator==(const self& x, const self& y) {
|
||||
return x._arc == y._arc; }
|
||||
protected:
|
||||
Arc* _arc;
|
||||
};
|
||||
|
||||
// The reason we have this instead of just using Vertex* is that we
|
||||
// want to use Vertex* as the vertex_descriptor instead of just
|
||||
// Vertex, which avoids problems with boost passing vertex descriptors
|
||||
// by value and how that interacts with the sgb_vertex_id_map.
|
||||
class sgb_vertex_iterator
|
||||
: public boost::forward_iterator_helper<
|
||||
sgb_vertex_iterator, Vertex*, std::ptrdiff_t, Vertex**, Vertex*>
|
||||
{
|
||||
typedef sgb_vertex_iterator self;
|
||||
public:
|
||||
sgb_vertex_iterator() : _v(0) { }
|
||||
sgb_vertex_iterator(Vertex* v) : _v(v) { }
|
||||
Vertex* operator*() { return _v; }
|
||||
self& operator++() { ++_v; return *this; }
|
||||
friend bool operator==(const self& x, const self& y) {
|
||||
return x._v == y._v; }
|
||||
protected:
|
||||
Vertex* _v;
|
||||
};
|
||||
|
||||
namespace boost {
|
||||
|
||||
inline std::pair<sgb_vertex_iterator,sgb_vertex_iterator>
|
||||
vertices(sgb_const_graph_ptr g)
|
||||
{
|
||||
return std::make_pair(sgb_vertex_iterator(g->vertices),
|
||||
sgb_vertex_iterator(g->vertices + g->n));
|
||||
}
|
||||
|
||||
inline std::pair<sgb_out_edge_iterator,sgb_out_edge_iterator>
|
||||
out_edges(Vertex* u, sgb_const_graph_ptr)
|
||||
{
|
||||
return std::make_pair( sgb_out_edge_iterator(u, u->arcs),
|
||||
sgb_out_edge_iterator(u, 0) );
|
||||
}
|
||||
|
||||
inline boost::graph_traits<sgb_graph_ptr>::degree_size_type
|
||||
out_degree(Vertex* u, sgb_const_graph_ptr g)
|
||||
{
|
||||
boost::graph_traits<sgb_graph_ptr>::out_edge_iterator i, i_end;
|
||||
boost::tie(i, i_end) = out_edges(u, g);
|
||||
return std::distance(i, i_end);
|
||||
}
|
||||
|
||||
// in_edges?
|
||||
|
||||
inline std::pair<sgb_adj_iterator,sgb_adj_iterator>
|
||||
adjacent_vertices(Vertex* u, sgb_const_graph_ptr)
|
||||
{
|
||||
return std::make_pair( sgb_adj_iterator(u->arcs),
|
||||
sgb_adj_iterator(0) );
|
||||
}
|
||||
|
||||
inline long num_vertices(sgb_const_graph_ptr g) { return g->n; }
|
||||
inline long num_edges(sgb_const_graph_ptr g) { return g->m; }
|
||||
|
||||
inline Vertex* vertex(long v, sgb_const_graph_ptr g)
|
||||
{ return g->vertices + v; }
|
||||
|
||||
// Various Property Maps
|
||||
|
||||
// Vertex ID
|
||||
class sgb_vertex_id_map
|
||||
: public boost::put_get_helper<long, sgb_vertex_id_map>
|
||||
{
|
||||
public:
|
||||
typedef boost::readable_property_map_tag category;
|
||||
typedef long value_type;
|
||||
typedef long reference;
|
||||
typedef Vertex* key_type;
|
||||
sgb_vertex_id_map() : _g(0) { }
|
||||
sgb_vertex_id_map(sgb_graph_ptr g) : _g(g) { }
|
||||
long operator[](Vertex* v) const { return v - _g->vertices; }
|
||||
protected:
|
||||
sgb_graph_ptr _g;
|
||||
};
|
||||
inline sgb_vertex_id_map get(vertex_index_t, sgb_graph_ptr g) {
|
||||
return sgb_vertex_id_map(g);
|
||||
}
|
||||
|
||||
// Vertex Name
|
||||
class sgb_vertex_name_map
|
||||
: public boost::put_get_helper<char*, sgb_vertex_name_map>
|
||||
{
|
||||
public:
|
||||
typedef boost::readable_property_map_tag category;
|
||||
typedef char* value_type;
|
||||
typedef char* reference;
|
||||
typedef Vertex* key_type;
|
||||
char* operator[](Vertex* v) const { return v->name; }
|
||||
};
|
||||
inline sgb_vertex_name_map get(vertex_name_t, sgb_graph_ptr) {
|
||||
return sgb_vertex_name_map();
|
||||
}
|
||||
|
||||
// Vertex Property Tags
|
||||
#define SGB_PROPERTY_TAG(KIND,TAG) \
|
||||
template <class T> struct TAG##_property { \
|
||||
typedef KIND##_property_tag kind; \
|
||||
typedef T type; \
|
||||
};
|
||||
SGB_PROPERTY_TAG(vertex, u)
|
||||
SGB_PROPERTY_TAG(vertex, v)
|
||||
SGB_PROPERTY_TAG(vertex, w)
|
||||
SGB_PROPERTY_TAG(vertex, x)
|
||||
SGB_PROPERTY_TAG(vertex, y)
|
||||
SGB_PROPERTY_TAG(vertex, z)
|
||||
|
||||
// Edge Property Tags
|
||||
SGB_PROPERTY_TAG(edge, a)
|
||||
SGB_PROPERTY_TAG(edge, b)
|
||||
|
||||
// Various Utility Maps
|
||||
|
||||
// helpers
|
||||
inline Vertex*& get_util(util& u, Vertex*) { return u.V; }
|
||||
inline Arc*& get_util(util& u, Arc*) { return u.A; }
|
||||
inline sgb_graph_ptr& get_util(util& u, sgb_graph_ptr) { return u.G; }
|
||||
inline char*& get_util(util& u, char*) { return u.S; }
|
||||
inline long& get_util(util& u, long) { return u.I; }
|
||||
|
||||
#define SGB_GET_UTIL_FIELD(KIND,X) \
|
||||
template <class T> \
|
||||
inline T& get_util_field(KIND* k, X##_property<T>) { \
|
||||
return get_util(k->X, T()); }
|
||||
|
||||
SGB_GET_UTIL_FIELD(Vertex, u)
|
||||
SGB_GET_UTIL_FIELD(Vertex, v)
|
||||
SGB_GET_UTIL_FIELD(Vertex, w)
|
||||
SGB_GET_UTIL_FIELD(Vertex, x)
|
||||
SGB_GET_UTIL_FIELD(Vertex, y)
|
||||
SGB_GET_UTIL_FIELD(Vertex, z)
|
||||
|
||||
SGB_GET_UTIL_FIELD(Arc, a)
|
||||
SGB_GET_UTIL_FIELD(Arc, b)
|
||||
|
||||
// Vertex Utility Map
|
||||
template <class Tag, class Ref>
|
||||
class sgb_vertex_util_map
|
||||
: public boost::put_get_helper<Ref, sgb_vertex_util_map<Tag, Ref> >
|
||||
{
|
||||
public:
|
||||
typedef boost::lvalue_property_map_tag category;
|
||||
typedef typename Tag::type value_type;
|
||||
typedef Vertex* key_type;
|
||||
typedef Ref reference;
|
||||
reference operator[](Vertex* v) const {
|
||||
return get_util_field(v, Tag());
|
||||
}
|
||||
};
|
||||
|
||||
// Edge Utility Map
|
||||
template <class Tag, class Ref>
|
||||
class sgb_edge_util_map
|
||||
: public boost::put_get_helper<Ref, sgb_edge_util_map<Tag, Ref> >
|
||||
{
|
||||
public:
|
||||
typedef boost::lvalue_property_map_tag category;
|
||||
typedef typename Tag::type value_type;
|
||||
typedef Vertex* key_type;
|
||||
typedef Ref reference;
|
||||
reference operator[](const sgb_edge& e) const {
|
||||
return get_util_field(e._arc, Tag());
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
template <class Tag>
|
||||
inline sgb_vertex_util_map<Tag, const typename Tag::type&>
|
||||
get_property_map(Tag, const sgb_graph_ptr& g, vertex_property_tag) {
|
||||
return sgb_vertex_util_map<Tag, const typename Tag::type&>();
|
||||
}
|
||||
template <class Tag>
|
||||
inline sgb_vertex_util_map<Tag, typename Tag::type&>
|
||||
get_property_map(Tag, sgb_graph_ptr& g, vertex_property_tag) {
|
||||
return sgb_vertex_util_map<Tag, typename Tag::type&>();
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
inline sgb_edge_util_map<Tag, const typename Tag::type&>
|
||||
get_property_map(Tag, const sgb_graph_ptr& g, edge_property_tag) {
|
||||
return sgb_edge_util_map<Tag, const typename Tag::type&>();
|
||||
}
|
||||
template <class Tag>
|
||||
inline sgb_edge_util_map<Tag, typename Tag::type&>
|
||||
get_property_map(Tag, sgb_graph_ptr& g, edge_property_tag) {
|
||||
return sgb_edge_util_map<Tag, typename Tag::type&>();
|
||||
}
|
||||
|
||||
#endif // ! BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
// Edge Length Access
|
||||
template <class Ref>
|
||||
class sgb_edge_length_map
|
||||
: public boost::put_get_helper<Ref, sgb_edge_length_map<Ref> >
|
||||
{
|
||||
public:
|
||||
typedef boost::lvalue_property_map_tag category;
|
||||
typedef long value_type;
|
||||
typedef sgb_edge key_type;
|
||||
typedef Ref reference;
|
||||
reference operator[](const sgb_edge& e) const {
|
||||
return e._arc->len;
|
||||
}
|
||||
};
|
||||
|
||||
inline sgb_edge_length_map<const long&>
|
||||
get(edge_length_t, const sgb_graph_ptr&) {
|
||||
return sgb_edge_length_map<const long&>();
|
||||
}
|
||||
inline sgb_edge_length_map<const long&>
|
||||
get(edge_length_t, const sgb_const_graph_ptr&) {
|
||||
return sgb_edge_length_map<const long&>();
|
||||
}
|
||||
inline sgb_edge_length_map<long&>
|
||||
get(edge_length_t, sgb_graph_ptr&) {
|
||||
return sgb_edge_length_map<long&>();
|
||||
}
|
||||
inline long
|
||||
get(edge_length_t, const sgb_graph_ptr&, const sgb_edge& key) {
|
||||
return key._arc->len;
|
||||
}
|
||||
inline long
|
||||
get(edge_length_t, const sgb_const_graph_ptr&, const sgb_edge& key) {
|
||||
return key._arc->len;
|
||||
}
|
||||
inline void
|
||||
put(edge_length_t, sgb_graph_ptr&, const sgb_edge& key, long value)
|
||||
{
|
||||
key._arc->len = value;
|
||||
}
|
||||
|
||||
// Property Map Traits Classes
|
||||
template <>
|
||||
struct property_map<sgb_graph_ptr, edge_length_t> {
|
||||
typedef sgb_edge_length_map<long&> type;
|
||||
typedef sgb_edge_length_map<const long&> const_type;
|
||||
};
|
||||
template <>
|
||||
struct property_map<sgb_graph_ptr, vertex_index_t> {
|
||||
typedef sgb_vertex_id_map type;
|
||||
typedef sgb_vertex_id_map const_type;
|
||||
};
|
||||
template <>
|
||||
struct property_map<sgb_graph_ptr, vertex_name_t> {
|
||||
typedef sgb_vertex_name_map type;
|
||||
typedef sgb_vertex_name_map const_type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct property_map<sgb_const_graph_ptr, edge_length_t> {
|
||||
typedef sgb_edge_length_map<const long&> const_type;
|
||||
};
|
||||
template <>
|
||||
struct property_map<sgb_const_graph_ptr, vertex_index_t> {
|
||||
typedef sgb_vertex_id_map const_type;
|
||||
};
|
||||
template <>
|
||||
struct property_map<sgb_const_graph_ptr, vertex_name_t> {
|
||||
typedef sgb_vertex_name_map const_type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
|
||||
namespace detail {
|
||||
template <class Kind, class PropertyTag>
|
||||
struct sgb_choose_property_map { };
|
||||
template <class PropertyTag>
|
||||
struct sgb_choose_property_map<vertex_property_tag, PropertyTag> {
|
||||
typedef typename PropertyTag::type value_type;
|
||||
typedef sgb_vertex_util_map<PropertyTag, value_type&> type;
|
||||
typedef sgb_vertex_util_map<PropertyTag, const value_type&> const_type;
|
||||
};
|
||||
template <class PropertyTag>
|
||||
struct sgb_choose_property_map<edge_property_tag, PropertyTag> {
|
||||
typedef typename PropertyTag::type value_type;
|
||||
typedef sgb_edge_util_map<PropertyTag, value_type&> type;
|
||||
typedef sgb_edge_util_map<PropertyTag, const value_type&> const_type;
|
||||
};
|
||||
} // namespace detail
|
||||
template <class PropertyTag>
|
||||
struct property_map<sgb_graph_ptr, PropertyTag> {
|
||||
typedef typename property_kind<PropertyTag>::type Kind;
|
||||
typedef detail::sgb_choose_property_map<Kind, PropertyTag> Choice;
|
||||
typedef typename Choice::type type;
|
||||
typedef typename Choice::const_type const_type;
|
||||
};
|
||||
template <class PropertyTag>
|
||||
struct property_map<sgb_const_graph_ptr, PropertyTag> {
|
||||
typedef typename property_kind<PropertyTag>::type Kind;
|
||||
typedef detail::sgb_choose_property_map<Kind, PropertyTag> Choice;
|
||||
typedef typename Choice::const_type const_type;
|
||||
};
|
||||
|
||||
#define SGB_UTIL_ACCESSOR(KIND,X) \
|
||||
template <class T> \
|
||||
inline sgb_##KIND##_util_map< X##_property<T>, T&> \
|
||||
get(X##_property<T>, sgb_graph_ptr&) { \
|
||||
return sgb_##KIND##_util_map< X##_property<T>, T&>(); \
|
||||
} \
|
||||
template <class T> \
|
||||
inline sgb_##KIND##_util_map< X##_property<T>, const T&> \
|
||||
get(X##_property<T>, const sgb_graph_ptr&) { \
|
||||
return sgb_##KIND##_util_map< X##_property<T>, const T&>(); \
|
||||
} \
|
||||
template <class T> \
|
||||
inline sgb_##KIND##_util_map< X##_property<T>, const T&> \
|
||||
get(X##_property<T>, const sgb_const_graph_ptr&) { \
|
||||
return sgb_##KIND##_util_map< X##_property<T>, const T&>(); \
|
||||
} \
|
||||
template <class T, class Key> \
|
||||
inline typename \
|
||||
sgb_##KIND##_util_map< X##_property<T>, const T&>::value_type \
|
||||
get(X##_property<T>, const sgb_graph_ptr&, const Key& key) { \
|
||||
return sgb_##KIND##_util_map< X##_property<T>, const T&>()[key]; \
|
||||
} \
|
||||
template <class T, class Key> \
|
||||
inline typename \
|
||||
sgb_##KIND##_util_map< X##_property<T>, const T&>::value_type \
|
||||
get(X##_property<T>, const sgb_const_graph_ptr&, const Key& key) { \
|
||||
return sgb_##KIND##_util_map< X##_property<T>, const T&>()[key]; \
|
||||
} \
|
||||
template <class T, class Key, class Value> \
|
||||
inline void \
|
||||
put(X##_property<T>, sgb_graph_ptr&, const Key& key, const Value& value) { \
|
||||
sgb_##KIND##_util_map< X##_property<T>, T&>()[key] = value; \
|
||||
}
|
||||
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
#define SGB_UTIL_ACCESSOR_TYPE(KIND,TAG,TYPE) \
|
||||
inline sgb_##KIND##_util_map< TAG<TYPE>, TYPE& > \
|
||||
get(TAG<TYPE>, sgb_graph_ptr&) { \
|
||||
return sgb_##KIND##_util_map< TAG<TYPE>, TYPE& >(); \
|
||||
} \
|
||||
inline sgb_##KIND##_util_map< TAG<TYPE>, const TYPE& > \
|
||||
get(TAG<TYPE>, const sgb_graph_ptr&) { \
|
||||
return sgb_##KIND##_util_map< TAG<TYPE>, const TYPE& >(); \
|
||||
} \
|
||||
inline sgb_##KIND##_util_map< TAG<TYPE>, const TYPE& > \
|
||||
get(TAG<TYPE>, const sgb_const_graph_ptr&) { \
|
||||
return sgb_##KIND##_util_map< TAG<TYPE>, const TYPE& >(); \
|
||||
} \
|
||||
template <class Key> \
|
||||
inline typename sgb_##KIND##_util_map< TAG<TYPE>, const TYPE& >::value_type \
|
||||
get(TAG<TYPE>, const sgb_graph_ptr&, const Key& key) { \
|
||||
return sgb_##KIND##_util_map< TAG<TYPE>, const TYPE& >()[key]; \
|
||||
} \
|
||||
template <class Key> \
|
||||
inline typename sgb_##KIND##_util_map< TAG<TYPE>, const TYPE& >::value_type \
|
||||
get(TAG<TYPE>, const sgb_const_graph_ptr&, const Key& key) { \
|
||||
return sgb_##KIND##_util_map< TAG<TYPE>, const TYPE& >()[key]; \
|
||||
} \
|
||||
template <class Key, class Value> \
|
||||
inline void \
|
||||
put(TAG<TYPE>, sgb_graph_ptr&, const Key& key, const Value& value) { \
|
||||
sgb_##KIND##_util_map< TAG<TYPE>, TYPE& >()[key] = value; \
|
||||
} \
|
||||
template <> struct property_map<sgb_graph_ptr, TAG<TYPE> > { \
|
||||
typedef sgb_##KIND##_util_map< TAG<TYPE>, TYPE&> type; \
|
||||
typedef sgb_##KIND##_util_map< TAG<TYPE>, const TYPE&> const_type; \
|
||||
}
|
||||
|
||||
#define SGB_UTIL_ACCESSOR(KIND,TAG) \
|
||||
SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, Vertex*); \
|
||||
SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, Arc*); \
|
||||
SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, sgb_graph_ptr); \
|
||||
SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, long); \
|
||||
SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, char*);
|
||||
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
SGB_UTIL_ACCESSOR(vertex, u)
|
||||
SGB_UTIL_ACCESSOR(vertex, v)
|
||||
SGB_UTIL_ACCESSOR(vertex, w)
|
||||
SGB_UTIL_ACCESSOR(vertex, x)
|
||||
SGB_UTIL_ACCESSOR(vertex, y)
|
||||
SGB_UTIL_ACCESSOR(vertex, z)
|
||||
|
||||
SGB_UTIL_ACCESSOR(edge, a)
|
||||
SGB_UTIL_ACCESSOR(edge, b)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_SGB_GRAPH_HPP
|
||||
@@ -1,350 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
#ifndef BOOST_GRAPH_STRONG_COMPONENTS_HPP
|
||||
#define BOOST_GRAPH_STRONG_COMPONENTS_HPP
|
||||
|
||||
#include <stack>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
#include <boost/type_traits/conversion_traits.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//==========================================================================
|
||||
// This is Tarjan's algorithm for strongly connected components
|
||||
// from his paper "Depth first search and linear graph algorithms".
|
||||
// It calculates the components in a single application of DFS.
|
||||
// We implement the algorithm as a dfs-visitor.
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename ComponentMap, typename RootMap, typename DiscoverTime,
|
||||
typename Stack>
|
||||
class tarjan_scc_visitor : public dfs_visitor<>
|
||||
{
|
||||
typedef typename property_traits<ComponentMap>::value_type comp_type;
|
||||
typedef typename property_traits<DiscoverTime>::value_type time_type;
|
||||
public:
|
||||
tarjan_scc_visitor(ComponentMap comp_map, RootMap r, DiscoverTime d,
|
||||
comp_type& c_, Stack& s_)
|
||||
: c(c_), comp(comp_map), root(r), discover_time(d),
|
||||
dfs_time(time_type()), s(s_) { }
|
||||
|
||||
template <typename Graph>
|
||||
void discover_vertex(typename graph_traits<Graph>::vertex_descriptor v,
|
||||
const Graph&) {
|
||||
put(root, v, v);
|
||||
put(comp, v, (std::numeric_limits<comp_type>::max)());
|
||||
put(discover_time, v, dfs_time++);
|
||||
s.push(v);
|
||||
}
|
||||
template <typename Graph>
|
||||
void finish_vertex(typename graph_traits<Graph>::vertex_descriptor v,
|
||||
const Graph& g) {
|
||||
typename graph_traits<Graph>::vertex_descriptor w;
|
||||
typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) {
|
||||
w = target(*ei, g);
|
||||
if (get(comp, w) == (std::numeric_limits<comp_type>::max)())
|
||||
put(root, v, this->min_discover_time(get(root,v), get(root,w)));
|
||||
}
|
||||
if (get(root, v) == v) {
|
||||
do {
|
||||
w = s.top(); s.pop();
|
||||
put(comp, w, c);
|
||||
} while (w != v);
|
||||
++c;
|
||||
}
|
||||
}
|
||||
private:
|
||||
template <typename Vertex>
|
||||
Vertex min_discover_time(Vertex u, Vertex v) {
|
||||
return get(discover_time, u) < get(discover_time,v) ? u : v;
|
||||
}
|
||||
|
||||
comp_type& c;
|
||||
ComponentMap comp;
|
||||
RootMap root;
|
||||
DiscoverTime discover_time;
|
||||
time_type dfs_time;
|
||||
Stack& s;
|
||||
};
|
||||
|
||||
template <class Graph, class ComponentMap, class RootMap,
|
||||
class DiscoverTime, class P, class T, class R>
|
||||
typename property_traits<ComponentMap>::value_type
|
||||
strong_components_impl
|
||||
(const Graph& g, // Input
|
||||
ComponentMap comp, // Output
|
||||
// Internal record keeping
|
||||
RootMap root,
|
||||
DiscoverTime discover_time,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
function_requires< ReadWritePropertyMapConcept<ComponentMap, Vertex> >();
|
||||
function_requires< ReadWritePropertyMapConcept<RootMap, Vertex> >();
|
||||
typedef typename property_traits<RootMap>::value_type RootV;
|
||||
function_requires< ConvertibleConcept<RootV, Vertex> >();
|
||||
function_requires< ReadWritePropertyMapConcept<DiscoverTime, Vertex> >();
|
||||
|
||||
typename property_traits<ComponentMap>::value_type total = 0;
|
||||
|
||||
std::stack<Vertex> s;
|
||||
detail::tarjan_scc_visitor<ComponentMap, RootMap, DiscoverTime,
|
||||
std::stack<Vertex> >
|
||||
vis(comp, root, discover_time, total, s);
|
||||
depth_first_search(g, params.visitor(vis));
|
||||
return total;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// The dispatch functions handle the defaults for the rank and discover
|
||||
// time property maps.
|
||||
// dispatch with class specialization to avoid VC++ bug
|
||||
|
||||
template <class DiscoverTimeMap>
|
||||
struct strong_comp_dispatch2 {
|
||||
template <class Graph, class ComponentMap, class RootMap, class P, class T, class R>
|
||||
inline static typename property_traits<ComponentMap>::value_type
|
||||
apply(const Graph& g,
|
||||
ComponentMap comp,
|
||||
RootMap r_map,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
DiscoverTimeMap time_map)
|
||||
{
|
||||
return strong_components_impl(g, comp, r_map, time_map, params);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct strong_comp_dispatch2<detail::error_property_not_found> {
|
||||
template <class Graph, class ComponentMap, class RootMap,
|
||||
class P, class T, class R>
|
||||
inline static typename property_traits<ComponentMap>::value_type
|
||||
apply(const Graph& g,
|
||||
ComponentMap comp,
|
||||
RootMap r_map,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
detail::error_property_not_found)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
||||
size_type n = num_vertices(g) > 0 ? num_vertices(g) : 1;
|
||||
std::vector<size_type> time_vec(n);
|
||||
return strong_components_impl
|
||||
(g, comp, r_map,
|
||||
make_iterator_property_map(time_vec.begin(), choose_const_pmap
|
||||
(get_param(params, vertex_index),
|
||||
g, vertex_index), time_vec[0]),
|
||||
params);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Graph, class ComponentMap, class RootMap,
|
||||
class P, class T, class R, class DiscoverTimeMap>
|
||||
inline typename property_traits<ComponentMap>::value_type
|
||||
scc_helper2(const Graph& g,
|
||||
ComponentMap comp,
|
||||
RootMap r_map,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
DiscoverTimeMap time_map)
|
||||
{
|
||||
return strong_comp_dispatch2<DiscoverTimeMap>::apply(g, comp, r_map, params, time_map);
|
||||
}
|
||||
|
||||
template <class RootMap>
|
||||
struct strong_comp_dispatch1 {
|
||||
|
||||
template <class Graph, class ComponentMap, class P, class T, class R>
|
||||
inline static typename property_traits<ComponentMap>::value_type
|
||||
apply(const Graph& g,
|
||||
ComponentMap comp,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
RootMap r_map)
|
||||
{
|
||||
return scc_helper2(g, comp, r_map, params, get_param(params, vertex_discover_time));
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct strong_comp_dispatch1<detail::error_property_not_found> {
|
||||
|
||||
template <class Graph, class ComponentMap,
|
||||
class P, class T, class R>
|
||||
inline static typename property_traits<ComponentMap>::value_type
|
||||
apply(const Graph& g,
|
||||
ComponentMap comp,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
detail::error_property_not_found)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typename std::vector<Vertex>::size_type
|
||||
n = num_vertices(g) > 0 ? num_vertices(g) : 1;
|
||||
std::vector<Vertex> root_vec(n);
|
||||
return scc_helper2
|
||||
(g, comp,
|
||||
make_iterator_property_map(root_vec.begin(), choose_const_pmap
|
||||
(get_param(params, vertex_index),
|
||||
g, vertex_index), root_vec[0]),
|
||||
params,
|
||||
get_param(params, vertex_discover_time));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Graph, class ComponentMap, class RootMap,
|
||||
class P, class T, class R>
|
||||
inline typename property_traits<ComponentMap>::value_type
|
||||
scc_helper1(const Graph& g,
|
||||
ComponentMap comp,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
RootMap r_map)
|
||||
{
|
||||
return detail::strong_comp_dispatch1<RootMap>::apply(g, comp, params,
|
||||
r_map);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Graph, class ComponentMap,
|
||||
class P, class T, class R>
|
||||
inline typename property_traits<ComponentMap>::value_type
|
||||
strong_components(const Graph& g, ComponentMap comp,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category DirCat;
|
||||
BOOST_STATIC_ASSERT((is_convertible<DirCat*, directed_tag*>::value == true));
|
||||
return detail::scc_helper1(g, comp, params,
|
||||
get_param(params, vertex_root_t()));
|
||||
}
|
||||
|
||||
template <class Graph, class ComponentMap>
|
||||
inline typename property_traits<ComponentMap>::value_type
|
||||
strong_components(const Graph& g, ComponentMap comp)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category DirCat;
|
||||
BOOST_STATIC_ASSERT((is_convertible<DirCat*, directed_tag*>::value == true));
|
||||
bgl_named_params<int, int> params(0);
|
||||
return strong_components(g, comp, params);
|
||||
}
|
||||
|
||||
template <typename Graph, typename ComponentMap, typename ComponentLists>
|
||||
void build_component_lists
|
||||
(const Graph& g,
|
||||
typename graph_traits<Graph>::vertices_size_type num_scc,
|
||||
ComponentMap component_number,
|
||||
ComponentLists& components)
|
||||
{
|
||||
components.resize(num_scc);
|
||||
typename graph_traits<Graph>::vertex_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
components[component_number[*vi]].push_back(*vi);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <boost/graph/transpose_graph.hpp>
|
||||
#include <boost/pending/indirect_cmp.hpp>
|
||||
#include <boost/graph/connected_components.hpp> // for components_recorder
|
||||
|
||||
namespace boost {
|
||||
|
||||
//==========================================================================
|
||||
// This is the version of strongly connected components from
|
||||
// "Intro. to Algorithms" by Cormen, Leiserson, Rivest, which was
|
||||
// adapted from "Data Structure and Algorithms" by Aho, Hopcroft,
|
||||
// and Ullman, who credit the algorithm to S.R. Kosaraju and M. Sharir.
|
||||
// The algorithm is based on computing DFS forests the graph
|
||||
// and its transpose.
|
||||
|
||||
// This algorithm is slower than Tarjan's by a constant factor, uses
|
||||
// more memory, and puts more requirements on the graph type.
|
||||
|
||||
template <class Graph, class DFSVisitor, class ComponentsMap,
|
||||
class DiscoverTime, class FinishTime,
|
||||
class ColorMap>
|
||||
typename property_traits<ComponentsMap>::value_type
|
||||
kosaraju_strong_components(Graph& G, ComponentsMap c,
|
||||
FinishTime finish_time, ColorMap color)
|
||||
{
|
||||
function_requires< MutableGraphConcept<Graph> >();
|
||||
// ...
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typename property_traits<FinishTime>::value_type time = 0;
|
||||
depth_first_search
|
||||
(G, make_dfs_visitor(stamp_times(finish_time, time, on_finish_vertex())),
|
||||
color);
|
||||
|
||||
Graph G_T(num_vertices(G));
|
||||
transpose_graph(G, G_T);
|
||||
|
||||
typedef typename property_traits<ComponentsMap>::value_type count_type;
|
||||
|
||||
count_type c_count(0);
|
||||
detail::components_recorder<ComponentsMap>
|
||||
vis(c, c_count);
|
||||
|
||||
// initialize G_T
|
||||
typename graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(G_T); ui != ui_end; ++ui)
|
||||
put(color, *ui, Color::white());
|
||||
|
||||
typedef typename property_traits<FinishTime>::value_type D;
|
||||
typedef indirect_cmp< FinishTime, std::less<D> > Compare;
|
||||
|
||||
Compare fl(finish_time);
|
||||
std::priority_queue<Vertex, std::vector<Vertex>, Compare > Q(fl);
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator i, j, iend, jend;
|
||||
tie(i, iend) = vertices(G_T);
|
||||
tie(j, jend) = vertices(G);
|
||||
for ( ; i != iend; ++i, ++j) {
|
||||
put(finish_time, *i, get(finish_time, *j));
|
||||
Q.push(*i);
|
||||
}
|
||||
|
||||
while ( !Q.empty() ) {
|
||||
Vertex u = Q.top();
|
||||
Q.pop();
|
||||
if (get(color, u) == Color::white()) {
|
||||
depth_first_visit(G_T, u, vis, color);
|
||||
++c_count;
|
||||
}
|
||||
}
|
||||
return c_count;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_STRONG_COMPONENTS_HPP
|
||||
@@ -1,861 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2001 University of Notre Dame.
|
||||
// Authors: Jeremy G. Siek and Lie-Quan Lee
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_SUBGRAPH_HPP
|
||||
#define BOOST_SUBGRAPH_HPP
|
||||
|
||||
// UNDER CONSTRUCTION
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct subgraph_tag { };
|
||||
|
||||
// Invariants of an induced subgraph:
|
||||
// - If vertex u is in subgraph g, then u must be in g.parent().
|
||||
// - If edge e is in subgraph g, then e must be in g.parent().
|
||||
// - If edge e=(u,v) is in the root graph, then edge e
|
||||
// is also in any subgraph that contains both vertex u and v.
|
||||
|
||||
// The Graph template parameter must have a vertex_index
|
||||
// and edge_index internal property. It is assumed that
|
||||
// the vertex indices are assigned automatically by the
|
||||
// graph during a call to add_vertex(). It is not
|
||||
// assumed that the edge vertices are assigned automatically,
|
||||
// they are explicitly assigned here.
|
||||
|
||||
template <typename Graph>
|
||||
class subgraph {
|
||||
typedef graph_traits<Graph> Traits;
|
||||
typedef std::list<subgraph<Graph>*> ChildrenList;
|
||||
public:
|
||||
// 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;
|
||||
|
||||
static vertex_descriptor null_vertex()
|
||||
{
|
||||
return Traits::null_vertex();
|
||||
}
|
||||
|
||||
|
||||
// IncidenceGraph requirements
|
||||
typedef typename Traits::out_edge_iterator out_edge_iterator;
|
||||
typedef typename Traits::degree_size_type degree_size_type;
|
||||
|
||||
// AdjacencyGraph requirements
|
||||
typedef typename Traits::adjacency_iterator adjacency_iterator;
|
||||
|
||||
// VertexListGraph requirements
|
||||
typedef typename Traits::vertex_iterator vertex_iterator;
|
||||
typedef typename Traits::vertices_size_type vertices_size_type;
|
||||
|
||||
// EdgeListGraph requirements
|
||||
typedef typename Traits::edge_iterator edge_iterator;
|
||||
typedef typename Traits::edges_size_type edges_size_type;
|
||||
|
||||
typedef typename Traits::in_edge_iterator in_edge_iterator;
|
||||
|
||||
typedef typename Graph::edge_property_type edge_property_type;
|
||||
typedef typename Graph::vertex_property_type vertex_property_type;
|
||||
typedef subgraph_tag graph_tag;
|
||||
typedef Graph graph_type;
|
||||
typedef typename Graph::graph_property_type graph_property_type;
|
||||
|
||||
// Constructors
|
||||
|
||||
// Create the main graph, the root of the subgraph tree
|
||||
subgraph()
|
||||
: m_parent(0), m_edge_counter(0)
|
||||
{ }
|
||||
subgraph(const graph_property_type& p)
|
||||
: m_graph(p), m_parent(0), m_edge_counter(0)
|
||||
{ }
|
||||
subgraph(vertices_size_type n,
|
||||
const graph_property_type& p = graph_property_type())
|
||||
: m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n)
|
||||
{
|
||||
typename Graph::vertex_iterator v, v_end;
|
||||
vertices_size_type i = 0;
|
||||
for (tie(v, v_end) = vertices(m_graph); v != v_end; ++v)
|
||||
m_global_vertex[i++] = *v;
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
subgraph(const subgraph& x)
|
||||
: m_graph(x.m_graph), m_parent(x.m_parent),
|
||||
m_edge_counter(x.m_edge_counter),
|
||||
m_global_vertex(x.m_global_vertex),
|
||||
m_global_edge(x.m_global_edge)
|
||||
{
|
||||
// Do a deep copy
|
||||
for (typename ChildrenList::const_iterator i = x.m_children.begin();
|
||||
i != x.m_children.end(); ++i)
|
||||
m_children.push_back(new subgraph<Graph>( **i ));
|
||||
}
|
||||
|
||||
|
||||
~subgraph() {
|
||||
for (typename ChildrenList::iterator i = m_children.begin();
|
||||
i != m_children.end(); ++i)
|
||||
delete *i;
|
||||
}
|
||||
|
||||
|
||||
// Create a subgraph
|
||||
subgraph<Graph>& create_subgraph() {
|
||||
m_children.push_back(new subgraph<Graph>());
|
||||
m_children.back()->m_parent = this;
|
||||
return *m_children.back();
|
||||
}
|
||||
|
||||
// Create a subgraph with the specified vertex set.
|
||||
template <typename VertexIterator>
|
||||
subgraph<Graph>& create_subgraph(VertexIterator first,
|
||||
VertexIterator last)
|
||||
{
|
||||
m_children.push_back(new subgraph<Graph>());
|
||||
m_children.back()->m_parent = this;
|
||||
for (; first != last; ++first)
|
||||
add_vertex(*first, *m_children.back());
|
||||
return *m_children.back();
|
||||
}
|
||||
|
||||
// local <-> global descriptor conversion functions
|
||||
vertex_descriptor local_to_global(vertex_descriptor u_local) const
|
||||
{
|
||||
return m_global_vertex[u_local];
|
||||
}
|
||||
vertex_descriptor global_to_local(vertex_descriptor u_global) const
|
||||
{
|
||||
vertex_descriptor u_local; bool in_subgraph;
|
||||
tie(u_local, in_subgraph) = this->find_vertex(u_global);
|
||||
assert(in_subgraph == true);
|
||||
return u_local;
|
||||
}
|
||||
edge_descriptor local_to_global(edge_descriptor e_local) const
|
||||
{
|
||||
return m_global_edge[get(get(edge_index, m_graph), e_local)];
|
||||
}
|
||||
edge_descriptor global_to_local(edge_descriptor e_global) const
|
||||
{
|
||||
return
|
||||
(*m_local_edge.find(get(get(edge_index, root().m_graph), e_global))).second;
|
||||
}
|
||||
|
||||
// Is vertex u (of the root graph) contained in this subgraph?
|
||||
// If so, return the matching local vertex.
|
||||
std::pair<vertex_descriptor, bool>
|
||||
find_vertex(vertex_descriptor u_global) const
|
||||
{
|
||||
typename std::map<vertex_descriptor, vertex_descriptor>::const_iterator
|
||||
i = m_local_vertex.find(u_global);
|
||||
bool valid = i != m_local_vertex.end();
|
||||
return std::make_pair((valid ? (*i).second : null_vertex()), valid);
|
||||
}
|
||||
|
||||
// Return the parent graph.
|
||||
subgraph& parent() { return *m_parent; }
|
||||
const subgraph& parent() const { return *m_parent; }
|
||||
|
||||
bool is_root() const { return m_parent == 0; }
|
||||
|
||||
// Return the root graph of the subgraph tree.
|
||||
subgraph& root() {
|
||||
if (this->is_root())
|
||||
return *this;
|
||||
else
|
||||
return m_parent->root();
|
||||
}
|
||||
const subgraph& root() const {
|
||||
if (this->is_root())
|
||||
return *this;
|
||||
else
|
||||
return m_parent->root();
|
||||
}
|
||||
|
||||
// Return the children subgraphs of this graph/subgraph.
|
||||
// Use a list of pointers because the VC++ std::list doesn't like
|
||||
// storing incomplete type.
|
||||
typedef indirect_iterator<
|
||||
typename ChildrenList::const_iterator
|
||||
, subgraph<Graph>
|
||||
, std::bidirectional_iterator_tag
|
||||
>
|
||||
children_iterator;
|
||||
|
||||
typedef indirect_iterator<
|
||||
typename ChildrenList::const_iterator
|
||||
, subgraph<Graph> const
|
||||
, std::bidirectional_iterator_tag
|
||||
>
|
||||
const_children_iterator;
|
||||
|
||||
std::pair<const_children_iterator, const_children_iterator>
|
||||
children() const
|
||||
{
|
||||
return std::make_pair(const_children_iterator(m_children.begin()),
|
||||
const_children_iterator(m_children.end()));
|
||||
}
|
||||
|
||||
std::pair<children_iterator, children_iterator>
|
||||
children()
|
||||
{
|
||||
return std::make_pair(children_iterator(m_children.begin()),
|
||||
children_iterator(m_children.end()));
|
||||
}
|
||||
|
||||
std::size_t num_children() const { return m_children.size(); }
|
||||
|
||||
// private:
|
||||
typedef typename property_map<Graph, edge_index_t>::type EdgeIndexMap;
|
||||
typedef typename property_traits<EdgeIndexMap>::value_type edge_index_type;
|
||||
BOOST_STATIC_ASSERT((!is_same<edge_index_type,
|
||||
boost::detail::error_property_not_found>::value));
|
||||
|
||||
Graph m_graph;
|
||||
subgraph<Graph>* m_parent;
|
||||
edge_index_type m_edge_counter; // for generating unique edge indices
|
||||
ChildrenList m_children;
|
||||
std::vector<vertex_descriptor> m_global_vertex; // local -> global
|
||||
std::map<vertex_descriptor, vertex_descriptor> m_local_vertex; // global -> local
|
||||
std::vector<edge_descriptor> m_global_edge; // local -> global
|
||||
std::map<edge_index_type, edge_descriptor> m_local_edge; // global -> local
|
||||
|
||||
edge_descriptor
|
||||
local_add_edge(vertex_descriptor u_local, vertex_descriptor v_local,
|
||||
edge_descriptor e_global)
|
||||
{
|
||||
edge_descriptor e_local;
|
||||
bool inserted;
|
||||
tie(e_local, inserted) = add_edge(u_local, v_local, m_graph);
|
||||
put(edge_index, m_graph, e_local, m_edge_counter++);
|
||||
m_global_edge.push_back(e_global);
|
||||
m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local;
|
||||
return e_local;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// Functions special to the Subgraph Class
|
||||
|
||||
template <typename G>
|
||||
typename subgraph<G>::vertex_descriptor
|
||||
add_vertex(typename subgraph<G>::vertex_descriptor u_global,
|
||||
subgraph<G>& g)
|
||||
{
|
||||
assert(!g.is_root());
|
||||
typename subgraph<G>::vertex_descriptor u_local, v_global, uu_global;
|
||||
typename subgraph<G>::edge_descriptor e_global;
|
||||
|
||||
u_local = add_vertex(g.m_graph);
|
||||
g.m_global_vertex.push_back(u_global);
|
||||
g.m_local_vertex[u_global] = u_local;
|
||||
|
||||
subgraph<G>& r = g.root();
|
||||
|
||||
// remember edge global and local maps
|
||||
{
|
||||
typename subgraph<G>::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = out_edges(u_global, r);
|
||||
ei != ei_end; ++ei) {
|
||||
e_global = *ei;
|
||||
v_global = target(e_global, r);
|
||||
if (g.find_vertex(v_global).second == true)
|
||||
g.local_add_edge(u_local, g.global_to_local(v_global), e_global);
|
||||
}
|
||||
}
|
||||
if (is_directed(g)) { // not necessary for undirected graph
|
||||
typename subgraph<G>::vertex_iterator vi, vi_end;
|
||||
typename subgraph<G>::out_edge_iterator ei, ei_end;
|
||||
for (tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) {
|
||||
v_global = *vi;
|
||||
if (g.find_vertex(v_global).second)
|
||||
for (tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) {
|
||||
e_global = *ei;
|
||||
uu_global = target(e_global, r);
|
||||
if (uu_global == u_global && g.find_vertex(v_global).second)
|
||||
g.local_add_edge(g.global_to_local(v_global), u_local, e_global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return u_local;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Functions required by the IncidenceGraph concept
|
||||
|
||||
template <typename G>
|
||||
std::pair<typename graph_traits<G>::out_edge_iterator,
|
||||
typename graph_traits<G>::out_edge_iterator>
|
||||
out_edges(typename graph_traits<G>::vertex_descriptor u_local,
|
||||
const subgraph<G>& g)
|
||||
{ return out_edges(u_local, g.m_graph); }
|
||||
|
||||
template <typename G>
|
||||
typename graph_traits<G>::degree_size_type
|
||||
out_degree(typename graph_traits<G>::vertex_descriptor u_local,
|
||||
const subgraph<G>& g)
|
||||
{ return out_degree(u_local, g.m_graph); }
|
||||
|
||||
template <typename G>
|
||||
typename graph_traits<G>::vertex_descriptor
|
||||
source(typename graph_traits<G>::edge_descriptor e_local,
|
||||
const subgraph<G>& g)
|
||||
{ return source(e_local, g.m_graph); }
|
||||
|
||||
template <typename G>
|
||||
typename graph_traits<G>::vertex_descriptor
|
||||
target(typename graph_traits<G>::edge_descriptor e_local,
|
||||
const subgraph<G>& g)
|
||||
{ return target(e_local, g.m_graph); }
|
||||
|
||||
//===========================================================================
|
||||
// Functions required by the BidirectionalGraph concept
|
||||
|
||||
template <typename G>
|
||||
std::pair<typename graph_traits<G>::in_edge_iterator,
|
||||
typename graph_traits<G>::in_edge_iterator>
|
||||
in_edges(typename graph_traits<G>::vertex_descriptor u_local,
|
||||
const subgraph<G>& g)
|
||||
{ return in_edges(u_local, g.m_graph); }
|
||||
|
||||
template <typename G>
|
||||
typename graph_traits<G>::degree_size_type
|
||||
in_degree(typename graph_traits<G>::vertex_descriptor u_local,
|
||||
const subgraph<G>& g)
|
||||
{ return in_degree(u_local, g.m_graph); }
|
||||
|
||||
template <typename G>
|
||||
typename graph_traits<G>::degree_size_type
|
||||
degree(typename graph_traits<G>::vertex_descriptor u_local,
|
||||
const subgraph<G>& g)
|
||||
{ return degree(u_local, g.m_graph); }
|
||||
|
||||
//===========================================================================
|
||||
// Functions required by the AdjacencyGraph concept
|
||||
|
||||
template <typename G>
|
||||
std::pair<typename subgraph<G>::adjacency_iterator,
|
||||
typename subgraph<G>::adjacency_iterator>
|
||||
adjacent_vertices(typename subgraph<G>::vertex_descriptor u_local,
|
||||
const subgraph<G>& g)
|
||||
{ return adjacent_vertices(u_local, g.m_graph); }
|
||||
|
||||
//===========================================================================
|
||||
// Functions required by the VertexListGraph concept
|
||||
|
||||
template <typename G>
|
||||
std::pair<typename subgraph<G>::vertex_iterator,
|
||||
typename subgraph<G>::vertex_iterator>
|
||||
vertices(const subgraph<G>& g)
|
||||
{ return vertices(g.m_graph); }
|
||||
|
||||
template <typename G>
|
||||
typename subgraph<G>::vertices_size_type
|
||||
num_vertices(const subgraph<G>& g)
|
||||
{ return num_vertices(g.m_graph); }
|
||||
|
||||
//===========================================================================
|
||||
// Functions required by the EdgeListGraph concept
|
||||
|
||||
template <typename G>
|
||||
std::pair<typename subgraph<G>::edge_iterator,
|
||||
typename subgraph<G>::edge_iterator>
|
||||
edges(const subgraph<G>& g)
|
||||
{ return edges(g.m_graph); }
|
||||
|
||||
template <typename G>
|
||||
typename subgraph<G>::edges_size_type
|
||||
num_edges(const subgraph<G>& g)
|
||||
{ return num_edges(g.m_graph); }
|
||||
|
||||
//===========================================================================
|
||||
// Functions required by the AdjacencyMatrix concept
|
||||
|
||||
template <typename G>
|
||||
std::pair<typename subgraph<G>::edge_descriptor, bool>
|
||||
edge(typename subgraph<G>::vertex_descriptor u_local,
|
||||
typename subgraph<G>::vertex_descriptor v_local,
|
||||
const subgraph<G>& g)
|
||||
{
|
||||
return edge(u_local, v_local, g.m_graph);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Functions required by the MutableGraph concept
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Vertex, typename Edge, typename Graph>
|
||||
void add_edge_recur_down
|
||||
(Vertex u_global, Vertex v_global, Edge e_global, subgraph<Graph>& g);
|
||||
|
||||
template <typename Vertex, typename Edge, typename Children, typename G>
|
||||
void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global,
|
||||
Children& c, subgraph<G>* orig)
|
||||
{
|
||||
for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
|
||||
if ((*i)->find_vertex(u_global).second
|
||||
&& (*i)->find_vertex(v_global).second)
|
||||
add_edge_recur_down(u_global, v_global, e_global, **i, orig);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Edge, typename Graph>
|
||||
void add_edge_recur_down
|
||||
(Vertex u_global, Vertex v_global, Edge e_global, subgraph<Graph>& g,
|
||||
subgraph<Graph>* orig)
|
||||
{
|
||||
if (&g != orig ) {
|
||||
// add local edge only if u_global and v_global are in subgraph g
|
||||
Vertex u_local, v_local;
|
||||
bool u_in_subgraph, v_in_subgraph;
|
||||
tie(u_local, u_in_subgraph) = g.find_vertex(u_global);
|
||||
tie(v_local, v_in_subgraph) = g.find_vertex(v_global);
|
||||
if (u_in_subgraph && v_in_subgraph)
|
||||
g.local_add_edge(u_local, v_local, e_global);
|
||||
}
|
||||
children_add_edge(u_global, v_global, e_global, g.m_children, orig);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
std::pair<typename subgraph<Graph>::edge_descriptor, bool>
|
||||
add_edge_recur_up(Vertex u_global, Vertex v_global,
|
||||
const typename Graph::edge_property_type& ep,
|
||||
subgraph<Graph>& g, subgraph<Graph>* orig)
|
||||
{
|
||||
if (g.is_root()) {
|
||||
typename subgraph<Graph>::edge_descriptor e_global;
|
||||
bool inserted;
|
||||
tie(e_global, inserted) = add_edge(u_global, v_global, ep, g.m_graph);
|
||||
put(edge_index, g.m_graph, e_global, g.m_edge_counter++);
|
||||
g.m_global_edge.push_back(e_global);
|
||||
children_add_edge(u_global, v_global, e_global, g.m_children, orig);
|
||||
return std::make_pair(e_global, inserted);
|
||||
} else
|
||||
return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Add an edge to the subgraph g, specified by the local vertex
|
||||
// descriptors u and v. In addition, the edge will be added to any
|
||||
// other subgraphs which contain vertex descriptors u and v.
|
||||
|
||||
template <typename G>
|
||||
std::pair<typename subgraph<G>::edge_descriptor, bool>
|
||||
add_edge(typename subgraph<G>::vertex_descriptor u_local,
|
||||
typename subgraph<G>::vertex_descriptor v_local,
|
||||
const typename G::edge_property_type& ep,
|
||||
subgraph<G>& g)
|
||||
{
|
||||
if (g.is_root()) // u_local and v_local are really global
|
||||
return detail::add_edge_recur_up(u_local, v_local, ep, g, &g);
|
||||
else {
|
||||
typename subgraph<G>::edge_descriptor e_local, e_global;
|
||||
bool inserted;
|
||||
tie(e_global, inserted) = detail::add_edge_recur_up
|
||||
(g.local_to_global(u_local), g.local_to_global(v_local), ep, g, &g);
|
||||
e_local = g.local_add_edge(u_local, v_local, e_global);
|
||||
return std::make_pair(e_local, inserted);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
std::pair<typename subgraph<G>::edge_descriptor, bool>
|
||||
add_edge(typename subgraph<G>::vertex_descriptor u,
|
||||
typename subgraph<G>::vertex_descriptor v,
|
||||
subgraph<G>& g)
|
||||
{
|
||||
typename G::edge_property_type ep;
|
||||
return add_edge(u, v, ep, g);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// implementation of remove_edge(u,v,g)
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void remove_edge_recur_down(Vertex u_global, Vertex v_global,
|
||||
subgraph<Graph>& g);
|
||||
|
||||
template <typename Vertex, typename Children>
|
||||
void children_remove_edge(Vertex u_global, Vertex v_global,
|
||||
Children& c)
|
||||
{
|
||||
for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
|
||||
if ((*i)->find_vertex(u_global).second
|
||||
&& (*i)->find_vertex(v_global).second)
|
||||
remove_edge_recur_down(u_global, v_global, **i);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void remove_edge_recur_down(Vertex u_global, Vertex v_global,
|
||||
subgraph<Graph>& g)
|
||||
{
|
||||
Vertex u_local, v_local;
|
||||
u_local = g.m_local_vertex[u_global];
|
||||
v_local = g.m_local_vertex[v_global];
|
||||
remove_edge(u_local, v_local, g.m_graph);
|
||||
children_remove_edge(u_global, v_global, g.m_children);
|
||||
}
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void remove_edge_recur_up(Vertex u_global, Vertex v_global,
|
||||
subgraph<Graph>& g)
|
||||
{
|
||||
if (g.is_root()) {
|
||||
remove_edge(u_global, v_global, g.m_graph);
|
||||
children_remove_edge(u_global, v_global, g.m_children);
|
||||
} else
|
||||
remove_edge_recur_up(u_global, v_global, *g.m_parent);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// implementation of remove_edge(e,g)
|
||||
|
||||
template <typename Edge, typename Graph>
|
||||
void remove_edge_recur_down(Edge e_global, subgraph<Graph>& g);
|
||||
|
||||
template <typename Edge, typename Children>
|
||||
void children_remove_edge(Edge e_global, Children& c)
|
||||
{
|
||||
for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
|
||||
if ((*i)->find_vertex(source(e_global, **i)).second
|
||||
&& (*i)->find_vertex(target(e_global, **i)).second)
|
||||
remove_edge_recur_down(source(e_global, **i),
|
||||
target(e_global, **i), **i);
|
||||
}
|
||||
|
||||
template <typename Edge, typename Graph>
|
||||
void remove_edge_recur_down(Edge e_global, subgraph<Graph>& g)
|
||||
{
|
||||
remove_edge(g.global_to_local(e_global), g.m_graph);
|
||||
children_remove_edge(e_global, g.m_children);
|
||||
}
|
||||
|
||||
template <typename Edge, typename Graph>
|
||||
void remove_edge_recur_up(Edge e_global, subgraph<Graph>& g)
|
||||
{
|
||||
if (g.is_root()) {
|
||||
remove_edge(e_global, g.m_graph);
|
||||
children_remove_edge(e_global, g.m_children);
|
||||
} else
|
||||
remove_edge_recur_up(e_global, *g.m_parent);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename G>
|
||||
void
|
||||
remove_edge(typename subgraph<G>::vertex_descriptor u_local,
|
||||
typename subgraph<G>::vertex_descriptor v_local,
|
||||
subgraph<G>& g)
|
||||
{
|
||||
if (g.is_root())
|
||||
detail::remove_edge_recur_up(u_local, v_local, g);
|
||||
else
|
||||
detail::remove_edge_recur_up(g.local_to_global(u_local),
|
||||
g.local_to_global(v_local), g);
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
void
|
||||
remove_edge(typename subgraph<G>::edge_descriptor e_local,
|
||||
subgraph<G>& g)
|
||||
{
|
||||
if (g.is_root())
|
||||
detail::remove_edge_recur_up(e_local, g);
|
||||
else
|
||||
detail::remove_edge_recur_up(g.local_to_global(e_local), g);
|
||||
}
|
||||
|
||||
template <typename Predicate, typename G>
|
||||
void
|
||||
remove_edge_if(Predicate p, subgraph<G>& g)
|
||||
{
|
||||
// This is wrong...
|
||||
remove_edge_if(p, g.m_graph);
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
void
|
||||
clear_vertex(typename subgraph<G>::vertex_descriptor v_local,
|
||||
subgraph<G>& g)
|
||||
{
|
||||
// this is wrong...
|
||||
clear_vertex(v_local, g.m_graph);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename G>
|
||||
typename subgraph<G>::vertex_descriptor
|
||||
add_vertex_recur_up(subgraph<G>& g)
|
||||
{
|
||||
typename subgraph<G>::vertex_descriptor u_local, u_global;
|
||||
if (g.is_root()) {
|
||||
u_global = add_vertex(g.m_graph);
|
||||
g.m_global_vertex.push_back(u_global);
|
||||
} else {
|
||||
u_global = add_vertex_recur_up(*g.m_parent);
|
||||
u_local = add_vertex(g.m_graph);
|
||||
g.m_global_vertex.push_back(u_global);
|
||||
g.m_local_vertex[u_global] = u_local;
|
||||
}
|
||||
return u_global;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename G>
|
||||
typename subgraph<G>::vertex_descriptor
|
||||
add_vertex(subgraph<G>& g)
|
||||
{
|
||||
typename subgraph<G>::vertex_descriptor u_local, u_global;
|
||||
if (g.is_root()) {
|
||||
u_global = add_vertex(g.m_graph);
|
||||
g.m_global_vertex.push_back(u_global);
|
||||
u_local = u_global;
|
||||
} else {
|
||||
u_global = detail::add_vertex_recur_up(g.parent());
|
||||
u_local = add_vertex(g.m_graph);
|
||||
g.m_global_vertex.push_back(u_global);
|
||||
g.m_local_vertex[u_global] = u_local;
|
||||
}
|
||||
return u_local;
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
void remove_vertex(typename subgraph<G>::vertex_descriptor u,
|
||||
subgraph<G>& g)
|
||||
{
|
||||
// UNDER CONSTRUCTION
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// Functions required by the PropertyGraph concept
|
||||
|
||||
template <typename GraphPtr, typename PropertyMap, typename Tag>
|
||||
class subgraph_global_property_map
|
||||
: public put_get_helper<
|
||||
typename property_traits<PropertyMap>::reference,
|
||||
subgraph_global_property_map<GraphPtr, PropertyMap, Tag> >
|
||||
{
|
||||
typedef property_traits<PropertyMap> Traits;
|
||||
public:
|
||||
typedef typename Traits::category category;
|
||||
typedef typename Traits::value_type value_type;
|
||||
typedef typename Traits::key_type key_type;
|
||||
typedef typename Traits::reference reference;
|
||||
|
||||
subgraph_global_property_map() { }
|
||||
|
||||
subgraph_global_property_map(GraphPtr g)
|
||||
: m_g(g) { }
|
||||
|
||||
inline reference operator[](key_type e_local) const {
|
||||
PropertyMap pmap = get(Tag(), m_g->root().m_graph);
|
||||
if (m_g->m_parent == 0)
|
||||
return pmap[e_local];
|
||||
else
|
||||
return pmap[m_g->local_to_global(e_local)];
|
||||
}
|
||||
GraphPtr m_g;
|
||||
};
|
||||
|
||||
template <typename GraphPtr, typename PropertyMap, typename Tag>
|
||||
class subgraph_local_property_map
|
||||
: public put_get_helper<
|
||||
typename property_traits<PropertyMap>::reference,
|
||||
subgraph_local_property_map<GraphPtr, PropertyMap, Tag> >
|
||||
{
|
||||
typedef property_traits<PropertyMap> Traits;
|
||||
public:
|
||||
typedef typename Traits::category category;
|
||||
typedef typename Traits::value_type value_type;
|
||||
typedef typename Traits::key_type key_type;
|
||||
typedef typename Traits::reference reference;
|
||||
|
||||
subgraph_local_property_map() { }
|
||||
|
||||
subgraph_local_property_map(GraphPtr g)
|
||||
: m_g(g) { }
|
||||
|
||||
inline reference operator[](key_type e_local) const {
|
||||
PropertyMap pmap = get(Tag(), *m_g);
|
||||
return pmap[e_local];
|
||||
}
|
||||
GraphPtr m_g;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct subgraph_any_pmap {
|
||||
template <class Tag, class SubGraph, class Property>
|
||||
class bind_ {
|
||||
typedef typename SubGraph::graph_type Graph;
|
||||
typedef SubGraph* SubGraphPtr;
|
||||
typedef const SubGraph* const_SubGraphPtr;
|
||||
typedef typename property_map<Graph, Tag>::type PMap;
|
||||
typedef typename property_map<Graph, Tag>::const_type const_PMap;
|
||||
public:
|
||||
typedef subgraph_global_property_map<SubGraphPtr, PMap, Tag> type;
|
||||
typedef subgraph_global_property_map<const_SubGraphPtr, const_PMap, Tag>
|
||||
const_type;
|
||||
};
|
||||
};
|
||||
struct subgraph_id_pmap {
|
||||
template <class Tag, class SubGraph, class Property>
|
||||
struct bind_ {
|
||||
typedef typename SubGraph::graph_type Graph;
|
||||
typedef SubGraph* SubGraphPtr;
|
||||
typedef const SubGraph* const_SubGraphPtr;
|
||||
typedef typename property_map<Graph, Tag>::type PMap;
|
||||
typedef typename property_map<Graph, Tag>::const_type const_PMap;
|
||||
public:
|
||||
typedef subgraph_local_property_map<SubGraphPtr, PMap, Tag> type;
|
||||
typedef subgraph_local_property_map<const_SubGraphPtr, const_PMap, Tag>
|
||||
const_type;
|
||||
};
|
||||
};
|
||||
template <class Tag>
|
||||
struct subgraph_choose_pmap_helper {
|
||||
typedef subgraph_any_pmap type;
|
||||
};
|
||||
template <>
|
||||
struct subgraph_choose_pmap_helper<vertex_index_t> {
|
||||
typedef subgraph_id_pmap type;
|
||||
};
|
||||
template <class Tag, class Graph, class Property>
|
||||
struct subgraph_choose_pmap {
|
||||
typedef typename subgraph_choose_pmap_helper<Tag>::type Helper;
|
||||
typedef typename Helper::template bind_<Tag, Graph, Property> Bind;
|
||||
typedef typename Bind::type type;
|
||||
typedef typename Bind::const_type const_type;
|
||||
};
|
||||
struct subgraph_property_generator {
|
||||
template <class SubGraph, class Property, class Tag>
|
||||
struct bind_ {
|
||||
typedef subgraph_choose_pmap<Tag, SubGraph, Property> Choice;
|
||||
typedef typename Choice::type type;
|
||||
typedef typename Choice::const_type const_type;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <>
|
||||
struct vertex_property_selector<subgraph_tag> {
|
||||
typedef detail::subgraph_property_generator type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct edge_property_selector<subgraph_tag> {
|
||||
typedef detail::subgraph_property_generator type;
|
||||
};
|
||||
|
||||
template <typename G, typename Property>
|
||||
typename property_map< subgraph<G>, Property>::type
|
||||
get(Property, subgraph<G>& g)
|
||||
{
|
||||
typedef typename property_map< subgraph<G>, Property>::type PMap;
|
||||
return PMap(&g);
|
||||
}
|
||||
|
||||
template <typename G, typename Property>
|
||||
typename property_map< subgraph<G>, Property>::const_type
|
||||
get(Property, const subgraph<G>& g)
|
||||
{
|
||||
typedef typename property_map< subgraph<G>, Property>::const_type PMap;
|
||||
return PMap(&g);
|
||||
}
|
||||
|
||||
template <typename G, typename Property, typename Key>
|
||||
typename property_traits<
|
||||
typename property_map< subgraph<G>, Property>::const_type
|
||||
>::value_type
|
||||
get(Property, const subgraph<G>& g, const Key& k)
|
||||
{
|
||||
typedef typename property_map< subgraph<G>, Property>::const_type PMap;
|
||||
PMap pmap(&g);
|
||||
return pmap[k];
|
||||
}
|
||||
|
||||
template <typename G, typename Property, typename Key, typename Value>
|
||||
void
|
||||
put(Property, subgraph<G>& g, const Key& k, const Value& val)
|
||||
{
|
||||
typedef typename property_map< subgraph<G>, Property>::type PMap;
|
||||
PMap pmap(&g);
|
||||
pmap[k] = val;
|
||||
}
|
||||
|
||||
template <typename G, typename Tag>
|
||||
inline
|
||||
typename graph_property<G, Tag>::type&
|
||||
get_property(subgraph<G>& g, Tag tag) {
|
||||
return get_property(g.root().m_graph, tag);
|
||||
}
|
||||
|
||||
template <typename G, typename Tag>
|
||||
inline
|
||||
const typename graph_property<G, Tag>::type&
|
||||
get_property(const subgraph<G>& g, Tag tag) {
|
||||
return get_property(g.root().m_graph, tag);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Miscellaneous Functions
|
||||
|
||||
template <typename G>
|
||||
typename subgraph<G>::vertex_descriptor
|
||||
vertex(typename subgraph<G>::vertices_size_type n, const subgraph<G>& g)
|
||||
{
|
||||
return vertex(n, g.m_graph);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_SUBGRAPH_HPP
|
||||
@@ -1,92 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#ifndef BOOST_GRAPH_TOPOLOGICAL_SORT_HPP
|
||||
#define BOOST_GRAPH_TOPOLOGICAL_SORT_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
#include <boost/graph/visitors.hpp>
|
||||
#include <boost/graph/exception.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
|
||||
// Topological sort visitor
|
||||
//
|
||||
// This visitor merely writes the linear ordering into an
|
||||
// OutputIterator. The OutputIterator could be something like an
|
||||
// ostream_iterator, or it could be a back/front_insert_iterator.
|
||||
// Note that if it is a back_insert_iterator, the recorded order is
|
||||
// the reverse topological order. On the other hand, if it is a
|
||||
// front_insert_iterator, the recorded order is the topological
|
||||
// order.
|
||||
//
|
||||
template <typename OutputIterator>
|
||||
struct topo_sort_visitor : public dfs_visitor<>
|
||||
{
|
||||
topo_sort_visitor(OutputIterator _iter)
|
||||
: m_iter(_iter) { }
|
||||
|
||||
template <typename Edge, typename Graph>
|
||||
void back_edge(const Edge& u, Graph&) { throw not_a_dag(); }
|
||||
|
||||
template <typename Vertex, typename Graph>
|
||||
void finish_vertex(const Vertex& u, Graph&) { *m_iter++ = u; }
|
||||
|
||||
OutputIterator m_iter;
|
||||
};
|
||||
|
||||
|
||||
// Topological Sort
|
||||
//
|
||||
// The topological sort algorithm creates a linear ordering
|
||||
// of the vertices such that if edge (u,v) appears in the graph,
|
||||
// then u comes before v in the ordering. The graph must
|
||||
// be a directed acyclic graph (DAG). The implementation
|
||||
// consists mainly of a call to depth-first search.
|
||||
//
|
||||
|
||||
template <typename VertexListGraph, typename OutputIterator,
|
||||
typename P, typename T, typename R>
|
||||
void topological_sort(VertexListGraph& g, OutputIterator result,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef topo_sort_visitor<OutputIterator> TopoVisitor;
|
||||
depth_first_search(g, params.visitor(TopoVisitor(result)));
|
||||
}
|
||||
|
||||
template <typename VertexListGraph, typename OutputIterator>
|
||||
void topological_sort(VertexListGraph& g, OutputIterator result)
|
||||
{
|
||||
topological_sort(g, result,
|
||||
bgl_named_params<int, buffer_param_t>(0)); // bogus
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif /*BOOST_GRAPH_TOPOLOGICAL_SORT_H*/
|
||||
@@ -1,370 +0,0 @@
|
||||
// Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su>
|
||||
// Copyright (C) 2001 Jeremy Siek <jsiek@cs.indiana.edu>
|
||||
// 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/transitive_closure.w
|
||||
|
||||
#ifndef BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP
|
||||
#define BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm> // for std::min and std::max
|
||||
#include <functional>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/graph/vector_as_graph.hpp>
|
||||
#include <boost/graph/strong_components.hpp>
|
||||
#include <boost/graph/topological_sort.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline void
|
||||
union_successor_sets(const std::vector < std::size_t > &s1,
|
||||
const std::vector < std::size_t > &s2,
|
||||
std::vector < std::size_t > &s3)
|
||||
{
|
||||
BOOST_USING_STD_MIN();
|
||||
for (std::size_t k = 0; k < s1.size(); ++k)
|
||||
s3[k] = min BOOST_PREVENT_MACRO_SUBSTITUTION(s1[k], s2[k]);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template < typename Container, typename ST = std::size_t,
|
||||
typename VT = typename Container::value_type >
|
||||
struct subscript_t:public std::unary_function < ST, VT >
|
||||
{
|
||||
typedef VT& result_type;
|
||||
|
||||
subscript_t(Container & c):container(&c)
|
||||
{
|
||||
}
|
||||
VT & operator() (const ST & i) const
|
||||
{
|
||||
return (*container)[i];
|
||||
}
|
||||
protected:
|
||||
Container * container;
|
||||
};
|
||||
template < typename Container >
|
||||
subscript_t < Container > subscript(Container & c) {
|
||||
return subscript_t < Container > (c);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template < typename Graph, typename GraphTC,
|
||||
typename G_to_TC_VertexMap,
|
||||
typename VertexIndexMap >
|
||||
void transitive_closure(const Graph & g, GraphTC & tc,
|
||||
G_to_TC_VertexMap g_to_tc_map,
|
||||
VertexIndexMap index_map)
|
||||
{
|
||||
if (num_vertices(g) == 0)
|
||||
return;
|
||||
typedef typename graph_traits < Graph >::vertex_descriptor vertex;
|
||||
typedef typename graph_traits < Graph >::edge_descriptor edge;
|
||||
typedef typename graph_traits < Graph >::vertex_iterator vertex_iterator;
|
||||
typedef typename property_traits < VertexIndexMap >::value_type size_type;
|
||||
typedef typename graph_traits <
|
||||
Graph >::adjacency_iterator adjacency_iterator;
|
||||
|
||||
function_requires < VertexListGraphConcept < Graph > >();
|
||||
function_requires < AdjacencyGraphConcept < Graph > >();
|
||||
function_requires < VertexMutableGraphConcept < GraphTC > >();
|
||||
function_requires < EdgeMutableGraphConcept < GraphTC > >();
|
||||
function_requires < ReadablePropertyMapConcept < VertexIndexMap,
|
||||
vertex > >();
|
||||
|
||||
typedef size_type cg_vertex;
|
||||
std::vector < cg_vertex > component_number_vec(num_vertices(g));
|
||||
iterator_property_map < cg_vertex *, VertexIndexMap, cg_vertex, cg_vertex& >
|
||||
component_number(&component_number_vec[0], index_map);
|
||||
|
||||
int num_scc = strong_components(g, component_number,
|
||||
vertex_index_map(index_map));
|
||||
|
||||
std::vector < std::vector < vertex > >components;
|
||||
build_component_lists(g, num_scc, component_number, components);
|
||||
|
||||
typedef std::vector<std::vector<cg_vertex> > CG_t;
|
||||
CG_t CG(num_scc);
|
||||
for (cg_vertex s = 0; s < components.size(); ++s) {
|
||||
std::vector < cg_vertex > adj;
|
||||
for (size_type i = 0; i < components[s].size(); ++i) {
|
||||
vertex u = components[s][i];
|
||||
adjacency_iterator v, v_end;
|
||||
for (tie(v, v_end) = adjacent_vertices(u, g); v != v_end; ++v) {
|
||||
cg_vertex t = component_number[*v];
|
||||
if (s != t) // Avoid loops in the condensation graph
|
||||
adj.push_back(t);
|
||||
}
|
||||
}
|
||||
std::sort(adj.begin(), adj.end());
|
||||
typename std::vector<cg_vertex>::iterator di =
|
||||
std::unique(adj.begin(), adj.end());
|
||||
if (di != adj.end())
|
||||
adj.erase(di, adj.end());
|
||||
CG[s] = adj;
|
||||
}
|
||||
|
||||
std::vector<cg_vertex> topo_order;
|
||||
std::vector<cg_vertex> topo_number(num_vertices(CG));
|
||||
topological_sort(CG, std::back_inserter(topo_order),
|
||||
vertex_index_map(identity_property_map()));
|
||||
std::reverse(topo_order.begin(), topo_order.end());
|
||||
size_type n = 0;
|
||||
for (typename std::vector<cg_vertex>::iterator iter = topo_order.begin();
|
||||
iter != topo_order.end(); ++iter)
|
||||
topo_number[*iter] = n++;
|
||||
|
||||
for (size_type i = 0; i < num_vertices(CG); ++i)
|
||||
std::sort(CG[i].begin(), CG[i].end(),
|
||||
boost::bind(std::less<cg_vertex>(),
|
||||
boost::bind(detail::subscript(topo_number), _1),
|
||||
boost::bind(detail::subscript(topo_number), _2)));
|
||||
|
||||
std::vector<std::vector<cg_vertex> > chains;
|
||||
{
|
||||
std::vector<cg_vertex> in_a_chain(num_vertices(CG));
|
||||
for (typename std::vector<cg_vertex>::iterator i = topo_order.begin();
|
||||
i != topo_order.end(); ++i) {
|
||||
cg_vertex v = *i;
|
||||
if (!in_a_chain[v]) {
|
||||
chains.resize(chains.size() + 1);
|
||||
std::vector<cg_vertex>& chain = chains.back();
|
||||
for (;;) {
|
||||
chain.push_back(v);
|
||||
in_a_chain[v] = true;
|
||||
typename graph_traits<CG_t>::adjacency_iterator adj_first, adj_last;
|
||||
tie(adj_first, adj_last) = adjacent_vertices(v, CG);
|
||||
typename graph_traits<CG_t>::adjacency_iterator next
|
||||
= std::find_if(adj_first, adj_last,
|
||||
not1(detail::subscript(in_a_chain)));
|
||||
if (next != adj_last)
|
||||
v = *next;
|
||||
else
|
||||
break; // end of chain, dead-end
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<size_type> chain_number(num_vertices(CG));
|
||||
std::vector<size_type> pos_in_chain(num_vertices(CG));
|
||||
for (size_type i = 0; i < chains.size(); ++i)
|
||||
for (size_type j = 0; j < chains[i].size(); ++j) {
|
||||
cg_vertex v = chains[i][j];
|
||||
chain_number[v] = i;
|
||||
pos_in_chain[v] = j;
|
||||
}
|
||||
|
||||
cg_vertex inf = (std::numeric_limits< cg_vertex >::max)();
|
||||
std::vector<std::vector<cg_vertex> > successors(num_vertices(CG),
|
||||
std::vector<cg_vertex>
|
||||
(chains.size(), inf));
|
||||
for (typename std::vector<cg_vertex>::reverse_iterator
|
||||
i = topo_order.rbegin(); i != topo_order.rend(); ++i) {
|
||||
cg_vertex u = *i;
|
||||
typename graph_traits<CG_t>::adjacency_iterator adj, adj_last;
|
||||
for (tie(adj, adj_last) = adjacent_vertices(u, CG);
|
||||
adj != adj_last; ++adj) {
|
||||
cg_vertex v = *adj;
|
||||
if (topo_number[v] < successors[u][chain_number[v]]) {
|
||||
// Succ(u) = Succ(u) U Succ(v)
|
||||
detail::union_successor_sets(successors[u], successors[v],
|
||||
successors[u]);
|
||||
// Succ(u) = Succ(u) U {v}
|
||||
successors[u][chain_number[v]] = topo_number[v];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_type i = 0; i < CG.size(); ++i)
|
||||
CG[i].clear();
|
||||
for (size_type i = 0; i < CG.size(); ++i)
|
||||
for (size_type j = 0; j < chains.size(); ++j) {
|
||||
size_type topo_num = successors[i][j];
|
||||
if (topo_num < inf) {
|
||||
cg_vertex v = topo_order[topo_num];
|
||||
for (size_type k = pos_in_chain[v]; k < chains[j].size(); ++k)
|
||||
CG[i].push_back(chains[j][k]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add vertices to the transitive closure graph
|
||||
typedef typename graph_traits < GraphTC >::vertex_descriptor tc_vertex;
|
||||
{
|
||||
vertex_iterator i, i_end;
|
||||
for (tie(i, i_end) = vertices(g); i != i_end; ++i)
|
||||
g_to_tc_map[*i] = add_vertex(tc);
|
||||
}
|
||||
// Add edges between all the vertices in two adjacent SCCs
|
||||
typename graph_traits<CG_t>::vertex_iterator si, si_end;
|
||||
for (tie(si, si_end) = vertices(CG); si != si_end; ++si) {
|
||||
cg_vertex s = *si;
|
||||
typename graph_traits<CG_t>::adjacency_iterator i, i_end;
|
||||
for (tie(i, i_end) = adjacent_vertices(s, CG); i != i_end; ++i) {
|
||||
cg_vertex t = *i;
|
||||
for (size_type k = 0; k < components[s].size(); ++k)
|
||||
for (size_type l = 0; l < components[t].size(); ++l)
|
||||
add_edge(g_to_tc_map[components[s][k]],
|
||||
g_to_tc_map[components[t][l]], tc);
|
||||
}
|
||||
}
|
||||
// Add edges connecting all vertices in a SCC
|
||||
for (size_type i = 0; i < components.size(); ++i)
|
||||
if (components[i].size() > 1)
|
||||
for (size_type k = 0; k < components[i].size(); ++k)
|
||||
for (size_type l = 0; l < components[i].size(); ++l) {
|
||||
vertex u = components[i][k], v = components[i][l];
|
||||
add_edge(g_to_tc_map[u], g_to_tc_map[v], tc);
|
||||
}
|
||||
|
||||
// Find loopbacks in the original graph.
|
||||
// Need to add it to transitive closure.
|
||||
{
|
||||
vertex_iterator i, i_end;
|
||||
for (tie(i, i_end) = vertices(g); i != i_end; ++i)
|
||||
{
|
||||
adjacency_iterator ab, ae;
|
||||
for (boost::tie(ab, ae) = adjacent_vertices(*i, g); ab != ae; ++ab)
|
||||
{
|
||||
if (*ab == *i)
|
||||
if (components[component_number[*i]].size() == 1)
|
||||
add_edge(g_to_tc_map[*i], g_to_tc_map[*i], tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Graph, typename GraphTC>
|
||||
void transitive_closure(const Graph & g, GraphTC & tc)
|
||||
{
|
||||
if (num_vertices(g) == 0)
|
||||
return;
|
||||
typedef typename property_map<Graph, vertex_index_t>::const_type
|
||||
VertexIndexMap;
|
||||
VertexIndexMap index_map = get(vertex_index, g);
|
||||
|
||||
typedef typename graph_traits<GraphTC>::vertex_descriptor tc_vertex;
|
||||
std::vector<tc_vertex> to_tc_vec(num_vertices(g));
|
||||
iterator_property_map < tc_vertex *, VertexIndexMap, tc_vertex, tc_vertex&>
|
||||
g_to_tc_map(&to_tc_vec[0], index_map);
|
||||
|
||||
transitive_closure(g, tc, g_to_tc_map, index_map);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template < typename Graph, typename GraphTC, typename G_to_TC_VertexMap,
|
||||
typename VertexIndexMap>
|
||||
void transitive_closure_dispatch
|
||||
(const Graph & g, GraphTC & tc,
|
||||
G_to_TC_VertexMap g_to_tc_map, VertexIndexMap index_map)
|
||||
{
|
||||
typedef typename graph_traits < GraphTC >::vertex_descriptor tc_vertex;
|
||||
typename std::vector < tc_vertex >::size_type
|
||||
n = is_default_param(g_to_tc_map) ? num_vertices(g) : 1;
|
||||
std::vector < tc_vertex > to_tc_vec(n);
|
||||
|
||||
transitive_closure
|
||||
(g, tc,
|
||||
choose_param(g_to_tc_map, make_iterator_property_map
|
||||
(to_tc_vec.begin(), index_map, to_tc_vec[0])),
|
||||
index_map);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template < typename Graph, typename GraphTC,
|
||||
typename P, typename T, typename R >
|
||||
void transitive_closure(const Graph & g, GraphTC & tc,
|
||||
const bgl_named_params < P, T, R > ¶ms)
|
||||
{
|
||||
if (num_vertices(g) == 0)
|
||||
return;
|
||||
detail::transitive_closure_dispatch
|
||||
(g, tc, get_param(params, orig_to_copy_t()),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index) );
|
||||
}
|
||||
|
||||
|
||||
template < typename G > void warshall_transitive_closure(G & g)
|
||||
{
|
||||
typedef typename graph_traits < G >::vertex_descriptor vertex;
|
||||
typedef typename graph_traits < G >::vertex_iterator vertex_iterator;
|
||||
|
||||
function_requires < AdjacencyMatrixConcept < G > >();
|
||||
function_requires < EdgeMutableGraphConcept < G > >();
|
||||
|
||||
// Matrix form:
|
||||
// for k
|
||||
// for i
|
||||
// if A[i,k]
|
||||
// for j
|
||||
// A[i,j] = A[i,j] | A[k,j]
|
||||
vertex_iterator ki, ke, ii, ie, ji, je;
|
||||
for (tie(ki, ke) = vertices(g); ki != ke; ++ki)
|
||||
for (tie(ii, ie) = vertices(g); ii != ie; ++ii)
|
||||
if (edge(*ii, *ki, g).second)
|
||||
for (tie(ji, je) = vertices(g); ji != je; ++ji)
|
||||
if (!edge(*ii, *ji, g).second && edge(*ki, *ji, g).second) {
|
||||
add_edge(*ii, *ji, g);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template < typename G > void warren_transitive_closure(G & g)
|
||||
{
|
||||
using namespace boost;
|
||||
typedef typename graph_traits < G >::vertex_descriptor vertex;
|
||||
typedef typename graph_traits < G >::vertex_iterator vertex_iterator;
|
||||
|
||||
function_requires < AdjacencyMatrixConcept < G > >();
|
||||
function_requires < EdgeMutableGraphConcept < G > >();
|
||||
|
||||
// Make sure second loop will work
|
||||
if (num_vertices(g) == 0)
|
||||
return;
|
||||
|
||||
// for i = 2 to n
|
||||
// for k = 1 to i - 1
|
||||
// if A[i,k]
|
||||
// for j = 1 to n
|
||||
// A[i,j] = A[i,j] | A[k,j]
|
||||
|
||||
vertex_iterator ic, ie, jc, je, kc, ke;
|
||||
for (tie(ic, ie) = vertices(g), ++ic; ic != ie; ++ic)
|
||||
for (tie(kc, ke) = vertices(g); *kc != *ic; ++kc)
|
||||
if (edge(*ic, *kc, g).second)
|
||||
for (tie(jc, je) = vertices(g); jc != je; ++jc)
|
||||
if (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second) {
|
||||
add_edge(*ic, *jc, g);
|
||||
}
|
||||
// for i = 1 to n - 1
|
||||
// for k = i + 1 to n
|
||||
// if A[i,k]
|
||||
// for j = 1 to n
|
||||
// A[i,j] = A[i,j] | A[k,j]
|
||||
|
||||
for (tie(ic, ie) = vertices(g), --ie; ic != ie; ++ic)
|
||||
for (kc = ic, ke = ie, ++kc; kc != ke; ++kc)
|
||||
if (edge(*ic, *kc, g).second)
|
||||
for (tie(jc, je) = vertices(g); jc != je; ++jc)
|
||||
if (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second) {
|
||||
add_edge(*ic, *jc, g);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP
|
||||
@@ -1,56 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#ifndef BOOST_GRAPH_TRANSPOSE_HPP
|
||||
#define BOOST_GRAPH_TRANSPOSE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/reverse_graph.hpp>
|
||||
#include <boost/graph/copy.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class VertexListGraph, class MutableGraph>
|
||||
void transpose_graph(const VertexListGraph& G, MutableGraph& G_T)
|
||||
{
|
||||
reverse_graph<VertexListGraph> R(G);
|
||||
copy_graph(R, G_T);
|
||||
}
|
||||
|
||||
template <class VertexListGraph, class MutableGraph,
|
||||
class P, class T, class R>
|
||||
void transpose_graph(const VertexListGraph& G, MutableGraph& G_T,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
reverse_graph<VertexListGraph> Rev(G);
|
||||
copy_graph(Rev, G_T, params);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_TRANSPOSE_HPP
|
||||
@@ -1,43 +0,0 @@
|
||||
// (C) Copyright Jeremy Siek 1999.
|
||||
// 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_TREE_STRUCTURE_HPP
|
||||
#define BOOST_TREE_STRUCTURE_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class T>
|
||||
struct tree_traits {
|
||||
typedef typename T::node_descriptor node_descriptor;
|
||||
typedef typename T::children_iterator children_iterator;
|
||||
};
|
||||
|
||||
|
||||
template <class Tree, class TreeVisitor>
|
||||
void traverse_tree(typename tree_traits<Tree>::node_descriptor v,
|
||||
Tree& t, TreeVisitor visitor)
|
||||
{
|
||||
visitor.preorder(v, t);
|
||||
typename tree_traits<Tree>::children_iterator i, end;
|
||||
tie(i, end) = children(v, t);
|
||||
if (i != end) {
|
||||
traverse_tree(*i++, t, visitor);
|
||||
visitor.inorder(v, t);
|
||||
while (i != end)
|
||||
traverse_tree(*i++, t, visitor);
|
||||
} else
|
||||
visitor.inorder(v, t);
|
||||
visitor.postorder(v, t);
|
||||
}
|
||||
|
||||
struct null_tree_visitor {
|
||||
template <typename Node, typename Tree> void preorder(Node, Tree&) { }
|
||||
template <typename Node, typename Tree> void inorder(Node, Tree&) { }
|
||||
template <typename Node, typename Tree> void postorder(Node, Tree&) { }
|
||||
};
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_TREE_STRUCTURE_HPP */
|
||||
@@ -1,195 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
#ifndef BOOST_GRAPH_UNDIRECTED_DFS_HPP
|
||||
#define BOOST_GRAPH_UNDIRECTED_DFS_HPP
|
||||
|
||||
#include <boost/graph/depth_first_search.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename IncidenceGraph, typename DFSVisitor,
|
||||
typename VertexColorMap, typename EdgeColorMap>
|
||||
void undir_dfv_impl
|
||||
(const IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
||||
DFSVisitor& vis, // pass-by-reference here, important!
|
||||
VertexColorMap vertex_color,
|
||||
EdgeColorMap edge_color)
|
||||
{
|
||||
function_requires<IncidenceGraphConcept<IncidenceGraph> >();
|
||||
function_requires<DFSVisitorConcept<DFSVisitor, IncidenceGraph> >();
|
||||
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<IncidenceGraph>::edge_descriptor Edge;
|
||||
function_requires<ReadWritePropertyMapConcept<VertexColorMap,Vertex> >();
|
||||
function_requires<ReadWritePropertyMapConcept<EdgeColorMap,Edge> >();
|
||||
typedef typename property_traits<VertexColorMap>::value_type ColorValue;
|
||||
typedef typename property_traits<EdgeColorMap>::value_type EColorValue;
|
||||
function_requires< ColorValueConcept<ColorValue> >();
|
||||
function_requires< ColorValueConcept<EColorValue> >();
|
||||
typedef color_traits<ColorValue> Color;
|
||||
typedef color_traits<EColorValue> EColor;
|
||||
typename graph_traits<IncidenceGraph>::out_edge_iterator ei, ei_end;
|
||||
|
||||
put(vertex_color, u, Color::gray()); vis.discover_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(vertex_color, v);
|
||||
EColorValue uv_color = get(edge_color, *ei);
|
||||
put(edge_color, *ei, EColor::black());
|
||||
if (v_color == Color::white()) { vis.tree_edge(*ei, g);
|
||||
undir_dfv_impl(g, v, vis, vertex_color, edge_color);
|
||||
} else if (v_color == Color::gray() && uv_color == EColor::white())
|
||||
vis.back_edge(*ei, g);
|
||||
}
|
||||
put(vertex_color, u, Color::black()); vis.finish_vertex(u, g);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename Graph, typename DFSVisitor,
|
||||
typename VertexColorMap, typename EdgeColorMap,
|
||||
typename Vertex>
|
||||
void
|
||||
undirected_dfs(const Graph& g, DFSVisitor vis,
|
||||
VertexColorMap vertex_color, EdgeColorMap edge_color,
|
||||
Vertex start_vertex)
|
||||
{
|
||||
function_requires<DFSVisitorConcept<DFSVisitor, Graph> >();
|
||||
function_requires<EdgeListGraphConcept<Graph> >();
|
||||
|
||||
typedef typename property_traits<VertexColorMap>::value_type ColorValue;
|
||||
typedef color_traits<ColorValue> Color;
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
||||
put(vertex_color, *ui, Color::white()); vis.initialize_vertex(*ui, g);
|
||||
}
|
||||
typename graph_traits<Graph>::edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
put(edge_color, *ei, Color::white());
|
||||
|
||||
if (start_vertex != *vertices(g).first){ vis.start_vertex(start_vertex, g);
|
||||
detail::undir_dfv_impl(g, start_vertex, vis, vertex_color, edge_color);
|
||||
}
|
||||
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
|
||||
ColorValue u_color = get(vertex_color, *ui);
|
||||
if (u_color == Color::white()) { vis.start_vertex(*ui, g);
|
||||
detail::undir_dfv_impl(g, *ui, vis, vertex_color, edge_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Graph, typename DFSVisitor, typename VertexColorMap,
|
||||
typename EdgeColorMap>
|
||||
void
|
||||
undirected_dfs(const Graph& g, DFSVisitor vis,
|
||||
VertexColorMap vertex_color, EdgeColorMap edge_color)
|
||||
{
|
||||
undirected_dfs(g, vis, vertex_color, edge_color, *vertices(g).first);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename VertexColorMap>
|
||||
struct udfs_dispatch {
|
||||
|
||||
template <typename Graph, typename Vertex,
|
||||
typename DFSVisitor, typename EdgeColorMap,
|
||||
typename P, typename T, typename R>
|
||||
static void
|
||||
apply(const Graph& g, DFSVisitor vis, Vertex start_vertex,
|
||||
const bgl_named_params<P, T, R>&,
|
||||
EdgeColorMap edge_color,
|
||||
VertexColorMap vertex_color)
|
||||
{
|
||||
undirected_dfs(g, vis, vertex_color, edge_color, start_vertex);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct udfs_dispatch<detail::error_property_not_found> {
|
||||
template <typename Graph, typename Vertex, typename DFSVisitor,
|
||||
typename EdgeColorMap,
|
||||
typename P, typename T, typename R>
|
||||
static void
|
||||
apply(const Graph& g, DFSVisitor vis, Vertex start_vertex,
|
||||
const bgl_named_params<P, T, R>& params,
|
||||
EdgeColorMap edge_color,
|
||||
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
|
||||
undirected_dfs
|
||||
(g, vis, make_iterator_property_map
|
||||
(color_vec.begin(),
|
||||
choose_const_pmap(get_param(params, vertex_index),
|
||||
g, vertex_index), c),
|
||||
edge_color,
|
||||
start_vertex);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// Named Parameter Variant
|
||||
template <typename Graph, typename P, typename T, typename R>
|
||||
void
|
||||
undirected_dfs(const Graph& g,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
typedef typename property_value< bgl_named_params<P, T, R>,
|
||||
vertex_color_t>::type C;
|
||||
detail::udfs_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, edge_color),
|
||||
get_param(params, vertex_color)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template <typename IncidenceGraph, typename DFSVisitor,
|
||||
typename VertexColorMap, typename EdgeColorMap>
|
||||
void undirected_depth_first_visit
|
||||
(const IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor u,
|
||||
DFSVisitor vis, VertexColorMap vertex_color, EdgeColorMap edge_color)
|
||||
{
|
||||
detail::undir_dfv_impl(g, u, vis, vertex_color, edge_color);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,331 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
|
||||
// The mutating functions (add_edge, etc.) were added by Vladimir Prus.
|
||||
|
||||
// Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su>
|
||||
// Permission to copy, use, modify, sell and distribute this software is
|
||||
// granted, provided this copyright notice appears in all copies and
|
||||
// modified version are clearly marked as such. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as to its
|
||||
// suitability for any purpose.
|
||||
|
||||
#ifndef BOOST_VECTOR_AS_GRAPH_HPP
|
||||
#define BOOST_VECTOR_AS_GRAPH_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
/*
|
||||
This module implements the VertexListGraph concept using a
|
||||
std::vector as the "back-bone" of the graph (the vector *is* the
|
||||
graph object). The edge-lists type of the graph is templated, so the
|
||||
user can choose any STL container, so long as the value_type of the
|
||||
container is convertible to the size_type of the vector. For now any
|
||||
graph properties must be stored seperately.
|
||||
|
||||
This module requires the C++ compiler to support partial
|
||||
specialization for the graph_traits class, so this is not portable
|
||||
to VC++.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#error The vector-as-graph module requires a compiler that supports partial specialization
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
template <class EdgeList> struct val_out_edge_ret;
|
||||
template <class EdgeList> struct val_out_edge_iter;
|
||||
template <class EdgeList> struct val_edge;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost {
|
||||
|
||||
struct vector_as_graph_traversal_tag
|
||||
: public vertex_list_graph_tag,
|
||||
public adjacency_graph_tag,
|
||||
public incidence_graph_tag { };
|
||||
|
||||
template <class EdgeList>
|
||||
struct graph_traits< std::vector<EdgeList> >
|
||||
{
|
||||
typedef typename EdgeList::value_type V;
|
||||
typedef V vertex_descriptor;
|
||||
typedef typename detail::val_edge<EdgeList>::type edge_descriptor;
|
||||
typedef typename EdgeList::const_iterator adjacency_iterator;
|
||||
typedef typename detail::val_out_edge_iter<EdgeList>::type
|
||||
out_edge_iterator;
|
||||
typedef void in_edge_iterator;
|
||||
typedef void edge_iterator;
|
||||
typedef typename integer_range<V>::iterator vertex_iterator;
|
||||
typedef directed_tag directed_category;
|
||||
typedef allow_parallel_edge_tag edge_parallel_category;
|
||||
typedef vector_as_graph_traversal_tag traversal_category;
|
||||
typedef typename std::vector<EdgeList>::size_type vertices_size_type;
|
||||
typedef void edges_size_type;
|
||||
typedef typename EdgeList::size_type degree_size_type;
|
||||
};
|
||||
template <class EdgeList>
|
||||
struct edge_property_type< std::vector<EdgeList> >
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
template <class EdgeList>
|
||||
struct vertex_property_type< std::vector<EdgeList> >
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
template <class EdgeList>
|
||||
struct graph_property_type< std::vector<EdgeList> >
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// "val" is short for Vector Adjacency List
|
||||
|
||||
template <class EdgeList>
|
||||
struct val_edge
|
||||
{
|
||||
typedef typename EdgeList::value_type V;
|
||||
typedef std::pair<V,V> type;
|
||||
};
|
||||
|
||||
// need rewrite this using boost::iterator_adaptor
|
||||
template <class V, class Iter>
|
||||
class val_out_edge_iterator
|
||||
: public boost::iterator<std::input_iterator_tag, std::pair<V,V>,
|
||||
std::ptrdiff_t, std::pair<V,V>*, const std::pair<V,V> >
|
||||
{
|
||||
typedef val_out_edge_iterator self;
|
||||
typedef std::pair<V,V> Edge;
|
||||
public:
|
||||
val_out_edge_iterator() { }
|
||||
val_out_edge_iterator(V s, Iter i) : _source(s), _iter(i) { }
|
||||
Edge operator*() const { return Edge(_source, *_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:
|
||||
V _source;
|
||||
Iter _iter;
|
||||
};
|
||||
|
||||
template <class EdgeList>
|
||||
struct val_out_edge_iter
|
||||
{
|
||||
typedef typename EdgeList::value_type V;
|
||||
typedef typename EdgeList::const_iterator Iter;
|
||||
typedef val_out_edge_iterator<V,Iter> type;
|
||||
};
|
||||
|
||||
template <class EdgeList>
|
||||
struct val_out_edge_ret
|
||||
{
|
||||
typedef typename val_out_edge_iter<EdgeList>::type IncIter;
|
||||
typedef std::pair<IncIter,IncIter> type;
|
||||
};
|
||||
|
||||
} // namesapce detail
|
||||
|
||||
template <class EdgeList, class Alloc>
|
||||
typename detail::val_out_edge_ret<EdgeList>::type
|
||||
out_edges(typename EdgeList::value_type v,
|
||||
const std::vector<EdgeList, Alloc>& g)
|
||||
{
|
||||
typedef typename detail::val_out_edge_iter<EdgeList>::type Iter;
|
||||
typedef typename detail::val_out_edge_ret<EdgeList>::type return_type;
|
||||
return return_type(Iter(v, g[v].begin()), Iter(v, g[v].end()));
|
||||
}
|
||||
|
||||
template <class EdgeList, class Alloc>
|
||||
typename EdgeList::size_type
|
||||
out_degree(typename EdgeList::value_type v,
|
||||
const std::vector<EdgeList, Alloc>& g)
|
||||
{
|
||||
return g[v].size();
|
||||
}
|
||||
|
||||
template <class EdgeList, class Alloc>
|
||||
std::pair<typename EdgeList::const_iterator,
|
||||
typename EdgeList::const_iterator>
|
||||
adjacent_vertices(typename EdgeList::value_type v,
|
||||
const std::vector<EdgeList, Alloc>& g)
|
||||
{
|
||||
return std::make_pair(g[v].begin(), g[v].end());
|
||||
}
|
||||
|
||||
// source() and target() already provided for pairs in graph_traits.hpp
|
||||
|
||||
template <class EdgeList, class Alloc>
|
||||
std::pair<typename boost::integer_range<typename EdgeList::value_type>
|
||||
::iterator,
|
||||
typename boost::integer_range<typename EdgeList::value_type>
|
||||
::iterator >
|
||||
vertices(const std::vector<EdgeList, Alloc>& v)
|
||||
{
|
||||
typedef typename boost::integer_range<typename EdgeList::value_type>
|
||||
::iterator Iter;
|
||||
return std::make_pair(Iter(0), Iter(v.size()));
|
||||
}
|
||||
|
||||
template <class EdgeList, class Alloc>
|
||||
typename std::vector<EdgeList, Alloc>::size_type
|
||||
num_vertices(const std::vector<EdgeList, Alloc>& v)
|
||||
{
|
||||
return v.size();
|
||||
}
|
||||
|
||||
template<class EdgeList, class Allocator>
|
||||
typename std::pair<typename detail::val_edge<EdgeList>::type, bool>
|
||||
add_edge(typename EdgeList::value_type u, typename EdgeList::value_type v,
|
||||
std::vector<EdgeList, Allocator>& g)
|
||||
{
|
||||
typedef typename detail::val_edge<EdgeList>::type edge_type;
|
||||
g[u].insert(g[u].end(), v);
|
||||
return std::make_pair(edge_type(u, v), true);
|
||||
}
|
||||
|
||||
template<class EdgeList, class Allocator>
|
||||
typename std::pair<typename detail::val_edge<EdgeList>::type, bool>
|
||||
edge(typename EdgeList::value_type u, typename EdgeList::value_type v,
|
||||
std::vector<EdgeList, Allocator>& g)
|
||||
{
|
||||
typedef typename detail::val_edge<EdgeList>::type edge_type;
|
||||
typename EdgeList::iterator i = g[u].begin(), end = g[u].end();
|
||||
for (; i != end; ++i)
|
||||
if (*i == v)
|
||||
return std::make_pair(edge_type(u, v), true);
|
||||
return std::make_pair(edge_type(), false);
|
||||
}
|
||||
|
||||
template<class EdgeList, class Allocator>
|
||||
void
|
||||
remove_edge(typename EdgeList::value_type u, typename EdgeList::value_type v,
|
||||
std::vector<EdgeList, Allocator>& g)
|
||||
{
|
||||
typename EdgeList::iterator i = std::remove(g[u].begin(), g[u].end(), v);
|
||||
if (i != g[u].end())
|
||||
g[u].erase(i, g[u].end());
|
||||
}
|
||||
|
||||
template<class EdgeList, class Allocator>
|
||||
void
|
||||
remove_edge(typename detail::val_edge<EdgeList>::type e,
|
||||
std::vector<EdgeList, Allocator>& g)
|
||||
{
|
||||
typename EdgeList::value_type u, v;
|
||||
u = e.first;
|
||||
v = e.second;
|
||||
// FIXME: edge type does not fully specify the edge to be deleted
|
||||
typename EdgeList::iterator i = std::remove(g[u].begin(), g[u].end(), v);
|
||||
if (i != g[u].end())
|
||||
g[u].erase(i, g[u].end());
|
||||
}
|
||||
|
||||
template<class EdgeList, class Allocator, class Predicate>
|
||||
void
|
||||
remove_edge_if(Predicate p,
|
||||
std::vector<EdgeList, Allocator>& g)
|
||||
{
|
||||
for (std::size_t u = 0; u < g.size(); ++u) {
|
||||
// Oops! gcc gets internal compiler error on compose_.......
|
||||
|
||||
typedef typename EdgeList::iterator iterator;
|
||||
iterator b = g[u].begin(), e = g[u].end();
|
||||
|
||||
if (!g[u].empty()) {
|
||||
|
||||
for(; b != e;) {
|
||||
if (p(std::make_pair(u, *b))) {
|
||||
--e;
|
||||
if (b == e)
|
||||
break;
|
||||
else
|
||||
iter_swap(b, e);
|
||||
} else {
|
||||
++b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e != g[u].end())
|
||||
g[u].erase(e, g[u].end());
|
||||
}
|
||||
}
|
||||
|
||||
template<class EdgeList, class Allocator>
|
||||
typename EdgeList::value_type
|
||||
add_vertex(std::vector<EdgeList, Allocator>& g)
|
||||
{
|
||||
g.resize(g.size()+1);
|
||||
return g.size()-1;
|
||||
}
|
||||
|
||||
template<class EdgeList, class Allocator>
|
||||
void
|
||||
clear_vertex(typename EdgeList::value_type u,
|
||||
std::vector<EdgeList, Allocator>& g)
|
||||
{
|
||||
g[u].clear();
|
||||
for (std::size_t i = 0; i < g.size(); ++i)
|
||||
remove_edge(i, u, g);
|
||||
}
|
||||
|
||||
template<class EdgeList, class Allocator>
|
||||
void
|
||||
remove_vertex(typename EdgeList::value_type u,
|
||||
std::vector<EdgeList, Allocator>& g)
|
||||
{
|
||||
typedef typename EdgeList::iterator iterator;
|
||||
clear_vertex(u, g);
|
||||
g.erase(g.begin() + u);
|
||||
for (std::size_t i = 0; i < g.size(); ++i)
|
||||
for ( iterator it = g[i].begin(); it != g[i].end(); ++it )
|
||||
// after clear_vertex *it is never equal to u
|
||||
if ( *it > u )
|
||||
--*it;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_VECTOR_AS_GRAPH_HPP
|
||||
@@ -1,285 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
// Revision History:
|
||||
// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)
|
||||
//
|
||||
#ifndef BOOST_GRAPH_GRAPH_SEARCH_VISITORS_HPP
|
||||
#define BOOST_GRAPH_GRAPH_SEARCH_VISITORS_HPP
|
||||
|
||||
#include <iosfwd>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/graph/detail/is_same.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// This is a bit more convenient than std::numeric_limits because
|
||||
// you don't have to explicitly provide type T.
|
||||
template <class T>
|
||||
inline T numeric_limits_max(T) { return (std::numeric_limits<T>::max)(); }
|
||||
|
||||
//========================================================================
|
||||
// Event Tags
|
||||
|
||||
namespace detail {
|
||||
// For partial specialization workaround
|
||||
enum event_visitor_enum
|
||||
{ on_no_event_num,
|
||||
on_initialize_vertex_num, on_start_vertex_num,
|
||||
on_discover_vertex_num, on_finish_vertex_num, on_examine_vertex_num,
|
||||
on_examine_edge_num, on_tree_edge_num, on_non_tree_edge_num,
|
||||
on_gray_target_num, on_black_target_num,
|
||||
on_forward_or_cross_edge_num, on_back_edge_num,
|
||||
on_edge_relaxed_num, on_edge_not_relaxed_num,
|
||||
on_edge_minimized_num, on_edge_not_minimized_num
|
||||
};
|
||||
|
||||
template<typename Event, typename Visitor>
|
||||
struct functor_to_visitor : Visitor
|
||||
{
|
||||
typedef Event event_filter;
|
||||
functor_to_visitor(const Visitor& visitor) : Visitor(visitor) {}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
struct on_no_event { enum { num = detail::on_no_event_num }; };
|
||||
|
||||
struct on_initialize_vertex {
|
||||
enum { num = detail::on_initialize_vertex_num }; };
|
||||
struct on_start_vertex { enum { num = detail::on_start_vertex_num }; };
|
||||
struct on_discover_vertex { enum { num = detail::on_discover_vertex_num }; };
|
||||
struct on_examine_vertex { enum { num = detail::on_examine_vertex_num }; };
|
||||
struct on_finish_vertex { enum { num = detail::on_finish_vertex_num }; };
|
||||
|
||||
struct on_examine_edge { enum { num = detail::on_examine_edge_num }; };
|
||||
struct on_tree_edge { enum { num = detail::on_tree_edge_num }; };
|
||||
struct on_non_tree_edge { enum { num = detail::on_non_tree_edge_num }; };
|
||||
struct on_gray_target { enum { num = detail::on_gray_target_num }; };
|
||||
struct on_black_target { enum { num = detail::on_black_target_num }; };
|
||||
struct on_forward_or_cross_edge {
|
||||
enum { num = detail::on_forward_or_cross_edge_num }; };
|
||||
struct on_back_edge { enum { num = detail::on_back_edge_num }; };
|
||||
|
||||
struct on_edge_relaxed { enum { num = detail::on_edge_relaxed_num }; };
|
||||
struct on_edge_not_relaxed {
|
||||
enum { num = detail::on_edge_not_relaxed_num }; };
|
||||
struct on_edge_minimized { enum { num = detail::on_edge_minimized_num }; };
|
||||
struct on_edge_not_minimized {
|
||||
enum { num = detail::on_edge_not_minimized_num }; };
|
||||
|
||||
struct true_tag { enum { num = true }; };
|
||||
struct false_tag { enum { num = false }; };
|
||||
|
||||
//========================================================================
|
||||
// base_visitor and null_visitor
|
||||
|
||||
// needed for MSVC workaround
|
||||
template <class Visitor>
|
||||
struct base_visitor {
|
||||
typedef on_no_event event_filter;
|
||||
template <class T, class Graph>
|
||||
void operator()(T, Graph&) { }
|
||||
};
|
||||
|
||||
struct null_visitor : public base_visitor<null_visitor> {
|
||||
typedef on_no_event event_filter;
|
||||
template <class T, class Graph>
|
||||
void operator()(T, Graph&) { }
|
||||
};
|
||||
|
||||
//========================================================================
|
||||
// The invoke_visitors() function
|
||||
|
||||
namespace detail {
|
||||
template <class Visitor, class T, class Graph>
|
||||
inline void
|
||||
invoke_dispatch(Visitor& v, T x, Graph& g, true_tag) {
|
||||
v(x, g);
|
||||
}
|
||||
template <class Visitor, class T, class Graph>
|
||||
inline void
|
||||
invoke_dispatch(Visitor&, T, Graph&, false_tag) { }
|
||||
} // namespace detail
|
||||
|
||||
template <class Visitor, class Rest, class T, class Graph, class Tag>
|
||||
inline void
|
||||
invoke_visitors(std::pair<Visitor, Rest>& vlist, T x, Graph& g, Tag tag) {
|
||||
typedef typename Visitor::event_filter Category;
|
||||
typedef typename graph_detail::is_same<Category, Tag>::is_same_tag
|
||||
IsSameTag;
|
||||
detail::invoke_dispatch(vlist.first, x, g, IsSameTag());
|
||||
invoke_visitors(vlist.second, x, g, tag);
|
||||
}
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
template <class Visitor, class T, class Graph, class Tag>
|
||||
inline void
|
||||
invoke_visitors(base_visitor<Visitor>& vis, T x, Graph& g, Tag) {
|
||||
typedef typename Visitor::event_filter Category;
|
||||
typedef typename graph_detail::is_same<Category, Tag>::is_same_tag
|
||||
IsSameTag;
|
||||
Visitor& v = static_cast<Visitor&>(vis);
|
||||
detail::invoke_dispatch(v, x, g, IsSameTag());
|
||||
}
|
||||
#else
|
||||
template <class Visitor, class T, class Graph, class Tag>
|
||||
inline void
|
||||
invoke_visitors(Visitor& v, T x, Graph& g, Tag) {
|
||||
typedef typename Visitor::event_filter Category;
|
||||
typedef typename graph_detail::is_same<Category, Tag>::is_same_tag
|
||||
IsSameTag;
|
||||
detail::invoke_dispatch(v, x, g, IsSameTag());
|
||||
}
|
||||
#endif
|
||||
|
||||
//========================================================================
|
||||
// predecessor_recorder
|
||||
|
||||
template <class PredecessorMap, class Tag>
|
||||
struct predecessor_recorder
|
||||
: public base_visitor<predecessor_recorder<PredecessorMap, Tag> >
|
||||
{
|
||||
typedef Tag event_filter;
|
||||
predecessor_recorder(PredecessorMap pa) : m_predecessor(pa) { }
|
||||
template <class Edge, class Graph>
|
||||
void operator()(Edge e, const Graph& g) {
|
||||
put(m_predecessor, target(e, g), source(e, g));
|
||||
}
|
||||
PredecessorMap m_predecessor;
|
||||
};
|
||||
template <class PredecessorMap, class Tag>
|
||||
predecessor_recorder<PredecessorMap, Tag>
|
||||
record_predecessors(PredecessorMap pa, Tag) {
|
||||
return predecessor_recorder<PredecessorMap, Tag> (pa);
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
// edge_predecessor_recorder
|
||||
|
||||
template <class PredEdgeMap, class Tag>
|
||||
struct edge_predecessor_recorder
|
||||
: public base_visitor<edge_predecessor_recorder<PredEdgeMap, Tag> >
|
||||
{
|
||||
typedef Tag event_filter;
|
||||
edge_predecessor_recorder(PredEdgeMap pa) : m_predecessor(pa) { }
|
||||
template <class Edge, class Graph>
|
||||
void operator()(Edge e, const Graph& g) {
|
||||
put(m_predecessor, target(e, g), e);
|
||||
}
|
||||
PredEdgeMap m_predecessor;
|
||||
};
|
||||
template <class PredEdgeMap, class Tag>
|
||||
edge_predecessor_recorder<PredEdgeMap, Tag>
|
||||
record_edge_predecessors(PredEdgeMap pa, Tag) {
|
||||
return edge_predecessor_recorder<PredEdgeMap, Tag> (pa);
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
// distance_recorder
|
||||
|
||||
template <class DistanceMap, class Tag>
|
||||
struct distance_recorder
|
||||
: public base_visitor<distance_recorder<DistanceMap, Tag> >
|
||||
{
|
||||
typedef Tag event_filter;
|
||||
distance_recorder(DistanceMap pa) : m_distance(pa) { }
|
||||
template <class Edge, class Graph>
|
||||
void operator()(Edge e, const Graph& g) {
|
||||
typename graph_traits<Graph>::vertex_descriptor
|
||||
u = source(e, g), v = target(e, g);
|
||||
put(m_distance, v, get(m_distance, u) + 1);
|
||||
}
|
||||
DistanceMap m_distance;
|
||||
};
|
||||
template <class DistanceMap, class Tag>
|
||||
distance_recorder<DistanceMap, Tag>
|
||||
record_distances(DistanceMap pa, Tag) {
|
||||
return distance_recorder<DistanceMap, Tag> (pa);
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
// time_stamper
|
||||
|
||||
|
||||
template <class TimeMap, class TimeT, class Tag>
|
||||
struct time_stamper
|
||||
: public base_visitor<time_stamper<TimeMap, TimeT, Tag> >
|
||||
{
|
||||
typedef Tag event_filter;
|
||||
time_stamper(TimeMap pa, TimeT& t) : m_time_pa(pa), m_time(t) { }
|
||||
template <class Vertex, class Graph>
|
||||
void operator()(Vertex u, const Graph&) {
|
||||
put(m_time_pa, u, ++m_time);
|
||||
}
|
||||
TimeMap m_time_pa;
|
||||
TimeT& m_time;
|
||||
};
|
||||
template <class TimeMap, class TimeT, class Tag>
|
||||
time_stamper<TimeMap, TimeT, Tag>
|
||||
stamp_times(TimeMap pa, TimeT& time_counter, Tag) {
|
||||
return time_stamper<TimeMap, TimeT, Tag>(pa, time_counter);
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
// property_writer
|
||||
|
||||
template <class PA, class OutputIterator, class Tag>
|
||||
struct property_writer
|
||||
: public base_visitor<property_writer<PA, OutputIterator, Tag> >
|
||||
{
|
||||
typedef Tag event_filter;
|
||||
|
||||
property_writer(PA pa, OutputIterator out) : m_pa(pa), m_out(out) { }
|
||||
|
||||
template <class T, class Graph>
|
||||
void operator()(T x, Graph&) { *m_out++ = get(m_pa, x); }
|
||||
PA m_pa;
|
||||
OutputIterator m_out;
|
||||
};
|
||||
template <class PA, class OutputIterator, class Tag>
|
||||
property_writer<PA, OutputIterator, Tag>
|
||||
write_property(PA pa, OutputIterator out, Tag) {
|
||||
return property_writer<PA, OutputIterator, Tag>(pa, out);
|
||||
}
|
||||
|
||||
#define BOOST_GRAPH_EVENT_STUB(Event,Kind) \
|
||||
typedef ::boost::Event Event##_type; \
|
||||
template<typename Visitor> \
|
||||
Kind##_visitor<std::pair<detail::functor_to_visitor<Event##_type, \
|
||||
Visitor>, Visitors> > \
|
||||
do_##Event(Visitor visitor) \
|
||||
{ \
|
||||
typedef std::pair<detail::functor_to_visitor<Event##_type, Visitor>, \
|
||||
Visitors> visitor_list; \
|
||||
typedef Kind##_visitor<visitor_list> result_type; \
|
||||
return result_type(visitor_list(visitor, m_vis)); \
|
||||
}
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#endif
|
||||
@@ -1,151 +0,0 @@
|
||||
//
|
||||
//=======================================================================
|
||||
// Copyright 2002 Marc Wintermantel (wintermantel@imes.mavt.ethz.ch)
|
||||
// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st)
|
||||
//
|
||||
// This file is part of the Boost Graph Library
|
||||
//
|
||||
// You should have received a copy of the License Agreement for the
|
||||
// Boost Graph Library along with the software; see the file LICENSE.
|
||||
// If not, contact Office of Research, University of Notre Dame, Notre
|
||||
// Dame, IN 46556.
|
||||
//
|
||||
// Permission to modify the code and to distribute modified code is
|
||||
// granted, provided the text of this NOTICE is retained, a notice that
|
||||
// the code was modified is included with the above COPYRIGHT NOTICE and
|
||||
// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
|
||||
// file is distributed with the modified code.
|
||||
//
|
||||
// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
|
||||
// By way of example, but not limitation, Licensor MAKES NO
|
||||
// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
|
||||
// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
|
||||
// OR OTHER RIGHTS.
|
||||
//=======================================================================
|
||||
//
|
||||
|
||||
#ifndef BOOST_GRAPH_WAVEFRONT_HPP
|
||||
#define BOOST_GRAPH_WAVEFRONT_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/detail/numeric_traits.hpp>
|
||||
#include <boost/graph/bandwidth.hpp>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <algorithm> // for std::min and std::max
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
ith_wavefront(typename graph_traits<Graph>::vertex_descriptor i,
|
||||
const Graph& g,
|
||||
VertexIndexMap index)
|
||||
{
|
||||
typename graph_traits<Graph>::vertex_descriptor v, w;
|
||||
typename graph_traits<Graph>::vertices_size_type b = 1;
|
||||
typename graph_traits<Graph>::out_edge_iterator edge_it2, edge_it2_end;
|
||||
typename graph_traits<Graph>::vertices_size_type index_i = index[i];
|
||||
std::vector<bool> rows_active(num_vertices(g), false);
|
||||
|
||||
rows_active[index_i] = true;
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
|
||||
{
|
||||
v = *ui;
|
||||
if(index[v] <= index_i)
|
||||
{
|
||||
for (tie(edge_it2, edge_it2_end) = out_edges(v, g); edge_it2 != edge_it2_end; ++edge_it2)
|
||||
{
|
||||
w = target(*edge_it2, g);
|
||||
if( (index[w] >= index_i) && (!rows_active[index[w]]) )
|
||||
{
|
||||
b++;
|
||||
rows_active[index[w]] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
ith_wavefront(typename graph_traits<Graph>::vertex_descriptor i,
|
||||
const Graph& g)
|
||||
{
|
||||
return ith_wavefront(i, g, get(vertex_index, g));
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
max_wavefront(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_wavefront(*i, g, index));
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
typename graph_traits<Graph>::vertices_size_type
|
||||
max_wavefront(const Graph& g)
|
||||
{
|
||||
return max_wavefront(g, get(vertex_index, g));
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
double
|
||||
aver_wavefront(const Graph& g, VertexIndexMap index)
|
||||
{
|
||||
double b = 0;
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
for (tie(i, end) = vertices(g); i != end; ++i)
|
||||
b += ith_wavefront(*i, g, index);
|
||||
|
||||
b /= num_vertices(g);
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
double
|
||||
aver_wavefront(const Graph& g)
|
||||
{
|
||||
return aver_wavefront(g, get(vertex_index, g));
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
double
|
||||
rms_wavefront(const Graph& g, VertexIndexMap index)
|
||||
{
|
||||
double b = 0;
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
for (tie(i, end) = vertices(g); i != end; ++i)
|
||||
b += std::pow(double ( ith_wavefront(*i, g, index) ), 2.0);
|
||||
|
||||
b /= num_vertices(g);
|
||||
|
||||
return std::sqrt(b);
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
double
|
||||
rms_wavefront(const Graph& g)
|
||||
{
|
||||
return rms_wavefront(g, get(vertex_index, g));
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GRAPH_WAVEFRONT_HPP
|
||||
@@ -21,8 +21,6 @@ test-suite graph :
|
||||
|
||||
[ compile bfs_cc.cpp : <sysinclude>$(BOOST_ROOT) ]
|
||||
|
||||
[ run brandes_betweenness_centrality_test.cpp ]
|
||||
|
||||
[ run dfs.cpp <lib>../../test/build/boost_test_exec_monitor
|
||||
: : : <sysinclude>$(BOOST_ROOT) ]
|
||||
|
||||
@@ -38,8 +36,6 @@ test-suite graph :
|
||||
|
||||
[ compile graph_concepts.cpp : <sysinclude>$(BOOST_ROOT) ]
|
||||
|
||||
[ run layout_test.cpp ]
|
||||
|
||||
[ compile reverse_graph_cc.cpp : <sysinclude>$(BOOST_ROOT) ]
|
||||
|
||||
[ run subgraph.cpp <lib>../../test/build/boost_test_exec_monitor
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Authors: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
#include <boost/graph/brandes_betweenness_centrality.hpp>
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
@@ -6,8 +14,8 @@
|
||||
#include <queue>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <boost/random/uniform_01.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
@@ -133,7 +141,8 @@ run_unweighted_test(Graph*, int V, unweighted_edge edge_init[], int E,
|
||||
|
||||
double relative_error =
|
||||
correct_centrality[v] == 0.0? centrality[v]
|
||||
: fabs(centrality[v] - correct_centrality[v]) / correct_centrality[v];
|
||||
: (centrality[v] - correct_centrality[v]) / correct_centrality[v];
|
||||
if (relative_error < 0) relative_error = -relative_error;
|
||||
BOOST_TEST(relative_error < error_tolerance);
|
||||
}
|
||||
|
||||
@@ -144,8 +153,9 @@ run_unweighted_test(Graph*, int V, unweighted_edge edge_init[], int E,
|
||||
if (correct_edge_centrality) {
|
||||
double relative_error =
|
||||
correct_edge_centrality[e] == 0.0? edge_centrality1[e]
|
||||
: fabs(edge_centrality1[e] - correct_edge_centrality[e])
|
||||
: (edge_centrality1[e] - correct_edge_centrality[e])
|
||||
/ correct_edge_centrality[e];
|
||||
if (relative_error < 0) relative_error = -relative_error;
|
||||
BOOST_TEST(relative_error < error_tolerance);
|
||||
|
||||
if (relative_error >= error_tolerance) {
|
||||
@@ -219,6 +229,9 @@ void randomly_add_edges(MutableGraph& g, double edge_probability)
|
||||
const bool is_undirected =
|
||||
is_same<directed_category, undirected_tag>::value;
|
||||
|
||||
minstd_rand gen;
|
||||
uniform_01<minstd_rand, double> rand_gen(gen);
|
||||
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex;
|
||||
typename graph_traits<MutableGraph>::vertex_iterator vi, vi_end;
|
||||
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
|
||||
@@ -228,7 +241,7 @@ void randomly_add_edges(MutableGraph& g, double edge_probability)
|
||||
while (wi != vi_end) {
|
||||
vertex w = *wi++;
|
||||
if (v != w) {
|
||||
if (drand48() < edge_probability) add_edge(v, w, g);
|
||||
if (rand_gen() < edge_probability) add_edge(v, w, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -459,11 +472,6 @@ int test_main(int, char*[])
|
||||
|
||||
run_wheel_test((Graph*)0, 15);
|
||||
|
||||
|
||||
long seed = time(0);
|
||||
std::cout << "Random seed = " << seed << std::endl;
|
||||
srand48(seed);
|
||||
|
||||
random_unweighted_test((Graph*)0, 500);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -112,9 +112,10 @@ struct kamada_kawai_done
|
||||
bool global)
|
||||
{
|
||||
if (global) {
|
||||
double diff = fabs(last_delta - delta_p);
|
||||
double diff = last_delta - delta_p;
|
||||
if (diff < 0) diff = -diff;
|
||||
last_delta = delta_p;
|
||||
return fabs(diff) < 0.01;
|
||||
return diff < 0.01;
|
||||
} else {
|
||||
return delta_p < 0.01;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user