mirror of
https://github.com/boostorg/graph.git
synced 2026-02-03 09:12:14 +00:00
Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41369]
This commit is contained in:
@@ -36,7 +36,10 @@
|
||||
#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/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/graph/detail/edge.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
@@ -238,12 +241,12 @@ namespace boost {
|
||||
namespace detail {
|
||||
template <class Directed> struct is_random_access {
|
||||
enum { value = false};
|
||||
typedef false_type type;
|
||||
typedef mpl::false_ type;
|
||||
};
|
||||
template <>
|
||||
struct is_random_access<vecS> {
|
||||
enum { value = true };
|
||||
typedef true_type type;
|
||||
typedef mpl::true_ type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -259,7 +262,8 @@ namespace boost {
|
||||
|
||||
template <class OutEdgeListS = vecS,
|
||||
class VertexListS = vecS,
|
||||
class DirectedS = directedS>
|
||||
class DirectedS = directedS,
|
||||
class EdgeListS = listS>
|
||||
struct adjacency_list_traits
|
||||
{
|
||||
typedef typename detail::is_random_access<VertexListS>::type
|
||||
@@ -267,9 +271,9 @@ namespace boost {
|
||||
typedef typename DirectedS::is_bidir_t is_bidir;
|
||||
typedef typename DirectedS::is_directed_t is_directed;
|
||||
|
||||
typedef typename boost::ct_if_t<is_bidir,
|
||||
typedef typename mpl::if_<is_bidir,
|
||||
bidirectional_tag,
|
||||
typename boost::ct_if_t<is_directed,
|
||||
typename mpl::if_<is_directed,
|
||||
directed_tag, undirected_tag
|
||||
>::type
|
||||
>::type directed_category;
|
||||
@@ -278,10 +282,26 @@ namespace boost {
|
||||
edge_parallel_category;
|
||||
|
||||
typedef void* vertex_ptr;
|
||||
typedef typename boost::ct_if_t<is_rand_access,
|
||||
typedef typename mpl::if_<is_rand_access,
|
||||
std::size_t, vertex_ptr>::type vertex_descriptor;
|
||||
typedef detail::edge_desc_impl<directed_category, vertex_descriptor>
|
||||
edge_descriptor;
|
||||
|
||||
typedef std::size_t vertices_size_type;
|
||||
|
||||
private:
|
||||
// Logic to figure out the edges_size_type
|
||||
struct dummy {};
|
||||
typedef typename container_gen<EdgeListS, dummy>::type EdgeContainer;
|
||||
typedef typename DirectedS::is_bidir_t BidirectionalT;
|
||||
typedef typename DirectedS::is_directed_t DirectedT;
|
||||
typedef typename mpl::and_<DirectedT,
|
||||
typename mpl::not_<BidirectionalT>::type >::type on_edge_storage;
|
||||
public:
|
||||
typedef typename mpl::if_<on_edge_storage,
|
||||
std::size_t, typename EdgeContainer::size_type
|
||||
>::type edges_size_type;
|
||||
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
@@ -335,10 +355,10 @@ namespace boost {
|
||||
edge_property_type;
|
||||
|
||||
// The types that are actually bundled
|
||||
typedef typename ct_if<(is_same<maybe_vertex_bundled, no_property>::value),
|
||||
typedef typename mpl::if_c<(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),
|
||||
typedef typename mpl::if_c<(is_same<maybe_edge_bundled, no_property>::value),
|
||||
no_edge_bundle,
|
||||
maybe_edge_bundled>::type edge_bundled;
|
||||
#else
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/graph_selectors.hpp>
|
||||
#include <boost/pending/ct_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/graph/adjacency_iterator.hpp>
|
||||
#include <boost/graph/detail/edge.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
@@ -441,7 +441,7 @@ namespace boost {
|
||||
BOOST_STATIC_ASSERT(type_traits::ice_not<(is_same<Directed, bidirectionalS>::value)>::value);
|
||||
#endif
|
||||
|
||||
typedef typename boost::ct_if_t<is_directed,
|
||||
typedef typename mpl::if_<is_directed,
|
||||
bidirectional_tag, undirected_tag>::type
|
||||
directed_category;
|
||||
|
||||
@@ -497,10 +497,10 @@ namespace boost {
|
||||
|
||||
public:
|
||||
// The types that are actually bundled
|
||||
typedef typename ct_if<(is_same<maybe_vertex_bundled, no_property>::value),
|
||||
typedef typename mpl::if_c<(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),
|
||||
typedef typename mpl::if_c<(is_same<maybe_edge_bundled, no_property>::value),
|
||||
no_edge_bundle,
|
||||
maybe_edge_bundled>::type edge_bundled;
|
||||
#else
|
||||
@@ -511,7 +511,7 @@ namespace boost {
|
||||
#endif
|
||||
|
||||
public: // should be private
|
||||
typedef typename ct_if_t<typename has_property<edge_property_type>::type,
|
||||
typedef typename mpl::if_<typename has_property<edge_property_type>::type,
|
||||
std::pair<bool, edge_property_type>, char>::type StoredEdge;
|
||||
#if (defined(BOOST_MSVC) && BOOST_MSVC <= 1300) || defined(BOOST_NO_STD_ALLOCATOR)
|
||||
typedef std::vector<StoredEdge> Matrix;
|
||||
@@ -545,7 +545,7 @@ namespace boost {
|
||||
vertex_descriptor, MatrixIter, size_type, edge_descriptor
|
||||
> UnDirOutEdgeIter;
|
||||
|
||||
typedef typename ct_if_t<
|
||||
typedef typename mpl::if_<
|
||||
typename Directed::is_directed_t, DirOutEdgeIter, UnDirOutEdgeIter
|
||||
>::type unfiltered_out_edge_iter;
|
||||
|
||||
@@ -557,7 +557,7 @@ namespace boost {
|
||||
vertex_descriptor, MatrixIter, size_type, edge_descriptor
|
||||
> UnDirInEdgeIter;
|
||||
|
||||
typedef typename ct_if_t<
|
||||
typedef typename mpl::if_<
|
||||
typename Directed::is_directed_t, DirInEdgeIter, UnDirInEdgeIter
|
||||
>::type unfiltered_in_edge_iter;
|
||||
|
||||
|
||||
@@ -417,7 +417,6 @@ namespace detail { namespace graph {
|
||||
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,
|
||||
@@ -432,7 +431,7 @@ namespace detail { namespace graph {
|
||||
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);
|
||||
std::vector<unsigned long long> path_count(V);
|
||||
|
||||
brandes_betweenness_centrality(
|
||||
g, centrality, edge_centrality_map,
|
||||
@@ -453,7 +452,6 @@ namespace detail { namespace graph {
|
||||
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,
|
||||
@@ -468,7 +466,7 @@ namespace detail { namespace graph {
|
||||
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);
|
||||
std::vector<unsigned long long> path_count(V);
|
||||
|
||||
brandes_betweenness_centrality(
|
||||
g, centrality, edge_centrality_map,
|
||||
|
||||
322
include/boost/graph/boyer_myrvold_planar_test.hpp
Normal file
322
include/boost/graph/boyer_myrvold_planar_test.hpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef __BOYER_MYRVOLD_PLANAR_TEST_HPP__
|
||||
#define __BOYER_MYRVOLD_PLANAR_TEST_HPP__
|
||||
|
||||
#include <boost/graph/planar_detail/boyer_myrvold_impl.hpp>
|
||||
#include <boost/parameter.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
struct no_kuratowski_subgraph_isolation {};
|
||||
struct no_planar_embedding {};
|
||||
|
||||
namespace boyer_myrvold_params
|
||||
{
|
||||
|
||||
BOOST_PARAMETER_KEYWORD(tag, graph)
|
||||
BOOST_PARAMETER_KEYWORD(tag, embedding)
|
||||
BOOST_PARAMETER_KEYWORD(tag, kuratowski_subgraph)
|
||||
BOOST_PARAMETER_KEYWORD(tag, vertex_index_map)
|
||||
BOOST_PARAMETER_KEYWORD(tag, edge_index_map)
|
||||
|
||||
typedef parameter::parameters< parameter::required<tag::graph>,
|
||||
tag::embedding,
|
||||
tag::kuratowski_subgraph,
|
||||
tag::vertex_index_map,
|
||||
tag::edge_index_map
|
||||
> boyer_myrvold_params_t;
|
||||
|
||||
namespace core
|
||||
{
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool dispatched_boyer_myrvold(ArgumentPack const& args,
|
||||
mpl::true_,
|
||||
mpl::true_
|
||||
)
|
||||
{
|
||||
//Dispatch for no planar embedding, no kuratowski subgraph isolation
|
||||
|
||||
typedef typename remove_const
|
||||
<
|
||||
typename remove_reference
|
||||
< typename parameter::binding
|
||||
< ArgumentPack, tag::graph>::type
|
||||
>::type
|
||||
>::type graph_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::vertex_index_map,
|
||||
typename property_map
|
||||
< typename remove_reference<graph_t>::type,
|
||||
vertex_index_t>::const_type
|
||||
>::type vertex_index_map_t;
|
||||
|
||||
boyer_myrvold_impl
|
||||
<graph_t,
|
||||
vertex_index_map_t,
|
||||
graph::detail::no_old_handles,
|
||||
graph::detail::no_embedding
|
||||
>
|
||||
planarity_tester(args[graph],
|
||||
args[vertex_index_map |
|
||||
get(vertex_index, args[graph])
|
||||
]
|
||||
);
|
||||
|
||||
return planarity_tester.is_planar() ? true : false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool dispatched_boyer_myrvold(ArgumentPack const& args,
|
||||
mpl::true_,
|
||||
mpl::false_
|
||||
)
|
||||
{
|
||||
//Dispatch for no planar embedding, kuratowski subgraph isolation
|
||||
typedef typename remove_const
|
||||
<
|
||||
typename remove_reference
|
||||
< typename parameter::binding
|
||||
< ArgumentPack, tag::graph>::type
|
||||
>::type
|
||||
>::type graph_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::vertex_index_map,
|
||||
typename property_map<graph_t, vertex_index_t>::type
|
||||
>::type vertex_index_map_t;
|
||||
|
||||
boyer_myrvold_impl
|
||||
<graph_t,
|
||||
vertex_index_map_t,
|
||||
graph::detail::store_old_handles,
|
||||
graph::detail::no_embedding
|
||||
>
|
||||
planarity_tester(args[graph],
|
||||
args[vertex_index_map |
|
||||
get(vertex_index, args[graph])
|
||||
]
|
||||
);
|
||||
|
||||
if (planarity_tester.is_planar())
|
||||
return true;
|
||||
else
|
||||
{
|
||||
planarity_tester.extract_kuratowski_subgraph
|
||||
(args[kuratowski_subgraph],
|
||||
args[edge_index_map|get(edge_index, args[graph])]
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool dispatched_boyer_myrvold(ArgumentPack const& args,
|
||||
mpl::false_,
|
||||
mpl::true_
|
||||
)
|
||||
{
|
||||
//Dispatch for planar embedding, no kuratowski subgraph isolation
|
||||
typedef typename remove_const
|
||||
<
|
||||
typename remove_reference
|
||||
< typename parameter::binding
|
||||
< ArgumentPack, tag::graph>::type
|
||||
>::type
|
||||
>::type graph_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::vertex_index_map,
|
||||
typename property_map<graph_t, vertex_index_t>::type
|
||||
>::type vertex_index_map_t;
|
||||
|
||||
boyer_myrvold_impl
|
||||
<graph_t,
|
||||
vertex_index_map_t,
|
||||
graph::detail::no_old_handles,
|
||||
#ifdef BOOST_GRAPH_PREFER_STD_LIB
|
||||
graph::detail::std_list
|
||||
#else
|
||||
graph::detail::recursive_lazy_list
|
||||
#endif
|
||||
>
|
||||
planarity_tester(args[graph],
|
||||
args[vertex_index_map |
|
||||
get(vertex_index, args[graph])
|
||||
]
|
||||
);
|
||||
|
||||
if (planarity_tester.is_planar())
|
||||
{
|
||||
planarity_tester.make_edge_permutation(args[embedding]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool dispatched_boyer_myrvold(ArgumentPack const& args,
|
||||
mpl::false_,
|
||||
mpl::false_
|
||||
)
|
||||
{
|
||||
//Dispatch for planar embedding, kuratowski subgraph isolation
|
||||
typedef typename remove_const
|
||||
<
|
||||
typename remove_reference
|
||||
< typename parameter::binding
|
||||
< ArgumentPack, tag::graph>::type
|
||||
>::type
|
||||
>::type graph_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::vertex_index_map,
|
||||
typename property_map<graph_t, vertex_index_t>::type
|
||||
>::type vertex_index_map_t;
|
||||
|
||||
boyer_myrvold_impl
|
||||
<graph_t,
|
||||
vertex_index_map_t,
|
||||
graph::detail::store_old_handles,
|
||||
#ifdef BOOST_BGL_PREFER_STD_LIB
|
||||
graph::detail::std_list
|
||||
#else
|
||||
graph::detail::recursive_lazy_list
|
||||
#endif
|
||||
>
|
||||
planarity_tester(args[graph],
|
||||
args[vertex_index_map |
|
||||
get(vertex_index, args[graph])
|
||||
]
|
||||
);
|
||||
|
||||
if (planarity_tester.is_planar())
|
||||
{
|
||||
planarity_tester.make_edge_permutation(args[embedding]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
planarity_tester.extract_kuratowski_subgraph
|
||||
(args[kuratowski_subgraph],
|
||||
args[edge_index_map | get(edge_index, args[graph])]
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename ArgumentPack>
|
||||
bool boyer_myrvold_planarity_test(ArgumentPack const& args)
|
||||
{
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::kuratowski_subgraph,
|
||||
const no_kuratowski_subgraph_isolation&
|
||||
>::type
|
||||
kuratowski_arg_t;
|
||||
|
||||
typedef typename parameter::binding
|
||||
< ArgumentPack,
|
||||
tag::embedding,
|
||||
const no_planar_embedding&
|
||||
>::type
|
||||
embedding_arg_t;
|
||||
|
||||
return dispatched_boyer_myrvold
|
||||
(args,
|
||||
boost::is_same
|
||||
<embedding_arg_t, const no_planar_embedding&>(),
|
||||
boost::is_same
|
||||
<kuratowski_arg_t, const no_kuratowski_subgraph_isolation&>()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} //namespace core
|
||||
|
||||
} //namespace boyer_myrvold_params
|
||||
|
||||
|
||||
template <typename A0>
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0));
|
||||
}
|
||||
|
||||
template <typename A0, typename A1>
|
||||
// bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1)
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1));
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2>
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0,
|
||||
A1 const& arg1,
|
||||
A2 const& arg2
|
||||
)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1,arg2));
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2, typename A3>
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0,
|
||||
A1 const& arg1,
|
||||
A2 const& arg2,
|
||||
A3 const& arg3
|
||||
)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1,arg2,arg3));
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename A2, typename A3, typename A4>
|
||||
bool boyer_myrvold_planarity_test(A0 const& arg0,
|
||||
A1 const& arg1,
|
||||
A2 const& arg2,
|
||||
A3 const& arg3,
|
||||
A4 const& arg4
|
||||
)
|
||||
{
|
||||
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
|
||||
(boyer_myrvold_params::boyer_myrvold_params_t()
|
||||
(arg0,arg1,arg2,arg3,arg4)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //__BOYER_MYRVOLD_PLANAR_TEST_HPP__
|
||||
270
include/boost/graph/chrobak_payne_drawing.hpp
Normal file
270
include/boost/graph/chrobak_payne_drawing.hpp
Normal file
@@ -0,0 +1,270 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef __CHROBAK_PAYNE_DRAWING_HPP__
|
||||
#define __CHROBAK_PAYNE_DRAWING_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next and prior
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace graph { namespace detail
|
||||
{
|
||||
|
||||
template<typename Graph,
|
||||
typename VertexToVertexMap,
|
||||
typename VertexTo1DCoordMap>
|
||||
void accumulate_offsets(typename graph_traits<Graph>::vertex_descriptor v,
|
||||
std::size_t offset,
|
||||
const Graph& g,
|
||||
VertexTo1DCoordMap x,
|
||||
VertexTo1DCoordMap delta_x,
|
||||
VertexToVertexMap left,
|
||||
VertexToVertexMap right)
|
||||
{
|
||||
if (v != graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
x[v] += delta_x[v] + offset;
|
||||
accumulate_offsets(left[v], x[v], g, x, delta_x, left, right);
|
||||
accumulate_offsets(right[v], x[v], g, x, delta_x, left, right);
|
||||
}
|
||||
}
|
||||
|
||||
} /*namespace detail*/ } /*namespace graph*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename ForwardIterator,
|
||||
typename GridPositionMap,
|
||||
typename VertexIndexMap>
|
||||
void chrobak_payne_straight_line_drawing(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
ForwardIterator ordering_begin,
|
||||
ForwardIterator ordering_end,
|
||||
GridPositionMap drawing,
|
||||
VertexIndexMap vm
|
||||
)
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename PlanarEmbedding::value_type::const_iterator
|
||||
edge_permutation_iterator_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef std::vector<vertex_t> vertex_vector_t;
|
||||
typedef std::vector<v_size_t> vsize_vector_t;
|
||||
typedef std::vector<bool> bool_vector_t;
|
||||
typedef boost::iterator_property_map
|
||||
<typename vertex_vector_t::iterator, VertexIndexMap>
|
||||
vertex_to_vertex_map_t;
|
||||
typedef boost::iterator_property_map
|
||||
<typename vsize_vector_t::iterator, VertexIndexMap>
|
||||
vertex_to_vsize_map_t;
|
||||
typedef boost::iterator_property_map
|
||||
<typename bool_vector_t::iterator, VertexIndexMap>
|
||||
vertex_to_bool_map_t;
|
||||
|
||||
vertex_vector_t left_vector(num_vertices(g),
|
||||
graph_traits<Graph>::null_vertex()
|
||||
);
|
||||
vertex_vector_t right_vector(num_vertices(g),
|
||||
graph_traits<Graph>::null_vertex()
|
||||
);
|
||||
vsize_vector_t seen_as_right_vector(num_vertices(g), 0);
|
||||
vsize_vector_t seen_vector(num_vertices(g), 0);
|
||||
vsize_vector_t delta_x_vector(num_vertices(g),0);
|
||||
vsize_vector_t y_vector(num_vertices(g));
|
||||
vsize_vector_t x_vector(num_vertices(g),0);
|
||||
bool_vector_t installed_vector(num_vertices(g),false);
|
||||
|
||||
vertex_to_vertex_map_t left(left_vector.begin(), vm);
|
||||
vertex_to_vertex_map_t right(right_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t seen_as_right(seen_as_right_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t seen(seen_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t delta_x(delta_x_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t y(y_vector.begin(), vm);
|
||||
vertex_to_vsize_map_t x(x_vector.begin(), vm);
|
||||
vertex_to_bool_map_t installed(installed_vector.begin(), vm);
|
||||
|
||||
v_size_t timestamp = 1;
|
||||
vertex_vector_t installed_neighbors;
|
||||
|
||||
ForwardIterator itr = ordering_begin;
|
||||
vertex_t v1 = *itr; ++itr;
|
||||
vertex_t v2 = *itr; ++itr;
|
||||
vertex_t v3 = *itr; ++itr;
|
||||
|
||||
delta_x[v2] = 1;
|
||||
delta_x[v3] = 1;
|
||||
|
||||
y[v1] = 0;
|
||||
y[v2] = 0;
|
||||
y[v3] = 1;
|
||||
|
||||
right[v1] = v3;
|
||||
right[v3] = v2;
|
||||
|
||||
installed[v1] = installed[v2] = installed[v3] = true;
|
||||
|
||||
for(ForwardIterator itr_end = ordering_end; itr != itr_end; ++itr)
|
||||
{
|
||||
vertex_t v = *itr;
|
||||
|
||||
// First, find the leftmost and rightmost neighbor of v on the outer
|
||||
// cycle of the embedding.
|
||||
// Note: since we're moving clockwise through the edges adjacent to v,
|
||||
// we're actually moving from right to left among v's neighbors on the
|
||||
// outer face (since v will be installed above them all) looking for
|
||||
// the leftmost and rightmost installed neigbhors
|
||||
|
||||
vertex_t leftmost = graph_traits<Graph>::null_vertex();
|
||||
vertex_t rightmost = graph_traits<Graph>::null_vertex();
|
||||
|
||||
installed_neighbors.clear();
|
||||
|
||||
vertex_t prev_vertex = graph_traits<Graph>::null_vertex();
|
||||
edge_permutation_iterator_t pi, pi_end;
|
||||
pi_end = embedding[v].end();
|
||||
for(pi = embedding[v].begin(); pi != pi_end; ++pi)
|
||||
{
|
||||
vertex_t curr_vertex = source(*pi,g) == v ?
|
||||
target(*pi,g) : source(*pi,g);
|
||||
|
||||
// Skip any self-loops or parallel edges
|
||||
if (curr_vertex == v || curr_vertex == prev_vertex)
|
||||
continue;
|
||||
|
||||
if (installed[curr_vertex])
|
||||
{
|
||||
seen[curr_vertex] = timestamp;
|
||||
|
||||
if (right[curr_vertex] != graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
seen_as_right[right[curr_vertex]] = timestamp;
|
||||
}
|
||||
installed_neighbors.push_back(curr_vertex);
|
||||
}
|
||||
|
||||
prev_vertex = curr_vertex;
|
||||
}
|
||||
|
||||
typename vertex_vector_t::iterator vi, vi_end;
|
||||
vi_end = installed_neighbors.end();
|
||||
for(vi = installed_neighbors.begin(); vi != vi_end; ++vi)
|
||||
{
|
||||
if (right[*vi] == graph_traits<Graph>::null_vertex() ||
|
||||
seen[right[*vi]] != timestamp
|
||||
)
|
||||
rightmost = *vi;
|
||||
if (seen_as_right[*vi] != timestamp)
|
||||
leftmost = *vi;
|
||||
}
|
||||
|
||||
++timestamp;
|
||||
|
||||
//stretch gaps
|
||||
++delta_x[right[leftmost]];
|
||||
++delta_x[rightmost];
|
||||
|
||||
//adjust offsets
|
||||
std::size_t delta_p_q = 0;
|
||||
vertex_t stopping_vertex = right[rightmost];
|
||||
for(vertex_t temp = right[leftmost]; temp != stopping_vertex;
|
||||
temp = right[temp]
|
||||
)
|
||||
{
|
||||
delta_p_q += delta_x[temp];
|
||||
}
|
||||
|
||||
delta_x[v] = (y[rightmost] - y[leftmost] + delta_p_q)/2;
|
||||
y[v] = (y[rightmost] + y[leftmost] + delta_p_q)/2;
|
||||
delta_x[rightmost] = delta_p_q - delta_x[v];
|
||||
|
||||
bool leftmost_and_rightmost_adjacent = right[leftmost] == rightmost;
|
||||
if (!leftmost_and_rightmost_adjacent)
|
||||
delta_x[right[leftmost]] -= delta_x[v];
|
||||
|
||||
//install v
|
||||
if (!leftmost_and_rightmost_adjacent)
|
||||
{
|
||||
left[v] = right[leftmost];
|
||||
vertex_t next_to_rightmost;
|
||||
for(vertex_t temp = leftmost; temp != rightmost;
|
||||
temp = right[temp]
|
||||
)
|
||||
{
|
||||
next_to_rightmost = temp;
|
||||
}
|
||||
|
||||
right[next_to_rightmost] = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
else
|
||||
{
|
||||
left[v] = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
|
||||
right[leftmost] = v;
|
||||
right[v] = rightmost;
|
||||
installed[v] = true;
|
||||
|
||||
}
|
||||
|
||||
graph::detail::accumulate_offsets
|
||||
(*ordering_begin,0,g,x,delta_x,left,right);
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_t v(*vi);
|
||||
drawing[v].x = x[v];
|
||||
drawing[v].y = y[v];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename ForwardIterator,
|
||||
typename GridPositionMap>
|
||||
inline void chrobak_payne_straight_line_drawing(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
ForwardIterator ord_begin,
|
||||
ForwardIterator ord_end,
|
||||
GridPositionMap drawing
|
||||
)
|
||||
{
|
||||
chrobak_payne_straight_line_drawing(g,
|
||||
embedding,
|
||||
ord_begin,
|
||||
ord_end,
|
||||
drawing,
|
||||
get(vertex_index,g)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //__CHROBAK_PAYNE_DRAWING_HPP__
|
||||
@@ -739,7 +739,7 @@ private:
|
||||
typedef graph_traits<BOOST_CSR_GRAPH_TYPE> traits;
|
||||
typedef VertexProperty vertex_bundled;
|
||||
typedef EdgeProperty edge_bundled;
|
||||
typedef typename ct_if<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
|
||||
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
|
||||
typename traits::vertex_descriptor,
|
||||
typename traits::edge_descriptor>::type
|
||||
descriptor;
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
|
||||
#include <boost/pending/ct_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/pending/container_traits.hpp>
|
||||
#include <boost/graph/detail/adj_list_edge_iterator.hpp>
|
||||
@@ -63,6 +65,11 @@
|
||||
*/
|
||||
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# define Graph Graph_
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
@@ -2268,7 +2275,7 @@ namespace boost {
|
||||
typedef typename container_gen<VertexListS,
|
||||
vertex_ptr>::type SeqVertexList;
|
||||
typedef boost::integer_range<std::size_t> RandVertexList;
|
||||
typedef typename boost::ct_if_t<is_rand_access,
|
||||
typedef typename mpl::if_<is_rand_access,
|
||||
RandVertexList, SeqVertexList>::type VertexList;
|
||||
|
||||
typedef typename VertexList::iterator vertex_iterator;
|
||||
@@ -2278,10 +2285,10 @@ namespace boost {
|
||||
typedef typename container_gen<EdgeListS,
|
||||
list_edge<vertex_descriptor, EdgeProperty> >::type EdgeContainer;
|
||||
|
||||
typedef typename ct_and<DirectedT,
|
||||
typename ct_not<BidirectionalT>::type >::type on_edge_storage;
|
||||
typedef typename mpl::and_<DirectedT,
|
||||
typename mpl::not_<BidirectionalT>::type >::type on_edge_storage;
|
||||
|
||||
typedef typename boost::ct_if_t<on_edge_storage,
|
||||
typedef typename mpl::if_<on_edge_storage,
|
||||
std::size_t, typename EdgeContainer::size_type
|
||||
>::type edges_size_type;
|
||||
|
||||
@@ -2289,9 +2296,9 @@ namespace boost {
|
||||
|
||||
typedef typename detail::is_random_access<EdgeListS>::type is_edge_ra;
|
||||
|
||||
typedef typename boost::ct_if_t<on_edge_storage,
|
||||
typedef typename mpl::if_<on_edge_storage,
|
||||
stored_edge_property<vertex_descriptor, EdgeProperty>,
|
||||
typename boost::ct_if_t<is_edge_ra,
|
||||
typename mpl::if_<is_edge_ra,
|
||||
stored_ra_edge_iter<vertex_descriptor, EdgeContainer, EdgeProperty>,
|
||||
stored_edge_iter<vertex_descriptor, EdgeIter, EdgeProperty>
|
||||
>::type
|
||||
@@ -2342,7 +2349,7 @@ namespace boost {
|
||||
typedef adj_list_edge_iterator<vertex_iterator, out_edge_iterator,
|
||||
graph_type> DirectedEdgeIter;
|
||||
|
||||
typedef typename boost::ct_if_t<on_edge_storage,
|
||||
typedef typename mpl::if_<on_edge_storage,
|
||||
DirectedEdgeIter, UndirectedEdgeIter>::type edge_iterator;
|
||||
|
||||
// stored_vertex and StoredVertexList
|
||||
@@ -2376,10 +2383,10 @@ namespace boost {
|
||||
InEdgeList m_in_edges;
|
||||
VertexProperty m_property;
|
||||
};
|
||||
typedef typename boost::ct_if_t<is_rand_access,
|
||||
typename boost::ct_if_t<BidirectionalT,
|
||||
typedef typename mpl::if_<is_rand_access,
|
||||
typename mpl::if_<BidirectionalT,
|
||||
bidir_rand_stored_vertex, rand_stored_vertex>::type,
|
||||
typename boost::ct_if_t<BidirectionalT,
|
||||
typename mpl::if_<BidirectionalT,
|
||||
bidir_seq_stored_vertex, seq_stored_vertex>::type
|
||||
>::type StoredVertex;
|
||||
struct stored_vertex : public StoredVertex {
|
||||
@@ -2389,20 +2396,20 @@ namespace boost {
|
||||
|
||||
typedef typename container_gen<VertexListS, stored_vertex>::type
|
||||
RandStoredVertexList;
|
||||
typedef typename boost::ct_if_t< is_rand_access,
|
||||
typedef typename mpl::if_< is_rand_access,
|
||||
RandStoredVertexList, SeqStoredVertexList>::type StoredVertexList;
|
||||
}; // end of config
|
||||
|
||||
|
||||
typedef typename boost::ct_if_t<BidirectionalT,
|
||||
typedef typename mpl::if_<BidirectionalT,
|
||||
bidirectional_graph_helper_with_property<config>,
|
||||
typename boost::ct_if_t<DirectedT,
|
||||
typename mpl::if_<DirectedT,
|
||||
directed_graph_helper<config>,
|
||||
undirected_graph_helper<config>
|
||||
>::type
|
||||
>::type DirectedHelper;
|
||||
|
||||
typedef typename boost::ct_if_t<is_rand_access,
|
||||
typedef typename mpl::if_<is_rand_access,
|
||||
vec_adj_list_impl<Graph, config, DirectedHelper>,
|
||||
adj_list_impl<Graph, config, DirectedHelper>
|
||||
>::type type;
|
||||
@@ -2807,6 +2814,11 @@ namespace BOOST_STD_EXTENSION_NAMESPACE {
|
||||
#undef stored_edge_property
|
||||
#undef stored_edge_iter
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
#undef Graph
|
||||
#endif
|
||||
|
||||
#endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,910 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2001 Jeremy G. Siek
|
||||
// Authors: Jeremy G. Siek
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
/*
|
||||
* 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,90 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2002 Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef BOOST_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
|
||||
@@ -49,7 +49,7 @@ namespace boost {
|
||||
// protected:
|
||||
property_type* m_eproperty;
|
||||
};
|
||||
|
||||
|
||||
template <class D, class V>
|
||||
inline bool
|
||||
operator==(const detail::edge_desc_impl<D,V>& a,
|
||||
@@ -65,6 +65,36 @@ namespace boost {
|
||||
return ! (a.get_property() == b.get_property());
|
||||
}
|
||||
|
||||
// Order edges according to the address of their property object
|
||||
template <class D, class V>
|
||||
inline bool
|
||||
operator<(const detail::edge_desc_impl<D,V>& a,
|
||||
const detail::edge_desc_impl<D,V>& b)
|
||||
{
|
||||
return a.get_property() < b.get_property();
|
||||
}
|
||||
template <class D, class V>
|
||||
inline bool
|
||||
operator<=(const detail::edge_desc_impl<D,V>& a,
|
||||
const detail::edge_desc_impl<D,V>& b)
|
||||
{
|
||||
return a.get_property() <= b.get_property();
|
||||
}
|
||||
template <class D, class V>
|
||||
inline bool
|
||||
operator>(const detail::edge_desc_impl<D,V>& a,
|
||||
const detail::edge_desc_impl<D,V>& b)
|
||||
{
|
||||
return a.get_property() > b.get_property();
|
||||
}
|
||||
template <class D, class V>
|
||||
inline bool
|
||||
operator>=(const detail::edge_desc_impl<D,V>& a,
|
||||
const detail::edge_desc_impl<D,V>& b)
|
||||
{
|
||||
return a.get_property() >= b.get_property();
|
||||
}
|
||||
|
||||
} //namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef BOOST_GRAPH_DETAIL_IS_SAME_HPP
|
||||
#define BOOST_GRAPH_DETAIL_IS_SAME_HPP
|
||||
|
||||
#include <boost/pending/ct_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
struct false_tag;
|
||||
@@ -30,7 +30,7 @@ namespace boost {
|
||||
template <class U, class V>
|
||||
struct is_same {
|
||||
enum { Unum = U::num, Vnum = V::num };
|
||||
typedef typename boost::ct_if< (Unum == Vnum),
|
||||
typedef typename mpl::if_c< (Unum == Vnum),
|
||||
boost::true_tag, boost::false_tag>::type is_same_tag;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -149,7 +149,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
ID
|
||||
= ( lexeme_d[((alpha_p | ch_p('_')) >> *(alnum_p | ch_p('_')))]
|
||||
| real_p
|
||||
| confix_p('"', *c_escape_ch_p, '"')
|
||||
| lexeme_d[confix_p('"', *c_escape_ch_p, '"')]
|
||||
| comment_nest_p('<', '>')
|
||||
)[ID.name = construct_<std::string>(arg1,arg2)]
|
||||
;
|
||||
@@ -161,7 +161,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
>> !( ch_p('=')
|
||||
>> ID[a_list.value = arg1])
|
||||
[phoenix::bind(&definition::call_prop_actor)
|
||||
(var(*this),a_list.key,a_list.value)],ch_p(','));
|
||||
(var(*this),a_list.key,a_list.value)],!ch_p(','));
|
||||
|
||||
attr_list = +(ch_p('[') >> !a_list >> ch_p(']'));
|
||||
|
||||
@@ -182,6 +182,14 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
= ( ID[node_id.name = arg1] >> (!port) )
|
||||
[phoenix::bind(&definition::memoize_node)(var(*this))];
|
||||
|
||||
graph_stmt
|
||||
= (ID[graph_stmt.key = arg1] >>
|
||||
ch_p('=') >>
|
||||
ID[graph_stmt.value = arg1])
|
||||
[phoenix::bind(&definition::call_graph_prop)
|
||||
(var(*this),graph_stmt.key,graph_stmt.value)]
|
||||
; // Graph property.
|
||||
|
||||
attr_stmt
|
||||
= (as_lower_d[keyword_p("graph")]
|
||||
>> attr_list(actor_t(phoenix::bind(&definition::default_graph_prop)
|
||||
@@ -236,7 +244,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
|
||||
|
||||
stmt
|
||||
= (ID >> ch_p('=') >> ID) // Graph property -- ignore.
|
||||
= graph_stmt
|
||||
| attr_stmt
|
||||
| data_stmt
|
||||
;
|
||||
@@ -331,7 +339,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
edge_stack_t& edge_stack = data_stmt.edge_stack();
|
||||
for(nodes_t::iterator i = sources.begin(); i != sources.end(); ++i) {
|
||||
for(nodes_t::iterator j = dests.begin(); j != dests.end(); ++j) {
|
||||
// Create the edge and and push onto the edge stack.
|
||||
// Create the edge and push onto the edge stack.
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
std::cout << "Edge " << *i << " to " << *j << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
@@ -376,8 +384,13 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
}
|
||||
}
|
||||
|
||||
// default_graph_prop - Just ignore graph properties.
|
||||
void default_graph_prop(id_t const&, id_t const&) { }
|
||||
// default_graph_prop - Store as a graph property.
|
||||
void default_graph_prop(id_t const& key, id_t const& value) {
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
std::cout << key << " = " << value << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
self.graph_.set_graph_property(key, value);
|
||||
}
|
||||
|
||||
// default_node_prop - declare default properties for any future new nodes
|
||||
void default_node_prop(id_t const& key, id_t const& value) {
|
||||
@@ -432,6 +445,15 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
actor(lhs,rhs);
|
||||
}
|
||||
|
||||
void call_graph_prop(std::string const& lhs, std::string const& rhs) {
|
||||
// If first and last characters of the rhs are double-quotes,
|
||||
// remove them.
|
||||
if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"')
|
||||
this->default_graph_prop(lhs, rhs.substr(1, rhs.size()-2));
|
||||
else
|
||||
this->default_graph_prop(lhs,rhs);
|
||||
}
|
||||
|
||||
void set_node_property(node_t const& node, id_t const& key,
|
||||
id_t const& value) {
|
||||
|
||||
@@ -454,7 +476,11 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
self.graph_.set_edge_property(key, edge, value);
|
||||
#ifdef BOOST_GRAPH_DEBUG
|
||||
// Tell the world
|
||||
std::cout << "(" << edge.first << "," << edge.second << "): "
|
||||
#if 0 // RG - edge representation changed,
|
||||
std::cout << "(" << edge.first << "," << edge.second << "): "
|
||||
#else
|
||||
std::cout << "an edge: "
|
||||
#endif // 0
|
||||
<< key << " = " << value << std::endl;
|
||||
#endif // BOOST_GRAPH_DEBUG
|
||||
}
|
||||
@@ -476,6 +502,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
|
||||
rule_t port_angle;
|
||||
rule_t port;
|
||||
boost::spirit::rule<ScannerT,node_id_closure::context_t> node_id;
|
||||
boost::spirit::rule<ScannerT,property_closure::context_t> graph_stmt;
|
||||
rule_t attr_stmt;
|
||||
boost::spirit::rule<ScannerT,data_stmt_closure::context_t> data_stmt;
|
||||
boost::spirit::rule<ScannerT,subgraph_closure::context_t> subgraph;
|
||||
@@ -527,9 +554,9 @@ struct dot_skipper : public boost::spirit::grammar<dot_skipper>
|
||||
using namespace boost::spirit;
|
||||
using namespace phoenix;
|
||||
// comment forms
|
||||
skip = space_p
|
||||
skip = eol_p >> comment_p("#")
|
||||
| space_p
|
||||
| comment_p("//")
|
||||
| comment_p("#")
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
|
||||
| confix_p(str_p("/*") ,*anychar_p, str_p("*/"))
|
||||
#else
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/pending/ct_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
@@ -241,11 +242,11 @@ namespace boost {
|
||||
template <class Cat>
|
||||
struct is_random {
|
||||
enum { RET = false };
|
||||
typedef false_type type;
|
||||
typedef mpl::false_ type;
|
||||
};
|
||||
template <>
|
||||
struct is_random<std::random_access_iterator_tag> {
|
||||
enum { RET = true }; typedef true_type type;
|
||||
enum { RET = true }; typedef mpl::true_ type;
|
||||
};
|
||||
|
||||
// The edge_list class conditionally inherits from one of the
|
||||
@@ -262,7 +263,7 @@ namespace boost {
|
||||
class Cat>
|
||||
#endif
|
||||
class edge_list
|
||||
: public ct_if_t< typename is_random<Cat>::type,
|
||||
: public mpl::if_< typename is_random<Cat>::type,
|
||||
edge_list_impl_ra< edge_list<EdgeIter,T,D,Cat>, EdgeIter,T,D>,
|
||||
edge_list_impl< edge_list<EdgeIter,T,D,Cat>, EdgeIter,T,D>
|
||||
>::type
|
||||
|
||||
@@ -18,125 +18,10 @@
|
||||
#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(u, g);
|
||||
n = out_degree(u, g);
|
||||
e = *p.first;
|
||||
u = source(e, g);
|
||||
v = target(e, g);
|
||||
const_constraints(g);
|
||||
}
|
||||
void const_constraints(const G& cg) {
|
||||
p = out_edges(u, cg);
|
||||
n = out_degree(u, cg);
|
||||
e = *p.first;
|
||||
u = source(e, cg);
|
||||
v = target(e, cg);
|
||||
}
|
||||
std::pair<out_edge_iterator, out_edge_iterator> p;
|
||||
typename graph_traits<G>::vertex_descriptor u, v;
|
||||
typename graph_traits<G>::edge_descriptor e;
|
||||
typename graph_traits<G>::degree_size_type n;
|
||||
G g;
|
||||
};
|
||||
|
||||
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& cg) {
|
||||
p = in_edges(v, cg);
|
||||
n = in_degree(v, cg);
|
||||
e = *p.first;
|
||||
}
|
||||
std::pair<in_edge_iterator, in_edge_iterator> p;
|
||||
typename graph_traits<G>::vertex_descriptor v;
|
||||
typename graph_traits<G>::edge_descriptor e;
|
||||
typename graph_traits<G>::degree_size_type n;
|
||||
G g;
|
||||
};
|
||||
|
||||
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& cg) {
|
||||
p = adjacent_vertices(v, cg);
|
||||
}
|
||||
std::pair<adjacency_iterator,adjacency_iterator> p;
|
||||
typename graph_traits<G>::vertex_descriptor v;
|
||||
G g;
|
||||
};
|
||||
#include <boost/concept/detail/concept_def.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
|
||||
// you want to use vector_as_graph, it is! I'm sure the graph
|
||||
// library leaves these out all over the place. Probably a
|
||||
@@ -156,18 +41,138 @@ template <class T>
|
||||
typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
#endif
|
||||
|
||||
template <class G>
|
||||
struct VertexListGraphConcept
|
||||
namespace concepts {
|
||||
BOOST_concept(MultiPassInputIterator,(T)) {
|
||||
BOOST_CONCEPT_USAGE(MultiPassInputIterator) {
|
||||
BOOST_CONCEPT_ASSERT((InputIterator<T>));
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_concept(Graph,(G))
|
||||
{
|
||||
typedef typename graph_traits<G>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<G>::directed_category directed_category;
|
||||
typedef typename graph_traits<G>::edge_parallel_category
|
||||
edge_parallel_category;
|
||||
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
|
||||
BOOST_CONCEPT_USAGE(Graph)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((DefaultConstructible<vertex_descriptor>));
|
||||
BOOST_CONCEPT_ASSERT((EqualityComparable<vertex_descriptor>));
|
||||
BOOST_CONCEPT_ASSERT((Assignable<vertex_descriptor>));
|
||||
}
|
||||
G g;
|
||||
};
|
||||
|
||||
BOOST_concept(IncidenceGraph,(G))
|
||||
: Graph<G>
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<G>::out_edge_iterator
|
||||
out_edge_iterator;
|
||||
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
|
||||
BOOST_CONCEPT_USAGE(IncidenceGraph) {
|
||||
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<out_edge_iterator>));
|
||||
BOOST_CONCEPT_ASSERT((DefaultConstructible<edge_descriptor>));
|
||||
BOOST_CONCEPT_ASSERT((EqualityComparable<edge_descriptor>));
|
||||
BOOST_CONCEPT_ASSERT((Assignable<edge_descriptor>));
|
||||
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
|
||||
incidence_graph_tag>));
|
||||
|
||||
p = out_edges(u, g);
|
||||
n = out_degree(u, g);
|
||||
e = *p.first;
|
||||
u = source(e, g);
|
||||
v = target(e, g);
|
||||
const_constraints(g);
|
||||
}
|
||||
void const_constraints(const G& cg) {
|
||||
p = out_edges(u, cg);
|
||||
n = out_degree(u, cg);
|
||||
e = *p.first;
|
||||
u = source(e, cg);
|
||||
v = target(e, cg);
|
||||
}
|
||||
std::pair<out_edge_iterator, out_edge_iterator> p;
|
||||
typename graph_traits<G>::vertex_descriptor u, v;
|
||||
typename graph_traits<G>::edge_descriptor e;
|
||||
typename graph_traits<G>::degree_size_type n;
|
||||
G g;
|
||||
};
|
||||
|
||||
BOOST_concept(BidirectionalGraph,(G))
|
||||
: IncidenceGraph<G>
|
||||
{
|
||||
typedef typename graph_traits<G>::in_edge_iterator
|
||||
in_edge_iterator;
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
|
||||
BOOST_CONCEPT_USAGE(BidirectionalGraph) {
|
||||
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<in_edge_iterator>));
|
||||
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
|
||||
bidirectional_graph_tag>));
|
||||
|
||||
p = in_edges(v, g);
|
||||
n = in_degree(v, g);
|
||||
e = *p.first;
|
||||
const_constraints(g);
|
||||
}
|
||||
void const_constraints(const G& cg) {
|
||||
p = in_edges(v, cg);
|
||||
n = in_degree(v, cg);
|
||||
e = *p.first;
|
||||
}
|
||||
std::pair<in_edge_iterator, in_edge_iterator> p;
|
||||
typename graph_traits<G>::vertex_descriptor v;
|
||||
typename graph_traits<G>::edge_descriptor e;
|
||||
typename graph_traits<G>::degree_size_type n;
|
||||
G g;
|
||||
};
|
||||
|
||||
BOOST_concept(AdjacencyGraph,(G))
|
||||
: Graph<G>
|
||||
{
|
||||
typedef typename graph_traits<G>::adjacency_iterator
|
||||
adjacency_iterator;
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
|
||||
BOOST_CONCEPT_USAGE(AdjacencyGraph) {
|
||||
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<adjacency_iterator>));
|
||||
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
|
||||
adjacency_graph_tag>));
|
||||
|
||||
p = adjacent_vertices(v, g);
|
||||
v = *p.first;
|
||||
const_constraints(g);
|
||||
}
|
||||
void const_constraints(const G& cg) {
|
||||
p = adjacent_vertices(v, cg);
|
||||
}
|
||||
std::pair<adjacency_iterator,adjacency_iterator> p;
|
||||
typename graph_traits<G>::vertex_descriptor v;
|
||||
G g;
|
||||
};
|
||||
|
||||
BOOST_concept(VertexListGraph,(G))
|
||||
: Graph<G>
|
||||
{
|
||||
typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
|
||||
typedef typename graph_traits<G>::vertices_size_type vertices_size_type;
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
function_requires< MultiPassInputIteratorConcept<vertex_iterator> >();
|
||||
function_requires< ConvertibleConcept<traversal_category,
|
||||
vertex_list_graph_tag> >();
|
||||
|
||||
BOOST_CONCEPT_USAGE(VertexListGraph) {
|
||||
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<vertex_iterator>));
|
||||
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
|
||||
vertex_list_graph_tag>));
|
||||
|
||||
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
|
||||
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
|
||||
@@ -201,22 +206,22 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
vertices_size_type V;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct EdgeListGraphConcept
|
||||
BOOST_concept(EdgeListGraph,(G))
|
||||
: Graph<G>
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<G>::edge_iterator edge_iterator;
|
||||
typedef typename graph_traits<G>::edges_size_type edges_size_type;
|
||||
typedef typename graph_traits<G>::traversal_category
|
||||
traversal_category;
|
||||
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> >();
|
||||
|
||||
BOOST_CONCEPT_USAGE(EdgeListGraph) {
|
||||
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<edge_iterator>));
|
||||
BOOST_CONCEPT_ASSERT((DefaultConstructible<edge_descriptor>));
|
||||
BOOST_CONCEPT_ASSERT((EqualityComparable<edge_descriptor>));
|
||||
BOOST_CONCEPT_ASSERT((Assignable<edge_descriptor>));
|
||||
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
|
||||
edge_list_graph_tag>));
|
||||
|
||||
p = edges(g);
|
||||
e = *p.first;
|
||||
@@ -238,13 +243,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
G g;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct VertexAndEdgeListGraphConcept
|
||||
BOOST_concept(VertexAndEdgeListGraph,(G))
|
||||
: VertexListGraph<G>
|
||||
, EdgeListGraph<G>
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< VertexListGraphConcept<G> >();
|
||||
function_requires< EdgeListGraphConcept<G> >();
|
||||
}
|
||||
};
|
||||
|
||||
// Where to put the requirement for this constructor?
|
||||
@@ -252,11 +254,11 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
// Not in mutable graph, then LEDA graph's can't be models of
|
||||
// MutableGraph.
|
||||
|
||||
template <class G>
|
||||
struct EdgeMutableGraphConcept
|
||||
BOOST_concept(EdgeMutableGraph,(G))
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
void constraints() {
|
||||
|
||||
BOOST_CONCEPT_USAGE(EdgeMutableGraph) {
|
||||
p = add_edge(u, v, g);
|
||||
remove_edge(u, v, g);
|
||||
remove_edge(e, g);
|
||||
@@ -268,10 +270,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
typename graph_traits<G>::vertex_descriptor u, v;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct VertexMutableGraphConcept
|
||||
BOOST_concept(VertexMutableGraph,(G))
|
||||
{
|
||||
void constraints() {
|
||||
|
||||
BOOST_CONCEPT_USAGE(VertexMutableGraph) {
|
||||
v = add_vertex(g);
|
||||
remove_vertex(v, g);
|
||||
}
|
||||
@@ -279,13 +281,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
typename graph_traits<G>::vertex_descriptor u, v;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct MutableGraphConcept
|
||||
BOOST_concept(MutableGraph,(G))
|
||||
: EdgeMutableGraph<G>
|
||||
, VertexMutableGraph<G>
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< EdgeMutableGraphConcept<G> >();
|
||||
function_requires< VertexMutableGraphConcept<G> >();
|
||||
}
|
||||
};
|
||||
|
||||
template <class edge_descriptor>
|
||||
@@ -295,11 +294,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
}
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct MutableIncidenceGraphConcept
|
||||
BOOST_concept(MutableIncidenceGraph,(G))
|
||||
: MutableGraph<G>
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< MutableGraphConcept<G> >();
|
||||
BOOST_CONCEPT_USAGE(MutableIncidenceGraph) {
|
||||
remove_edge(iter, g);
|
||||
remove_out_edge_if(u, p, g);
|
||||
}
|
||||
@@ -310,24 +308,23 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
typename boost::graph_traits<G>::out_edge_iterator iter;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct MutableBidirectionalGraphConcept
|
||||
BOOST_concept(MutableBidirectionalGraph,(G))
|
||||
: MutableIncidenceGraph<G>
|
||||
{
|
||||
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;
|
||||
BOOST_CONCEPT_USAGE(MutableBidirectionalGraph)
|
||||
{
|
||||
remove_in_edge_if(u, p, g);
|
||||
}
|
||||
G g;
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
dummy_edge_predicate<edge_descriptor> p;
|
||||
typename boost::graph_traits<G>::vertex_descriptor u;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct MutableEdgeListGraphConcept
|
||||
BOOST_concept(MutableEdgeListGraph,(G))
|
||||
: EdgeMutableGraph<G>
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< EdgeMutableGraphConcept<G> >();
|
||||
BOOST_CONCEPT_USAGE(MutableEdgeListGraph) {
|
||||
remove_edge_if(p, g);
|
||||
}
|
||||
G g;
|
||||
@@ -335,11 +332,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
dummy_edge_predicate<edge_descriptor> p;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct VertexMutablePropertyGraphConcept
|
||||
BOOST_concept(VertexMutablePropertyGraph,(G))
|
||||
: VertexMutableGraph<G>
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< VertexMutableGraphConcept<G> >();
|
||||
BOOST_CONCEPT_USAGE(VertexMutablePropertyGraph) {
|
||||
v = add_vertex(vp, g);
|
||||
}
|
||||
G g;
|
||||
@@ -347,12 +343,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
typename vertex_property<G>::type vp;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct EdgeMutablePropertyGraphConcept
|
||||
BOOST_concept(EdgeMutablePropertyGraph,(G))
|
||||
: EdgeMutableGraph<G>
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
void constraints() {
|
||||
function_requires< EdgeMutableGraphConcept<G> >();
|
||||
|
||||
BOOST_CONCEPT_USAGE(EdgeMutablePropertyGraph) {
|
||||
p = add_edge(u, v, ep, g);
|
||||
}
|
||||
G g;
|
||||
@@ -361,13 +357,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
typename edge_property<G>::type ep;
|
||||
};
|
||||
|
||||
template <class G>
|
||||
struct AdjacencyMatrixConcept
|
||||
BOOST_concept(AdjacencyMatrix,(G))
|
||||
: Graph<G>
|
||||
{
|
||||
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
|
||||
|
||||
BOOST_CONCEPT_USAGE(AdjacencyMatrix) {
|
||||
p = edge(u, v, g);
|
||||
const_constraints(g);
|
||||
}
|
||||
@@ -379,13 +374,14 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
G g;
|
||||
};
|
||||
|
||||
template <class G, class X, class Property>
|
||||
struct ReadablePropertyGraphConcept
|
||||
BOOST_concept(ReadablePropertyGraph,(G)(X)(Property))
|
||||
: Graph<G>
|
||||
{
|
||||
typedef typename property_map<G, Property>::const_type const_Map;
|
||||
void constraints() {
|
||||
function_requires< GraphConcept<G> >();
|
||||
function_requires< ReadablePropertyMapConcept<const_Map, X> >();
|
||||
|
||||
BOOST_CONCEPT_USAGE(ReadablePropertyGraph)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept<const_Map, X>));
|
||||
|
||||
const_constraints(g);
|
||||
}
|
||||
@@ -399,13 +395,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
typename property_traits<const_Map>::value_type pval;
|
||||
};
|
||||
|
||||
template <class G, class X, class Property>
|
||||
struct PropertyGraphConcept
|
||||
BOOST_concept(PropertyGraph,(G)(X)(Property))
|
||||
: ReadablePropertyGraph<G, X, Property>
|
||||
{
|
||||
typedef typename property_map<G, Property>::type Map;
|
||||
void constraints() {
|
||||
function_requires< ReadablePropertyGraphConcept<G, X, Property> >();
|
||||
function_requires< ReadWritePropertyMapConcept<Map, X> >();
|
||||
BOOST_CONCEPT_USAGE(PropertyGraph) {
|
||||
BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept<Map, X>));
|
||||
|
||||
Map pmap = get(Property(), g);
|
||||
pval = get(Property(), g, x);
|
||||
@@ -417,14 +412,14 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
typename property_traits<Map>::value_type pval;
|
||||
};
|
||||
|
||||
template <class G, class X, class Property>
|
||||
struct LvaluePropertyGraphConcept
|
||||
BOOST_concept(LvaluePropertyGraph,(G)(X)(Property))
|
||||
: ReadablePropertyGraph<G, X, Property>
|
||||
{
|
||||
typedef typename property_map<G, Property>::type Map;
|
||||
typedef typename property_map<G, Property>::const_type const_Map;
|
||||
void constraints() {
|
||||
function_requires< ReadablePropertyGraphConcept<G, X, Property> >();
|
||||
function_requires< LvaluePropertyMapConcept<const_Map, X> >();
|
||||
|
||||
BOOST_CONCEPT_USAGE(LvaluePropertyGraph) {
|
||||
BOOST_CONCEPT_ASSERT((LvaluePropertyMapConcept<const_Map, X>));
|
||||
|
||||
pval = get(Property(), g, x);
|
||||
put(Property(), g, x, pval);
|
||||
@@ -435,10 +430,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
};
|
||||
|
||||
// This needs to move out of the graph library
|
||||
template <class B>
|
||||
struct BufferConcept
|
||||
BOOST_concept(Buffer,(B))
|
||||
{
|
||||
void constraints() {
|
||||
BOOST_CONCEPT_USAGE(Buffer) {
|
||||
b.push(t);
|
||||
b.pop();
|
||||
typename B::value_type& v = b.top();
|
||||
@@ -457,13 +451,11 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
B b;
|
||||
};
|
||||
|
||||
template <class C>
|
||||
struct ColorValueConcept
|
||||
BOOST_concept(ColorValue,(C))
|
||||
: EqualityComparable<C>
|
||||
, DefaultConstructible<C>
|
||||
{
|
||||
void constraints() {
|
||||
function_requires< EqualityComparableConcept<C> >();
|
||||
function_requires< DefaultConstructibleConcept<C> >();
|
||||
|
||||
BOOST_CONCEPT_USAGE(ColorValue) {
|
||||
c = color_traits<C>::white();
|
||||
c = color_traits<C>::gray();
|
||||
c = color_traits<C>::black();
|
||||
@@ -471,10 +463,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
C c;
|
||||
};
|
||||
|
||||
template <class M, class I, class V>
|
||||
struct BasicMatrixConcept
|
||||
BOOST_concept(BasicMatrix,(M)(I)(V))
|
||||
{
|
||||
void constraints() {
|
||||
BOOST_CONCEPT_USAGE(BasicMatrix) {
|
||||
V& elt = A[i][j];
|
||||
const_constraints(A);
|
||||
ignore_unused_variable_warning(elt);
|
||||
@@ -487,6 +478,33 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
|
||||
I i, j;
|
||||
};
|
||||
|
||||
} // end namespace concepts
|
||||
|
||||
using boost::concepts::MultiPassInputIteratorConcept;
|
||||
using boost::concepts::GraphConcept;
|
||||
using boost::concepts::IncidenceGraphConcept;
|
||||
using boost::concepts::BidirectionalGraphConcept;
|
||||
using boost::concepts::AdjacencyGraphConcept;
|
||||
using boost::concepts::VertexListGraphConcept;
|
||||
using boost::concepts::EdgeListGraphConcept;
|
||||
using boost::concepts::VertexAndEdgeListGraphConcept;
|
||||
using boost::concepts::EdgeMutableGraphConcept;
|
||||
using boost::concepts::VertexMutableGraphConcept;
|
||||
using boost::concepts::MutableGraphConcept;
|
||||
using boost::concepts::MutableIncidenceGraphConcept;
|
||||
using boost::concepts::MutableBidirectionalGraphConcept;
|
||||
using boost::concepts::MutableEdgeListGraphConcept;
|
||||
using boost::concepts::VertexMutablePropertyGraphConcept;
|
||||
using boost::concepts::EdgeMutablePropertyGraphConcept;
|
||||
using boost::concepts::AdjacencyMatrixConcept;
|
||||
using boost::concepts::ReadablePropertyGraphConcept;
|
||||
using boost::concepts::PropertyGraphConcept;
|
||||
using boost::concepts::LvaluePropertyGraphConcept;
|
||||
using boost::concepts::BufferConcept;
|
||||
using boost::concepts::ColorValueConcept;
|
||||
using boost::concepts::BasicMatrixConcept;
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/concept/detail/concept_undef.hpp>
|
||||
|
||||
#endif /* BOOST_GRAPH_CONCEPTS_H */
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef BOOST_GRAPH_SELECTORS_HPP
|
||||
#define BOOST_GRAPH_SELECTORS_HPP
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//===========================================================================
|
||||
@@ -17,18 +19,18 @@ namespace boost {
|
||||
// and adjacency_matrix.
|
||||
|
||||
struct directedS { enum { is_directed = true, is_bidir = false };
|
||||
typedef true_type is_directed_t;
|
||||
typedef false_type is_bidir_t;
|
||||
typedef mpl::true_ is_directed_t;
|
||||
typedef mpl::false_ is_bidir_t;
|
||||
};
|
||||
struct undirectedS {
|
||||
enum { is_directed = false, is_bidir = false };
|
||||
typedef false_type is_directed_t;
|
||||
typedef false_type is_bidir_t;
|
||||
typedef mpl::false_ is_directed_t;
|
||||
typedef mpl::false_ is_bidir_t;
|
||||
};
|
||||
struct bidirectionalS {
|
||||
enum { is_directed = true, is_bidir = true };
|
||||
typedef true_type is_directed_t;
|
||||
typedef true_type is_bidir_t;
|
||||
typedef mpl::true_ is_directed_t;
|
||||
typedef mpl::true_ is_bidir_t;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace boost {
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
edge_t e = *p.first;
|
||||
BOOST_CHECK(source(e, g) == u);
|
||||
BOOST_CHECK(contains(adj, target(e, g)) == true);
|
||||
BOOST_CHECK(container_contains(adj, target(e, g)) == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ namespace boost {
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
edge_t e = *p.first;
|
||||
BOOST_CHECK(target(e, g) == v);
|
||||
BOOST_CHECK(contains(inv_adj, source(e, g)) == true);
|
||||
BOOST_CHECK(container_contains(inv_adj, source(e, g)) == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ namespace boost {
|
||||
BOOST_CHECK(deg_size_t(std::distance(p.first, p.second)) == adj.size());
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
vertex_t v = *p.first;
|
||||
BOOST_CHECK(contains(adj, v) == true);
|
||||
BOOST_CHECK(container_contains(adj, v) == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,7 +155,7 @@ namespace boost {
|
||||
BOOST_CHECK(n == num_vertices(g));
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
vertex_t v = *p.first;
|
||||
BOOST_CHECK(contains(vertex_set, v) == true);
|
||||
BOOST_CHECK(container_contains(vertex_set, v) == true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,8 +172,8 @@ namespace boost {
|
||||
for (; p.first != p.second; ++p.first) {
|
||||
edge_t e = *p.first;
|
||||
BOOST_CHECK(any_if(edge_set, connects(source(e, g), target(e, g), g)));
|
||||
BOOST_CHECK(contains(vertex_set, source(e, g)) == true);
|
||||
BOOST_CHECK(contains(vertex_set, target(e, g)) == true);
|
||||
BOOST_CHECK(container_contains(vertex_set, source(e, g)) == true);
|
||||
BOOST_CHECK(container_contains(vertex_set, target(e, g)) == true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ namespace boost {
|
||||
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);
|
||||
bool parallel_edge_exists = container_contains(adjacent_vertices(u, g), v);
|
||||
|
||||
std::pair<edge_t, bool> p = add_edge(u, v, g);
|
||||
edge_t e = p.first;
|
||||
@@ -249,7 +249,7 @@ namespace boost {
|
||||
if (p.second == true) { // edge added
|
||||
BOOST_CHECK(num_edges(g) == num_edges(cpy) + 1);
|
||||
|
||||
BOOST_CHECK(contains(out_edges(u, g), e) == true);
|
||||
BOOST_CHECK(container_contains(out_edges(u, g), e) == true);
|
||||
|
||||
BOOST_CHECK((verify_isomorphism
|
||||
(make_filtered_graph(g, ignore_edge(e)), cpy, iso_map)));
|
||||
|
||||
332
include/boost/graph/graphml.hpp
Normal file
332
include/boost/graph/graphml.hpp
Normal file
@@ -0,0 +1,332 @@
|
||||
// Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de>
|
||||
// Copyright (C) 2004 The Trustees of Indiana University.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Authors: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
// Tiago de Paula Peixoto
|
||||
|
||||
#ifndef BOOST_GRAPH_GRAPHML_HPP
|
||||
#define BOOST_GRAPH_GRAPHML_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/graph/graphviz.hpp> // for exceptions
|
||||
#include <typeinfo>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Graph reader exceptions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
struct parse_error: public graph_exception
|
||||
{
|
||||
parse_error(const std::string& error) {statement = "parse error: " + error;}
|
||||
virtual ~parse_error() throw() {}
|
||||
virtual const char* what() const throw() {return statement.c_str();}
|
||||
std::string statement;
|
||||
};
|
||||
|
||||
|
||||
class mutate_graph
|
||||
{
|
||||
public:
|
||||
virtual ~mutate_graph() {}
|
||||
virtual bool is_directed() const = 0;
|
||||
|
||||
virtual boost::any do_add_vertex() = 0;
|
||||
virtual std::pair<boost::any,bool> do_add_edge(boost::any source, boost::any target) = 0;
|
||||
|
||||
virtual void
|
||||
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0;
|
||||
|
||||
virtual void
|
||||
set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0;
|
||||
|
||||
virtual void
|
||||
set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0;
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
class mutate_graph_impl : public mutate_graph
|
||||
{
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<MutableGraph>::edge_descriptor edge_descriptor;
|
||||
|
||||
public:
|
||||
mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
|
||||
: m_g(g), m_dp(dp) { }
|
||||
|
||||
bool is_directed() const
|
||||
{
|
||||
return is_convertible<typename graph_traits<MutableGraph>::directed_category,
|
||||
directed_tag>::value;
|
||||
}
|
||||
|
||||
virtual any do_add_vertex()
|
||||
{
|
||||
return any(add_vertex(m_g));
|
||||
}
|
||||
|
||||
virtual std::pair<any,bool> do_add_edge(any source, any target)
|
||||
{
|
||||
std::pair<edge_descriptor,bool> retval = add_edge(any_cast<vertex_descriptor>(source),
|
||||
any_cast<vertex_descriptor>(target), m_g);
|
||||
return std::make_pair(any(retval.first), retval.second);
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<MutableGraph,value_types>
|
||||
(name, m_dp, m_g, value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
throw parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type);
|
||||
}
|
||||
if (!type_found)
|
||||
throw parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name);
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<vertex_descriptor,value_types>
|
||||
(name, m_dp, any_cast<vertex_descriptor>(vertex),
|
||||
value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
throw parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type);
|
||||
}
|
||||
if (!type_found)
|
||||
throw parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name);
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<edge_descriptor,value_types>
|
||||
(name, m_dp, any_cast<edge_descriptor>(edge),
|
||||
value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
throw parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type);
|
||||
}
|
||||
if (!type_found)
|
||||
throw parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name);
|
||||
}
|
||||
|
||||
template <typename Key, typename ValueVector>
|
||||
class put_property
|
||||
{
|
||||
public:
|
||||
put_property(const std::string& name, dynamic_properties& dp, const Key& key,
|
||||
const std::string& value, const std::string& value_type,
|
||||
char** type_names, bool& type_found)
|
||||
: m_name(name), m_dp(dp), m_key(key), m_value(value),
|
||||
m_value_type(value_type), m_type_names(type_names),
|
||||
m_type_found(type_found) {}
|
||||
template <class Value>
|
||||
void operator()(Value)
|
||||
{
|
||||
if (m_value_type == m_type_names[mpl::find<ValueVector,Value>::type::pos::value])
|
||||
{
|
||||
put(m_name, m_dp, m_key, lexical_cast<Value>(m_value));
|
||||
m_type_found = true;
|
||||
}
|
||||
}
|
||||
private:
|
||||
const std::string& m_name;
|
||||
dynamic_properties& m_dp;
|
||||
const Key& m_key;
|
||||
const std::string& m_value;
|
||||
const std::string& m_value_type;
|
||||
char** m_type_names;
|
||||
bool& m_type_found;
|
||||
};
|
||||
|
||||
protected:
|
||||
MutableGraph& m_g;
|
||||
dynamic_properties& m_dp;
|
||||
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
|
||||
static char* m_type_names[];
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
char* mutate_graph_impl<MutableGraph>::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"};
|
||||
|
||||
void
|
||||
read_graphml(std::istream& in, mutate_graph& g);
|
||||
|
||||
template<typename MutableGraph>
|
||||
void
|
||||
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp)
|
||||
{
|
||||
mutate_graph_impl<MutableGraph> mg(g,dp);
|
||||
read_graphml(in, mg);
|
||||
}
|
||||
|
||||
template <typename Types>
|
||||
class get_type_name
|
||||
{
|
||||
public:
|
||||
get_type_name(const std::type_info& type, char** type_names, std::string& type_name)
|
||||
: m_type(type), m_type_names(type_names), m_type_name(type_name) {}
|
||||
template <typename Type>
|
||||
void operator()(Type)
|
||||
{
|
||||
if (typeid(Type) == m_type)
|
||||
m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
|
||||
}
|
||||
private:
|
||||
const std::type_info &m_type;
|
||||
char** m_type_names;
|
||||
std::string &m_type_name;
|
||||
};
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
void
|
||||
write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
|
||||
const dynamic_properties& dp, bool ordered_vertices=false)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category directed_category;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool,
|
||||
graph_is_directed =
|
||||
(is_convertible<directed_category*, directed_tag*>::value));
|
||||
|
||||
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
<< "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
|
||||
|
||||
typedef mpl::vector<bool, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, std::string> value_types;
|
||||
char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"};
|
||||
std::map<std::string, std::string> graph_key_ids;
|
||||
std::map<std::string, std::string> vertex_key_ids;
|
||||
std::map<std::string, std::string> edge_key_ids;
|
||||
int key_count = 0;
|
||||
|
||||
// Output keys
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
std::string key_id = "key" + lexical_cast<std::string>(key_count++);
|
||||
if (i->second->key() == typeid(Graph))
|
||||
vertex_key_ids[i->first] = key_id;
|
||||
else if (i->second->key() == typeid(vertex_descriptor))
|
||||
vertex_key_ids[i->first] = key_id;
|
||||
else if (i->second->key() == typeid(edge_descriptor))
|
||||
edge_key_ids[i->first] = key_id;
|
||||
else
|
||||
continue;
|
||||
std::string type_name = "string";
|
||||
mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
|
||||
out << " <key id=\"" << key_id << "\" for=\""
|
||||
<< (i->second->key() == typeid(Graph) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\""
|
||||
<< " attr.name=\"" << i->first << "\""
|
||||
<< " attr.type=\"" << type_name << "\""
|
||||
<< " />\n";
|
||||
}
|
||||
|
||||
out << " <graph id=\"G\" edgedefault=\""
|
||||
<< (graph_is_directed ? "directed" : "undirected") << "\""
|
||||
<< " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free") << "\""
|
||||
<< " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
|
||||
|
||||
// Output graph data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == typeid(Graph))
|
||||
{
|
||||
out << " <data key=\"" << graph_key_ids[i->first] << "\">"
|
||||
<< i->second->get_string(g) << "</data>\n";
|
||||
}
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
vertex_iterator v, v_end;
|
||||
for (tie(v, v_end) = vertices(g); v != v_end; ++v)
|
||||
{
|
||||
out << " <node id=\"n" << get(vertex_index, *v) << "\">\n";
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == typeid(vertex_descriptor))
|
||||
{
|
||||
out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
|
||||
<< i->second->get_string(*v) << "</data>\n";
|
||||
}
|
||||
}
|
||||
out << " </node>\n";
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
|
||||
edge_iterator e, e_end;
|
||||
typename graph_traits<Graph>::edges_size_type edge_count = 0;
|
||||
for (tie(e, e_end) = edges(g); e != e_end; ++e)
|
||||
{
|
||||
out << " <edge id=\"e" << edge_count++ << "\" source=\"n"
|
||||
<< get(vertex_index, source(*e, g)) << "\" target=\"n"
|
||||
<< get(vertex_index, target(*e, g)) << "\">\n";
|
||||
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == typeid(edge_descriptor))
|
||||
{
|
||||
out << " <data key=\"" << edge_key_ids[i->first] << "\">"
|
||||
<< i->second->get_string(*e) << "</data>\n";
|
||||
}
|
||||
}
|
||||
out << " </edge>\n";
|
||||
}
|
||||
|
||||
out << " </graph>\n"
|
||||
<< "</graphml>\n";
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
void
|
||||
write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp,
|
||||
bool ordered_vertices=false)
|
||||
{
|
||||
write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
|
||||
}
|
||||
|
||||
} // boost namespace
|
||||
|
||||
#endif // BOOST_GRAPH_GRAPHML_HPP
|
||||
@@ -679,6 +679,9 @@ class mutate_graph
|
||||
|
||||
virtual void
|
||||
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0;
|
||||
|
||||
virtual void // RG: need new second parameter to support BGL subgraphs
|
||||
set_graph_property(const id_t& key, const id_t& value) = 0;
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
@@ -740,6 +743,14 @@ class mutate_graph_impl : public mutate_graph
|
||||
put(key, dp_, bgl_edges[edge], value);
|
||||
}
|
||||
|
||||
void
|
||||
set_graph_property(const id_t& key, const id_t& value)
|
||||
{
|
||||
/* RG: pointer to graph prevents copying */
|
||||
put(key, dp_, &graph_, value);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
MutableGraph& graph_;
|
||||
dynamic_properties& dp_;
|
||||
|
||||
611
include/boost/graph/howard_cycle_ratio.hpp
Normal file
611
include/boost/graph/howard_cycle_ratio.hpp
Normal file
@@ -0,0 +1,611 @@
|
||||
/*!
|
||||
* Copyright 2007 Technical University of Catalonia
|
||||
*
|
||||
* Use, modification and distribution is subject to the Boost Software
|
||||
* License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* Authors: Dmitry Bufistov
|
||||
* Andrey Parfenov
|
||||
*/
|
||||
|
||||
#ifndef BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP
|
||||
#define BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP
|
||||
|
||||
/*!
|
||||
* \file Maximum cycle ratio algorithm (Jean Cochet-Terrasson, Guy
|
||||
* Cochen and others)
|
||||
*/
|
||||
#include <exception>
|
||||
#include <set>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/reverse_graph.hpp>
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include <boost/graph/iteration_macros.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
/// To avoid round error.
|
||||
static const double mcr_howard_ltolerance = 0.00001;
|
||||
|
||||
/*!
|
||||
* Calculate maximum cycle ratio of "good" directed multigraph
|
||||
* g. Use Howard's iteration policy algorithm ("Numerical
|
||||
* Computation of Spectral Elements in MAX-PLUS algebra" by Jean
|
||||
* Cochet-Terrasson, Guy Cochen and others).
|
||||
*
|
||||
* \param g = (V, E) - a "good" directed multigraph (out_degree of
|
||||
* each vertex is greater then 0). If graph is strongly connected
|
||||
* then it is "good".
|
||||
*
|
||||
* \param vim - Vertex Index, read property Map: V -> [0,
|
||||
* num_vertices(g)).
|
||||
*
|
||||
* \param ewm - edge weight read property map: E -> R
|
||||
*
|
||||
* \param ewm2 - edge weight2 read property map: E -> R+
|
||||
*
|
||||
* \return maximum_{for all cycles C}CR(C), or
|
||||
* -(std::numeric_limits<double>)::max() if g is not "good".
|
||||
*/
|
||||
template <typename TGraph, typename TVertexIndexMap,
|
||||
typename TWeight1EdgeMap, typename TWeight2EdgeMap >
|
||||
class Cmcr_Howard
|
||||
{
|
||||
public:
|
||||
Cmcr_Howard(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm,
|
||||
TWeight2EdgeMap ew2m)
|
||||
: m_g(g), m_vim(vim), m_ew1m(ewm), m_ew2m(ew2m),
|
||||
m_g2pi_g_vm(std::vector<pi_vertex_t>().end(), m_vim), /// Stupid dummy initialization
|
||||
m_minus_infinity(-(std::numeric_limits<double>::max)())
|
||||
{
|
||||
typedef typename boost::graph_traits<TGraph>::directed_category DirCat;
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<DirCat*, boost::directed_tag*>::value == true));
|
||||
m_cr = m_minus_infinity;
|
||||
}
|
||||
|
||||
double operator()()
|
||||
{
|
||||
return maximum_cycle_ratio_Howard();
|
||||
}
|
||||
|
||||
virtual ~Cmcr_Howard() { }
|
||||
|
||||
protected:
|
||||
typedef typename boost::graph_traits<TGraph>::vertex_descriptor
|
||||
mcr_vertex_t;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor
|
||||
mcr_edge_t;
|
||||
|
||||
const TGraph& m_g;
|
||||
typedef std::vector<double> eigenmode_t;
|
||||
eigenmode_t m_eigen_value;
|
||||
eigenmode_t m_eigen_vector;
|
||||
TVertexIndexMap m_vim;
|
||||
TWeight1EdgeMap m_ew1m;
|
||||
TWeight2EdgeMap m_ew2m;
|
||||
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeight1EdgeMap>::value_type>::type mcr_edge_weight1_t;
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeight2EdgeMap>::value_type>::type mcr_edge_weight2_t;
|
||||
typedef typename boost::adjacency_list<
|
||||
boost::listS, boost::vecS, boost::bidirectionalS,
|
||||
boost::no_property,
|
||||
boost::property<boost::edge_weight_t,
|
||||
mcr_edge_weight1_t,
|
||||
boost::property<boost::edge_weight2_t,
|
||||
mcr_edge_weight2_t> > >
|
||||
pi_graph_t;
|
||||
typedef typename boost::property_map<pi_graph_t, boost::vertex_index_t>::type TPiGraphVertexIndexMap;
|
||||
typedef typename boost::property_map<pi_graph_t, boost::edge_weight_t>::type TPiGraphEdgeWeight1Map;
|
||||
typedef typename boost::property_map<pi_graph_t, boost::edge_weight2_t>::type TPiGraphEdgeWeight2Map;
|
||||
|
||||
typedef typename boost::property_traits<TPiGraphVertexIndexMap>::value_type pigraph_vertex_index_t;
|
||||
|
||||
pi_graph_t m_pi_g;
|
||||
typedef typename boost::graph_traits<pi_graph_t>::vertex_descriptor pi_vertex_t;
|
||||
typedef typename boost::graph_traits<pi_graph_t>::edge_descriptor pi_edge_t;
|
||||
typedef typename boost::iterator_property_map<typename std::vector<pi_vertex_t>::iterator, TVertexIndexMap> g2pi_g_vm_t;
|
||||
g2pi_g_vm_t m_g2pi_g_vm; ///Graph to Pi graph vertex map
|
||||
std::vector<pi_vertex_t> m_g2pig;
|
||||
int m_step_number;
|
||||
const double m_minus_infinity;
|
||||
typedef typename std::vector<mcr_edge_t> critical_cycle_t;
|
||||
double m_cr; ///Cycle ratio that already has been found
|
||||
|
||||
class bad_graph
|
||||
{
|
||||
public:
|
||||
typedef typename boost::property_traits<TVertexIndexMap>::value_type
|
||||
v_index_t;
|
||||
|
||||
bad_graph(v_index_t bvi) : bad_vertex_index(bvi) {}
|
||||
v_index_t what() const throw()
|
||||
{
|
||||
return bad_vertex_index;
|
||||
}
|
||||
|
||||
private:
|
||||
v_index_t bad_vertex_index;
|
||||
};
|
||||
|
||||
double maximum_cycle_ratio_Howard()
|
||||
{
|
||||
try
|
||||
{
|
||||
construct_pi_graph();
|
||||
}
|
||||
catch (const bad_graph& a)
|
||||
{
|
||||
return m_minus_infinity;
|
||||
}
|
||||
std::vector<double> max_eigen_val(boost::num_vertices(m_g));
|
||||
m_eigen_value.resize(boost::num_vertices(m_g));
|
||||
m_eigen_vector.resize(boost::num_vertices(m_g));
|
||||
m_step_number = 0;
|
||||
do
|
||||
{
|
||||
pi_eingen_value(get(vertex_index, m_pi_g), get(boost::edge_weight, m_pi_g), get(boost::edge_weight2, m_pi_g));
|
||||
++m_step_number;
|
||||
}
|
||||
while (improve_policy_try1(max_eigen_val) || improve_policy_try2(max_eigen_val));
|
||||
return *(std::max_element(m_eigen_value.begin(), m_eigen_value.end()));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Construct an arbitrary policy m_pi_g.
|
||||
*/
|
||||
void construct_pi_graph()
|
||||
{
|
||||
m_g2pig.resize(boost::num_vertices(m_g));
|
||||
m_g2pi_g_vm = boost::make_iterator_property_map(m_g2pig.begin(), m_vim);
|
||||
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
|
||||
{
|
||||
m_g2pi_g_vm[vd] = boost::add_vertex(m_pi_g);
|
||||
store_pivertex(m_g2pi_g_vm[vd], vd);
|
||||
}
|
||||
BGL_FORALL_VERTICES_T(vd1, m_g, TGraph)
|
||||
{
|
||||
if (boost::out_edges(vd1, m_g).first == boost::out_edges(vd1, m_g).second) throw bad_graph(m_vim[vd1]);
|
||||
mcr_edge_t ed = *boost::out_edges(vd1, m_g).first;
|
||||
pi_edge_t pied = boost::add_edge(m_g2pi_g_vm[source(ed, m_g)], m_g2pi_g_vm[target(ed, m_g)], m_pi_g).first;
|
||||
boost::put(boost::edge_weight, m_pi_g, pied, m_ew1m[ed]);
|
||||
boost::put(boost::edge_weight2, m_pi_g, pied, m_ew2m[ed]);
|
||||
}
|
||||
}
|
||||
|
||||
class bfs_eingmode_visitor : public boost::default_bfs_visitor
|
||||
{
|
||||
public:
|
||||
bfs_eingmode_visitor(TPiGraphVertexIndexMap vi_m, TPiGraphEdgeWeight1Map w_m, TPiGraphEdgeWeight2Map& d_m,
|
||||
eigenmode_t& e_val, eigenmode_t& e_vec, double ev) : m_index_map(vi_m), m_weight_map(w_m), m_delay_map(d_m),
|
||||
m_eig_value(&e_val), m_eig_vec(&e_vec), m_eigen_value(ev) { }
|
||||
|
||||
template < typename Edge, typename g_t>
|
||||
void examine_edge(Edge e, const g_t & g) const
|
||||
{
|
||||
typedef typename boost::graph_traits<g_t>::vertex_descriptor Vertex;
|
||||
Vertex u = boost::target(e, g), v = boost::source(e, g);
|
||||
pigraph_vertex_index_t ind = m_index_map[u];
|
||||
(*m_eig_value)[ind] = m_eigen_value;
|
||||
(*m_eig_vec)[ind] = m_weight_map[e] - m_eigen_value * m_delay_map[e] + (*m_eig_vec)[m_index_map[v]];
|
||||
}
|
||||
private:
|
||||
TPiGraphVertexIndexMap m_index_map;
|
||||
TPiGraphEdgeWeight1Map m_weight_map;
|
||||
TPiGraphEdgeWeight2Map m_delay_map;
|
||||
eigenmode_t* m_eig_value;
|
||||
eigenmode_t* m_eig_vec;
|
||||
double m_eigen_value;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Find a vertex in the Pi Graph which belongs to cycle, just a DFV until back edge found
|
||||
*/
|
||||
pi_vertex_t find_good_source(const pi_vertex_t start_vertex)
|
||||
{
|
||||
pi_vertex_t good_vertex = start_vertex;
|
||||
typename std::set<pi_vertex_t> s;
|
||||
s.insert(start_vertex);
|
||||
do
|
||||
{
|
||||
good_vertex = boost::target(*boost::out_edges(good_vertex, m_pi_g).first, m_pi_g);
|
||||
}
|
||||
while (s.insert(good_vertex).second);
|
||||
return good_vertex;
|
||||
}
|
||||
virtual void store_pivertex(pi_vertex_t pivd, mcr_vertex_t vd) {}
|
||||
virtual void store_critical_edge(pi_edge_t ed, critical_cycle_t& cc) {}
|
||||
virtual void store_critical_cycle(critical_cycle_t& cc) {}
|
||||
|
||||
/*!
|
||||
* \param startV - vertex that belongs to a cycle in policy graph m_pi_g
|
||||
*/
|
||||
double calculate_eigen_value(pi_vertex_t startV)
|
||||
{
|
||||
std::pair<double, double> accum_sums(0., 0.);
|
||||
pi_vertex_t vd = startV;
|
||||
critical_cycle_t cc;
|
||||
do
|
||||
{
|
||||
pi_edge_t tmp_ed = *(boost::out_edges(vd, m_pi_g).first);
|
||||
store_critical_edge(tmp_ed, cc);
|
||||
accum_sums.first += boost::get(boost::edge_weight, m_pi_g, tmp_ed);
|
||||
accum_sums.second += boost::get(boost::edge_weight2, m_pi_g, tmp_ed);
|
||||
vd = boost::target(tmp_ed, m_pi_g);
|
||||
}
|
||||
while (vd != startV);
|
||||
//assert((std::abs<double>(accum_sums.first) <= 0.00000001) && "Division by zerro!");
|
||||
double cr = accum_sums.first / accum_sums.second;
|
||||
if (cr > m_cr)
|
||||
{
|
||||
m_cr = cr;
|
||||
store_critical_cycle(cc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Value determination. Find a generalized eigenmode (n^{k+1}, x^{k+1}) of A^{Ï_{k+1}} of the pi graph (Algorithm IV.1).
|
||||
*/
|
||||
void pi_eingen_value(
|
||||
TPiGraphVertexIndexMap index_map,
|
||||
TPiGraphEdgeWeight1Map weight_map,
|
||||
TPiGraphEdgeWeight2Map weigh2_map)
|
||||
{
|
||||
using namespace boost;
|
||||
typedef std::vector<default_color_type> color_map_t;
|
||||
color_map_t vcm(num_vertices(m_pi_g), white_color);//Vertex color map
|
||||
color_map_t::iterator uv_itr = vcm.begin(); //Undiscovered vertex
|
||||
reverse_graph<pi_graph_t> rev_g(m_pi_g); //For backward breadth visit
|
||||
|
||||
while ((uv_itr = std::find_if(uv_itr, vcm.end(),
|
||||
boost::bind(std::equal_to<default_color_type>(), boost::white_color, _1))) != vcm.end())
|
||||
///While there are undiscovered vertices
|
||||
{
|
||||
pi_vertex_t gv = find_good_source(pi_vertex_t(uv_itr - vcm.begin()));
|
||||
pigraph_vertex_index_t gv_ind = index_map[gv];
|
||||
m_eigen_value[gv_ind] = calculate_eigen_value(gv) ;
|
||||
bfs_eingmode_visitor bfs_vis(index_map, weight_map, weigh2_map, m_eigen_value, m_eigen_vector, m_eigen_value[gv_ind]);
|
||||
typename boost::queue<pi_vertex_t> Q;
|
||||
breadth_first_visit(rev_g, gv, Q, bfs_vis, make_iterator_property_map(vcm.begin(), index_map));
|
||||
}
|
||||
}
|
||||
|
||||
void improve_policy(mcr_vertex_t vd, mcr_edge_t new_edge)
|
||||
{
|
||||
remove_edge(*(out_edges(m_g2pi_g_vm[vd], m_pi_g).first), m_pi_g);
|
||||
pi_edge_t ned = add_edge(m_g2pi_g_vm[vd], m_g2pi_g_vm[target(new_edge, m_g)], m_pi_g).first;
|
||||
put(edge_weight, m_pi_g, ned, m_ew1m[new_edge]);
|
||||
put(edge_weight2, m_pi_g, ned, m_ew2m[new_edge]);
|
||||
}
|
||||
/*!
|
||||
* Policy Improvement. Improve the policy graph. The new policy graph has greater cycle ratio.
|
||||
* \return false if nothing can be improved.
|
||||
*/
|
||||
bool improve_policy_try1(std::vector<double>& max_eing_vals)
|
||||
{
|
||||
bool improved = false;
|
||||
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
|
||||
{
|
||||
double max_ev = m_minus_infinity;/// Maximum eigen value for vertex
|
||||
mcr_edge_t cr_ed;///Critical edge
|
||||
|
||||
BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph)
|
||||
{
|
||||
if (m_eigen_value[m_vim[target(outed, m_g)]] > max_ev)
|
||||
{
|
||||
max_ev = m_eigen_value[m_vim[boost::target(outed, m_g)]];
|
||||
cr_ed = outed;
|
||||
}
|
||||
}
|
||||
if (max_ev > m_eigen_value[get(m_vim,vd)])
|
||||
{
|
||||
improve_policy(vd, cr_ed);
|
||||
improved = true;
|
||||
}
|
||||
max_eing_vals[get(m_vim,vd)] = max_ev;
|
||||
}
|
||||
return improved;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \param max_eigen_values[u] = max_(for all adjacent vertices (u,v)) m_eigen_value[v]
|
||||
*/
|
||||
bool improve_policy_try2(const std::vector<double>& max_eigen_values)
|
||||
{
|
||||
bool improved = false;
|
||||
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
|
||||
{
|
||||
mcr_edge_t impr_edge;
|
||||
double max_val = m_minus_infinity;
|
||||
BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph)
|
||||
{
|
||||
///If vertex vd is in the K(vd) set
|
||||
if (max_eigen_values[get(m_vim, vd)] <= m_eigen_value[get(m_vim, target(outed, m_g))])
|
||||
{
|
||||
double c_val = m_ew1m[outed] - m_ew2m[outed] * m_eigen_value[m_vim[boost::target(outed, m_g)]] +
|
||||
m_eigen_vector[m_vim[boost::target(outed, m_g)]];
|
||||
if (c_val > max_val)
|
||||
{
|
||||
max_val = c_val;
|
||||
impr_edge = outed;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((max_val - m_eigen_vector[get(m_vim, vd)]) > mcr_howard_ltolerance)
|
||||
///If m_eigen_vector[vd] == max_val
|
||||
{
|
||||
improve_policy(vd, impr_edge);
|
||||
improved = true;
|
||||
}
|
||||
}
|
||||
return improved;
|
||||
}
|
||||
};///Cmcr_Howard
|
||||
|
||||
/*!
|
||||
* \return maximum cycle ratio and one critical cycle.
|
||||
*/
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
|
||||
class Cmcr_Howard1 : public Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap>
|
||||
{
|
||||
public:
|
||||
typedef Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap> inhr_t;
|
||||
Cmcr_Howard1(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m) : inhr_t(g, vim, ewm, ew2m)
|
||||
{
|
||||
m_pi_g2g.resize(boost::num_vertices(g));
|
||||
m_pi_g2g_vm = boost::make_iterator_property_map(m_pi_g2g.begin(), boost::get(boost::vertex_index, this->m_pi_g));
|
||||
}
|
||||
|
||||
void get_critical_cycle(typename inhr_t::critical_cycle_t& cc) { return cc.swap(m_critical_cycle); }
|
||||
protected:
|
||||
void store_pivertex(typename inhr_t::pi_vertex_t pivd, typename inhr_t::mcr_vertex_t vd)
|
||||
{
|
||||
m_pi_g2g_vm[pivd] = vd;
|
||||
}
|
||||
void store_critical_edge(typename inhr_t::pi_edge_t ed, typename inhr_t::critical_cycle_t& cc)
|
||||
{
|
||||
typename inhr_t::pi_vertex_t s = boost::source(ed, this->m_pi_g);
|
||||
typename inhr_t::pi_vertex_t t = boost::target(ed, this->m_pi_g);
|
||||
assert(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).second);
|
||||
cc.push_back(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).first); ///Store corresponding edge of the m_g
|
||||
}
|
||||
void store_critical_cycle(typename inhr_t::critical_cycle_t& cc)
|
||||
{
|
||||
m_critical_cycle.swap(cc);
|
||||
}
|
||||
private:
|
||||
typename inhr_t::critical_cycle_t m_critical_cycle;
|
||||
typedef typename boost::iterator_property_map<typename std::vector<typename inhr_t::mcr_vertex_t>::iterator, typename inhr_t::TPiGraphVertexIndexMap> pi_g2g_vm_t;
|
||||
pi_g2g_vm_t m_pi_g2g_vm; ///Maps policy graph vertices to input graph vertices
|
||||
typename std::vector<typename inhr_t::mcr_vertex_t> m_pi_g2g;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Add sink vertex - this will make any graph good, the selfloop will have ratio equal to infinity
|
||||
* Properties must be "self increasing"
|
||||
*/
|
||||
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
|
||||
typename boost::graph_traits<TGraph>::vertex_descriptor
|
||||
make_graph_good(TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
|
||||
typename boost::property_traits<TWeight1EdgeMap>::value_type infinity)
|
||||
{
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
typename boost::graph_traits<TGraph>::vertex_descriptor sink = boost::add_vertex(g);
|
||||
|
||||
BGL_FORALL_VERTICES_T(vd, g, TGraph)
|
||||
{
|
||||
Edge newed = boost::add_edge(vd, sink, g).first;
|
||||
boost::put(ewm, newed, 0);
|
||||
boost::put(ew2m, newed, 1);
|
||||
}
|
||||
Edge selfed = boost::edge(sink, sink, g).first;
|
||||
boost::put(ewm, selfed, infinity);
|
||||
return sink;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Construct from input graph g "safe" (suitable for maximum_cycle_ratio1() call) version - safeg
|
||||
*/
|
||||
template <typename TG, typename TIndVertexMap, typename TW1EdgeMap, typename TW2EdgeMap, typename TSafeG, typename SafeG2GEdgeMap>
|
||||
void construct_safe_graph(const TG& g, TIndVertexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TSafeG& safeg, SafeG2GEdgeMap& sg2gm)
|
||||
{
|
||||
assert(num_vertices(g) == num_vertices(safeg));
|
||||
typedef typename graph_traits<TSafeG>::edge_descriptor tmp_edge_t;
|
||||
typedef typename graph_traits<TG>::edge_descriptor edge_t;
|
||||
typename graph_traits<TG>::edge_iterator ei, ei_end;
|
||||
|
||||
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
{
|
||||
tmp_edge_t tmped = add_edge(vim[source(*ei, g)], vim[target(*ei, g)], safeg).first;
|
||||
sg2gm[tmped] = *ei;
|
||||
put(edge_weight, safeg, tmped, get(ew1m, *ei));
|
||||
put(edge_weight2, safeg, tmped, get(ew2m, *ei));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
|
||||
double maximum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0)
|
||||
{
|
||||
if (pcc == 0)
|
||||
{
|
||||
return detail::Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap>(g, vim, ewm, ew2m)();
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::Cmcr_Howard1<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap> obj(g, vim, ewm, ew2m);
|
||||
double maxcr = obj();
|
||||
obj.get_critical_cycle(*pcc);
|
||||
return maxcr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap, typename TEdgeIndexMap>
|
||||
double minimum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm,
|
||||
TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0)
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeight1EdgeMap>::value_type>::type weight_value_t;
|
||||
BOOST_STATIC_ASSERT(!is_integral<weight_value_t>::value || is_signed<weight_value_t>::value);
|
||||
typename std::vector<weight_value_t> ne_w(boost::num_edges(g));
|
||||
BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ewm[ed];
|
||||
return -maximum_cycle_ratio_good_graph(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \param g directed multigraph.
|
||||
* \param pcc - pointer to the critical edges list.
|
||||
* \param minus_infinity must be small enough to garanty that g has at least one cycle with greater ratio.
|
||||
* \return minus_infinity if there're no cycles in the graph
|
||||
*/
|
||||
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
|
||||
double maximum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TWeight1EdgeMap>::value_type minus_infinity = -(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename boost::graph_traits<TGraph>::vertex_descriptor Vertex;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight1EdgeMap, Edge> >();
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight2EdgeMap, Edge> >();
|
||||
|
||||
TGraph& ncg = const_cast<TGraph&>(g);
|
||||
Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, minus_infinity );
|
||||
|
||||
double res = maximum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, g), ewm, ew2m, pcc);
|
||||
boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Edge index MUST be in diapazon [0,..., num_edges(g)-1]
|
||||
* \return plus_infinity if g has no cycles.
|
||||
*/
|
||||
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap, typename TEdgeIndexMap>
|
||||
double minimum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TWeight1EdgeMap>::value_type plus_infinity = (std::numeric_limits<int>::max)()
|
||||
)
|
||||
{
|
||||
typedef typename boost::property_traits<TEdgeIndexMap>::value_type ei_t;
|
||||
typedef typename boost::graph_traits<TGraph>::vertex_descriptor Vertex;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight1EdgeMap, Edge> >();
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight2EdgeMap, Edge> >();
|
||||
boost::function_requires< boost::ReadWritePropertyMapConcept<TEdgeIndexMap, Edge> >();
|
||||
|
||||
TGraph& ncg = const_cast<TGraph&>(g);
|
||||
|
||||
ei_t nei = ei_t(boost::num_edges(g));
|
||||
Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, plus_infinity );
|
||||
///Maintain edge index invariant
|
||||
BGL_FORALL_VERTICES_T(vd, ncg, TGraph)
|
||||
{
|
||||
typename boost::graph_traits<TGraph>::edge_descriptor ed = boost::edge(vd, sink, ncg).first;
|
||||
boost::put(eim, ed, nei++);
|
||||
}
|
||||
double res = minimum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, ncg), ewm, ew2m, eim, pcc);
|
||||
boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg);
|
||||
return res;
|
||||
}
|
||||
struct edge_less_than
|
||||
{
|
||||
template <typename TEdgeDescriptor> bool operator()(const TEdgeDescriptor& x, const TEdgeDescriptor& y) const
|
||||
{
|
||||
return x.get_property() < y.get_property();
|
||||
}
|
||||
};
|
||||
}///namespace detail
|
||||
namespace
|
||||
{
|
||||
template <typename TW1, typename TW2> struct safe_graph
|
||||
{
|
||||
typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::no_property,
|
||||
typename boost::property<boost::edge_weight_t, TW1, typename boost::property<boost::edge_weight2_t, TW2> > > type;
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* Calculate the maximum cycle ratio (mcr) of the directed multigraph g.
|
||||
* \param g directed multigraph
|
||||
* \param pcc - If provided then a critical cycle will be written to corresponding vector.
|
||||
* \param minus_infinity small enough value to garanty that g has at least one cycle with greater ratio.
|
||||
* \return mcr or minus_infinity if g has no cycles.
|
||||
*/
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TW1EdgeMap, typename TW2EdgeMap>
|
||||
double maximum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TW1EdgeMap>::value_type minus_infinity =
|
||||
-(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename remove_const<typename property_traits<TW1EdgeMap>::value_type>::type w1_t;
|
||||
typedef typename remove_const<typename property_traits<TW2EdgeMap>::value_type>::type w2_t;
|
||||
typedef typename safe_graph<w1_t, w2_t>::type safe_graph_t;
|
||||
typedef typename graph_traits<safe_graph_t>::edge_descriptor tmp_edge_t;
|
||||
typedef typename graph_traits<TGraph>::edge_descriptor edge_t;
|
||||
typename std::map<tmp_edge_t, edge_t, detail::edge_less_than> tmpg2g;
|
||||
std::vector<tmp_edge_t> cc;
|
||||
safe_graph_t sg(num_vertices(g));
|
||||
detail::construct_safe_graph(g, vim, ew1m, ew2m, sg, tmpg2g);
|
||||
double mcr = maximum_cycle_ratio1(sg, get(edge_weight, sg), get(edge_weight2, sg), pcc ? &cc : 0, minus_infinity);
|
||||
if (pcc && (mcr > minus_infinity))
|
||||
{
|
||||
pcc->clear();
|
||||
for (typename std::vector<tmp_edge_t>::iterator it = cc.begin(); it != cc.end(); ++it) pcc->push_back(tmpg2g[*it]);
|
||||
}
|
||||
return mcr;
|
||||
}
|
||||
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TW1EdgeMap, typename TW2EdgeMap, typename TIndEdgeMap>
|
||||
double minimum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TIndEdgeMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TW1EdgeMap>::value_type plus_infinity =
|
||||
(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TW1EdgeMap>::value_type>::type weight_value_t;
|
||||
BOOST_STATIC_ASSERT(!is_integral<weight_value_t>::value || is_signed<weight_value_t>::value);
|
||||
typename std::vector<weight_value_t> ne_w(boost::num_edges(g));
|
||||
BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ew1m[ed];
|
||||
return -maximum_cycle_ratio(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc, -plus_infinity);
|
||||
}
|
||||
/*!
|
||||
* Calculate maximum mean cycle of directed weighted multigraph.
|
||||
* \param g directed multigraph
|
||||
* \return maximum mean cycle of g or minus_infinity if g has no cycles.
|
||||
*/
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeightEdgeMap, typename TIndEdgeMap>
|
||||
double maximum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TWeightEdgeMap>::value_type minus_infinity =
|
||||
-(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeightEdgeMap>::value_type>::type weight_value_t;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
typename std::vector<weight_value_t> ed_w2(boost::num_edges(g), 1);
|
||||
return maximum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), pcc, minus_infinity);
|
||||
}
|
||||
|
||||
template <typename TGraph, typename TVertexIndexMap, typename TWeightEdgeMap, typename TIndEdgeMap>
|
||||
double minimum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim,
|
||||
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
|
||||
typename boost::property_traits<TWeightEdgeMap>::value_type plus_infinity =
|
||||
(std::numeric_limits<int>::max)())
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::property_traits<TWeightEdgeMap>::value_type>::type weight_value_t;
|
||||
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
|
||||
typename std::vector<weight_value_t> ed_w2(boost::num_edges(g), 1);
|
||||
return minimum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), eim, pcc, plus_infinity);
|
||||
}
|
||||
} //namespace boost
|
||||
#endif
|
||||
332
include/boost/graph/is_kuratowski_subgraph.hpp
Normal file
332
include/boost/graph/is_kuratowski_subgraph.hpp
Normal file
@@ -0,0 +1,332 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
#ifndef __IS_KURATOWSKI_SUBGRAPH_HPP__
|
||||
#define __IS_KURATOWSKI_SUBGRAPH_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next/prior
|
||||
#include <boost/tuple/tuple.hpp> //for tie
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/isomorphism.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Graph>
|
||||
Graph make_K_5()
|
||||
{
|
||||
typename graph_traits<Graph>::vertex_iterator vi, vi_end, inner_vi;
|
||||
Graph K_5(5);
|
||||
for(tie(vi,vi_end) = vertices(K_5); vi != vi_end; ++vi)
|
||||
for(inner_vi = next(vi); inner_vi != vi_end; ++inner_vi)
|
||||
add_edge(*vi, *inner_vi, K_5);
|
||||
return K_5;
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
Graph make_K_3_3()
|
||||
{
|
||||
typename graph_traits<Graph>::vertex_iterator
|
||||
vi, vi_end, bipartition_start, inner_vi;
|
||||
Graph K_3_3(6);
|
||||
bipartition_start = next(next(next(vertices(K_3_3).first)));
|
||||
for(tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; ++vi)
|
||||
for(inner_vi= bipartition_start; inner_vi != vi_end; ++inner_vi)
|
||||
add_edge(*vi, *inner_vi, K_3_3);
|
||||
return K_3_3;
|
||||
}
|
||||
|
||||
|
||||
template <typename AdjacencyList, typename Vertex>
|
||||
void contract_edge(AdjacencyList& neighbors, Vertex u, Vertex v)
|
||||
{
|
||||
// Remove u from v's neighbor list
|
||||
neighbors[v].erase(std::remove(neighbors[v].begin(),
|
||||
neighbors[v].end(), u
|
||||
),
|
||||
neighbors[v].end()
|
||||
);
|
||||
|
||||
// Replace any references to u with references to v
|
||||
typedef typename AdjacencyList::value_type::iterator
|
||||
adjacency_iterator_t;
|
||||
|
||||
adjacency_iterator_t u_neighbor_end = neighbors[u].end();
|
||||
for(adjacency_iterator_t u_neighbor_itr = neighbors[u].begin();
|
||||
u_neighbor_itr != u_neighbor_end; ++u_neighbor_itr
|
||||
)
|
||||
{
|
||||
Vertex u_neighbor(*u_neighbor_itr);
|
||||
std::replace(neighbors[u_neighbor].begin(),
|
||||
neighbors[u_neighbor].end(), u, v
|
||||
);
|
||||
}
|
||||
|
||||
// Remove v from u's neighbor list
|
||||
neighbors[u].erase(std::remove(neighbors[u].begin(),
|
||||
neighbors[u].end(), v
|
||||
),
|
||||
neighbors[u].end()
|
||||
);
|
||||
|
||||
// Add everything in u's neighbor list to v's neighbor list
|
||||
std::copy(neighbors[u].begin(),
|
||||
neighbors[u].end(),
|
||||
std::back_inserter(neighbors[v])
|
||||
);
|
||||
|
||||
// Clear u's neighbor list
|
||||
neighbors[u].clear();
|
||||
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename ForwardIterator, typename VertexIndexMap>
|
||||
bool is_kuratowski_subgraph(const Graph& g,
|
||||
ForwardIterator begin,
|
||||
ForwardIterator end,
|
||||
VertexIndexMap vm
|
||||
)
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::edges_size_type e_size_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef typename std::vector<vertex_t> v_list_t;
|
||||
typedef typename v_list_t::iterator v_list_iterator_t;
|
||||
typedef iterator_property_map
|
||||
<typename std::vector<v_list_t>::iterator, VertexIndexMap>
|
||||
vertex_to_v_list_map_t;
|
||||
|
||||
typedef adjacency_list<vecS, vecS, undirectedS> small_graph_t;
|
||||
|
||||
enum target_graph_t { k_3_3, k_5};
|
||||
|
||||
target_graph_t target_graph = k_3_3; //unless we decide otherwise later
|
||||
|
||||
static small_graph_t K_5(detail::make_K_5<small_graph_t>());
|
||||
|
||||
static small_graph_t K_3_3(detail::make_K_3_3<small_graph_t>());
|
||||
|
||||
v_size_t n_vertices(num_vertices(g));
|
||||
v_size_t max_num_edges(3*n_vertices - 5);
|
||||
|
||||
std::vector<v_list_t> neighbors_vector(n_vertices);
|
||||
vertex_to_v_list_map_t neighbors(neighbors_vector.begin(), vm);
|
||||
|
||||
e_size_t count = 0;
|
||||
for(ForwardIterator itr = begin; itr != end; ++itr)
|
||||
{
|
||||
|
||||
if (count++ > max_num_edges)
|
||||
return false;
|
||||
|
||||
edge_t e(*itr);
|
||||
vertex_t u(source(e,g));
|
||||
vertex_t v(target(e,g));
|
||||
|
||||
neighbors[u].push_back(v);
|
||||
neighbors[v].push_back(u);
|
||||
|
||||
}
|
||||
|
||||
|
||||
for(v_size_t max_size = 2; max_size < 5; ++max_size)
|
||||
{
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_t v(*vi);
|
||||
|
||||
//a hack to make sure we don't contract the middle edge of a path
|
||||
//of four degree-3 vertices
|
||||
if (max_size == 4 && neighbors[v].size() == 3)
|
||||
{
|
||||
if (neighbors[neighbors[v][0]].size() +
|
||||
neighbors[neighbors[v][1]].size() +
|
||||
neighbors[neighbors[v][2]].size()
|
||||
< 11 // so, it has two degree-3 neighbors
|
||||
)
|
||||
continue;
|
||||
}
|
||||
|
||||
while (neighbors[v].size() > 0 && neighbors[v].size() < max_size)
|
||||
{
|
||||
// Find one of v's neighbors u such that that v and u
|
||||
// have no neighbors in common. We'll look for such a
|
||||
// neighbor with a naive cubic-time algorithm since the
|
||||
// max size of any of the neighbor sets we'll consider
|
||||
// merging is 3
|
||||
|
||||
bool neighbor_sets_intersect = false;
|
||||
|
||||
vertex_t min_u = graph_traits<Graph>::null_vertex();
|
||||
vertex_t u;
|
||||
v_list_iterator_t v_neighbor_end = neighbors[v].end();
|
||||
for(v_list_iterator_t v_neighbor_itr = neighbors[v].begin();
|
||||
v_neighbor_itr != v_neighbor_end;
|
||||
++v_neighbor_itr
|
||||
)
|
||||
{
|
||||
neighbor_sets_intersect = false;
|
||||
u = *v_neighbor_itr;
|
||||
v_list_iterator_t u_neighbor_end = neighbors[u].end();
|
||||
for(v_list_iterator_t u_neighbor_itr =
|
||||
neighbors[u].begin();
|
||||
u_neighbor_itr != u_neighbor_end &&
|
||||
!neighbor_sets_intersect;
|
||||
++u_neighbor_itr
|
||||
)
|
||||
{
|
||||
for(v_list_iterator_t inner_v_neighbor_itr =
|
||||
neighbors[v].begin();
|
||||
inner_v_neighbor_itr != v_neighbor_end;
|
||||
++inner_v_neighbor_itr
|
||||
)
|
||||
{
|
||||
if (*u_neighbor_itr == *inner_v_neighbor_itr)
|
||||
{
|
||||
neighbor_sets_intersect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!neighbor_sets_intersect &&
|
||||
(min_u == graph_traits<Graph>::null_vertex() ||
|
||||
neighbors[u].size() < neighbors[min_u].size())
|
||||
)
|
||||
{
|
||||
min_u = u;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (min_u == graph_traits<Graph>::null_vertex())
|
||||
// Exited the loop without finding an appropriate neighbor of
|
||||
// v, so v must be a lost cause. Move on to other vertices.
|
||||
break;
|
||||
else
|
||||
u = min_u;
|
||||
|
||||
detail::contract_edge(neighbors, u, v);
|
||||
|
||||
}//end iteration over v's neighbors
|
||||
|
||||
}//end iteration through vertices v
|
||||
|
||||
if (max_size == 3)
|
||||
{
|
||||
// check to see whether we should go on to find a K_5
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
if (neighbors[*vi].size() == 4)
|
||||
{
|
||||
target_graph = k_5;
|
||||
break;
|
||||
}
|
||||
|
||||
if (target_graph == k_3_3)
|
||||
break;
|
||||
}
|
||||
|
||||
}//end iteration through max degree 2,3, and 4
|
||||
|
||||
|
||||
//Now, there should only be 5 or 6 vertices with any neighbors. Find them.
|
||||
|
||||
v_list_t main_vertices;
|
||||
vertex_iterator_t vi, vi_end;
|
||||
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
if (!neighbors[*vi].empty())
|
||||
main_vertices.push_back(*vi);
|
||||
}
|
||||
|
||||
// create a graph isomorphic to the contracted graph to test
|
||||
// against K_5 and K_3_3
|
||||
small_graph_t contracted_graph(main_vertices.size());
|
||||
std::map<vertex_t,typename graph_traits<small_graph_t>::vertex_descriptor>
|
||||
contracted_vertex_map;
|
||||
|
||||
typename v_list_t::iterator itr, itr_end;
|
||||
itr_end = main_vertices.end();
|
||||
typename graph_traits<small_graph_t>::vertex_iterator
|
||||
si = vertices(contracted_graph).first;
|
||||
|
||||
for(itr = main_vertices.begin(); itr != itr_end; ++itr, ++si)
|
||||
{
|
||||
contracted_vertex_map[*itr] = *si;
|
||||
}
|
||||
|
||||
typename v_list_t::iterator jtr, jtr_end;
|
||||
for(itr = main_vertices.begin(); itr != itr_end; ++itr)
|
||||
{
|
||||
jtr_end = neighbors[*itr].end();
|
||||
for(jtr = neighbors[*itr].begin(); jtr != jtr_end; ++jtr)
|
||||
{
|
||||
if (get(vm,*itr) < get(vm,*jtr))
|
||||
{
|
||||
add_edge(contracted_vertex_map[*itr],
|
||||
contracted_vertex_map[*jtr],
|
||||
contracted_graph
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target_graph == k_5)
|
||||
{
|
||||
return isomorphism(K_5,contracted_graph);
|
||||
}
|
||||
else //target_graph == k_3_3
|
||||
{
|
||||
return isomorphism(K_3_3,contracted_graph);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename ForwardIterator>
|
||||
bool is_kuratowski_subgraph(const Graph& g,
|
||||
ForwardIterator begin,
|
||||
ForwardIterator end
|
||||
)
|
||||
{
|
||||
return is_kuratowski_subgraph(g, begin, end, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //__IS_KURATOWSKI_SUBGRAPH_HPP__
|
||||
232
include/boost/graph/is_straight_line_drawing.hpp
Normal file
232
include/boost/graph/is_straight_line_drawing.hpp
Normal file
@@ -0,0 +1,232 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
#ifndef __IS_STRAIGHT_LINE_DRAWING_HPP__
|
||||
#define __IS_STRAIGHT_LINE_DRAWING_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next and prior
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/tuple/tuple_comparison.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/planar_detail/bucket_sort.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// Return true exactly when the line segments s1 = ((x1,y1), (x2,y2)) and
|
||||
// s2 = ((a1,b1), (a2,b2)) intersect in a point other than the endpoints of
|
||||
// the line segments. The one exception to this rule is when s1 = s2, in
|
||||
// which case false is returned - this is to accomodate multiple edges
|
||||
// between the same pair of vertices, which shouldn't invalidate the straight
|
||||
// line embedding. A tolerance variable epsilon can also be used, which
|
||||
// defines how far away from the endpoints of s1 and s2 we want to consider
|
||||
// an intersection.
|
||||
|
||||
bool intersects(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double a1, double b1,
|
||||
double a2, double b2,
|
||||
double epsilon = 0.000001
|
||||
)
|
||||
{
|
||||
|
||||
if (x1 - x2 == 0)
|
||||
{
|
||||
std::swap(x1,a1);
|
||||
std::swap(y1,b1);
|
||||
std::swap(x2,a2);
|
||||
std::swap(y2,b2);
|
||||
}
|
||||
|
||||
if (x1 - x2 == 0)
|
||||
{
|
||||
BOOST_USING_STD_MAX();
|
||||
BOOST_USING_STD_MIN();
|
||||
|
||||
//two vertical line segments
|
||||
double min_y = min BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2);
|
||||
double max_y = max BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2);
|
||||
double min_b = min BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2);
|
||||
double max_b = max BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2);
|
||||
if ((max_y > max_b && max_b > min_y) ||
|
||||
(max_b > max_y && max_y > min_b)
|
||||
)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
double x_diff = x1 - x2;
|
||||
double y_diff = y1 - y2;
|
||||
double a_diff = a2 - a1;
|
||||
double b_diff = b2 - b1;
|
||||
|
||||
double beta_denominator = b_diff - (y_diff/((double)x_diff)) * a_diff;
|
||||
|
||||
if (beta_denominator == 0)
|
||||
{
|
||||
//parallel lines
|
||||
return false;
|
||||
}
|
||||
|
||||
double beta = (b2 - y2 - (y_diff/((double)x_diff)) * (a2 - x2)) /
|
||||
beta_denominator;
|
||||
double alpha = (a2 - x2 - beta*(a_diff))/x_diff;
|
||||
|
||||
double upper_bound = 1 - epsilon;
|
||||
double lower_bound = 0 + epsilon;
|
||||
|
||||
return (beta < upper_bound && beta > lower_bound &&
|
||||
alpha < upper_bound && alpha > lower_bound);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename GridPositionMap,
|
||||
typename VertexIndexMap
|
||||
>
|
||||
bool is_straight_line_drawing(const Graph& g,
|
||||
GridPositionMap drawing,
|
||||
VertexIndexMap vm
|
||||
)
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
|
||||
typedef typename graph_traits<Graph>::edges_size_type e_size_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
|
||||
typedef std::size_t x_coord_t;
|
||||
typedef std::size_t y_coord_t;
|
||||
typedef boost::tuple<edge_t, x_coord_t, y_coord_t> edge_event_t;
|
||||
typedef typename std::vector< edge_event_t > edge_event_queue_t;
|
||||
|
||||
typedef tuple<y_coord_t, y_coord_t, x_coord_t, x_coord_t> active_map_key_t;
|
||||
typedef edge_t active_map_value_t;
|
||||
typedef std::map< active_map_key_t, active_map_value_t > active_map_t;
|
||||
typedef typename active_map_t::iterator active_map_iterator_t;
|
||||
|
||||
|
||||
edge_event_queue_t edge_event_queue;
|
||||
active_map_t active_edges;
|
||||
|
||||
edge_iterator_t ei, ei_end;
|
||||
for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
{
|
||||
edge_t e(*ei);
|
||||
vertex_t s(source(e,g));
|
||||
vertex_t t(target(e,g));
|
||||
edge_event_queue.push_back
|
||||
(make_tuple(e,
|
||||
static_cast<std::size_t>(drawing[s].x),
|
||||
static_cast<std::size_t>(drawing[s].y)
|
||||
)
|
||||
);
|
||||
edge_event_queue.push_back
|
||||
(make_tuple(e,
|
||||
static_cast<std::size_t>(drawing[t].x),
|
||||
static_cast<std::size_t>(drawing[t].y)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Order by edge_event_queue by first, then second coordinate
|
||||
// (bucket_sort is a stable sort.)
|
||||
bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
|
||||
property_map_tuple_adaptor<edge_event_t, 2>()
|
||||
);
|
||||
|
||||
bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
|
||||
property_map_tuple_adaptor<edge_event_t, 1>()
|
||||
);
|
||||
|
||||
typedef typename edge_event_queue_t::iterator event_queue_iterator_t;
|
||||
event_queue_iterator_t itr_end = edge_event_queue.end();
|
||||
for(event_queue_iterator_t itr = edge_event_queue.begin();
|
||||
itr != itr_end; ++itr
|
||||
)
|
||||
{
|
||||
edge_t e(get<0>(*itr));
|
||||
vertex_t source_v(source(e,g));
|
||||
vertex_t target_v(target(e,g));
|
||||
if (drawing[source_v].x > drawing[target_v].x)
|
||||
std::swap(source_v, target_v);
|
||||
|
||||
active_map_key_t key(get(drawing, source_v).y,
|
||||
get(drawing, target_v).y,
|
||||
get(drawing, source_v).x,
|
||||
get(drawing, target_v).x
|
||||
);
|
||||
|
||||
active_map_iterator_t a_itr = active_edges.find(key);
|
||||
if (a_itr == active_edges.end())
|
||||
{
|
||||
active_edges[key] = e;
|
||||
}
|
||||
else
|
||||
{
|
||||
active_map_iterator_t before, after;
|
||||
if (a_itr == active_edges.begin())
|
||||
before = active_edges.end();
|
||||
else
|
||||
before = prior(a_itr);
|
||||
after = next(a_itr);
|
||||
|
||||
if (after != active_edges.end() || before != active_edges.end())
|
||||
{
|
||||
|
||||
edge_t f = after != active_edges.end() ?
|
||||
after->second : before->second;
|
||||
|
||||
vertex_t e_source(source(e,g));
|
||||
vertex_t e_target(target(e,g));
|
||||
vertex_t f_source(source(f,g));
|
||||
vertex_t f_target(target(f,g));
|
||||
|
||||
if (intersects(drawing[e_source].x,
|
||||
drawing[e_source].y,
|
||||
drawing[e_target].x,
|
||||
drawing[e_target].y,
|
||||
drawing[f_source].x,
|
||||
drawing[f_source].y,
|
||||
drawing[f_target].x,
|
||||
drawing[f_target].y
|
||||
)
|
||||
)
|
||||
return false;
|
||||
}
|
||||
|
||||
active_edges.erase(a_itr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph, typename GridPositionMap>
|
||||
bool is_straight_line_drawing(const Graph& g, GridPositionMap drawing)
|
||||
{
|
||||
return is_straight_line_drawing(g, drawing, get(vertex_index,g));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // __IS_STRAIGHT_LINE_DRAWING_HPP__
|
||||
@@ -245,7 +245,7 @@ namespace boost {
|
||||
|
||||
}
|
||||
else {
|
||||
if (contains(adjacent_vertices(f[i], G2), f[j])) {
|
||||
if (container_contains(adjacent_vertices(f[i], G2), f[j])) {
|
||||
++num_edges_on_k;
|
||||
if (match(next(iter), dfs_num_k))
|
||||
return true;
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#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 {
|
||||
|
||||
807
include/boost/graph/kolmogorov_max_flow.hpp
Normal file
807
include/boost/graph/kolmogorov_max_flow.hpp
Normal file
@@ -0,0 +1,807 @@
|
||||
// Copyright (c) 2006, Stephan Diederich
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_KOLMOGOROV_MAX_FLOW_HPP
|
||||
#define BOOST_KOLMOGOROV_MAX_FLOW_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <iosfwd>
|
||||
#include <algorithm> // for std::min and std::max
|
||||
|
||||
#include <boost/pending/queue.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/none_t.hpp>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/named_function_params.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template <class Graph,
|
||||
class EdgeCapacityMap,
|
||||
class ResidualCapacityEdgeMap,
|
||||
class ReverseEdgeMap,
|
||||
class PredecessorMap,
|
||||
class ColorMap,
|
||||
class DistanceMap,
|
||||
class IndexMap>
|
||||
class kolmogorov{
|
||||
typedef typename property_traits<EdgeCapacityMap>::value_type tEdgeVal;
|
||||
typedef graph_traits<Graph> tGraphTraits;
|
||||
typedef typename tGraphTraits::vertex_iterator vertex_iterator;
|
||||
typedef typename tGraphTraits::vertex_descriptor vertex_descriptor;
|
||||
typedef typename tGraphTraits::edge_descriptor edge_descriptor;
|
||||
typedef typename tGraphTraits::edge_iterator edge_iterator;
|
||||
typedef typename tGraphTraits::out_edge_iterator out_edge_iterator;
|
||||
typedef boost::queue<vertex_descriptor> tQueue; //queue of vertices, used in adoption-stage
|
||||
typedef typename property_traits<ColorMap>::value_type tColorValue;
|
||||
typedef color_traits<tColorValue> tColorTraits;
|
||||
typedef typename property_traits<DistanceMap>::value_type tDistanceVal;
|
||||
|
||||
public:
|
||||
kolmogorov(Graph& g,
|
||||
EdgeCapacityMap cap,
|
||||
ResidualCapacityEdgeMap res,
|
||||
ReverseEdgeMap rev,
|
||||
PredecessorMap pre,
|
||||
ColorMap color,
|
||||
DistanceMap dist,
|
||||
IndexMap idx,
|
||||
vertex_descriptor src,
|
||||
vertex_descriptor sink):
|
||||
m_g(g),
|
||||
m_index_map(idx),
|
||||
m_cap_map(cap),
|
||||
m_res_cap_map(res),
|
||||
m_rev_edge_map(rev),
|
||||
m_pre_map(pre),
|
||||
m_tree_map(color),
|
||||
m_dist_map(dist),
|
||||
m_source(src),
|
||||
m_sink(sink),
|
||||
m_active_nodes(),
|
||||
m_in_active_list_vec(num_vertices(g), false),
|
||||
m_in_active_list_map(make_iterator_property_map(m_in_active_list_vec.begin(), m_index_map)),
|
||||
m_has_parent_vec(num_vertices(g), false),
|
||||
m_has_parent_map(make_iterator_property_map(m_has_parent_vec.begin(), m_index_map)),
|
||||
m_time_vec(num_vertices(g), 0),
|
||||
m_time_map(make_iterator_property_map(m_time_vec.begin(), m_index_map)),
|
||||
m_flow(0),
|
||||
m_time(1),
|
||||
m_last_grow_vertex(graph_traits<Graph>::null_vertex()){
|
||||
// initialize the color-map with gray-values
|
||||
vertex_iterator vi, v_end;
|
||||
for(tie(vi, v_end) = vertices(m_g); vi != v_end; ++vi){
|
||||
set_tree(*vi, tColorTraits::gray());
|
||||
}
|
||||
// Initialize flow to zero which means initializing
|
||||
// the residual capacity equal to the capacity
|
||||
edge_iterator ei, e_end;
|
||||
for(tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) {
|
||||
m_res_cap_map[*ei] = m_cap_map[*ei];
|
||||
assert(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly
|
||||
}
|
||||
//init the search trees with the two terminals
|
||||
set_tree(m_source, tColorTraits::black());
|
||||
set_tree(m_sink, tColorTraits::white());
|
||||
m_time_map[m_source] = 1;
|
||||
m_time_map[m_sink] = 1;
|
||||
}
|
||||
|
||||
~kolmogorov(){}
|
||||
|
||||
tEdgeVal max_flow(){
|
||||
//augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK
|
||||
augment_direct_paths();
|
||||
//start the main-loop
|
||||
while(true){
|
||||
bool path_found;
|
||||
edge_descriptor connecting_edge;
|
||||
tie(connecting_edge, path_found) = grow(); //find a path from source to sink
|
||||
if(!path_found){
|
||||
//we're finished, no more paths were found
|
||||
break;
|
||||
}
|
||||
++m_time;
|
||||
augment(connecting_edge); //augment that path
|
||||
adopt(); //rebuild search tree structure
|
||||
}
|
||||
return m_flow;
|
||||
}
|
||||
|
||||
//the complete class is protected, as we want access to members in derived test-class (see $(BOOST_ROOT)/libs/graph/test/kolmogorov_max_flow_test.cpp)
|
||||
protected:
|
||||
void augment_direct_paths(){
|
||||
//in a first step, we augment all direct paths from source->NODE->sink
|
||||
//and additionally paths from source->sink
|
||||
//this improves especially graphcuts for segmentation, as most of the nodes have source/sink connects
|
||||
//but shouldn't have an impact on other maxflow problems (this is done in grow() anyway)
|
||||
out_edge_iterator ei, e_end;
|
||||
for(tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end; ++ei){
|
||||
edge_descriptor from_source = *ei;
|
||||
vertex_descriptor current_node = target(from_source, m_g);
|
||||
if(current_node == m_sink){
|
||||
tEdgeVal cap = m_res_cap_map[from_source];
|
||||
m_res_cap_map[from_source] = 0;
|
||||
m_flow += cap;
|
||||
continue;
|
||||
}
|
||||
edge_descriptor to_sink;
|
||||
bool is_there;
|
||||
tie(to_sink, is_there) = edge(current_node, m_sink, m_g);
|
||||
if(is_there){
|
||||
tEdgeVal cap_from_source = m_res_cap_map[from_source];
|
||||
tEdgeVal cap_to_sink = m_res_cap_map[to_sink];
|
||||
if(cap_from_source > cap_to_sink){
|
||||
set_tree(current_node, tColorTraits::black());
|
||||
add_active_node(current_node);
|
||||
set_edge_to_parent(current_node, from_source);
|
||||
m_dist_map[current_node] = 1;
|
||||
m_time_map[current_node] = 1;
|
||||
//add stuff to flow and update residuals
|
||||
//we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow
|
||||
m_res_cap_map[from_source] -= cap_to_sink;
|
||||
m_res_cap_map[to_sink] = 0;
|
||||
m_flow += cap_to_sink;
|
||||
} else if(cap_to_sink > 0){
|
||||
set_tree(current_node, tColorTraits::white());
|
||||
add_active_node(current_node);
|
||||
set_edge_to_parent(current_node, to_sink);
|
||||
m_dist_map[current_node] = 1;
|
||||
m_time_map[current_node] = 1;
|
||||
//add stuff to flow and update residuals
|
||||
//we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow
|
||||
m_res_cap_map[to_sink] -= cap_from_source;
|
||||
m_res_cap_map[from_source] = 0;
|
||||
m_flow += cap_from_source;
|
||||
}
|
||||
} else if(m_res_cap_map[from_source]){
|
||||
//there is no sink connect, so we can't augment this path
|
||||
//but to avoid adding m_source to the active nodes, we just activate this node and set the approciate things
|
||||
set_tree(current_node, tColorTraits::black());
|
||||
set_edge_to_parent(current_node, from_source);
|
||||
m_dist_map[current_node] = 1;
|
||||
m_time_map[current_node] = 1;
|
||||
add_active_node(current_node);
|
||||
}
|
||||
}
|
||||
for(tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){
|
||||
edge_descriptor to_sink = m_rev_edge_map[*ei];
|
||||
vertex_descriptor current_node = source(to_sink, m_g);
|
||||
if(m_res_cap_map[to_sink]){
|
||||
set_tree(current_node, tColorTraits::white());
|
||||
set_edge_to_parent(current_node, to_sink);
|
||||
m_dist_map[current_node] = 1;
|
||||
m_time_map[current_node] = 1;
|
||||
add_active_node(current_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a pair of an edge and a boolean. if the bool is true, the edge is a connection of a found path from s->t , read "the link" and
|
||||
* source(returnVal, m_g) is the end of the path found in the source-tree
|
||||
* target(returnVal, m_g) is the beginning of the path found in the sink-tree
|
||||
*/
|
||||
std::pair<edge_descriptor, bool> grow(){
|
||||
assert(m_orphans.empty());
|
||||
vertex_descriptor current_node;
|
||||
while((current_node = get_next_active_node()) != graph_traits<Graph>::null_vertex()){ //if there is one
|
||||
assert(get_tree(current_node) != tColorTraits::gray() && (has_parent(current_node) || current_node==m_source || current_node==m_sink));
|
||||
if(get_tree(current_node) == tColorTraits::black()){
|
||||
//source tree growing
|
||||
out_edge_iterator ei, e_end;
|
||||
if(current_node != m_last_grow_vertex){
|
||||
m_last_grow_vertex = current_node;
|
||||
tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
|
||||
}
|
||||
for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){
|
||||
edge_descriptor out_edge = *m_last_grow_edge_it;
|
||||
if(m_res_cap_map[out_edge] > 0){ //check if we have capacity left on this edge
|
||||
vertex_descriptor other_node = target(out_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
|
||||
set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree
|
||||
set_edge_to_parent(other_node, out_edge); //set us as parent
|
||||
m_dist_map[other_node] = m_dist_map[current_node] + 1; //and update the distance-heuristic
|
||||
m_time_map[other_node] = m_time_map[current_node];
|
||||
add_active_node(other_node);
|
||||
} else if(get_tree(other_node) == tColorTraits::black()){
|
||||
if(is_closer_to_terminal(current_node, other_node)){ //we do this to get shorter paths. check if we are nearer to the source as its parent is
|
||||
set_edge_to_parent(other_node, out_edge);
|
||||
m_dist_map[other_node] = m_dist_map[current_node] + 1;
|
||||
m_time_map[other_node] = m_time_map[current_node];
|
||||
}
|
||||
} else{
|
||||
assert(get_tree(other_node)==tColorTraits::white());
|
||||
//kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir
|
||||
return std::make_pair(out_edge, true);
|
||||
}
|
||||
}
|
||||
} //for all out-edges
|
||||
} //source-tree-growing
|
||||
else{
|
||||
assert(get_tree(current_node) == tColorTraits::white());
|
||||
out_edge_iterator ei, e_end;
|
||||
if(current_node != m_last_grow_vertex){
|
||||
m_last_grow_vertex = current_node;
|
||||
tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
|
||||
}
|
||||
for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){
|
||||
edge_descriptor in_edge = m_rev_edge_map[*m_last_grow_edge_it];
|
||||
if(m_res_cap_map[in_edge] > 0){ //check if there is capacity left
|
||||
vertex_descriptor other_node = source(in_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
|
||||
set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree
|
||||
set_edge_to_parent(other_node, in_edge); //set us as parent
|
||||
add_active_node(other_node); //activate that node
|
||||
m_dist_map[other_node] = m_dist_map[current_node] + 1; //set its distance
|
||||
m_time_map[other_node] = m_time_map[current_node]; //and time
|
||||
} else if(get_tree(other_node) == tColorTraits::white()){
|
||||
if(is_closer_to_terminal(current_node, other_node)){
|
||||
//we are closer to the sink than its parent is, so we "adopt" him
|
||||
set_edge_to_parent(other_node, in_edge);
|
||||
m_dist_map[other_node] = m_dist_map[current_node] + 1;
|
||||
m_time_map[other_node] = m_time_map[current_node];
|
||||
}
|
||||
} else{
|
||||
assert(get_tree(other_node)==tColorTraits::black());
|
||||
//kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir
|
||||
return std::make_pair(in_edge, true);
|
||||
}
|
||||
}
|
||||
} //for all out-edges
|
||||
} //sink-tree growing
|
||||
//all edges of that node are processed, and no more paths were found. so remove if from the front of the active queue
|
||||
finish_node(current_node);
|
||||
} //while active_nodes not empty
|
||||
return std::make_pair(edge_descriptor(), false); //no active nodes anymore and no path found, we're done
|
||||
}
|
||||
|
||||
/**
|
||||
* augments path from s->t and updates residual graph
|
||||
* source(e, m_g) is the end of the path found in the source-tree
|
||||
* target(e, m_g) is the beginning of the path found in the sink-tree
|
||||
* this phase generates orphans on satured edges, if the attached verts are from different search-trees
|
||||
* orphans are ordered in distance to sink/source. first the farest from the source are front_inserted into the orphans list,
|
||||
* and after that the sink-tree-orphans are front_inserted. when going to adoption stage the orphans are popped_front, and so we process the nearest
|
||||
* verts to the terminals first
|
||||
*/
|
||||
void augment(edge_descriptor e){
|
||||
assert(get_tree(target(e, m_g)) == tColorTraits::white());
|
||||
assert(get_tree(source(e, m_g)) == tColorTraits::black());
|
||||
assert(m_orphans.empty());
|
||||
|
||||
const tEdgeVal bottleneck = find_bottleneck(e);
|
||||
//now we push the found flow through the path
|
||||
//for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans
|
||||
//now process the connecting edge
|
||||
m_res_cap_map[e] -= bottleneck;
|
||||
assert(m_res_cap_map[e] >= 0);
|
||||
m_res_cap_map[m_rev_edge_map[e]] += bottleneck;
|
||||
|
||||
//now we follow the path back to the source
|
||||
vertex_descriptor current_node = source(e, m_g);
|
||||
while(current_node != m_source){
|
||||
edge_descriptor pred = get_edge_to_parent(current_node);
|
||||
m_res_cap_map[pred] -= bottleneck;
|
||||
assert(m_res_cap_map[pred] >= 0);
|
||||
m_res_cap_map[m_rev_edge_map[pred]] += bottleneck;
|
||||
if(m_res_cap_map[pred] == 0){
|
||||
set_no_parent(current_node);
|
||||
m_orphans.push_front(current_node);
|
||||
}
|
||||
current_node = source(pred, m_g);
|
||||
}
|
||||
//then go forward in the sink-tree
|
||||
current_node = target(e, m_g);
|
||||
while(current_node != m_sink){
|
||||
edge_descriptor pred = get_edge_to_parent(current_node);
|
||||
m_res_cap_map[pred] -= bottleneck;
|
||||
assert(m_res_cap_map[pred] >= 0);
|
||||
m_res_cap_map[m_rev_edge_map[pred]] += bottleneck;
|
||||
if(m_res_cap_map[pred] == 0){
|
||||
set_no_parent(current_node);
|
||||
m_orphans.push_front(current_node);
|
||||
}
|
||||
current_node = target(pred, m_g);
|
||||
}
|
||||
//and add it to the max-flow
|
||||
m_flow += bottleneck;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the bottleneck of a s->t path (end_of_path is last vertex in source-tree, begin_of_path is first vertex in sink-tree)
|
||||
*/
|
||||
inline tEdgeVal find_bottleneck(edge_descriptor e){
|
||||
BOOST_USING_STD_MIN();
|
||||
tEdgeVal minimum_cap = m_res_cap_map[e];
|
||||
vertex_descriptor current_node = source(e, m_g);
|
||||
//first go back in the source tree
|
||||
while(current_node != m_source){
|
||||
edge_descriptor pred = get_edge_to_parent(current_node);
|
||||
minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]);
|
||||
current_node = source(pred, m_g);
|
||||
}
|
||||
//then go forward in the sink-tree
|
||||
current_node = target(e, m_g);
|
||||
while(current_node != m_sink){
|
||||
edge_descriptor pred = get_edge_to_parent(current_node);
|
||||
minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]);
|
||||
current_node = target(pred, m_g);
|
||||
}
|
||||
return minimum_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* rebuild search trees
|
||||
* empty the queue of orphans, and find new parents for them or just drop them from the search trees
|
||||
*/
|
||||
void adopt(){
|
||||
while(!m_orphans.empty() || !m_child_orphans.empty()){
|
||||
vertex_descriptor current_node;
|
||||
if(m_child_orphans.empty()){
|
||||
//get the next orphan from the main-queue and remove it
|
||||
current_node = m_orphans.front();
|
||||
m_orphans.pop_front();
|
||||
} else{
|
||||
current_node = m_child_orphans.front();
|
||||
m_child_orphans.pop();
|
||||
}
|
||||
if(get_tree(current_node) == tColorTraits::black()){
|
||||
//we're in the source-tree
|
||||
tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
|
||||
edge_descriptor new_parent_edge;
|
||||
out_edge_iterator ei, e_end;
|
||||
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
|
||||
const edge_descriptor in_edge = m_rev_edge_map[*ei];
|
||||
assert(target(in_edge, m_g) == current_node); //we should be the target of this edge
|
||||
if(m_res_cap_map[in_edge] > 0){
|
||||
vertex_descriptor other_node = source(in_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){
|
||||
if(m_dist_map[other_node] < min_distance){
|
||||
min_distance = m_dist_map[other_node];
|
||||
new_parent_edge = in_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
|
||||
set_edge_to_parent(current_node, new_parent_edge);
|
||||
m_dist_map[current_node] = min_distance + 1;
|
||||
m_time_map[current_node] = m_time;
|
||||
} else{
|
||||
m_time_map[current_node] = 0;
|
||||
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
|
||||
edge_descriptor in_edge = m_rev_edge_map[*ei];
|
||||
vertex_descriptor other_node = source(in_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){
|
||||
if(m_res_cap_map[in_edge] > 0){
|
||||
add_active_node(other_node);
|
||||
}
|
||||
if(source(get_edge_to_parent(other_node), m_g) == current_node){
|
||||
//we are the parent of that node
|
||||
//it has to find a new parent, too
|
||||
set_no_parent(other_node);
|
||||
m_child_orphans.push(other_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
set_tree(current_node, tColorTraits::gray());
|
||||
} //no parent found
|
||||
} //source-tree-adoption
|
||||
else{
|
||||
//now we should be in the sink-tree, check that...
|
||||
assert(get_tree(current_node) == tColorTraits::white());
|
||||
out_edge_iterator ei, e_end;
|
||||
edge_descriptor new_parent_edge;
|
||||
tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
|
||||
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
|
||||
const edge_descriptor out_edge = *ei;
|
||||
if(m_res_cap_map[out_edge] > 0){
|
||||
const vertex_descriptor other_node = target(out_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node))
|
||||
if(m_dist_map[other_node] < min_distance){
|
||||
min_distance = m_dist_map[other_node];
|
||||
new_parent_edge = out_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
|
||||
set_edge_to_parent(current_node, new_parent_edge);
|
||||
m_dist_map[current_node] = min_distance + 1;
|
||||
m_time_map[current_node] = m_time;
|
||||
} else{
|
||||
m_time_map[current_node] = 0;
|
||||
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
|
||||
const edge_descriptor out_edge = *ei;
|
||||
const vertex_descriptor other_node = target(out_edge, m_g);
|
||||
if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){
|
||||
if(m_res_cap_map[out_edge] > 0){
|
||||
add_active_node(other_node);
|
||||
}
|
||||
if(target(get_edge_to_parent(other_node), m_g) == current_node){
|
||||
//we were it's parent, so it has to find a new one, too
|
||||
set_no_parent(other_node);
|
||||
m_child_orphans.push(other_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
set_tree(current_node, tColorTraits::gray());
|
||||
} //no parent found
|
||||
} //sink-tree adoption
|
||||
} //while !orphans.empty()
|
||||
} //adopt
|
||||
|
||||
/**
|
||||
* return next active vertex if there is one, otherwise a null_vertex
|
||||
*/
|
||||
inline vertex_descriptor get_next_active_node(){
|
||||
while(true){
|
||||
if(m_active_nodes.empty())
|
||||
return graph_traits<Graph>::null_vertex();
|
||||
vertex_descriptor v = m_active_nodes.front();
|
||||
|
||||
if(!has_parent(v) && v != m_source && v != m_sink){ //if it has no parent, this node can't be active(if its not source or sink)
|
||||
m_active_nodes.pop();
|
||||
m_in_active_list_map[v] = false;
|
||||
} else{
|
||||
assert(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white());
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* adds v as an active vertex, but only if its not in the list already
|
||||
*/
|
||||
inline void add_active_node(vertex_descriptor v){
|
||||
assert(get_tree(v) != tColorTraits::gray());
|
||||
if(m_in_active_list_map[v]){
|
||||
return;
|
||||
} else{
|
||||
m_in_active_list_map[v] = true;
|
||||
m_active_nodes.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node)
|
||||
*/
|
||||
inline void finish_node(vertex_descriptor v){
|
||||
assert(m_active_nodes.front() == v);
|
||||
m_active_nodes.pop();
|
||||
m_in_active_list_map[v] = false;
|
||||
m_last_grow_vertex = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a vertex from the queue of active nodes (actually this does nothing,
|
||||
* but checks if this node has no parent edge, as this is the criteria for beeing no more active)
|
||||
*/
|
||||
inline void remove_active_node(vertex_descriptor v){
|
||||
assert(!has_parent(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree
|
||||
*/
|
||||
inline tColorValue get_tree(vertex_descriptor v) const {
|
||||
return m_tree_map[v];
|
||||
}
|
||||
|
||||
/**
|
||||
* sets search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree
|
||||
*/
|
||||
inline void set_tree(vertex_descriptor v, tColorValue t){
|
||||
m_tree_map[v] = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns edge to parent vertex of v;
|
||||
*/
|
||||
inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{
|
||||
return m_pre_map[v];
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the edge stored in m_pre_map[v] is a valid entry
|
||||
*/
|
||||
inline bool has_parent(vertex_descriptor v) const{
|
||||
return m_has_parent_map[v];
|
||||
}
|
||||
|
||||
/**
|
||||
* sets edge to parent vertex of v;
|
||||
*/
|
||||
inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){
|
||||
assert(m_res_cap_map[f_edge_to_parent] > 0);
|
||||
m_pre_map[v] = f_edge_to_parent;
|
||||
m_has_parent_map[v] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* removes the edge to parent of v (this is done by invalidating the entry an additional map)
|
||||
*/
|
||||
inline void set_no_parent(vertex_descriptor v){
|
||||
m_has_parent_map[v] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if vertex v has a connect to the sink-vertex (@var m_sink)
|
||||
* @param v the vertex which is checked
|
||||
* @return true if a path to the sink was found, false if not
|
||||
*/
|
||||
inline bool has_sink_connect(vertex_descriptor v){
|
||||
tDistanceVal current_distance = 0;
|
||||
vertex_descriptor current_vertex = v;
|
||||
while(true){
|
||||
if(m_time_map[current_vertex] == m_time){
|
||||
//we found a node which was already checked this round. use it for distance calculations
|
||||
current_distance += m_dist_map[current_vertex];
|
||||
break;
|
||||
}
|
||||
if(current_vertex == m_sink){
|
||||
m_time_map[m_sink] = m_time;
|
||||
break;
|
||||
}
|
||||
if(has_parent(current_vertex)){
|
||||
//it has a parent, so get it
|
||||
current_vertex = target(get_edge_to_parent(current_vertex), m_g);
|
||||
++current_distance;
|
||||
} else{
|
||||
//no path found
|
||||
return false;
|
||||
}
|
||||
}
|
||||
current_vertex=v;
|
||||
while(m_time_map[current_vertex] != m_time){
|
||||
m_dist_map[current_vertex] = current_distance--;
|
||||
m_time_map[current_vertex] = m_time;
|
||||
current_vertex = target(get_edge_to_parent(current_vertex), m_g);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if vertex v has a connect to the source-vertex (@var m_source)
|
||||
* @param v the vertex which is checked
|
||||
* @return true if a path to the source was found, false if not
|
||||
*/
|
||||
inline bool has_source_connect(vertex_descriptor v){
|
||||
tDistanceVal current_distance = 0;
|
||||
vertex_descriptor current_vertex = v;
|
||||
while(true){
|
||||
if(m_time_map[current_vertex] == m_time){
|
||||
//we found a node which was already checked this round. use it for distance calculations
|
||||
current_distance += m_dist_map[current_vertex];
|
||||
break;
|
||||
}
|
||||
if(current_vertex == m_source){
|
||||
m_time_map[m_source] = m_time;
|
||||
break;
|
||||
}
|
||||
if(has_parent(current_vertex)){
|
||||
//it has a parent, so get it
|
||||
current_vertex = source(get_edge_to_parent(current_vertex), m_g);
|
||||
++current_distance;
|
||||
} else{
|
||||
//no path found
|
||||
return false;
|
||||
}
|
||||
}
|
||||
current_vertex=v;
|
||||
while(m_time_map[current_vertex] != m_time){
|
||||
m_dist_map[current_vertex] = current_distance-- ;
|
||||
m_time_map[current_vertex] = m_time;
|
||||
current_vertex = source(get_edge_to_parent(current_vertex), m_g);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true, if p is closer to a terminal than q
|
||||
*/
|
||||
inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){
|
||||
//checks the timestamps first, to build no cycles, and after that the real distance
|
||||
return (m_time_map[q] <= m_time_map[p] && m_dist_map[q] > m_dist_map[p]+1);
|
||||
}
|
||||
|
||||
////////
|
||||
// member vars
|
||||
////////
|
||||
Graph& m_g;
|
||||
IndexMap m_index_map;
|
||||
EdgeCapacityMap m_cap_map;
|
||||
ResidualCapacityEdgeMap m_res_cap_map;
|
||||
ReverseEdgeMap m_rev_edge_map;
|
||||
PredecessorMap m_pre_map; //stores paths found in the growth stage
|
||||
ColorMap m_tree_map; //maps each vertex into one of the two search tree or none (gray())
|
||||
DistanceMap m_dist_map; //stores distance to source/sink nodes
|
||||
vertex_descriptor m_source;
|
||||
vertex_descriptor m_sink;
|
||||
|
||||
tQueue m_active_nodes;
|
||||
std::vector<bool> m_in_active_list_vec;
|
||||
iterator_property_map<std::vector<bool>::iterator, IndexMap> m_in_active_list_map;
|
||||
|
||||
std::list<vertex_descriptor> m_orphans;
|
||||
tQueue m_child_orphans; // we use a second queuqe for child orphans, as they are FIFO processed
|
||||
|
||||
std::vector<bool> m_has_parent_vec;
|
||||
iterator_property_map<std::vector<bool>::iterator, IndexMap> m_has_parent_map;
|
||||
|
||||
std::vector<long> m_time_vec; //timestamp of each node, used for sink/source-path calculations
|
||||
iterator_property_map<std::vector<long>::iterator, IndexMap> m_time_map;
|
||||
tEdgeVal m_flow;
|
||||
long m_time;
|
||||
vertex_descriptor m_last_grow_vertex;
|
||||
out_edge_iterator m_last_grow_edge_it;
|
||||
out_edge_iterator m_last_grow_edge_end;
|
||||
};
|
||||
} //namespace detail
|
||||
|
||||
/**
|
||||
* non-named-parameter version, given everything
|
||||
* this is the catch all version
|
||||
*/
|
||||
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap,
|
||||
class PredecessorMap, class ColorMap, class DistanceMap, class IndexMap>
|
||||
typename property_traits<CapacityEdgeMap>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
CapacityEdgeMap cap,
|
||||
ResidualCapacityEdgeMap res_cap,
|
||||
ReverseEdgeMap rev_map,
|
||||
PredecessorMap pre_map,
|
||||
ColorMap color,
|
||||
DistanceMap dist,
|
||||
IndexMap idx,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink
|
||||
)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
//as this method is the last one before we instantiate the solver, we do the concept checks here
|
||||
function_requires<VertexListGraphConcept<Graph> >(); //to have vertices(), num_vertices(),
|
||||
function_requires<EdgeListGraphConcept<Graph> >(); //to have edges()
|
||||
function_requires<IncidenceGraphConcept<Graph> >(); //to have source(), target() and out_edges()
|
||||
function_requires<LvaluePropertyMapConcept<CapacityEdgeMap, edge_descriptor> >(); //read flow-values from edges
|
||||
function_requires<Mutable_LvaluePropertyMapConcept<ResidualCapacityEdgeMap, edge_descriptor> >(); //write flow-values to residuals
|
||||
function_requires<LvaluePropertyMapConcept<ReverseEdgeMap, edge_descriptor> >(); //read out reverse edges
|
||||
function_requires<Mutable_LvaluePropertyMapConcept<PredecessorMap, vertex_descriptor> >(); //store predecessor there
|
||||
function_requires<Mutable_LvaluePropertyMapConcept<ColorMap, vertex_descriptor> >(); //write corresponding tree
|
||||
function_requires<Mutable_LvaluePropertyMapConcept<DistanceMap, vertex_descriptor> >(); //write distance to source/sink
|
||||
function_requires<ReadablePropertyMapConcept<IndexMap, vertex_descriptor> >(); //get index 0...|V|-1
|
||||
assert(num_vertices(g) >= 2 && src != sink);
|
||||
detail::kolmogorov<Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, ReverseEdgeMap, PredecessorMap, ColorMap, DistanceMap, IndexMap>
|
||||
algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink);
|
||||
return algo.max_flow();
|
||||
}
|
||||
|
||||
/**
|
||||
* non-named-parameter version, given: capacity, residucal_capacity, reverse_edges, and an index map.
|
||||
*/
|
||||
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap, class IndexMap>
|
||||
typename property_traits<CapacityEdgeMap>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
CapacityEdgeMap cap,
|
||||
ResidualCapacityEdgeMap res_cap,
|
||||
ReverseEdgeMap rev,
|
||||
IndexMap idx,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink)
|
||||
{
|
||||
typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
|
||||
std::vector<default_color_type> color_vec(n_verts);
|
||||
std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
|
||||
return kolmogorov_max_flow
|
||||
(g, cap, res_cap, rev,
|
||||
make_iterator_property_map(predecessor_vec.begin(), idx),
|
||||
make_iterator_property_map(color_vec.begin(), idx),
|
||||
make_iterator_property_map(distance_vec.begin(), idx),
|
||||
idx, src, sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* non-named-parameter version, some given: capacity, residual_capacity, reverse_edges, color_map and an index map.
|
||||
* Use this if you are interested in the minimum cut, as the color map provides that info
|
||||
*/
|
||||
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap, class ColorMap, class IndexMap>
|
||||
typename property_traits<CapacityEdgeMap>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
CapacityEdgeMap cap,
|
||||
ResidualCapacityEdgeMap res_cap,
|
||||
ReverseEdgeMap rev,
|
||||
ColorMap color,
|
||||
IndexMap idx,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink)
|
||||
{
|
||||
typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
|
||||
std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
|
||||
|
||||
return kolmogorov_max_flow
|
||||
(g, cap, res_cap, rev,
|
||||
make_iterator_property_map(predecessor_vec.begin(), idx),
|
||||
color,
|
||||
make_iterator_property_map(distance_vec.begin(), idx),
|
||||
idx, src, sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* named-parameter version, some given
|
||||
*/
|
||||
template <class Graph, class P, class T, class R>
|
||||
typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
const bgl_named_params<P, T, R>& params)
|
||||
{
|
||||
return kolmogorov_max_flow(g,
|
||||
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
|
||||
choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity),
|
||||
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
|
||||
choose_pmap(get_param(params, vertex_predecessor), g, vertex_predecessor),
|
||||
choose_pmap(get_param(params, vertex_color), g, vertex_color),
|
||||
choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
|
||||
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
|
||||
src, sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* named-parameter version, none given
|
||||
*/
|
||||
template <class Graph>
|
||||
typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
|
||||
kolmogorov_max_flow
|
||||
(Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink)
|
||||
{
|
||||
bgl_named_params<int, buffer_param_t> params(0); // bogus empty param
|
||||
return kolmogorov_max_flow(g, src, sink, params);
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_KOLMOGOROV_MAX_FLOW_HPP
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
//=======================================================================
|
||||
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor
|
||||
// Copyright 2007 University of Karlsruhe
|
||||
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor,
|
||||
// Jens Mueller
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -23,9 +25,6 @@
|
||||
// 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++)
|
||||
|
||||
@@ -41,95 +40,103 @@ namespace boost {
|
||||
|
||||
template <class vtype, class etype>
|
||||
struct graph_traits< leda::GRAPH<vtype,etype> > {
|
||||
typedef leda_node vertex_descriptor;
|
||||
typedef leda_edge edge_descriptor;
|
||||
typedef leda::node vertex_descriptor;
|
||||
typedef leda::edge edge_descriptor;
|
||||
|
||||
class adjacency_iterator
|
||||
: public iterator_facade<adjacency_iterator,
|
||||
leda_node,
|
||||
leda::node,
|
||||
bidirectional_traversal_tag,
|
||||
leda_node,
|
||||
const leda_node*>
|
||||
leda::node,
|
||||
const leda::node*>
|
||||
{
|
||||
public:
|
||||
explicit adjacency_iterator(leda_edge edge = 0) : base(edge) {}
|
||||
|
||||
adjacency_iterator(leda::node node = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(node), g(g) {}
|
||||
private:
|
||||
leda_node dereference() const { return leda::target(base); }
|
||||
leda::node dereference() const { return leda::target(base); }
|
||||
|
||||
bool equal(const adjacency_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = Succ_Adj_Edge(base, 0); }
|
||||
void decrement() { base = Pred_Adj_Edge(base, 0); }
|
||||
void increment() { base = g->adj_succ(base); }
|
||||
void decrement() { base = g->adj_pred(base); }
|
||||
|
||||
leda_edge base;
|
||||
leda::edge base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
|
||||
class out_edge_iterator
|
||||
: public iterator_facade<out_edge_iterator,
|
||||
leda_edge,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda_edge&,
|
||||
const leda_edge*>
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
explicit out_edge_iterator(leda_edge edge = 0) : base(edge) {}
|
||||
out_edge_iterator(leda::node node = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(node), g(g) {}
|
||||
|
||||
private:
|
||||
const leda_edge& dereference() const { return base; }
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const out_edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = Succ_Adj_Edge(base, 0); }
|
||||
void decrement() { base = Pred_Adj_Edge(base, 0); }
|
||||
void increment() { base = g->adj_succ(base); }
|
||||
void decrement() { base = g->adj_pred(base); }
|
||||
|
||||
leda_edge base;
|
||||
leda::edge base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
|
||||
class in_edge_iterator
|
||||
: public iterator_facade<in_edge_iterator,
|
||||
leda_edge,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda_edge&,
|
||||
const leda_edge*>
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
explicit in_edge_iterator(leda_edge edge = 0) : base(edge) {}
|
||||
in_edge_iterator(leda::node node = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(node), g(g) {}
|
||||
|
||||
private:
|
||||
const leda_edge& dereference() const { return base; }
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const in_edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = Succ_Adj_Edge(base, 1); }
|
||||
void decrement() { base = Pred_Adj_Edge(base, 1); }
|
||||
void increment() { base = g->in_succ(base); }
|
||||
void decrement() { base = g->in_pred(base); }
|
||||
|
||||
leda_edge base;
|
||||
leda::edge base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class vertex_iterator
|
||||
: public iterator_facade<vertex_iterator,
|
||||
leda_node,
|
||||
leda::node,
|
||||
bidirectional_traversal_tag,
|
||||
const leda_node&,
|
||||
const leda_node*>
|
||||
const leda::node&,
|
||||
const leda::node*>
|
||||
{
|
||||
public:
|
||||
vertex_iterator(leda_node node = 0,
|
||||
vertex_iterator(leda::node node = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(node), g(g) {}
|
||||
|
||||
private:
|
||||
const leda_node& dereference() const { return base; }
|
||||
const leda::node& dereference() const { return base; }
|
||||
|
||||
bool equal(const vertex_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
@@ -137,7 +144,34 @@ namespace boost {
|
||||
void increment() { base = g->succ_node(base); }
|
||||
void decrement() { base = g->pred_node(base); }
|
||||
|
||||
leda_node base;
|
||||
leda::node base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class edge_iterator
|
||||
: public iterator_facade<edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
edge_iterator(leda::edge edge = 0,
|
||||
const leda::GRAPH<vtype, etype>* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->succ_edge(base); }
|
||||
void decrement() { base = g->pred_edge(base); }
|
||||
|
||||
leda::node base;
|
||||
const leda::GRAPH<vtype, etype>* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
@@ -151,14 +185,154 @@ namespace boost {
|
||||
typedef int degree_size_type;
|
||||
};
|
||||
|
||||
template <class vtype, class etype>
|
||||
struct vertex_property< leda::GRAPH<vtype,etype> > {
|
||||
typedef vtype type;
|
||||
};
|
||||
|
||||
template <class vtype, class etype>
|
||||
struct edge_property< leda::GRAPH<vtype,etype> > {
|
||||
typedef etype type;
|
||||
|
||||
template<>
|
||||
struct graph_traits<leda::graph> {
|
||||
typedef leda::node vertex_descriptor;
|
||||
typedef leda::edge edge_descriptor;
|
||||
|
||||
class adjacency_iterator
|
||||
: public iterator_facade<adjacency_iterator,
|
||||
leda::node,
|
||||
bidirectional_traversal_tag,
|
||||
leda::node,
|
||||
const leda::node*>
|
||||
{
|
||||
public:
|
||||
adjacency_iterator(leda::edge edge = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
leda::node dereference() const { return leda::target(base); }
|
||||
|
||||
bool equal(const adjacency_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->adj_succ(base); }
|
||||
void decrement() { base = g->adj_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class out_edge_iterator
|
||||
: public iterator_facade<out_edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
out_edge_iterator(leda::edge edge = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const out_edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->adj_succ(base); }
|
||||
void decrement() { base = g->adj_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class in_edge_iterator
|
||||
: public iterator_facade<in_edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
in_edge_iterator(leda::edge edge = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const in_edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->in_succ(base); }
|
||||
void decrement() { base = g->in_pred(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class vertex_iterator
|
||||
: public iterator_facade<vertex_iterator,
|
||||
leda::node,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::node&,
|
||||
const leda::node*>
|
||||
{
|
||||
public:
|
||||
vertex_iterator(leda::node node = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(node), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::node& dereference() const { return base; }
|
||||
|
||||
bool equal(const vertex_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->succ_node(base); }
|
||||
void decrement() { base = g->pred_node(base); }
|
||||
|
||||
leda::node base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
class edge_iterator
|
||||
: public iterator_facade<edge_iterator,
|
||||
leda::edge,
|
||||
bidirectional_traversal_tag,
|
||||
const leda::edge&,
|
||||
const leda::edge*>
|
||||
{
|
||||
public:
|
||||
edge_iterator(leda::edge edge = 0,
|
||||
const leda::graph* g = 0)
|
||||
: base(edge), g(g) {}
|
||||
|
||||
private:
|
||||
const leda::edge& dereference() const { return base; }
|
||||
|
||||
bool equal(const edge_iterator& other) const
|
||||
{ return base == other.base; }
|
||||
|
||||
void increment() { base = g->succ_edge(base); }
|
||||
void decrement() { base = g->pred_edge(base); }
|
||||
|
||||
leda::edge base;
|
||||
const leda::graph* g;
|
||||
|
||||
friend class iterator_core_access;
|
||||
};
|
||||
|
||||
typedef directed_tag directed_category;
|
||||
typedef allow_parallel_edge_tag edge_parallel_category; // not sure here
|
||||
typedef leda_graph_traversal_category traversal_category;
|
||||
typedef int vertices_size_type;
|
||||
typedef int edges_size_type;
|
||||
typedef int degree_size_type;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
@@ -166,6 +340,9 @@ namespace boost {
|
||||
|
||||
namespace boost {
|
||||
|
||||
//===========================================================================
|
||||
// functions for GRAPH<vtype,etype>
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor
|
||||
source(typename graph_traits< leda::GRAPH<vtype,etype> >::edge_descriptor e,
|
||||
@@ -193,7 +370,16 @@ namespace boost {
|
||||
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< leda::GRAPH<vtype,etype> >::edge_iterator,
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::edge_iterator >
|
||||
edges(const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >::edge_iterator
|
||||
Iter;
|
||||
return std::make_pair( Iter(g.first_edge(),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
inline std::pair<
|
||||
@@ -205,7 +391,7 @@ namespace boost {
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
|
||||
::out_edge_iterator Iter;
|
||||
return std::make_pair( Iter(First_Adj_Edge(u,0)), Iter(0) );
|
||||
return std::make_pair( Iter(g.first_adj_edge(u,0),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
@@ -218,7 +404,7 @@ namespace boost {
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
|
||||
::in_edge_iterator Iter;
|
||||
return std::make_pair( Iter(First_Adj_Edge(u,1)), Iter(0) );
|
||||
return std::make_pair( Iter(g.first_adj_edge(u,1),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
@@ -231,7 +417,7 @@ namespace boost {
|
||||
{
|
||||
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
|
||||
::adjacency_iterator Iter;
|
||||
return std::make_pair( Iter(First_Adj_Edge(u,0)), Iter(0) );
|
||||
return std::make_pair( Iter(g.first_adj_edge(u,0),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
@@ -252,29 +438,29 @@ namespace boost {
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
|
||||
out_degree(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>&)
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return outdeg(u);
|
||||
return g.outdeg(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
|
||||
in_degree(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>&)
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return indeg(u);
|
||||
return g.indeg(u);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
|
||||
degree(
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
const leda::GRAPH<vtype,etype>&)
|
||||
const leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
return outdeg(u) + indeg(u);
|
||||
return g.outdeg(u) + g.indeg(u);
|
||||
}
|
||||
|
||||
|
||||
template <class vtype, class etype>
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor
|
||||
add_vertex(leda::GRAPH<vtype,etype>& g)
|
||||
@@ -289,14 +475,18 @@ namespace boost {
|
||||
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< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
|
||||
leda::GRAPH<vtype,etype>& g)
|
||||
{
|
||||
g.del_node(u);
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end)=out_edges(u,g); ei!=ei_end; ei++)
|
||||
remove_edge(*ei);
|
||||
|
||||
typename graph_traits< leda::GRAPH<vtype,etype> >::in_edge_iterator iei, iei_end;
|
||||
for (tie(iei, iei_end)=in_edges(u,g); iei!=iei_end; iei++)
|
||||
remove_edge(*iei);
|
||||
}
|
||||
|
||||
template <class vtype, class etype>
|
||||
@@ -356,8 +546,174 @@ namespace boost {
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// property maps
|
||||
|
||||
// functions for graph (non-templated version)
|
||||
|
||||
graph_traits<leda::graph>::vertex_descriptor
|
||||
source(graph_traits<leda::graph>::edge_descriptor e,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return source(e);
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::vertex_descriptor
|
||||
target(graph_traits<leda::graph>::edge_descriptor e,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return target(e);
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::vertex_iterator,
|
||||
graph_traits<leda::graph>::vertex_iterator >
|
||||
vertices(const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>::vertex_iterator
|
||||
Iter;
|
||||
return std::make_pair( Iter(g.first_node(),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::edge_iterator,
|
||||
graph_traits<leda::graph>::edge_iterator >
|
||||
edges(const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>::edge_iterator
|
||||
Iter;
|
||||
return std::make_pair( Iter(g.first_edge(),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::out_edge_iterator,
|
||||
graph_traits<leda::graph>::out_edge_iterator >
|
||||
out_edges(
|
||||
graph_traits<leda::graph>::vertex_descriptor u, const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>::out_edge_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_adj_edge(u),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::in_edge_iterator,
|
||||
graph_traits<leda::graph>::in_edge_iterator >
|
||||
in_edges(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>
|
||||
::in_edge_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_in_edge(u),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
inline std::pair<
|
||||
graph_traits<leda::graph>::adjacency_iterator,
|
||||
graph_traits<leda::graph>::adjacency_iterator >
|
||||
adjacent_vertices(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
typedef graph_traits<leda::graph>
|
||||
::adjacency_iterator Iter;
|
||||
return std::make_pair( Iter(g.first_adj_edge(u),&g), Iter(0,&g) );
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::vertices_size_type
|
||||
num_vertices(const leda::graph& g)
|
||||
{
|
||||
return g.number_of_nodes();
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::edges_size_type
|
||||
num_edges(const leda::graph& g)
|
||||
{
|
||||
return g.number_of_edges();
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::degree_size_type
|
||||
out_degree(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return g.outdeg(u);
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::degree_size_type
|
||||
in_degree(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return g.indeg(u);
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::degree_size_type
|
||||
degree(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
const leda::graph& g)
|
||||
{
|
||||
return g.outdeg(u) + g.indeg(u);
|
||||
}
|
||||
|
||||
graph_traits<leda::graph>::vertex_descriptor
|
||||
add_vertex(leda::graph& g)
|
||||
{
|
||||
return g.new_node();
|
||||
}
|
||||
|
||||
void
|
||||
remove_edge(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
graph_traits<leda::graph>::vertex_descriptor v,
|
||||
leda::graph& g)
|
||||
{
|
||||
graph_traits<leda::graph>::out_edge_iterator
|
||||
i,iend;
|
||||
for (boost::tie(i,iend) = out_edges(u,g); i != iend; ++i)
|
||||
if (target(*i,g) == v)
|
||||
g.del_edge(*i);
|
||||
}
|
||||
|
||||
void
|
||||
remove_edge(
|
||||
graph_traits<leda::graph>::edge_descriptor e,
|
||||
leda::graph& g)
|
||||
{
|
||||
g.del_edge(e);
|
||||
}
|
||||
|
||||
void clear_vertex(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
leda::graph& g)
|
||||
{
|
||||
graph_traits<leda::graph>::out_edge_iterator ei, ei_end;
|
||||
for (tie(ei, ei_end)=out_edges(u,g); ei!=ei_end; ei++)
|
||||
remove_edge(*ei, g);
|
||||
|
||||
graph_traits<leda::graph>::in_edge_iterator iei, iei_end;
|
||||
for (tie(iei, iei_end)=in_edges(u,g); iei!=iei_end; iei++)
|
||||
remove_edge(*iei, g);
|
||||
}
|
||||
|
||||
void remove_vertex(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
leda::graph& g)
|
||||
{
|
||||
g.del_node(u);
|
||||
}
|
||||
|
||||
std::pair<
|
||||
graph_traits<leda::graph>::edge_descriptor,
|
||||
bool>
|
||||
add_edge(
|
||||
graph_traits<leda::graph>::vertex_descriptor u,
|
||||
graph_traits<leda::graph>::vertex_descriptor v,
|
||||
leda::graph& g)
|
||||
{
|
||||
return std::make_pair(g.new_edge(u, v), true);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// property maps for GRAPH<vtype,etype>
|
||||
|
||||
class leda_graph_id_map
|
||||
: public put_get_helper<int, leda_graph_id_map>
|
||||
{
|
||||
@@ -365,7 +721,7 @@ namespace boost {
|
||||
typedef readable_property_map_tag category;
|
||||
typedef int value_type;
|
||||
typedef int reference;
|
||||
typedef leda_node key_type;
|
||||
typedef leda::node key_type;
|
||||
leda_graph_id_map() { }
|
||||
template <class T>
|
||||
long operator[](T x) const { return x->id(); }
|
||||
@@ -476,42 +832,42 @@ namespace boost {
|
||||
public:
|
||||
typedef E value_type;
|
||||
typedef ERef reference;
|
||||
typedef leda_node key_type;
|
||||
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]; }
|
||||
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)
|
||||
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>*>
|
||||
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)
|
||||
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;
|
||||
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)
|
||||
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>*>
|
||||
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)
|
||||
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;
|
||||
typedef leda_node_property_map<E, E&, leda::node_map<E>*> pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
|
||||
@@ -528,11 +884,11 @@ namespace boost {
|
||||
inline
|
||||
typename boost::property_traits<
|
||||
typename boost::property_map<leda::GRAPH<vtype, etype>,PropertyTag>::const_type
|
||||
>::value_type
|
||||
::value_type
|
||||
get(PropertyTag p, const leda::GRAPH<vtype, etype>& g, const Key& key) {
|
||||
return get(get(p, g), key);
|
||||
}
|
||||
|
||||
|
||||
template <class vtype, class etype, class PropertyTag, class Key,class Value>
|
||||
inline void
|
||||
put(PropertyTag p, leda::GRAPH<vtype, etype>& g,
|
||||
@@ -543,7 +899,54 @@ namespace boost {
|
||||
put(pmap, key, value);
|
||||
}
|
||||
|
||||
// property map interface to the LEDA edge_array class
|
||||
|
||||
template <class E, class ERef, class EdgeMapPtr>
|
||||
class leda_edge_property_map
|
||||
: public put_get_helper<ERef, leda_edge_property_map<E, ERef, EdgeMapPtr> >
|
||||
{
|
||||
public:
|
||||
typedef E value_type;
|
||||
typedef ERef reference;
|
||||
typedef leda::edge key_type;
|
||||
typedef lvalue_property_map_tag category;
|
||||
leda_edge_property_map(EdgeMapPtr a) : m_array(a) { }
|
||||
ERef operator[](leda::edge n) const { return (*m_array)[n]; }
|
||||
protected:
|
||||
EdgeMapPtr m_array;
|
||||
};
|
||||
template <class E>
|
||||
leda_edge_property_map<E, const E&, const leda::edge_array<E>*>
|
||||
make_leda_node_property_map(const leda::node_array<E>& a)
|
||||
{
|
||||
typedef leda_edge_property_map<E, const E&, const leda::node_array<E>*>
|
||||
pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
template <class E>
|
||||
leda_edge_property_map<E, E&, leda::edge_array<E>*>
|
||||
make_leda_edge_property_map(leda::edge_array<E>& a)
|
||||
{
|
||||
typedef leda_edge_property_map<E, E&, leda::edge_array<E>*> pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
leda_edge_property_map<E, const E&, const leda::edge_map<E>*>
|
||||
make_leda_edge_property_map(const leda::edge_map<E>& a)
|
||||
{
|
||||
typedef leda_edge_property_map<E,const E&,const leda::edge_map<E>*>
|
||||
pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
template <class E>
|
||||
leda_edge_property_map<E, E&, leda::edge_map<E>*>
|
||||
make_leda_edge_property_map(leda::edge_map<E>& a)
|
||||
{
|
||||
typedef leda_edge_property_map<E, E&, leda::edge_map<E>*> pmap_type;
|
||||
return pmap_type(&a);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GRAPH_LEDA_HPP
|
||||
|
||||
121
include/boost/graph/make_biconnected_planar.hpp
Normal file
121
include/boost/graph/make_biconnected_planar.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
#ifndef __MAKE_BICONNECTED_PLANAR_HPP__
|
||||
#define __MAKE_BICONNECTED_PLANAR_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/tuple/tuple.hpp> //for tie
|
||||
#include <boost/graph/biconnected_components.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename EdgeIndexMap,
|
||||
typename AddEdgeVisitor
|
||||
>
|
||||
void make_biconnected_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
EdgeIndexMap em,
|
||||
AddEdgeVisitor& vis
|
||||
)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::edges_size_type edge_size_t;
|
||||
typedef typename
|
||||
property_traits<PlanarEmbedding>::value_type embedding_value_t;
|
||||
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
|
||||
typedef iterator_property_map
|
||||
<std::vector<std::size_t>::iterator, EdgeIndexMap> component_map_t;
|
||||
|
||||
edge_size_t n_edges(num_edges(g));
|
||||
std::vector<vertex_t> articulation_points;
|
||||
std::vector<edge_size_t> component_vector(n_edges);
|
||||
component_map_t component_map(component_vector.begin(), em);
|
||||
|
||||
biconnected_components(g, component_map,
|
||||
std::back_inserter(articulation_points));
|
||||
|
||||
typename std::vector<vertex_t>::iterator ap, ap_end;
|
||||
ap_end = articulation_points.end();
|
||||
for(ap = articulation_points.begin(); ap != ap_end; ++ap)
|
||||
{
|
||||
vertex_t v(*ap);
|
||||
embedding_iterator_t pi = embedding[v].begin();
|
||||
embedding_iterator_t pi_end = embedding[v].end();
|
||||
edge_size_t previous_component(n_edges + 1);
|
||||
vertex_t previous_vertex = graph_traits<Graph>::null_vertex();
|
||||
|
||||
for(; pi != pi_end; ++pi)
|
||||
{
|
||||
edge_t e(*pi);
|
||||
vertex_t e_source(source(e,g));
|
||||
vertex_t e_target(target(e,g));
|
||||
|
||||
//Skip self-loops and parallel edges
|
||||
if (e_source == e_target || previous_vertex == e_target)
|
||||
continue;
|
||||
|
||||
vertex_t current_vertex = e_source == v ? e_target : e_source;
|
||||
edge_size_t current_component = component_map[e];
|
||||
if (previous_vertex != graph_traits<Graph>::null_vertex() &&
|
||||
current_component != previous_component)
|
||||
{
|
||||
vis.visit_vertex_pair(current_vertex, previous_vertex, g);
|
||||
}
|
||||
previous_vertex = current_vertex;
|
||||
previous_component = current_component;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename EdgeIndexMap
|
||||
>
|
||||
inline void make_biconnected_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
EdgeIndexMap em
|
||||
)
|
||||
{
|
||||
default_add_edge_visitor vis;
|
||||
make_biconnected_planar(g, embedding, em, vis);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding
|
||||
>
|
||||
inline void make_biconnected_planar(Graph& g, PlanarEmbedding embedding)
|
||||
{
|
||||
make_biconnected_planar(g, embedding, get(edge_index,g));
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif //__MAKE_BICONNECTED_PLANAR_HPP__
|
||||
99
include/boost/graph/make_connected.hpp
Normal file
99
include/boost/graph/make_connected.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
#ifndef __MAKE_CONNECTED_HPP__
|
||||
#define __MAKE_CONNECTED_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next
|
||||
#include <boost/tuple/tuple.hpp> //for tie
|
||||
#include <boost/graph/connected_components.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
|
||||
#include <boost/graph/planar_detail/bucket_sort.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename VertexIndexMap,
|
||||
typename AddEdgeVisitor
|
||||
>
|
||||
void make_connected(Graph& g, VertexIndexMap vm, AddEdgeVisitor& vis)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef iterator_property_map< typename std::vector<v_size_t>::iterator,
|
||||
VertexIndexMap
|
||||
> vertex_to_v_size_map_t;
|
||||
|
||||
std::vector<v_size_t> component_vector(num_vertices(g));
|
||||
vertex_to_v_size_map_t component(component_vector.begin(), vm);
|
||||
std::vector<vertex_t> vertices_by_component(num_vertices(g));
|
||||
|
||||
v_size_t num_components = connected_components(g, component);
|
||||
|
||||
if (num_components < 2)
|
||||
return;
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
tie(vi,vi_end) = vertices(g);
|
||||
std::copy(vi, vi_end, vertices_by_component.begin());
|
||||
|
||||
bucket_sort(vertices_by_component.begin(),
|
||||
vertices_by_component.end(),
|
||||
component,
|
||||
num_components
|
||||
);
|
||||
|
||||
typedef typename std::vector<vertex_t>::iterator vec_of_vertices_itr_t;
|
||||
|
||||
vec_of_vertices_itr_t ci_end = vertices_by_component.end();
|
||||
vec_of_vertices_itr_t ci_prev = vertices_by_component.begin();
|
||||
if (ci_prev == ci_end)
|
||||
return;
|
||||
|
||||
for(vec_of_vertices_itr_t ci = next(ci_prev);
|
||||
ci != ci_end; ci_prev = ci, ++ci
|
||||
)
|
||||
{
|
||||
if (component[*ci_prev] != component[*ci])
|
||||
vis.visit_vertex_pair(*ci_prev, *ci, g);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
inline void make_connected(Graph& g, VertexIndexMap vm)
|
||||
{
|
||||
default_add_edge_visitor vis;
|
||||
make_connected(g, vm, vis);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
inline void make_connected(Graph& g)
|
||||
{
|
||||
make_connected(g, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //__MAKE_CONNECTED_HPP__
|
||||
275
include/boost/graph/make_maximal_planar.hpp
Normal file
275
include/boost/graph/make_maximal_planar.hpp
Normal file
@@ -0,0 +1,275 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
#ifndef __MAKE_MAXIMAL_PLANAR_HPP__
|
||||
#define __MAKE_MAXIMAL_PLANAR_HPP__
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/tuple/tuple.hpp> //for tie
|
||||
#include <boost/graph/biconnected_components.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/graph/planar_face_traversal.hpp>
|
||||
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap, typename AddEdgeVisitor>
|
||||
struct triangulation_visitor : public planar_face_traversal_visitor
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
|
||||
typedef typename graph_traits<Graph>::degree_size_type degree_size_t;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::adjacency_iterator
|
||||
adjacency_iterator_t;
|
||||
typedef typename std::vector<vertex_t> vertex_vector_t;
|
||||
typedef typename std::vector<v_size_t> v_size_vector_t;
|
||||
typedef typename std::vector<degree_size_t> degree_size_vector_t;
|
||||
typedef iterator_property_map
|
||||
< typename v_size_vector_t::iterator, VertexIndexMap >
|
||||
vertex_to_v_size_map_t;
|
||||
typedef iterator_property_map
|
||||
< typename degree_size_vector_t::iterator, VertexIndexMap >
|
||||
vertex_to_degree_size_map_t;
|
||||
typedef typename vertex_vector_t::iterator face_iterator;
|
||||
|
||||
|
||||
triangulation_visitor(Graph& arg_g,
|
||||
VertexIndexMap arg_vm,
|
||||
AddEdgeVisitor arg_add_edge_visitor
|
||||
) :
|
||||
g(arg_g),
|
||||
vm(arg_vm),
|
||||
add_edge_visitor(arg_add_edge_visitor),
|
||||
timestamp(0),
|
||||
marked_vector(num_vertices(g), timestamp),
|
||||
degree_vector(num_vertices(g), 0),
|
||||
marked(marked_vector.begin(), vm),
|
||||
degree(degree_vector.begin(), vm)
|
||||
{
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(degree, *vi, out_degree(*vi, g));
|
||||
}
|
||||
|
||||
template <typename Vertex>
|
||||
void next_vertex(Vertex v)
|
||||
{
|
||||
// Self-loops will appear as consecutive vertices in the list of
|
||||
// vertices on a face. We want to skip these.
|
||||
if (!vertices_on_face.empty() &&
|
||||
(vertices_on_face.back() == v || vertices_on_face.front() == v)
|
||||
)
|
||||
return;
|
||||
|
||||
vertices_on_face.push_back(v);
|
||||
}
|
||||
|
||||
void end_face()
|
||||
{
|
||||
++timestamp;
|
||||
|
||||
if (vertices_on_face.size() <= 3)
|
||||
{
|
||||
// At most three vertices on this face - don't need to triangulate
|
||||
vertices_on_face.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find vertex on face of minimum degree
|
||||
degree_size_t min_degree = num_vertices(g);
|
||||
typename vertex_vector_t::iterator min_degree_vertex_itr;
|
||||
face_iterator fi_end = vertices_on_face.end();
|
||||
for(face_iterator fi = vertices_on_face.begin(); fi != fi_end; ++fi)
|
||||
{
|
||||
degree_size_t deg = get(degree,*fi);
|
||||
if (deg < min_degree)
|
||||
{
|
||||
min_degree_vertex_itr = fi;
|
||||
min_degree = deg;
|
||||
}
|
||||
}
|
||||
|
||||
// To simplify some of the manipulations, we'll re-arrange
|
||||
// vertices_on_face so that it still contains the same
|
||||
// (counter-clockwise) order of the vertices on this face, but now the
|
||||
// min_degree_vertex is the first element in vertices_on_face.
|
||||
vertex_vector_t temp_vector;
|
||||
std::copy(min_degree_vertex_itr, vertices_on_face.end(),
|
||||
std::back_inserter(temp_vector));
|
||||
std::copy(vertices_on_face.begin(), min_degree_vertex_itr,
|
||||
std::back_inserter(temp_vector));
|
||||
vertices_on_face.swap(temp_vector);
|
||||
|
||||
// Mark all of the min degree vertex's neighbors
|
||||
adjacency_iterator_t ai, ai_end;
|
||||
for(tie(ai,ai_end) = adjacent_vertices(vertices_on_face.front(),g);
|
||||
ai != ai_end; ++ai
|
||||
)
|
||||
{
|
||||
put(marked, *ai, timestamp);
|
||||
}
|
||||
|
||||
typename vertex_vector_t::iterator marked_neighbor
|
||||
= vertices_on_face.end();
|
||||
|
||||
// The iterator manipulations on the next two lines are safe because
|
||||
// vertices_on_face.size() > 3 (from the first test in this function)
|
||||
fi_end = prior(vertices_on_face.end());
|
||||
for(face_iterator fi = next(next(vertices_on_face.begin()));
|
||||
fi != fi_end; ++fi
|
||||
)
|
||||
{
|
||||
if (get(marked, *fi) == timestamp)
|
||||
{
|
||||
marked_neighbor = fi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (marked_neighbor == vertices_on_face.end())
|
||||
{
|
||||
add_edge_range(
|
||||
vertices_on_face[0],
|
||||
next(next(vertices_on_face.begin())),
|
||||
prior(vertices_on_face.end())
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_edge_range(
|
||||
vertices_on_face[1],
|
||||
next(marked_neighbor),
|
||||
vertices_on_face.end()
|
||||
);
|
||||
|
||||
add_edge_range(
|
||||
*next(marked_neighbor),
|
||||
next(next(vertices_on_face.begin())),
|
||||
marked_neighbor
|
||||
);
|
||||
}
|
||||
|
||||
//reset for the next face
|
||||
vertices_on_face.clear();
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void add_edge_range(vertex_t anchor,
|
||||
face_iterator fi,
|
||||
face_iterator fi_end
|
||||
)
|
||||
{
|
||||
for (; fi != fi_end; ++fi)
|
||||
{
|
||||
vertex_t v(*fi);
|
||||
add_edge_visitor.visit_vertex_pair(anchor, v, g);
|
||||
put(degree, anchor, get(degree, anchor) + 1);
|
||||
put(degree, v, get(degree, v) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Graph& g;
|
||||
VertexIndexMap vm;
|
||||
AddEdgeVisitor add_edge_visitor;
|
||||
v_size_t timestamp;
|
||||
vertex_vector_t vertices_on_face;
|
||||
v_size_vector_t marked_vector;
|
||||
degree_size_vector_t degree_vector;
|
||||
vertex_to_v_size_map_t marked;
|
||||
vertex_to_degree_size_map_t degree;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename VertexIndexMap,
|
||||
typename EdgeIndexMap,
|
||||
typename AddEdgeVisitor
|
||||
>
|
||||
void make_maximal_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
VertexIndexMap vm,
|
||||
EdgeIndexMap em,
|
||||
AddEdgeVisitor& vis)
|
||||
{
|
||||
triangulation_visitor<Graph,VertexIndexMap,AddEdgeVisitor>
|
||||
visitor(g, vm, vis);
|
||||
planar_face_traversal(g, embedding, visitor, em);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename VertexIndexMap,
|
||||
typename EdgeIndexMap
|
||||
>
|
||||
void make_maximal_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
VertexIndexMap vm,
|
||||
EdgeIndexMap em
|
||||
)
|
||||
{
|
||||
default_add_edge_visitor vis;
|
||||
make_maximal_planar(g, embedding, vm, em, vis);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename VertexIndexMap
|
||||
>
|
||||
void make_maximal_planar(Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
VertexIndexMap vm
|
||||
)
|
||||
{
|
||||
make_maximal_planar(g, embedding, vm, get(edge_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename PlanarEmbedding
|
||||
>
|
||||
void make_maximal_planar(Graph& g,
|
||||
PlanarEmbedding embedding
|
||||
)
|
||||
{
|
||||
make_maximal_planar(g, embedding, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif //__MAKE_MAXIMAL_PLANAR_HPP__
|
||||
@@ -45,10 +45,10 @@ namespace boost
|
||||
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_descriptor_t v = *vi;
|
||||
if (get(mate,v) != graph_traits<Graph>::null_vertex()
|
||||
vertex_descriptor_t v = *vi;
|
||||
if (get(mate,v) != graph_traits<Graph>::null_vertex()
|
||||
&& get(vm,v) < get(vm,get(mate,v)))
|
||||
++size_of_matching;
|
||||
++size_of_matching;
|
||||
}
|
||||
return size_of_matching;
|
||||
}
|
||||
@@ -76,10 +76,10 @@ namespace boost
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for( tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_descriptor_t v = *vi;
|
||||
if (get(mate,v) != graph_traits<Graph>::null_vertex()
|
||||
vertex_descriptor_t v = *vi;
|
||||
if (get(mate,v) != graph_traits<Graph>::null_vertex()
|
||||
&& v != get(mate,get(mate,v)))
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ namespace boost
|
||||
{
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
mate[*vi] = get(arg_mate, *vi);
|
||||
mate[*vi] = get(arg_mate, *vi);
|
||||
}
|
||||
|
||||
|
||||
@@ -206,25 +206,25 @@ namespace boost
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_descriptor_t u = *vi;
|
||||
{
|
||||
vertex_descriptor_t u = *vi;
|
||||
|
||||
origin[u] = u;
|
||||
pred[u] = u;
|
||||
ancestor_of_v[u] = 0;
|
||||
ancestor_of_w[u] = 0;
|
||||
ds.make_set(u);
|
||||
origin[u] = u;
|
||||
pred[u] = u;
|
||||
ancestor_of_v[u] = 0;
|
||||
ancestor_of_w[u] = 0;
|
||||
ds.make_set(u);
|
||||
|
||||
if (mate[u] == graph_traits<Graph>::null_vertex())
|
||||
if (mate[u] == graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
vertex_state[u] = graph::detail::V_EVEN;
|
||||
out_edge_iterator_t ei, ei_end;
|
||||
for(tie(ei,ei_end) = out_edges(u,g); ei != ei_end; ++ei)
|
||||
even_edges.push_back( *ei );
|
||||
even_edges.push_back( *ei );
|
||||
}
|
||||
else
|
||||
vertex_state[u] = graph::detail::V_UNREACHED;
|
||||
}
|
||||
else
|
||||
vertex_state[u] = graph::detail::V_UNREACHED;
|
||||
}
|
||||
|
||||
//end initializations
|
||||
|
||||
@@ -234,40 +234,41 @@ namespace boost
|
||||
bool found_alternating_path = false;
|
||||
|
||||
while(!even_edges.empty() && !found_alternating_path)
|
||||
{
|
||||
// since we push even edges onto the back of the list as
|
||||
// they're discovered, taking them off the back will search
|
||||
// for augmenting paths depth-first.
|
||||
edge_descriptor_t current_edge = even_edges.back();
|
||||
even_edges.pop_back();
|
||||
{
|
||||
// since we push even edges onto the back of the list as
|
||||
// they're discovered, taking them off the back will search
|
||||
// for augmenting paths depth-first.
|
||||
edge_descriptor_t current_edge = even_edges.back();
|
||||
even_edges.pop_back();
|
||||
|
||||
v = source(current_edge,g);
|
||||
w = target(current_edge,g);
|
||||
v = source(current_edge,g);
|
||||
w = target(current_edge,g);
|
||||
|
||||
vertex_descriptor_t v_prime = origin[ds.find_set(v)];
|
||||
vertex_descriptor_t w_prime = origin[ds.find_set(w)];
|
||||
vertex_descriptor_t v_prime = origin[ds.find_set(v)];
|
||||
vertex_descriptor_t w_prime = origin[ds.find_set(w)];
|
||||
|
||||
// because of the way we put all of the edges on the queue,
|
||||
// v_prime should be labeled V_EVEN; the following is a
|
||||
// little paranoid but it could happen...
|
||||
if (vertex_state[v_prime] != graph::detail::V_EVEN)
|
||||
// because of the way we put all of the edges on the queue,
|
||||
// v_prime should be labeled V_EVEN; the following is a
|
||||
// little paranoid but it could happen...
|
||||
if (vertex_state[v_prime] != graph::detail::V_EVEN)
|
||||
{
|
||||
std::swap(v_prime,w_prime);
|
||||
std::swap(v,w);
|
||||
}
|
||||
|
||||
if (vertex_state[w_prime] == graph::detail::V_UNREACHED)
|
||||
if (vertex_state[w_prime] == graph::detail::V_UNREACHED)
|
||||
{
|
||||
vertex_state[w_prime] = graph::detail::V_ODD;
|
||||
vertex_state[mate[w_prime]] = graph::detail::V_EVEN;
|
||||
out_edge_iterator_t ei, ei_end;
|
||||
for( tie(ei,ei_end) = out_edges(mate[w_prime], g); ei != ei_end; ++ei)
|
||||
even_edges.push_back(*ei);
|
||||
even_edges.push_back(*ei);
|
||||
pred[w_prime] = v;
|
||||
}
|
||||
//w_prime == v_prime can happen below if we get an edge that has been
|
||||
//shrunk into a blossom
|
||||
else if (vertex_state[w_prime] == graph::detail::V_EVEN && w_prime != v_prime)
|
||||
|
||||
//w_prime == v_prime can happen below if we get an edge that has been
|
||||
//shrunk into a blossom
|
||||
else if (vertex_state[w_prime] == graph::detail::V_EVEN && w_prime != v_prime)
|
||||
{
|
||||
vertex_descriptor_t w_up = w_prime;
|
||||
vertex_descriptor_t v_up = v_prime;
|
||||
@@ -291,42 +292,42 @@ namespace boost
|
||||
w_free_ancestor == graph_traits<Graph>::null_vertex()
|
||||
)
|
||||
)
|
||||
{
|
||||
ancestor_of_w[w_up] = timestamp;
|
||||
ancestor_of_v[v_up] = timestamp;
|
||||
{
|
||||
ancestor_of_w[w_up] = timestamp;
|
||||
ancestor_of_v[v_up] = timestamp;
|
||||
|
||||
if (w_free_ancestor == graph_traits<Graph>::null_vertex())
|
||||
w_up = parent(w_up);
|
||||
if (v_free_ancestor == graph_traits<Graph>::null_vertex())
|
||||
v_up = parent(v_up);
|
||||
if (w_free_ancestor == graph_traits<Graph>::null_vertex())
|
||||
w_up = parent(w_up);
|
||||
if (v_free_ancestor == graph_traits<Graph>::null_vertex())
|
||||
v_up = parent(v_up);
|
||||
|
||||
if (mate[v_up] == graph_traits<Graph>::null_vertex())
|
||||
v_free_ancestor = v_up;
|
||||
if (mate[w_up] == graph_traits<Graph>::null_vertex())
|
||||
w_free_ancestor = w_up;
|
||||
if (mate[v_up] == graph_traits<Graph>::null_vertex())
|
||||
v_free_ancestor = v_up;
|
||||
if (mate[w_up] == graph_traits<Graph>::null_vertex())
|
||||
w_free_ancestor = w_up;
|
||||
|
||||
if (ancestor_of_w[v_up] == timestamp)
|
||||
if (ancestor_of_w[v_up] == timestamp)
|
||||
nearest_common_ancestor = v_up;
|
||||
else if (ancestor_of_v[w_up] == timestamp)
|
||||
nearest_common_ancestor = w_up;
|
||||
else if (v_free_ancestor == w_free_ancestor &&
|
||||
v_free_ancestor != graph_traits<Graph>::null_vertex())
|
||||
nearest_common_ancestor = v_up;
|
||||
else if (ancestor_of_v[w_up] == timestamp)
|
||||
nearest_common_ancestor = w_up;
|
||||
else if (v_free_ancestor == w_free_ancestor &&
|
||||
v_free_ancestor != graph_traits<Graph>::null_vertex())
|
||||
nearest_common_ancestor = v_up;
|
||||
}
|
||||
}
|
||||
|
||||
if (nearest_common_ancestor == graph_traits<Graph>::null_vertex())
|
||||
found_alternating_path = true; //to break out of the loop
|
||||
found_alternating_path = true; //to break out of the loop
|
||||
else
|
||||
{
|
||||
//shrink the blossom
|
||||
link_and_set_bridges(w_prime, nearest_common_ancestor, std::make_pair(w,v));
|
||||
link_and_set_bridges(v_prime, nearest_common_ancestor, std::make_pair(v,w));
|
||||
}
|
||||
{
|
||||
//shrink the blossom
|
||||
link_and_set_bridges(w_prime, nearest_common_ancestor, std::make_pair(w,v));
|
||||
link_and_set_bridges(v_prime, nearest_common_ancestor, std::make_pair(v,w));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_alternating_path)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
// retrieve the augmenting path and put it in aug_path
|
||||
reversed_retrieve_augmenting_path(v, v_free_ancestor);
|
||||
@@ -335,14 +336,14 @@ namespace boost
|
||||
// augment the matching along aug_path
|
||||
vertex_descriptor_t a,b;
|
||||
while (!aug_path.empty())
|
||||
{
|
||||
a = aug_path.front();
|
||||
aug_path.pop_front();
|
||||
b = aug_path.front();
|
||||
aug_path.pop_front();
|
||||
mate[a] = b;
|
||||
mate[b] = a;
|
||||
}
|
||||
{
|
||||
a = aug_path.front();
|
||||
aug_path.pop_front();
|
||||
b = aug_path.front();
|
||||
aug_path.pop_front();
|
||||
mate[a] = b;
|
||||
mate[b] = a;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -356,7 +357,7 @@ namespace boost
|
||||
{
|
||||
vertex_iterator_t vi,vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(pm, *vi, mate[*vi]);
|
||||
put(pm, *vi, mate[*vi]);
|
||||
}
|
||||
|
||||
|
||||
@@ -367,7 +368,7 @@ namespace boost
|
||||
{
|
||||
vertex_iterator_t vi,vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]);
|
||||
put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]);
|
||||
}
|
||||
|
||||
|
||||
@@ -379,11 +380,11 @@ namespace boost
|
||||
{
|
||||
if (vertex_state[x] == graph::detail::V_EVEN
|
||||
&& mate[x] != graph_traits<Graph>::null_vertex())
|
||||
return mate[x];
|
||||
return mate[x];
|
||||
else if (vertex_state[x] == graph::detail::V_ODD)
|
||||
return origin[ds.find_set(pred[x])];
|
||||
return origin[ds.find_set(pred[x])];
|
||||
else
|
||||
return x;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@@ -394,18 +395,18 @@ namespace boost
|
||||
vertex_pair_t the_bridge)
|
||||
{
|
||||
for(vertex_descriptor_t v = x; v != stop_vertex; v = parent(v))
|
||||
{
|
||||
ds.union_set(v, stop_vertex);
|
||||
origin[ds.find_set(stop_vertex)] = stop_vertex;
|
||||
{
|
||||
ds.union_set(v, stop_vertex);
|
||||
origin[ds.find_set(stop_vertex)] = stop_vertex;
|
||||
|
||||
if (vertex_state[v] == graph::detail::V_ODD)
|
||||
if (vertex_state[v] == graph::detail::V_ODD)
|
||||
{
|
||||
bridge[v] = the_bridge;
|
||||
out_edge_iterator_t oei, oei_end;
|
||||
for(tie(oei, oei_end) = out_edges(v,g); oei != oei_end; ++oei)
|
||||
even_edges.push_back(*oei);
|
||||
even_edges.push_back(*oei);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -426,19 +427,19 @@ namespace boost
|
||||
void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w)
|
||||
{
|
||||
if (v == w)
|
||||
aug_path.push_back(v);
|
||||
aug_path.push_back(v);
|
||||
else if (vertex_state[v] == graph::detail::V_EVEN)
|
||||
{
|
||||
aug_path.push_back(v);
|
||||
aug_path.push_back(mate[v]);
|
||||
retrieve_augmenting_path(pred[mate[v]], w);
|
||||
}
|
||||
{
|
||||
aug_path.push_back(v);
|
||||
aug_path.push_back(mate[v]);
|
||||
retrieve_augmenting_path(pred[mate[v]], w);
|
||||
}
|
||||
else //vertex_state[v] == graph::detail::V_ODD
|
||||
{
|
||||
aug_path.push_back(v);
|
||||
reversed_retrieve_augmenting_path(bridge[v].first, mate[v]);
|
||||
retrieve_augmenting_path(bridge[v].second, w);
|
||||
}
|
||||
{
|
||||
aug_path.push_back(v);
|
||||
reversed_retrieve_augmenting_path(bridge[v].first, mate[v]);
|
||||
retrieve_augmenting_path(bridge[v].second, w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -447,19 +448,19 @@ namespace boost
|
||||
{
|
||||
|
||||
if (v == w)
|
||||
aug_path.push_back(v);
|
||||
aug_path.push_back(v);
|
||||
else if (vertex_state[v] == graph::detail::V_EVEN)
|
||||
{
|
||||
reversed_retrieve_augmenting_path(pred[mate[v]], w);
|
||||
aug_path.push_back(mate[v]);
|
||||
aug_path.push_back(v);
|
||||
}
|
||||
{
|
||||
reversed_retrieve_augmenting_path(pred[mate[v]], w);
|
||||
aug_path.push_back(mate[v]);
|
||||
aug_path.push_back(v);
|
||||
}
|
||||
else //vertex_state[v] == graph::detail::V_ODD
|
||||
{
|
||||
reversed_retrieve_augmenting_path(bridge[v].second, w);
|
||||
retrieve_augmenting_path(bridge[v].first, mate[v]);
|
||||
aug_path.push_back(v);
|
||||
}
|
||||
{
|
||||
reversed_retrieve_augmenting_path(bridge[v].second, w);
|
||||
retrieve_augmenting_path(bridge[v].first, mate[v]);
|
||||
aug_path.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -520,23 +521,23 @@ namespace boost
|
||||
{
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
|
||||
edge_iterator_t ei, ei_end;
|
||||
for( tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
{
|
||||
edge_descriptor_t e = *ei;
|
||||
vertex_descriptor_t u = source(e,g);
|
||||
vertex_descriptor_t v = target(e,g);
|
||||
{
|
||||
edge_descriptor_t e = *ei;
|
||||
vertex_descriptor_t u = source(e,g);
|
||||
vertex_descriptor_t v = target(e,g);
|
||||
|
||||
if (get(mate,u) == get(mate,v))
|
||||
if (get(mate,u) == get(mate,v))
|
||||
//only way equality can hold is if
|
||||
// mate[u] == mate[v] == null_vertex
|
||||
// mate[u] == mate[v] == null_vertex
|
||||
{
|
||||
put(mate,u,v);
|
||||
put(mate,v,u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -581,9 +582,9 @@ namespace boost
|
||||
less_than_by_degree(const Graph& g): m_g(g) {}
|
||||
bool operator() (const vertex_pair_t x, const vertex_pair_t y)
|
||||
{
|
||||
return
|
||||
out_degree(PairSelector::select_vertex(x), m_g)
|
||||
< out_degree(PairSelector::select_vertex(y), m_g);
|
||||
return
|
||||
out_degree(PairSelector::select_vertex(x), m_g)
|
||||
< out_degree(PairSelector::select_vertex(y), m_g);
|
||||
}
|
||||
private:
|
||||
const Graph& m_g;
|
||||
@@ -598,17 +599,17 @@ namespace boost
|
||||
directed_edges_vector_t edge_list;
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
|
||||
edge_iterator_t ei, ei_end;
|
||||
for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
|
||||
{
|
||||
edge_descriptor_t e = *ei;
|
||||
vertex_descriptor_t u = source(e,g);
|
||||
vertex_descriptor_t v = target(e,g);
|
||||
edge_list.push_back(std::make_pair(u,v));
|
||||
edge_list.push_back(std::make_pair(v,u));
|
||||
}
|
||||
{
|
||||
edge_descriptor_t e = *ei;
|
||||
vertex_descriptor_t u = source(e,g);
|
||||
vertex_descriptor_t v = target(e,g);
|
||||
edge_list.push_back(std::make_pair(u,v));
|
||||
edge_list.push_back(std::make_pair(v,u));
|
||||
}
|
||||
|
||||
//sort the edges by the degree of the target, then (using a
|
||||
//stable sort) by degree of the source
|
||||
@@ -619,14 +620,14 @@ namespace boost
|
||||
|
||||
//construct the extra greedy matching
|
||||
for(typename directed_edges_vector_t::const_iterator itr = edge_list.begin(); itr != edge_list.end(); ++itr)
|
||||
{
|
||||
if (get(mate,itr->first) == get(mate,itr->second))
|
||||
{
|
||||
if (get(mate,itr->first) == get(mate,itr->second))
|
||||
//only way equality can hold is if mate[itr->first] == mate[itr->second] == null_vertex
|
||||
{
|
||||
put(mate, itr->first, itr->second);
|
||||
put(mate, itr->second, itr->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -642,7 +643,7 @@ namespace boost
|
||||
{
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
put(mate, *vi, graph_traits<Graph>::null_vertex());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -666,29 +667,29 @@ namespace boost
|
||||
{
|
||||
public:
|
||||
odd_components_counter(SizeType& c_count):
|
||||
m_count(c_count)
|
||||
m_count(c_count)
|
||||
{
|
||||
m_count = 0;
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void start_vertex(Vertex v, Graph&)
|
||||
{
|
||||
addend = -1;
|
||||
{
|
||||
m_parity = false;
|
||||
}
|
||||
|
||||
template <class Vertex, class Graph>
|
||||
void discover_vertex(Vertex u, Graph&)
|
||||
{
|
||||
addend *= -1;
|
||||
m_count += addend;
|
||||
m_parity = !m_parity;
|
||||
m_parity ? ++m_count : --m_count;
|
||||
}
|
||||
|
||||
protected:
|
||||
SizeType& m_count;
|
||||
|
||||
private:
|
||||
SizeType addend;
|
||||
bool m_parity;
|
||||
|
||||
};
|
||||
|
||||
@@ -728,21 +729,27 @@ namespace boost
|
||||
typedef typename map_vertex_to_<vertex_descriptor_t>::type
|
||||
vertex_to_vertex_map_t;
|
||||
|
||||
|
||||
template <typename VertexStateMap>
|
||||
struct non_odd_vertex {
|
||||
//this predicate is used to create a filtered graph that
|
||||
//excludes vertices labeled "graph::detail::V_ODD"
|
||||
non_odd_vertex() : vertex_state(0) { }
|
||||
non_odd_vertex(VertexStateMap* arg_vertex_state)
|
||||
|
||||
non_odd_vertex(VertexStateMap* arg_vertex_state)
|
||||
: vertex_state(arg_vertex_state) { }
|
||||
template <typename Vertex>
|
||||
bool operator()(const Vertex& v) const {
|
||||
BOOST_ASSERT(vertex_state);
|
||||
return get(*vertex_state, v) != graph::detail::V_ODD;
|
||||
|
||||
template <typename Vertex>
|
||||
bool operator()(const Vertex& v) const
|
||||
{
|
||||
BOOST_ASSERT(vertex_state);
|
||||
return get(*vertex_state, v) != graph::detail::V_ODD;
|
||||
}
|
||||
|
||||
VertexStateMap* vertex_state;
|
||||
};
|
||||
|
||||
|
||||
static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
|
||||
{
|
||||
//For any graph G, let o(G) be the number of connected
|
||||
@@ -763,7 +770,7 @@ namespace boost
|
||||
|
||||
//first, make sure it's a valid matching
|
||||
if (!is_a_matching(g,mate,vm))
|
||||
return false;
|
||||
return false;
|
||||
|
||||
//We'll try to augment the matching once. This serves two
|
||||
//purposes: first, if we find some augmenting path, the matching
|
||||
@@ -775,7 +782,7 @@ namespace boost
|
||||
edmonds_augmenting_path_finder<Graph,MateMap,VertexIndexMap>
|
||||
augmentor(g,mate,vm);
|
||||
if (augmentor.augment_matching())
|
||||
return false;
|
||||
return false;
|
||||
|
||||
std::vector<int> vertex_state_vector(num_vertices(g));
|
||||
vertex_to_int_map_t vertex_state(vertex_state_vector.begin(), vm);
|
||||
@@ -785,8 +792,8 @@ namespace boost
|
||||
v_size_t num_odd_vertices = 0;
|
||||
vertex_iterator_t vi, vi_end;
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
if (vertex_state[*vi] == graph::detail::V_ODD)
|
||||
++num_odd_vertices;
|
||||
if (vertex_state[*vi] == graph::detail::V_ODD)
|
||||
++num_odd_vertices;
|
||||
|
||||
//count the number of connected components with odd cardinality
|
||||
//in the graph without graph::detail::V_ODD vertices
|
||||
@@ -798,9 +805,9 @@ namespace boost
|
||||
depth_first_search(fg, visitor(occ).vertex_index_map(vm));
|
||||
|
||||
if (2 * matching_size(g,mate,vm) == num_vertices(g) + num_odd_vertices - num_odd_components)
|
||||
return true;
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -822,7 +829,7 @@ namespace boost
|
||||
bool not_maximum_yet = true;
|
||||
while(not_maximum_yet)
|
||||
{
|
||||
not_maximum_yet = augmentor.augment_matching();
|
||||
not_maximum_yet = augmentor.augment_matching();
|
||||
}
|
||||
augmentor.get_current_matching(mate);
|
||||
|
||||
|
||||
@@ -284,6 +284,27 @@ namespace boost {
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant1_t, self>
|
||||
vertex_invariant1(const VertexInvar& c) const {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant1_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant2_t, self>
|
||||
vertex_invariant2(const VertexInvar& c) const {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant2_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexMaxInvar>
|
||||
bgl_named_params<VertexMaxInvar, vertex_max_invariant_t, self>
|
||||
vertex_max_invariant(const VertexMaxInvar& c) const {
|
||||
typedef bgl_named_params<VertexMaxInvar, vertex_max_invariant_t, self> Params;
|
||||
return Params(c, *this);
|
||||
}
|
||||
|
||||
template <typename VertexDisplacement>
|
||||
bgl_named_params<VertexDisplacement, vertex_displacement_t, self>
|
||||
displacement_map(const VertexDisplacement& c) const {
|
||||
@@ -547,6 +568,27 @@ namespace boost {
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant1_t>
|
||||
vertex_invariant1(const VertexInvar& c) {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant1_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexInvar>
|
||||
bgl_named_params<VertexInvar, vertex_invariant2_t>
|
||||
vertex_invariant2(const VertexInvar& c) {
|
||||
typedef bgl_named_params<VertexInvar, vertex_invariant2_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexMaxInvar>
|
||||
bgl_named_params<VertexMaxInvar, vertex_max_invariant_t>
|
||||
vertex_max_invariant(const VertexMaxInvar& c) {
|
||||
typedef bgl_named_params<VertexMaxInvar, vertex_max_invariant_t> Params;
|
||||
return Params(c);
|
||||
}
|
||||
|
||||
template <typename VertexDisplacement>
|
||||
bgl_named_params<VertexDisplacement, vertex_displacement_t>
|
||||
displacement_map(const VertexDisplacement& c) {
|
||||
|
||||
211
include/boost/graph/planar_canonical_ordering.hpp
Normal file
211
include/boost/graph/planar_canonical_ordering.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef __PLANAR_CANONICAL_ORDERING_HPP__
|
||||
#define __PLANAR_CANONICAL_ORDERING_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp> //for next and prior
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename OutputIterator,
|
||||
typename VertexIndexMap>
|
||||
void planar_canonical_ordering(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
OutputIterator ordering,
|
||||
VertexIndexMap vm)
|
||||
{
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::adjacency_iterator
|
||||
adjacency_iterator_t;
|
||||
typedef typename std::pair<vertex_t, vertex_t> vertex_pair_t;
|
||||
typedef typename property_traits<PlanarEmbedding>::value_type
|
||||
embedding_value_t;
|
||||
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
|
||||
typedef iterator_property_map
|
||||
<typename std::vector<vertex_t>::iterator, VertexIndexMap>
|
||||
vertex_to_vertex_map_t;
|
||||
typedef iterator_property_map
|
||||
<typename std::vector<std::size_t>::iterator, VertexIndexMap>
|
||||
vertex_to_size_t_map_t;
|
||||
|
||||
enum {PROCESSED,
|
||||
UNPROCESSED,
|
||||
ONE_NEIGHBOR_PROCESSED,
|
||||
READY_TO_BE_PROCESSED};
|
||||
|
||||
std::vector<vertex_t> processed_neighbor_vector(num_vertices(g));
|
||||
vertex_to_vertex_map_t processed_neighbor
|
||||
(processed_neighbor_vector.begin(), vm);
|
||||
|
||||
std::vector<std::size_t> status_vector(num_vertices(g), UNPROCESSED);
|
||||
vertex_to_size_t_map_t status(status_vector.begin(), vm);
|
||||
|
||||
std::list<vertex_t> ready_to_be_processed;
|
||||
|
||||
vertex_t first_vertex = *vertices(g).first;
|
||||
vertex_t second_vertex;
|
||||
adjacency_iterator_t ai, ai_end;
|
||||
for(tie(ai,ai_end) = adjacent_vertices(first_vertex,g); ai != ai_end; ++ai)
|
||||
{
|
||||
if (*ai == first_vertex)
|
||||
continue;
|
||||
second_vertex = *ai;
|
||||
break;
|
||||
}
|
||||
|
||||
ready_to_be_processed.push_back(first_vertex);
|
||||
status[first_vertex] = READY_TO_BE_PROCESSED;
|
||||
ready_to_be_processed.push_back(second_vertex);
|
||||
status[second_vertex] = READY_TO_BE_PROCESSED;
|
||||
|
||||
while(!ready_to_be_processed.empty())
|
||||
{
|
||||
vertex_t u = ready_to_be_processed.front();
|
||||
ready_to_be_processed.pop_front();
|
||||
|
||||
if (status[u] != READY_TO_BE_PROCESSED && u != second_vertex)
|
||||
continue;
|
||||
|
||||
embedding_iterator_t ei, ei_start, ei_end;
|
||||
embedding_iterator_t next_edge_itr, prior_edge_itr;
|
||||
|
||||
ei_start = embedding[u].begin();
|
||||
ei_end = embedding[u].end();
|
||||
prior_edge_itr = prior(ei_end);
|
||||
while(source(*prior_edge_itr, g) == target(*prior_edge_itr,g))
|
||||
prior_edge_itr = prior(prior_edge_itr);
|
||||
|
||||
for(ei = ei_start; ei != ei_end; ++ei)
|
||||
{
|
||||
|
||||
edge_t e(*ei); // e = (u,v)
|
||||
next_edge_itr = next(ei) == ei_end ? ei_start : next(ei);
|
||||
vertex_t v = source(e,g) == u ? target(e,g) : source(e,g);
|
||||
|
||||
vertex_t prior_vertex = source(*prior_edge_itr, g) == u ?
|
||||
target(*prior_edge_itr, g) : source(*prior_edge_itr, g);
|
||||
vertex_t next_vertex = source(*next_edge_itr, g) == u ?
|
||||
target(*next_edge_itr, g) : source(*next_edge_itr, g);
|
||||
|
||||
// Need prior_vertex, u, v, and next_vertex to all be
|
||||
// distinct. This is possible, since the input graph is
|
||||
// triangulated. It'll be true all the time in a simple
|
||||
// graph, but loops and parallel edges cause some complications.
|
||||
if (prior_vertex == v || prior_vertex == u)
|
||||
{
|
||||
prior_edge_itr = ei;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Skip any self-loops
|
||||
if (u == v)
|
||||
continue;
|
||||
|
||||
// Move next_edge_itr (and next_vertex) forwards
|
||||
// past any loops or parallel edges
|
||||
while (next_vertex == v || next_vertex == u)
|
||||
{
|
||||
next_edge_itr = next(next_edge_itr) == ei_end ?
|
||||
ei_start : next(next_edge_itr);
|
||||
next_vertex = source(*next_edge_itr, g) == u ?
|
||||
target(*next_edge_itr, g) : source(*next_edge_itr, g);
|
||||
}
|
||||
|
||||
|
||||
if (status[v] == UNPROCESSED)
|
||||
{
|
||||
status[v] = ONE_NEIGHBOR_PROCESSED;
|
||||
processed_neighbor[v] = u;
|
||||
}
|
||||
else if (status[v] == ONE_NEIGHBOR_PROCESSED)
|
||||
{
|
||||
vertex_t x = processed_neighbor[v];
|
||||
//are edges (v,u) and (v,x) adjacent in the planar
|
||||
//embedding? if so, set status[v] = 1. otherwise, set
|
||||
//status[v] = 2.
|
||||
|
||||
if ((next_vertex == x &&
|
||||
!(first_vertex == u && second_vertex == x)
|
||||
)
|
||||
||
|
||||
(prior_vertex == x &&
|
||||
!(first_vertex == x && second_vertex == u)
|
||||
)
|
||||
)
|
||||
{
|
||||
status[v] = READY_TO_BE_PROCESSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
status[v] = READY_TO_BE_PROCESSED + 1;
|
||||
}
|
||||
}
|
||||
else if (status[v] > ONE_NEIGHBOR_PROCESSED)
|
||||
{
|
||||
//check the two edges before and after (v,u) in the planar
|
||||
//embedding, and update status[v] accordingly
|
||||
|
||||
bool processed_before = false;
|
||||
if (status[prior_vertex] == PROCESSED)
|
||||
processed_before = true;
|
||||
|
||||
bool processed_after = false;
|
||||
if (status[next_vertex] == PROCESSED)
|
||||
processed_after = true;
|
||||
|
||||
if (!processed_before && !processed_after)
|
||||
++status[v];
|
||||
|
||||
else if (processed_before && processed_after)
|
||||
--status[v];
|
||||
|
||||
}
|
||||
|
||||
if (status[v] == READY_TO_BE_PROCESSED)
|
||||
ready_to_be_processed.push_back(v);
|
||||
|
||||
prior_edge_itr = ei;
|
||||
|
||||
}
|
||||
|
||||
status[u] = PROCESSED;
|
||||
*ordering = u;
|
||||
++ordering;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename Graph, typename PlanarEmbedding, typename OutputIterator>
|
||||
void planar_canonical_ordering(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
OutputIterator ordering
|
||||
)
|
||||
{
|
||||
planar_canonical_ordering(g, embedding, ordering, get(vertex_index,g));
|
||||
}
|
||||
|
||||
|
||||
} //namespace boost
|
||||
|
||||
#endif //__PLANAR_CANONICAL_ORDERING_HPP__
|
||||
59
include/boost/graph/planar_detail/add_edge_visitors.hpp
Normal file
59
include/boost/graph/planar_detail/add_edge_visitors.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
#ifndef __ADD_EDGE_VISITORS_HPP__
|
||||
#define __ADD_EDGE_VISITORS_HPP__
|
||||
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
struct default_add_edge_visitor
|
||||
{
|
||||
|
||||
template <typename Graph, typename Vertex>
|
||||
void visit_vertex_pair(Vertex u, Vertex v, Graph& g)
|
||||
{
|
||||
add_edge(u,v,g);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename EdgeIndexMap>
|
||||
struct edge_index_update_visitor
|
||||
{
|
||||
|
||||
typedef typename
|
||||
property_traits<EdgeIndexMap>::value_type edge_index_value_t;
|
||||
|
||||
edge_index_update_visitor(EdgeIndexMap em,
|
||||
edge_index_value_t next_index_available
|
||||
) :
|
||||
m_em(em),
|
||||
m_next_index(next_index_available)
|
||||
{}
|
||||
|
||||
template <typename Graph, typename Vertex>
|
||||
void visit_vertex_pair(Vertex u, Vertex v, Graph& g)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
std::pair<edge_t, bool> return_value = add_edge(u,v,g);
|
||||
if (return_value.second)
|
||||
put( m_em, return_value.first, m_next_index++);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
EdgeIndexMap m_em;
|
||||
edge_index_value_t m_next_index;
|
||||
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //__ADD_EDGE_VISITORS_HPP__
|
||||
2010
include/boost/graph/planar_detail/boyer_myrvold_impl.hpp
Normal file
2010
include/boost/graph/planar_detail/boyer_myrvold_impl.hpp
Normal file
File diff suppressed because it is too large
Load Diff
144
include/boost/graph/planar_detail/bucket_sort.hpp
Normal file
144
include/boost/graph/planar_detail/bucket_sort.hpp
Normal file
@@ -0,0 +1,144 @@
|
||||
//=======================================================================
|
||||
// Copyright 2007 Aaron Windsor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
#ifndef __BUCKET_SORT_HPP__
|
||||
#define __BUCKET_SORT_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <boost/property_map.hpp>
|
||||
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
template <typename ItemToRankMap>
|
||||
struct rank_comparison
|
||||
{
|
||||
rank_comparison(ItemToRankMap arg_itrm) : itrm(arg_itrm) {}
|
||||
|
||||
template <typename Item>
|
||||
bool operator() (Item x, Item y) const
|
||||
{
|
||||
return get(itrm, x) < get(itrm, y);
|
||||
}
|
||||
|
||||
private:
|
||||
ItemToRankMap itrm;
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename TupleType,
|
||||
int N,
|
||||
typename PropertyMapWrapper = identity_property_map>
|
||||
struct property_map_tuple_adaptor :
|
||||
public put_get_helper< typename PropertyMapWrapper::value_type,
|
||||
property_map_tuple_adaptor
|
||||
<TupleType, N, PropertyMapWrapper>
|
||||
>
|
||||
{
|
||||
typedef typename PropertyMapWrapper::reference reference;
|
||||
typedef typename PropertyMapWrapper::value_type value_type;
|
||||
typedef TupleType key_type;
|
||||
typedef readable_property_map_tag category;
|
||||
|
||||
property_map_tuple_adaptor() {}
|
||||
|
||||
property_map_tuple_adaptor(PropertyMapWrapper wrapper_map) :
|
||||
m_wrapper_map(wrapper_map)
|
||||
{}
|
||||
|
||||
inline value_type operator[](const key_type& x) const
|
||||
{
|
||||
return get(m_wrapper_map, get<n>(x));
|
||||
}
|
||||
|
||||
static const int n = N;
|
||||
PropertyMapWrapper m_wrapper_map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// This function sorts a sequence of n items by their ranks in linear time,
|
||||
// given that all ranks are in the range [0, range). This sort is stable.
|
||||
template <typename ForwardIterator,
|
||||
typename ItemToRankMap,
|
||||
typename SizeType>
|
||||
void bucket_sort(ForwardIterator begin,
|
||||
ForwardIterator end,
|
||||
ItemToRankMap rank,
|
||||
SizeType range = 0)
|
||||
{
|
||||
#ifdef BOOST_GRAPH_PREFER_STD_LIB
|
||||
std::stable_sort(begin, end, rank_comparison<ItemToRankMap>(rank));
|
||||
#else
|
||||
typedef std::vector
|
||||
< typename boost::property_traits<ItemToRankMap>::key_type >
|
||||
vector_of_values_t;
|
||||
typedef std::vector< vector_of_values_t > vector_of_vectors_t;
|
||||
|
||||
if (!range)
|
||||
{
|
||||
rank_comparison<ItemToRankMap> cmp(rank);
|
||||
ForwardIterator max_by_rank = std::max_element(begin, end, cmp);
|
||||
if (max_by_rank == end)
|
||||
return;
|
||||
range = get(rank, *max_by_rank) + 1;
|
||||
}
|
||||
|
||||
vector_of_vectors_t temp_values(range);
|
||||
|
||||
for(ForwardIterator itr = begin; itr != end; ++itr)
|
||||
{
|
||||
temp_values[get(rank, *itr)].push_back(*itr);
|
||||
}
|
||||
|
||||
ForwardIterator orig_seq_itr = begin;
|
||||
typename vector_of_vectors_t::iterator itr_end = temp_values.end();
|
||||
for(typename vector_of_vectors_t::iterator itr = temp_values.begin();
|
||||
itr != itr_end; ++itr
|
||||
)
|
||||
{
|
||||
typename vector_of_values_t::iterator jtr_end = itr->end();
|
||||
for(typename vector_of_values_t::iterator jtr = itr->begin();
|
||||
jtr != jtr_end; ++jtr
|
||||
)
|
||||
{
|
||||
*orig_seq_itr = *jtr;
|
||||
++orig_seq_itr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <typename ForwardIterator, typename ItemToRankMap>
|
||||
void bucket_sort(ForwardIterator begin,
|
||||
ForwardIterator end,
|
||||
ItemToRankMap rank)
|
||||
{
|
||||
bucket_sort(begin, end, rank, 0);
|
||||
}
|
||||
|
||||
template <typename ForwardIterator>
|
||||
void bucket_sort(ForwardIterator begin,
|
||||
ForwardIterator end
|
||||
)
|
||||
{
|
||||
bucket_sort(begin, end, identity_property_map());
|
||||
}
|
||||
|
||||
|
||||
} //namespace boost
|
||||
|
||||
|
||||
#endif //__BUCKET_SORT_HPP__
|
||||
497
include/boost/graph/planar_detail/face_handles.hpp
Normal file
497
include/boost/graph/planar_detail/face_handles.hpp
Normal file
@@ -0,0 +1,497 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef __FACE_HANDLES_HPP__
|
||||
#define __FACE_HANDLES_HPP__
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
||||
// A "face handle" is an optimization meant to serve two purposes in
|
||||
// the implementation of the Boyer-Myrvold planarity test: (1) it holds
|
||||
// the partial planar embedding of a particular vertex as it's being
|
||||
// constructed, and (2) it allows for efficient traversal around the
|
||||
// outer face of the partial embedding at that particular vertex. A face
|
||||
// handle is lightweight, just a shared pointer to the actual implementation,
|
||||
// since it is passed around/copied liberally in the algorithm. It consists
|
||||
// of an "anchor" (the actual vertex it's associated with) as well as a
|
||||
// sequence of edges. The functions first_vertex/second_vertex and
|
||||
// first_edge/second_edge allow fast access to the beginning and end of the
|
||||
// stored sequence, which allows one to traverse the outer face of the partial
|
||||
// planar embedding as it's being created.
|
||||
//
|
||||
// There are some policies below that define the contents of the face handles:
|
||||
// in the case no embedding is needed (for example, if one just wants to use
|
||||
// the Boyer-Myrvold algorithm as a true/false test for planarity, the
|
||||
// no_embedding class can be passed as the StoreEmbedding policy. Otherwise,
|
||||
// either std_list (which uses as std::list) or recursive_lazy_list can be
|
||||
// passed as this policy. recursive_lazy_list has the best theoretical
|
||||
// performance (O(n) for a sequence of interleaved concatenations and reversals
|
||||
// of the underlying list), but I've noticed little difference between std_list
|
||||
// and recursive_lazy_list in my tests, even though using std_list changes
|
||||
// the worst-case complexity of the planarity test to O(n^2)
|
||||
//
|
||||
// Another policy is StoreOldHandlesPolicy, which specifies whether or not
|
||||
// to keep a record of the previous first/second vertex/edge - this is needed
|
||||
// if a Kuratowski subgraph needs to be isolated.
|
||||
|
||||
|
||||
namespace boost { namespace graph { namespace detail {
|
||||
|
||||
|
||||
//face handle policies
|
||||
|
||||
//EmbeddingStorage policy
|
||||
struct store_embedding {};
|
||||
struct recursive_lazy_list : public store_embedding {};
|
||||
struct std_list : public store_embedding {};
|
||||
struct no_embedding {};
|
||||
|
||||
//StoreOldHandlesPolicy
|
||||
struct store_old_handles {};
|
||||
struct no_old_handles {};
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename DataType>
|
||||
struct lazy_list_node
|
||||
{
|
||||
typedef shared_ptr< lazy_list_node<DataType> > ptr_t;
|
||||
|
||||
lazy_list_node(const DataType& data) :
|
||||
m_reversed(false),
|
||||
m_data(data),
|
||||
m_has_data(true)
|
||||
{}
|
||||
|
||||
lazy_list_node(ptr_t left_child, ptr_t right_child) :
|
||||
m_reversed(false),
|
||||
m_has_data(false),
|
||||
m_left_child(left_child),
|
||||
m_right_child(right_child)
|
||||
{}
|
||||
|
||||
bool m_reversed;
|
||||
DataType m_data;
|
||||
bool m_has_data;
|
||||
shared_ptr<lazy_list_node> m_left_child;
|
||||
shared_ptr<lazy_list_node> m_right_child;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename StoreOldHandlesPolicy, typename Vertex, typename Edge>
|
||||
struct old_handles_storage;
|
||||
|
||||
template <typename Vertex, typename Edge>
|
||||
struct old_handles_storage<store_old_handles, Vertex, Edge>
|
||||
{
|
||||
Vertex first_vertex;
|
||||
Vertex second_vertex;
|
||||
Edge first_edge;
|
||||
Edge second_edge;
|
||||
};
|
||||
|
||||
template <typename Vertex, typename Edge>
|
||||
struct old_handles_storage<no_old_handles, Vertex, Edge>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename StoreEmbeddingPolicy, typename Edge>
|
||||
struct edge_list_storage;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Edge>
|
||||
struct edge_list_storage<no_embedding, Edge>
|
||||
{
|
||||
typedef void type;
|
||||
|
||||
void push_back(Edge) {}
|
||||
void push_front(Edge) {}
|
||||
void reverse() {}
|
||||
void concat_front(edge_list_storage<no_embedding,Edge>) {}
|
||||
void concat_back(edge_list_storage<no_embedding,Edge>) {}
|
||||
template <typename OutputIterator>
|
||||
void get_list(OutputIterator) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Edge>
|
||||
struct edge_list_storage<recursive_lazy_list, Edge>
|
||||
{
|
||||
typedef lazy_list_node<Edge> node_type;
|
||||
typedef shared_ptr< node_type > type;
|
||||
type value;
|
||||
|
||||
void push_back(Edge e)
|
||||
{
|
||||
type new_node(new node_type(e));
|
||||
value = type(new node_type(value, new_node));
|
||||
}
|
||||
|
||||
void push_front(Edge e)
|
||||
{
|
||||
type new_node(new node_type(e));
|
||||
value = type(new node_type(new_node, value));
|
||||
}
|
||||
|
||||
void reverse()
|
||||
{
|
||||
value->m_reversed = !value->m_reversed;
|
||||
}
|
||||
|
||||
void concat_front(edge_list_storage<recursive_lazy_list, Edge> other)
|
||||
{
|
||||
value = type(new node_type(other.value, value));
|
||||
}
|
||||
|
||||
void concat_back(edge_list_storage<recursive_lazy_list, Edge> other)
|
||||
{
|
||||
value = type(new node_type(value, other.value));
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
void get_list(OutputIterator out)
|
||||
{
|
||||
get_list_helper(out, value);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename OutputIterator>
|
||||
void get_list_helper(OutputIterator o_itr,
|
||||
type root,
|
||||
bool flipped = false
|
||||
)
|
||||
{
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
if (root->m_has_data)
|
||||
*o_itr = root->m_data;
|
||||
|
||||
if ((flipped && !root->m_reversed) ||
|
||||
(!flipped && root->m_reversed)
|
||||
)
|
||||
{
|
||||
get_list_helper(o_itr, root->m_right_child, true);
|
||||
get_list_helper(o_itr, root->m_left_child, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_list_helper(o_itr, root->m_left_child, false);
|
||||
get_list_helper(o_itr, root->m_right_child, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Edge>
|
||||
struct edge_list_storage<std_list, Edge>
|
||||
{
|
||||
typedef std::list<Edge> type;
|
||||
type value;
|
||||
|
||||
void push_back(Edge e)
|
||||
{
|
||||
value.push_back(e);
|
||||
}
|
||||
|
||||
void push_front(Edge e)
|
||||
{
|
||||
value.push_front(e);
|
||||
}
|
||||
|
||||
void reverse()
|
||||
{
|
||||
value.reverse();
|
||||
}
|
||||
|
||||
void concat_front(edge_list_storage<std_list,Edge> other)
|
||||
{
|
||||
value.splice(value.begin(), other.value);
|
||||
}
|
||||
|
||||
void concat_back(edge_list_storage<std_list, Edge> other)
|
||||
{
|
||||
value.splice(value.end(), other.value);
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
void get_list(OutputIterator out)
|
||||
{
|
||||
std::copy(value.begin(), value.end(), out);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename StoreOldHandlesPolicy,
|
||||
typename StoreEmbeddingPolicy
|
||||
>
|
||||
struct face_handle_impl
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename edge_list_storage<StoreEmbeddingPolicy, edge_t>::type
|
||||
edge_list_storage_t;
|
||||
|
||||
|
||||
face_handle_impl() :
|
||||
cached_first_vertex(graph_traits<Graph>::null_vertex()),
|
||||
cached_second_vertex(graph_traits<Graph>::null_vertex()),
|
||||
true_first_vertex(graph_traits<Graph>::null_vertex()),
|
||||
true_second_vertex(graph_traits<Graph>::null_vertex()),
|
||||
anchor(graph_traits<Graph>::null_vertex())
|
||||
{
|
||||
initialize_old_vertices_dispatch(StoreOldHandlesPolicy());
|
||||
}
|
||||
|
||||
void initialize_old_vertices_dispatch(store_old_handles)
|
||||
{
|
||||
old_handles.first_vertex = graph_traits<Graph>::null_vertex();
|
||||
old_handles.second_vertex = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
|
||||
void initialize_old_vertices_dispatch(no_old_handles) {}
|
||||
|
||||
vertex_t cached_first_vertex;
|
||||
vertex_t cached_second_vertex;
|
||||
vertex_t true_first_vertex;
|
||||
vertex_t true_second_vertex;
|
||||
vertex_t anchor;
|
||||
edge_t cached_first_edge;
|
||||
edge_t cached_second_edge;
|
||||
|
||||
edge_list_storage<StoreEmbeddingPolicy, edge_t> edge_list;
|
||||
old_handles_storage<StoreOldHandlesPolicy, vertex_t, edge_t> old_handles;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename StoreOldHandlesPolicy = store_old_handles,
|
||||
typename StoreEmbeddingPolicy = recursive_lazy_list
|
||||
>
|
||||
class face_handle
|
||||
{
|
||||
public:
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef face_handle_impl
|
||||
<Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> impl_t;
|
||||
typedef face_handle
|
||||
<Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> self_t;
|
||||
|
||||
face_handle(vertex_t anchor = graph_traits<Graph>::null_vertex()) :
|
||||
pimpl(new impl_t())
|
||||
{
|
||||
pimpl->anchor = anchor;
|
||||
}
|
||||
|
||||
face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) :
|
||||
pimpl(new impl_t())
|
||||
{
|
||||
vertex_t s(source(initial_edge,g));
|
||||
vertex_t t(target(initial_edge,g));
|
||||
vertex_t other_vertex = s == anchor ? t : s;
|
||||
pimpl->anchor = anchor;
|
||||
pimpl->cached_first_edge = initial_edge;
|
||||
pimpl->cached_second_edge = initial_edge;
|
||||
pimpl->cached_first_vertex = other_vertex;
|
||||
pimpl->cached_second_vertex = other_vertex;
|
||||
pimpl->true_first_vertex = other_vertex;
|
||||
pimpl->true_second_vertex = other_vertex;
|
||||
|
||||
pimpl->edge_list.push_back(initial_edge);
|
||||
store_old_face_handles_dispatch(StoreOldHandlesPolicy());
|
||||
}
|
||||
|
||||
//default copy construction, assignment okay.
|
||||
|
||||
void push_first(edge_t e, const Graph& g)
|
||||
{
|
||||
pimpl->edge_list.push_front(e);
|
||||
pimpl->cached_first_vertex = pimpl->true_first_vertex =
|
||||
source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
|
||||
pimpl->cached_first_edge = e;
|
||||
}
|
||||
|
||||
void push_second(edge_t e, const Graph& g)
|
||||
{
|
||||
pimpl->edge_list.push_back(e);
|
||||
pimpl->cached_second_vertex = pimpl->true_second_vertex =
|
||||
source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
|
||||
pimpl->cached_second_edge = e;
|
||||
}
|
||||
|
||||
inline void store_old_face_handles()
|
||||
{
|
||||
store_old_face_handles_dispatch(StoreOldHandlesPolicy());
|
||||
}
|
||||
|
||||
inline vertex_t first_vertex() const
|
||||
{
|
||||
return pimpl->cached_first_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t second_vertex() const
|
||||
{
|
||||
return pimpl->cached_second_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t true_first_vertex() const
|
||||
{
|
||||
return pimpl->true_first_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t true_second_vertex() const
|
||||
{
|
||||
return pimpl->true_second_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t old_first_vertex() const
|
||||
{
|
||||
return pimpl->old_handles.first_vertex;
|
||||
}
|
||||
|
||||
inline vertex_t old_second_vertex() const
|
||||
{
|
||||
return pimpl->old_handles.second_vertex;
|
||||
}
|
||||
|
||||
inline edge_t old_first_edge() const
|
||||
{
|
||||
return pimpl->old_handles.first_edge;
|
||||
}
|
||||
|
||||
inline edge_t old_second_edge() const
|
||||
{
|
||||
return pimpl->old_handles.second_edge;
|
||||
}
|
||||
|
||||
inline edge_t first_edge() const
|
||||
{
|
||||
return pimpl->cached_first_edge;
|
||||
}
|
||||
|
||||
inline edge_t second_edge() const
|
||||
{
|
||||
return pimpl->cached_second_edge;
|
||||
}
|
||||
|
||||
inline vertex_t get_anchor() const
|
||||
{
|
||||
return pimpl->anchor;
|
||||
}
|
||||
|
||||
void glue_first_to_second
|
||||
(face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
|
||||
{
|
||||
pimpl->edge_list.concat_front(bottom.pimpl->edge_list);
|
||||
pimpl->true_first_vertex = bottom.pimpl->true_first_vertex;
|
||||
pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex;
|
||||
pimpl->cached_first_edge = bottom.pimpl->cached_first_edge;
|
||||
}
|
||||
|
||||
void glue_second_to_first
|
||||
(face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
|
||||
{
|
||||
pimpl->edge_list.concat_back(bottom.pimpl->edge_list);
|
||||
pimpl->true_second_vertex = bottom.pimpl->true_second_vertex;
|
||||
pimpl->cached_second_vertex = bottom.pimpl->cached_second_vertex;
|
||||
pimpl->cached_second_edge = bottom.pimpl->cached_second_edge;
|
||||
}
|
||||
|
||||
void flip()
|
||||
{
|
||||
pimpl->edge_list.reverse();
|
||||
std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex);
|
||||
std::swap(pimpl->cached_first_vertex, pimpl->cached_second_vertex);
|
||||
std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge);
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
void get_list(OutputIterator o_itr)
|
||||
{
|
||||
pimpl->edge_list.get_list(o_itr);
|
||||
}
|
||||
|
||||
void reset_vertex_cache()
|
||||
{
|
||||
pimpl->cached_first_vertex = pimpl->true_first_vertex;
|
||||
pimpl->cached_second_vertex = pimpl->true_second_vertex;
|
||||
}
|
||||
|
||||
inline void set_first_vertex(vertex_t v)
|
||||
{
|
||||
pimpl->cached_first_vertex = v;
|
||||
}
|
||||
|
||||
inline void set_second_vertex(vertex_t v)
|
||||
{
|
||||
pimpl->cached_second_vertex = v;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void store_old_face_handles_dispatch(store_old_handles)
|
||||
{
|
||||
pimpl->old_handles.first_vertex = pimpl->true_first_vertex;
|
||||
pimpl->old_handles.second_vertex = pimpl->true_second_vertex;
|
||||
pimpl->old_handles.first_edge = pimpl->cached_first_edge;
|
||||
pimpl->old_handles.second_edge = pimpl->cached_second_edge;
|
||||
}
|
||||
|
||||
void store_old_face_handles_dispatch(no_old_handles) {}
|
||||
|
||||
|
||||
|
||||
boost::shared_ptr<impl_t> pimpl;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} /* namespace detail */ } /* namespace graph */ } /* namespace boost */
|
||||
|
||||
|
||||
#endif //__FACE_HANDLES_HPP__
|
||||
375
include/boost/graph/planar_detail/face_iterators.hpp
Normal file
375
include/boost/graph/planar_detail/face_iterators.hpp
Normal file
@@ -0,0 +1,375 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef __FACE_ITERATORS_HPP__
|
||||
#define __FACE_ITERATORS_HPP__
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
//tags for defining traversal properties
|
||||
|
||||
//VisitorType
|
||||
struct lead_visitor {};
|
||||
struct follow_visitor {};
|
||||
|
||||
//TraversalType
|
||||
struct single_side {};
|
||||
struct both_sides {};
|
||||
|
||||
//TraversalSubType
|
||||
struct first_side {}; //for single_side
|
||||
struct second_side {}; //for single_side
|
||||
struct alternating {}; //for both_sides
|
||||
|
||||
//Time
|
||||
struct current_iteration {};
|
||||
struct previous_iteration {};
|
||||
|
||||
// Why TraversalType AND TraversalSubType? TraversalSubType is a function
|
||||
// template parameter passed in to the constructor of the face iterator,
|
||||
// whereas TraversalType is a class template parameter. This lets us decide
|
||||
// at runtime whether to move along the first or second side of a bicomp (by
|
||||
// assigning a face_iterator that has been constructed with TraversalSubType
|
||||
// = first_side or second_side to a face_iterator variable) without any of
|
||||
// the virtual function overhead that comes with implementing this
|
||||
// functionality as a more structured form of type erasure. It also allows
|
||||
// a single face_iterator to be the end iterator of two iterators traversing
|
||||
// both sides of a bicomp.
|
||||
|
||||
//ValueType is either graph_traits<Graph>::vertex_descriptor
|
||||
//or graph_traits<Graph>::edge_descriptor
|
||||
|
||||
|
||||
//forward declaration (defining defaults)
|
||||
template <typename Graph,
|
||||
typename FaceHandlesMap,
|
||||
typename ValueType,
|
||||
typename BicompSideToTraverse = single_side,
|
||||
typename VisitorType = lead_visitor,
|
||||
typename Time = current_iteration
|
||||
>
|
||||
class face_iterator;
|
||||
|
||||
|
||||
|
||||
template <typename Graph, bool StoreEdge>
|
||||
struct edge_storage
|
||||
{};
|
||||
|
||||
template <typename Graph>
|
||||
struct edge_storage <Graph, true>
|
||||
{
|
||||
typename graph_traits<Graph>::edge_descriptor value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//specialization for TraversalType = traverse_vertices
|
||||
template <typename Graph,
|
||||
typename FaceHandlesMap,
|
||||
typename ValueType,
|
||||
typename TraversalType,
|
||||
typename VisitorType,
|
||||
typename Time
|
||||
>
|
||||
|
||||
class face_iterator
|
||||
: public boost::iterator_facade < face_iterator<Graph,
|
||||
FaceHandlesMap,
|
||||
ValueType,
|
||||
TraversalType,
|
||||
VisitorType,
|
||||
Time
|
||||
>,
|
||||
ValueType,
|
||||
boost::forward_traversal_tag,
|
||||
ValueType
|
||||
>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef face_iterator
|
||||
<Graph,FaceHandlesMap,ValueType,TraversalType,VisitorType,Time> self;
|
||||
typedef typename FaceHandlesMap::value_type face_handle_t;
|
||||
|
||||
face_iterator() :
|
||||
m_lead(graph_traits<Graph>::null_vertex()),
|
||||
m_follow(graph_traits<Graph>::null_vertex())
|
||||
{}
|
||||
|
||||
template <typename TraversalSubType>
|
||||
face_iterator(face_handle_t anchor_handle,
|
||||
FaceHandlesMap face_handles,
|
||||
TraversalSubType traversal_type):
|
||||
m_follow(anchor_handle.get_anchor()),
|
||||
m_face_handles(face_handles)
|
||||
{
|
||||
set_lead_dispatch(anchor_handle, traversal_type);
|
||||
}
|
||||
|
||||
template <typename TraversalSubType>
|
||||
face_iterator(vertex_t anchor,
|
||||
FaceHandlesMap face_handles,
|
||||
TraversalSubType traversal_type):
|
||||
m_follow(anchor),
|
||||
m_face_handles(face_handles)
|
||||
{
|
||||
set_lead_dispatch(m_face_handles[anchor], traversal_type);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
|
||||
|
||||
|
||||
inline vertex_t get_first_vertex(face_handle_t anchor_handle,
|
||||
current_iteration
|
||||
)
|
||||
{
|
||||
return anchor_handle.first_vertex();
|
||||
}
|
||||
|
||||
inline vertex_t get_second_vertex(face_handle_t anchor_handle,
|
||||
current_iteration
|
||||
)
|
||||
{
|
||||
return anchor_handle.second_vertex();
|
||||
}
|
||||
|
||||
inline vertex_t get_first_vertex(face_handle_t anchor_handle,
|
||||
previous_iteration
|
||||
)
|
||||
{
|
||||
return anchor_handle.old_first_vertex();
|
||||
}
|
||||
|
||||
inline vertex_t get_second_vertex(face_handle_t anchor_handle,
|
||||
previous_iteration
|
||||
)
|
||||
{
|
||||
return anchor_handle.old_second_vertex();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline void set_lead_dispatch(face_handle_t anchor_handle, first_side)
|
||||
{
|
||||
m_lead = get_first_vertex(anchor_handle, Time());
|
||||
set_edge_to_first_dispatch(anchor_handle, ValueType(), Time());
|
||||
}
|
||||
|
||||
inline void set_lead_dispatch(face_handle_t anchor_handle, second_side)
|
||||
{
|
||||
m_lead = get_second_vertex(anchor_handle, Time());
|
||||
set_edge_to_second_dispatch(anchor_handle, ValueType(), Time());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline void set_edge_to_first_dispatch(face_handle_t anchor_handle,
|
||||
edge_t,
|
||||
current_iteration
|
||||
)
|
||||
{
|
||||
m_edge.value = anchor_handle.first_edge();
|
||||
}
|
||||
|
||||
inline void set_edge_to_second_dispatch(face_handle_t anchor_handle,
|
||||
edge_t,
|
||||
current_iteration
|
||||
)
|
||||
{
|
||||
m_edge.value = anchor_handle.second_edge();
|
||||
}
|
||||
|
||||
inline void set_edge_to_first_dispatch(face_handle_t anchor_handle,
|
||||
edge_t,
|
||||
previous_iteration
|
||||
)
|
||||
{
|
||||
m_edge.value = anchor_handle.old_first_edge();
|
||||
}
|
||||
|
||||
inline void set_edge_to_second_dispatch(face_handle_t anchor_handle,
|
||||
edge_t,
|
||||
previous_iteration
|
||||
)
|
||||
{
|
||||
m_edge.value = anchor_handle.old_second_edge();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void set_edge_to_first_dispatch(face_handle_t, vertex_t, T)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
inline void set_edge_to_second_dispatch(face_handle_t, vertex_t, T)
|
||||
{}
|
||||
|
||||
void increment()
|
||||
{
|
||||
face_handle_t curr_face_handle(m_face_handles[m_lead]);
|
||||
vertex_t first = get_first_vertex(curr_face_handle, Time());
|
||||
vertex_t second = get_second_vertex(curr_face_handle, Time());
|
||||
if (first == m_follow)
|
||||
{
|
||||
m_follow = m_lead;
|
||||
set_edge_to_second_dispatch(curr_face_handle, ValueType(), Time());
|
||||
m_lead = second;
|
||||
}
|
||||
else if (second == m_follow)
|
||||
{
|
||||
m_follow = m_lead;
|
||||
set_edge_to_first_dispatch(curr_face_handle, ValueType(), Time());
|
||||
m_lead = first;
|
||||
}
|
||||
else
|
||||
m_lead = m_follow = graph_traits<Graph>::null_vertex();
|
||||
}
|
||||
|
||||
bool equal(self const& other) const
|
||||
{
|
||||
return m_lead == other.m_lead && m_follow == other.m_follow;
|
||||
}
|
||||
|
||||
ValueType dereference() const
|
||||
{
|
||||
return dereference_dispatch(VisitorType(), ValueType());
|
||||
}
|
||||
|
||||
inline ValueType dereference_dispatch(lead_visitor, vertex_t) const
|
||||
{ return m_lead; }
|
||||
|
||||
inline ValueType dereference_dispatch(follow_visitor, vertex_t) const
|
||||
{ return m_follow; }
|
||||
|
||||
inline ValueType dereference_dispatch(lead_visitor, edge_t) const
|
||||
{ return m_edge.value; }
|
||||
|
||||
inline ValueType dereference_dispatch(follow_visitor, edge_t) const
|
||||
{ return m_edge.value; }
|
||||
|
||||
vertex_t m_lead;
|
||||
vertex_t m_follow;
|
||||
edge_storage<Graph, boost::is_same<ValueType, edge_t>::value > m_edge;
|
||||
FaceHandlesMap m_face_handles;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename Graph,
|
||||
typename FaceHandlesMap,
|
||||
typename ValueType,
|
||||
typename VisitorType,
|
||||
typename Time
|
||||
>
|
||||
class face_iterator
|
||||
<Graph, FaceHandlesMap, ValueType, both_sides, VisitorType, Time>
|
||||
: public boost::iterator_facade< face_iterator<Graph,
|
||||
FaceHandlesMap,
|
||||
ValueType,
|
||||
both_sides,
|
||||
VisitorType,
|
||||
Time>,
|
||||
ValueType,
|
||||
boost::forward_traversal_tag,
|
||||
ValueType >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef face_iterator
|
||||
<Graph,FaceHandlesMap,ValueType,both_sides,VisitorType,Time> self;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename FaceHandlesMap::value_type face_handle_t;
|
||||
|
||||
face_iterator() {}
|
||||
|
||||
face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles):
|
||||
first_itr(anchor_handle, face_handles, first_side()),
|
||||
second_itr(anchor_handle, face_handles, second_side()),
|
||||
first_is_active(true),
|
||||
first_increment(true)
|
||||
{}
|
||||
|
||||
face_iterator(vertex_t anchor, FaceHandlesMap face_handles):
|
||||
first_itr(face_handles[anchor], face_handles, first_side()),
|
||||
second_itr(face_handles[anchor], face_handles, second_side()),
|
||||
first_is_active(true),
|
||||
first_increment(true)
|
||||
{}
|
||||
|
||||
private:
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
typedef face_iterator
|
||||
<Graph, FaceHandlesMap, ValueType, single_side, follow_visitor, Time>
|
||||
inner_itr_t;
|
||||
|
||||
void increment()
|
||||
{
|
||||
if (first_increment)
|
||||
{
|
||||
++first_itr;
|
||||
++second_itr;
|
||||
first_increment = false;
|
||||
}
|
||||
else if (first_is_active)
|
||||
++first_itr;
|
||||
else
|
||||
++second_itr;
|
||||
first_is_active = !first_is_active;
|
||||
}
|
||||
|
||||
bool equal(self const& other) const
|
||||
{
|
||||
//Want this iterator to be equal to the "end" iterator when at least
|
||||
//one of the iterators has reached the root of the current bicomp.
|
||||
//This isn't ideal, but it works.
|
||||
|
||||
return (first_itr == other.first_itr || second_itr == other.second_itr);
|
||||
}
|
||||
|
||||
ValueType dereference() const
|
||||
{
|
||||
return first_is_active ? *first_itr : *second_itr;
|
||||
}
|
||||
|
||||
inner_itr_t first_itr;
|
||||
inner_itr_t second_itr;
|
||||
inner_itr_t face_end;
|
||||
bool first_is_active;
|
||||
bool first_increment;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
|
||||
#endif //__FACE_ITERATORS_HPP__
|
||||
210
include/boost/graph/planar_face_traversal.hpp
Normal file
210
include/boost/graph/planar_face_traversal.hpp
Normal file
@@ -0,0 +1,210 @@
|
||||
//=======================================================================
|
||||
// Copyright (c) Aaron Windsor 2007
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef __PLANAR_FACE_TRAVERSAL_HPP__
|
||||
#define __PLANAR_FACE_TRAVERSAL_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <boost/utility.hpp> //for next and prior
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
struct planar_face_traversal_visitor
|
||||
{
|
||||
void begin_traversal()
|
||||
{}
|
||||
|
||||
void begin_face()
|
||||
{}
|
||||
|
||||
template <typename Edge>
|
||||
void next_edge(Edge e)
|
||||
{}
|
||||
|
||||
template <typename Vertex>
|
||||
void next_vertex(Vertex v)
|
||||
{}
|
||||
|
||||
void end_face()
|
||||
{}
|
||||
|
||||
void end_traversal()
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename Graph,
|
||||
typename PlanarEmbedding,
|
||||
typename Visitor,
|
||||
typename EdgeIndexMap>
|
||||
void planar_face_traversal(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
Visitor& visitor, EdgeIndexMap em
|
||||
)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
|
||||
typedef typename
|
||||
property_traits<PlanarEmbedding>::value_type embedding_value_t;
|
||||
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
|
||||
|
||||
typedef typename
|
||||
std::vector< std::set<vertex_t> > distinguished_edge_storage_t;
|
||||
typedef typename
|
||||
std::vector< std::map<vertex_t, edge_t> >
|
||||
distinguished_edge_to_edge_storage_t;
|
||||
|
||||
typedef typename
|
||||
boost::iterator_property_map
|
||||
<typename distinguished_edge_storage_t::iterator, EdgeIndexMap>
|
||||
distinguished_edge_map_t;
|
||||
|
||||
typedef typename
|
||||
boost::iterator_property_map
|
||||
<typename distinguished_edge_to_edge_storage_t::iterator, EdgeIndexMap>
|
||||
distinguished_edge_to_edge_map_t;
|
||||
|
||||
distinguished_edge_storage_t visited_vector(num_edges(g));
|
||||
distinguished_edge_to_edge_storage_t next_edge_vector(num_edges(g));
|
||||
|
||||
distinguished_edge_map_t visited(visited_vector.begin(), em);
|
||||
distinguished_edge_to_edge_map_t next_edge(next_edge_vector.begin(), em);
|
||||
|
||||
vertex_iterator_t vi, vi_end;
|
||||
typename std::vector<edge_t>::iterator ei, ei_end;
|
||||
edge_iterator_t fi, fi_end;
|
||||
embedding_iterator_t pi, pi_begin, pi_end;
|
||||
|
||||
visitor.begin_traversal();
|
||||
|
||||
// Initialize the next_edge property map. This map is initialized from the
|
||||
// PlanarEmbedding so that get(next_edge, e)[v] is the edge that comes
|
||||
// after e in the clockwise embedding around vertex v.
|
||||
|
||||
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
|
||||
{
|
||||
vertex_t v(*vi);
|
||||
pi_begin = embedding[v].begin();
|
||||
pi_end = embedding[v].end();
|
||||
for(pi = pi_begin; pi != pi_end; ++pi)
|
||||
{
|
||||
edge_t e(*pi);
|
||||
std::map<vertex_t, edge_t> m = get(next_edge, e);
|
||||
m[v] = next(pi) == pi_end ? *pi_begin : *next(pi);
|
||||
put(next_edge, e, m);
|
||||
}
|
||||
}
|
||||
|
||||
// Take a copy of the edges in the graph here, since we want to accomodate
|
||||
// face traversals that add edges to the graph (for triangulation, in
|
||||
// particular) and don't want to use invalidated edge iterators.
|
||||
// Also, while iterating over all edges in the graph, we single out
|
||||
// any self-loops, which need some special treatment in the face traversal.
|
||||
|
||||
std::vector<edge_t> self_loops;
|
||||
std::vector<edge_t> edges_cache;
|
||||
std::vector<vertex_t> vertices_in_edge;
|
||||
|
||||
for(tie(fi,fi_end) = edges(g); fi != fi_end; ++fi)
|
||||
{
|
||||
edge_t e(*fi);
|
||||
edges_cache.push_back(e);
|
||||
if (source(e,g) == target(e,g))
|
||||
self_loops.push_back(e);
|
||||
}
|
||||
|
||||
|
||||
// Iterate over all edges in the graph
|
||||
ei_end = edges_cache.end();
|
||||
for(ei = edges_cache.begin(); ei != ei_end; ++ei)
|
||||
{
|
||||
|
||||
edge_t e(*ei);
|
||||
vertices_in_edge.clear();
|
||||
vertices_in_edge.push_back(source(e,g));
|
||||
vertices_in_edge.push_back(target(e,g));
|
||||
|
||||
typename std::vector<vertex_t>::iterator vi, vi_end;
|
||||
vi_end = vertices_in_edge.end();
|
||||
|
||||
//Iterate over both vertices in the current edge
|
||||
for(vi = vertices_in_edge.begin(); vi != vi_end; ++vi)
|
||||
{
|
||||
|
||||
vertex_t v(*vi);
|
||||
std::set<vertex_t> e_visited = get(visited, e);
|
||||
typename std::set<vertex_t>::iterator e_visited_found
|
||||
= e_visited.find(v);
|
||||
|
||||
if (e_visited_found == e_visited.end())
|
||||
visitor.begin_face();
|
||||
|
||||
while (e_visited.find(v) == e_visited.end())
|
||||
{
|
||||
visitor.next_vertex(v);
|
||||
visitor.next_edge(e);
|
||||
e_visited.insert(v);
|
||||
put(visited, e, e_visited);
|
||||
v = source(e,g) == v ? target(e,g) : source(e,g);
|
||||
e = get(next_edge, e)[v];
|
||||
e_visited = get(visited, e);
|
||||
}
|
||||
|
||||
if (e_visited_found == e_visited.end())
|
||||
visitor.end_face();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Iterate over all self-loops, visiting them once separately
|
||||
// (they've already been visited once, this visitation is for
|
||||
// the "inside" of the self-loop)
|
||||
|
||||
ei_end = self_loops.end();
|
||||
for(ei = self_loops.begin(); ei != ei_end; ++ei)
|
||||
{
|
||||
visitor.begin_face();
|
||||
visitor.next_edge(*ei);
|
||||
visitor.next_vertex(source(*ei,g));
|
||||
visitor.end_face();
|
||||
}
|
||||
|
||||
visitor.end_traversal();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename Graph, typename PlanarEmbedding, typename Visitor>
|
||||
inline void planar_face_traversal(const Graph& g,
|
||||
PlanarEmbedding embedding,
|
||||
Visitor& visitor
|
||||
)
|
||||
{
|
||||
planar_face_traversal(g, embedding, visitor, get(edge_index, g));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} //namespace boost
|
||||
|
||||
#endif //__PLANAR_FACE_TRAVERSAL_HPP__
|
||||
@@ -16,6 +16,13 @@
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# define Graph Graph_
|
||||
# define RandomAccessContainer RandomAccessContainer_
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
enum default_color_type { white_color, gray_color, green_color, red_color, black_color };
|
||||
@@ -322,7 +329,7 @@ namespace boost {
|
||||
#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
|
||||
@@ -354,11 +361,11 @@ namespace boost {
|
||||
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),
|
||||
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
|
||||
typename traits::vertex_descriptor,
|
||||
typename traits::edge_descriptor>::type
|
||||
descriptor;
|
||||
typedef typename ct_if<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
|
||||
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
|
||||
vertex_bundled,
|
||||
edge_bundled>::type
|
||||
actual_bundle;
|
||||
@@ -372,4 +379,11 @@ namespace boost {
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# undef Graph
|
||||
# undef RandomAccessIterator
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* BOOST_GRAPH_PROPERTIES_HPPA */
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include <boost/property_map_iterator.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/pending/ct_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
@@ -34,7 +34,7 @@ namespace boost {
|
||||
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,
|
||||
typedef typename mpl::if_c<is_same<Kind, vertex_property_tag>::value,
|
||||
typename graph_traits<Graph>::vertex_iterator,
|
||||
typename graph_traits<Graph>::edge_iterator>::type iter;
|
||||
public:
|
||||
|
||||
@@ -9,15 +9,13 @@
|
||||
|
||||
/*
|
||||
Reads maximal flow problem in extended DIMACS format.
|
||||
|
||||
Reads from stdin.
|
||||
|
||||
This works, but could use some polishing.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
#include <vector>
|
||||
#include <istream>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace boost {
|
||||
@@ -27,7 +25,8 @@ 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)
|
||||
typename graph_traits<Graph>::vertex_descriptor& sink,
|
||||
std::istream& in=std::cin)
|
||||
{
|
||||
// const int MAXLINE = 100; /* max line length in the input file */
|
||||
const int ARC_FIELDS = 3; /* no of fields in arc line */
|
||||
@@ -114,7 +113,7 @@ int read_dimacs_max_flow(Graph& g,
|
||||
- does service functions
|
||||
*/
|
||||
|
||||
while (std::getline(std::cin, in_line)) {
|
||||
while (std::getline(in, in_line)) {
|
||||
++no_lines;
|
||||
|
||||
switch (in_line[0]) {
|
||||
|
||||
@@ -24,11 +24,11 @@ namespace boost {
|
||||
{
|
||||
T operator()(const T& a, const T& b) const {
|
||||
using namespace std;
|
||||
T zero(0);
|
||||
T result = a + b;
|
||||
if (result < zero && a >= zero && b >= zero)
|
||||
return (numeric_limits<T>::max)();
|
||||
return result;
|
||||
T zero(0);
|
||||
T result = a + b;
|
||||
if (result < zero && a >= zero && b >= zero)
|
||||
return (numeric_limits<T>::max)();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# define BidirectionalGraph BidirectionalGraph_
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct reverse_graph_tag { };
|
||||
@@ -311,4 +316,9 @@ get_property(const reverse_graph<BidirectionalGraph,GRef>& g, Tag tag)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# undef BidirectionalGraph
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/graph/detail/is_same.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# define Graph Graph_
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
// This is a bit more convenient than std::numeric_limits because
|
||||
@@ -266,4 +271,9 @@ namespace boost {
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of the concept checking class
|
||||
# undef Graph
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
72
include/boost/graph/write_dimacs.hpp
Normal file
72
include/boost/graph/write_dimacs.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2006, Stephan Diederich
|
||||
//
|
||||
// This code may be used under either of the following two licences:
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE.
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
Writes maximal flow problem in extended DIMACS format to an OutputIterator
|
||||
Vertex indices are read from an IndexMap and shiftet by 1.
|
||||
so their new range is [1..num_vertices(g)]
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Graph, class CapacityMap, class IndexMap>
|
||||
void write_dimacs_max_flow(const Graph& g,
|
||||
CapacityMap capacity,
|
||||
IndexMap idx,
|
||||
typename graph_traits<Graph>::vertex_descriptor src,
|
||||
typename graph_traits<Graph>::vertex_descriptor sink,
|
||||
std::ostream& out)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
|
||||
|
||||
out << "c DIMACS max-flow file generated from boost::write_dimacs_max_flow" << std::endl;
|
||||
out << "p max " << num_vertices(g) << " " << num_edges(g) << std::endl; //print problem description "max" and number of verts and edges
|
||||
out << "n " << get(idx, src) + 1 << " s" << std::endl;; //say which one is source
|
||||
out << "n " << get(idx, sink) + 1 << " t" << std::endl; //say which one is sink
|
||||
|
||||
//output the edges
|
||||
edge_iterator ei, e_end;
|
||||
for(tie(ei,e_end) = edges(g); ei!=e_end; ++ei){
|
||||
out << "a " << idx[ source(*ei, g) ] + 1 << " " << idx[ target(*ei, g) ] + 1 << " " << get(capacity,*ei) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
@@ -39,6 +39,12 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of concept checking class templates
|
||||
# define Container Container_
|
||||
# define AssociativeContainer AssociativeContainer_
|
||||
#endif
|
||||
|
||||
// The content of this file is in 'graph_detail' because otherwise
|
||||
// there will be name clashes with
|
||||
// sandbox/boost/sequence_algo/container_traits.hpp
|
||||
@@ -410,4 +416,10 @@ namespace boost { namespace graph_detail {
|
||||
|
||||
}} // namespace boost::graph_detail
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
// Stay out of the way of concept checking class templates
|
||||
# undef Container
|
||||
# undef AssociativeContainer
|
||||
#endif
|
||||
|
||||
#endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
|
||||
|
||||
@@ -120,12 +120,14 @@ public:
|
||||
new_roots[r] = nil();
|
||||
if (_compare(_key[u], _key[v])) {
|
||||
_degree[v] = r;
|
||||
_mark[v] = false;
|
||||
std::swap(u, v);
|
||||
}
|
||||
make_child(u, v, r);
|
||||
++r;
|
||||
}
|
||||
_degree[v] = r;
|
||||
_mark[v] = false;
|
||||
}
|
||||
// 40
|
||||
void make_child(size_type u, size_type v, size_type r) {
|
||||
@@ -178,7 +180,7 @@ public:
|
||||
if (p == nil()) {
|
||||
if (_compare(d, _key[_root]))
|
||||
_root = v;
|
||||
} else if (_compare(d, _key[_root]))
|
||||
} else if (_compare(d, _key[p]))
|
||||
while (1) {
|
||||
size_type r = _degree[p];
|
||||
if (r >= 2)
|
||||
@@ -191,6 +193,7 @@ public:
|
||||
}
|
||||
if (_mark[p] == false) {
|
||||
_mark[p] = true;
|
||||
--_degree[p];
|
||||
break;
|
||||
} else
|
||||
--_degree[p];
|
||||
@@ -237,7 +240,7 @@ protected:
|
||||
void print_recur(size_type x, std::ostream& os) {
|
||||
if (x != nil()) {
|
||||
os << x;
|
||||
if (_child[x] != nil()) {
|
||||
if (_degree[x] > 0) {
|
||||
os << "(";
|
||||
size_type i = _child[x];
|
||||
do {
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <boost/property_map.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <vector>
|
||||
#include <climits> // for CHAR_BIT
|
||||
#include <boost/none.hpp>
|
||||
|
||||
#ifdef BOOST_RELAXED_HEAP_DEBUG
|
||||
# include <iostream>
|
||||
@@ -172,14 +174,14 @@ public:
|
||||
value_type& top()
|
||||
{
|
||||
find_smallest();
|
||||
assert(smallest_value->value != 0);
|
||||
assert(smallest_value->value != none);
|
||||
return *smallest_value->value;
|
||||
}
|
||||
|
||||
const value_type& top() const
|
||||
{
|
||||
find_smallest();
|
||||
assert(smallest_value->value != 0);
|
||||
assert(smallest_value->value != none);
|
||||
return *smallest_value->value;
|
||||
}
|
||||
|
||||
@@ -202,7 +204,7 @@ public:
|
||||
rank_type r = x->rank;
|
||||
group* p = x->parent;
|
||||
{
|
||||
assert(x->value != 0);
|
||||
assert(x->value != none);
|
||||
|
||||
// Find x's group
|
||||
size_type start = get(id, *x->value) - get(id, *x->value) % log_n;
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_STRINGTOK_HPP
|
||||
#define BOOST_STRINGTOK_HPP
|
||||
|
||||
/*
|
||||
* stringtok.hpp -- Breaks a string into tokens. This is an example for lib3.
|
||||
*
|
||||
@@ -109,3 +112,5 @@ stringtok (Container &l, std::string const &s, char const * const ws = " \t\n")
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_STRINGTOK_HPP
|
||||
|
||||
Reference in New Issue
Block a user