blob: 2dee17dfaa6f4a5b48aa0c4e19ef38413000f505 [file] [log] [blame]
//=======================================================================
// Copyright 2001 University of Notre Dame.
// Copyright 2006 Trustees of Indiana University
// Authors: Jeremy G. Siek and Douglas Gregor <dgregor@cs.indiana.edu>
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef BOOST_ADJACENCY_MATRIX_HPP
#define BOOST_ADJACENCY_MATRIX_HPP
#include <boost/config.hpp>
#include <vector>
#include <memory>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/iterator.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_mutability_traits.hpp>
#include <boost/graph/graph_selectors.hpp>
#include <boost/mpl/if.hpp>
#include <boost/graph/adjacency_iterator.hpp>
#include <boost/graph/detail/edge.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/range/irange.hpp>
#include <boost/graph/properties.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/ice.hpp>
namespace boost {
namespace detail {
template <class Directed, class Vertex>
class matrix_edge_desc_impl : public edge_desc_impl<Directed,Vertex>
{
typedef edge_desc_impl<Directed,Vertex> Base;
public:
matrix_edge_desc_impl() { }
matrix_edge_desc_impl(bool exists, Vertex s, Vertex d,
const void* ep = 0)
: Base(s, d, ep), m_exists(exists) { }
bool exists() const { return m_exists; }
private:
bool m_exists;
};
struct does_edge_exist {
template <class Edge>
bool operator()(const Edge& e) const { return e.exists(); }
};
// Note to self... The int for get_edge_exists and set_edge exist helps
// make these calls unambiguous.
template <typename EdgeProperty>
bool get_edge_exists(const std::pair<bool, EdgeProperty>& stored_edge, int) {
return stored_edge.first;
}
template <typename EdgeProperty>
void set_edge_exists(
std::pair<bool, EdgeProperty>& stored_edge,
bool flag,
int
) {
stored_edge.first = flag;
}
template <typename EdgeProxy>
bool get_edge_exists(const EdgeProxy& edge_proxy, ...) {
return edge_proxy;
}
template <typename EdgeProxy>
EdgeProxy& set_edge_exists(EdgeProxy& edge_proxy, bool flag, ...) {
edge_proxy = flag;
return edge_proxy; // just to avoid never used warning
}
// NOTE: These functions collide with the get_property function for
// accessing bundled graph properties. Be excplicit when using them.
template <typename EdgeProperty>
const EdgeProperty&
get_edge_property(const std::pair<bool, EdgeProperty>& stored_edge) {
return stored_edge.second;
}
template <typename EdgeProperty>
EdgeProperty&
get_edge_property(std::pair<bool, EdgeProperty>& stored_edge) {
return stored_edge.second;
}
template <typename StoredEdgeProperty, typename EdgeProperty>
inline void
set_edge_property(std::pair<bool, StoredEdgeProperty>& stored_edge,
const EdgeProperty& ep, int) {
stored_edge.second = ep;
}
inline const no_property& get_edge_property(const char&) {
static no_property s_prop;
return s_prop;
}
inline no_property& get_edge_property(char&) {
static no_property s_prop;
return s_prop;
}
template <typename EdgeProxy, typename EdgeProperty>
inline void set_edge_property(EdgeProxy, const EdgeProperty&, ...) {}
//=======================================================================
// Directed Out Edge Iterator
template <
typename VertexDescriptor, typename MatrixIter
, typename VerticesSizeType, typename EdgeDescriptor
>
struct dir_adj_matrix_out_edge_iter
: iterator_adaptor<
dir_adj_matrix_out_edge_iter<VertexDescriptor, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
>
{
typedef iterator_adaptor<
dir_adj_matrix_out_edge_iter<VertexDescriptor, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
> super_t;
dir_adj_matrix_out_edge_iter() { }
dir_adj_matrix_out_edge_iter(
const MatrixIter& i
, const VertexDescriptor& src
, const VerticesSizeType& n
)
: super_t(i), m_src(src), m_targ(0), m_n(n)
{ }
void increment() {
++this->base_reference();
++m_targ;
}
inline EdgeDescriptor
dereference() const
{
return EdgeDescriptor(get_edge_exists(*this->base(), 0),
m_src, m_targ,
&get_edge_property(*this->base()));
}
VertexDescriptor m_src, m_targ;
VerticesSizeType m_n;
};
//=======================================================================
// Directed In Edge Iterator
template <
typename VertexDescriptor, typename MatrixIter
, typename VerticesSizeType, typename EdgeDescriptor
>
struct dir_adj_matrix_in_edge_iter
: iterator_adaptor<
dir_adj_matrix_in_edge_iter<VertexDescriptor, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
>
{
typedef iterator_adaptor<
dir_adj_matrix_in_edge_iter<VertexDescriptor, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
> super_t;
dir_adj_matrix_in_edge_iter() { }
dir_adj_matrix_in_edge_iter(
const MatrixIter& i
, const MatrixIter& last
, const VertexDescriptor& tgt
, const VerticesSizeType& n
)
: super_t(i), m_last(last), m_src(0), m_targ(tgt), m_n(n)
{ }
void increment() {
if (VerticesSizeType(m_last - this->base_reference()) >= m_n) {
this->base_reference() += m_n;
++m_src;
} else {
this->base_reference() = m_last;
}
}
inline EdgeDescriptor
dereference() const
{
return EdgeDescriptor(get_edge_exists(*this->base(), 0),
m_src, m_targ,
&get_edge_property(*this->base()));
}
MatrixIter m_last;
VertexDescriptor m_src, m_targ;
VerticesSizeType m_n;
};
//=======================================================================
// Undirected Out Edge Iterator
template <
typename VertexDescriptor, typename MatrixIter
, typename VerticesSizeType, typename EdgeDescriptor
>
struct undir_adj_matrix_out_edge_iter
: iterator_adaptor<
undir_adj_matrix_out_edge_iter<VertexDescriptor, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
>
{
typedef iterator_adaptor<
undir_adj_matrix_out_edge_iter<VertexDescriptor, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
> super_t;
undir_adj_matrix_out_edge_iter() { }
undir_adj_matrix_out_edge_iter(
const MatrixIter& i
, const VertexDescriptor& src
, const VerticesSizeType& n
)
: super_t(i), m_src(src), m_inc(src), m_targ(0), m_n(n)
{}
void increment()
{
if (m_targ < m_src) // first half
{
++this->base_reference();
}
else if (m_targ < m_n - 1)
{ // second half
++m_inc;
this->base_reference() += m_inc;
}
else
{ // past-the-end
this->base_reference() += m_n - m_src;
}
++m_targ;
}
inline EdgeDescriptor
dereference() const
{
return EdgeDescriptor(get_edge_exists(*this->base(), 0),
m_src, m_targ,
&get_edge_property(*this->base()));
}
VertexDescriptor m_src, m_inc, m_targ;
VerticesSizeType m_n;
};
//=======================================================================
// Undirected In Edge Iterator
template <
typename VertexDescriptor, typename MatrixIter
, typename VerticesSizeType, typename EdgeDescriptor
>
struct undir_adj_matrix_in_edge_iter
: iterator_adaptor<
undir_adj_matrix_in_edge_iter<VertexDescriptor, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
>
{
typedef iterator_adaptor<
undir_adj_matrix_in_edge_iter<VertexDescriptor, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
> super_t;
undir_adj_matrix_in_edge_iter() { }
undir_adj_matrix_in_edge_iter(
const MatrixIter& i
, const VertexDescriptor& src
, const VerticesSizeType& n
)
: super_t(i), m_src(src), m_inc(src), m_targ(0), m_n(n)
{}
void increment()
{
if (m_targ < m_src) // first half
{
++this->base_reference();
}
else if (m_targ < m_n - 1)
{ // second half
++m_inc;
this->base_reference() += m_inc;
}
else
{ // past-the-end
this->base_reference() += m_n - m_src;
}
++m_targ;
}
inline EdgeDescriptor
dereference() const
{
return EdgeDescriptor(get_edge_exists(*this->base(), 0),
m_targ, m_src,
&get_edge_property(*this->base()));
}
VertexDescriptor m_src, m_inc, m_targ;
VerticesSizeType m_n;
};
//=======================================================================
// Edge Iterator
template <typename Directed, typename MatrixIter,
typename VerticesSizeType, typename EdgeDescriptor>
struct adj_matrix_edge_iter
: iterator_adaptor<
adj_matrix_edge_iter<Directed, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
>
{
typedef iterator_adaptor<
adj_matrix_edge_iter<Directed, MatrixIter, VerticesSizeType, EdgeDescriptor>
, MatrixIter
, EdgeDescriptor
, use_default
, EdgeDescriptor
, std::ptrdiff_t
> super_t;
adj_matrix_edge_iter() { }
adj_matrix_edge_iter(const MatrixIter& i, const MatrixIter& start, const VerticesSizeType& n)
: super_t(i), m_start(start), m_src(0), m_targ(0), m_n(n) { }
void increment()
{
increment_dispatch(this->base_reference(), Directed());
}
void increment_dispatch(MatrixIter& i, directedS)
{
++i;
if (m_targ == m_n - 1)
{
m_targ = 0;
++m_src;
}
else
{
++m_targ;
}
}
void increment_dispatch(MatrixIter& i, undirectedS)
{
++i;
if (m_targ == m_src)
{
m_targ = 0;
++m_src;
}
else
{
++m_targ;
}
}
inline EdgeDescriptor
dereference() const
{
return EdgeDescriptor(get_edge_exists(*this->base(), 0),
m_src, m_targ,
&get_edge_property(*this->base()));
}
MatrixIter m_start;
VerticesSizeType m_src, m_targ, m_n;
};
} // namespace detail
//=========================================================================
// Adjacency Matrix Traits
template <typename Directed = directedS>
class adjacency_matrix_traits {
typedef typename Directed::is_directed_t is_directed;
public:
// The bidirectionalS tag is not allowed with the adjacency_matrix
// graph type. Instead, use directedS, which also provides the
// functionality required for a Bidirectional Graph (in_edges,
// in_degree, etc.).
#if !defined(_MSC_VER) || _MSC_VER > 1300
BOOST_STATIC_ASSERT(type_traits::ice_not<(is_same<Directed, bidirectionalS>::value)>::value);
#endif
typedef typename mpl::if_<is_directed,
bidirectional_tag, undirected_tag>::type
directed_category;
typedef disallow_parallel_edge_tag edge_parallel_category;
typedef std::size_t vertex_descriptor;
typedef detail::matrix_edge_desc_impl<directed_category,
vertex_descriptor> edge_descriptor;
};
struct adjacency_matrix_class_tag { };
struct adj_matrix_traversal_tag :
public virtual adjacency_matrix_tag,
public virtual vertex_list_graph_tag,
public virtual incidence_graph_tag,
public virtual adjacency_graph_tag,
public virtual edge_list_graph_tag { };
//=========================================================================
// Adjacency Matrix Class
template <typename Directed = directedS,
typename VertexProperty = no_property,
typename EdgeProperty = no_property,
typename GraphProperty = no_property,
typename Allocator = std::allocator<bool> >
class adjacency_matrix {
typedef adjacency_matrix self;
typedef adjacency_matrix_traits<Directed> Traits;
public:
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
// The bidirectionalS tag is not allowed with the adjacency_matrix
// graph type. Instead, use directedS, which also provides the
// functionality required for a Bidirectional Graph (in_edges,
// in_degree, etc.).
BOOST_STATIC_ASSERT(!(is_same<Directed, bidirectionalS>::value));
#endif
#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
typedef typename graph_detail::graph_prop<GraphProperty>::property graph_property_type;
typedef typename graph_detail::graph_prop<GraphProperty>::bundle graph_bundled;
typedef typename graph_detail::vertex_prop<VertexProperty>::property vertex_property_type;
typedef typename graph_detail::vertex_prop<VertexProperty>::bundle vertex_bundled;
typedef typename graph_detail::edge_prop<EdgeProperty>::property edge_property_type;
typedef typename graph_detail::edge_prop<EdgeProperty>::bundle edge_bundled;
#else
typedef GraphProperty graph_property_type;
typedef no_graph_bundle graph_bundled;
typedef VertexProperty vertex_property_type;
typedef no_vertex_bundle vertex_bundled;
typedef EdgeProperty edge_property_type;
typedef no_edge_bundle edge_bundled;
#endif
public: // should be private
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;
#else
// This causes internal compiler error for MSVC
typedef typename Allocator::template rebind<StoredEdge>::other Alloc;
typedef std::vector<StoredEdge, Alloc> Matrix;
#endif
typedef typename Matrix::iterator MatrixIter;
typedef typename Matrix::size_type size_type;
public:
// Graph concept required types
typedef typename Traits::vertex_descriptor vertex_descriptor;
typedef typename Traits::edge_descriptor edge_descriptor;
typedef typename Traits::directed_category directed_category;
typedef typename Traits::edge_parallel_category edge_parallel_category;
typedef adj_matrix_traversal_tag traversal_category;
static vertex_descriptor null_vertex()
{
return (std::numeric_limits<vertex_descriptor>::max)();
}
//private: if friends worked, these would be private
typedef detail::dir_adj_matrix_out_edge_iter<
vertex_descriptor, MatrixIter, size_type, edge_descriptor
> DirOutEdgeIter;
typedef detail::undir_adj_matrix_out_edge_iter<
vertex_descriptor, MatrixIter, size_type, edge_descriptor
> UnDirOutEdgeIter;
typedef typename mpl::if_<
typename Directed::is_directed_t, DirOutEdgeIter, UnDirOutEdgeIter
>::type unfiltered_out_edge_iter;
typedef detail::dir_adj_matrix_in_edge_iter<
vertex_descriptor, MatrixIter, size_type, edge_descriptor
> DirInEdgeIter;
typedef detail::undir_adj_matrix_in_edge_iter<
vertex_descriptor, MatrixIter, size_type, edge_descriptor
> UnDirInEdgeIter;
typedef typename mpl::if_<
typename Directed::is_directed_t, DirInEdgeIter, UnDirInEdgeIter
>::type unfiltered_in_edge_iter;
typedef detail::adj_matrix_edge_iter<
Directed, MatrixIter, size_type, edge_descriptor
> unfiltered_edge_iter;
public:
// IncidenceGraph concept required types
typedef filter_iterator<detail::does_edge_exist, unfiltered_out_edge_iter>
out_edge_iterator;
typedef size_type degree_size_type;
// BidirectionalGraph required types
typedef filter_iterator<detail::does_edge_exist, unfiltered_in_edge_iter>
in_edge_iterator;
// AdjacencyGraph required types
typedef typename adjacency_iterator_generator<self,
vertex_descriptor, out_edge_iterator>::type adjacency_iterator;
// VertexListGraph required types
typedef size_type vertices_size_type;
typedef integer_range<vertex_descriptor> VertexList;
typedef typename VertexList::iterator vertex_iterator;
// EdgeListGraph required types
typedef size_type edges_size_type;
typedef filter_iterator<
detail::does_edge_exist, unfiltered_edge_iter
> edge_iterator;
// PropertyGraph required types
typedef adjacency_matrix_class_tag graph_tag;
// Constructor required by MutableGraph
adjacency_matrix(vertices_size_type n_vertices,
const GraphProperty& p = GraphProperty())
: m_matrix(Directed::is_directed ?
(n_vertices * n_vertices)
: (n_vertices * (n_vertices + 1) / 2)),
m_vertex_set(0, n_vertices),
m_vertex_properties(n_vertices),
m_num_edges(0),
m_property(p) { }
template <typename EdgeIterator>
adjacency_matrix(EdgeIterator first,
EdgeIterator last,
vertices_size_type n_vertices,
const GraphProperty& p = GraphProperty())
: m_matrix(Directed::is_directed ?
(n_vertices * n_vertices)
: (n_vertices * (n_vertices + 1) / 2)),
m_vertex_set(0, n_vertices),
m_vertex_properties(n_vertices),
m_num_edges(0),
m_property(p)
{
for (; first != last; ++first) {
add_edge(first->first, first->second, *this);
}
}
template <typename EdgeIterator, typename EdgePropertyIterator>
adjacency_matrix(EdgeIterator first,
EdgeIterator last,
EdgePropertyIterator ep_iter,
vertices_size_type n_vertices,
const GraphProperty& p = GraphProperty())
: m_matrix(Directed::is_directed ?
(n_vertices * n_vertices)
: (n_vertices * (n_vertices + 1) / 2)),
m_vertex_set(0, n_vertices),
m_vertex_properties(n_vertices),
m_num_edges(0),
m_property(p)
{
for (; first != last; ++first, ++ep_iter) {
add_edge(first->first, first->second, *ep_iter, *this);
}
}
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
// Directly access a vertex or edge bundle
vertex_bundled& operator[](vertex_descriptor v)
{ return get(vertex_bundle, *this)[v]; }
const vertex_bundled& operator[](vertex_descriptor v) const
{ return get(vertex_bundle, *this)[v]; }
edge_bundled& operator[](edge_descriptor e)
{ return get(edge_bundle, *this)[e]; }
const edge_bundled& operator[](edge_descriptor e) const
{ return get(edge_bundle, *this)[e]; }
graph_bundled& operator[](graph_bundle_t)
{ return get_property(*this); }
const graph_bundled& operator[](graph_bundle_t) const
{ return get_property(*this); }
#endif
//private: if friends worked, these would be private
typename Matrix::const_reference
get_edge(vertex_descriptor u, vertex_descriptor v) const {
if (Directed::is_directed)
return m_matrix[u * m_vertex_set.size() + v];
else {
if (v > u)
std::swap(u, v);
return m_matrix[u * (u + 1)/2 + v];
}
}
typename Matrix::reference
get_edge(vertex_descriptor u, vertex_descriptor v) {
if (Directed::is_directed)
return m_matrix[u * m_vertex_set.size() + v];
else {
if (v > u)
std::swap(u, v);
return m_matrix[u * (u + 1)/2 + v];
}
}
Matrix m_matrix;
VertexList m_vertex_set;
std::vector<vertex_property_type> m_vertex_properties;
size_type m_num_edges;
graph_property_type m_property;
};
//=========================================================================
// Functions required by the AdjacencyMatrix concept
template <typename D, typename VP, typename EP, typename GP, typename A>
std::pair<typename adjacency_matrix<D,VP,EP,GP,A>::edge_descriptor,
bool>
edge(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor u,
typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor v,
const adjacency_matrix<D,VP,EP,GP,A>& g)
{
bool exists = detail::get_edge_exists(g.get_edge(u,v), 0);
typename adjacency_matrix<D,VP,EP,GP,A>::edge_descriptor
e(exists, u, v, &detail::get_edge_property(g.get_edge(u,v)));
return std::make_pair(e, exists);
}
//=========================================================================
// Functions required by the IncidenceGraph concept
// O(1)
template <typename VP, typename EP, typename GP, typename A>
std::pair<typename adjacency_matrix<directedS,VP,EP,GP,A>::out_edge_iterator,
typename adjacency_matrix<directedS,VP,EP,GP,A>::out_edge_iterator>
out_edges
(typename adjacency_matrix<directedS,VP,EP,GP,A>::vertex_descriptor u,
const adjacency_matrix<directedS,VP,EP,GP,A>& g_)
{
typedef adjacency_matrix<directedS,VP,EP,GP,A> Graph;
Graph& g = const_cast<Graph&>(g_);
typename Graph::vertices_size_type offset = u * g.m_vertex_set.size();
typename Graph::MatrixIter f = g.m_matrix.begin() + offset;
typename Graph::MatrixIter l = f + g.m_vertex_set.size();
typename Graph::unfiltered_out_edge_iter
first(f, u, g.m_vertex_set.size())
, last(l, u, g.m_vertex_set.size());
detail::does_edge_exist pred;
typedef typename Graph::out_edge_iterator out_edge_iterator;
return std::make_pair(out_edge_iterator(pred, first, last),
out_edge_iterator(pred, last, last));
}
// O(1)
template <typename VP, typename EP, typename GP, typename A>
std::pair<
typename adjacency_matrix<undirectedS,VP,EP,GP,A>::out_edge_iterator,
typename adjacency_matrix<undirectedS,VP,EP,GP,A>::out_edge_iterator>
out_edges
(typename adjacency_matrix<undirectedS,VP,EP,GP,A>::vertex_descriptor u,
const adjacency_matrix<undirectedS,VP,EP,GP,A>& g_)
{
typedef adjacency_matrix<undirectedS,VP,EP,GP,A> Graph;
Graph& g = const_cast<Graph&>(g_);
typename Graph::vertices_size_type offset = u * (u + 1) / 2;
typename Graph::MatrixIter f = g.m_matrix.begin() + offset;
typename Graph::MatrixIter l = g.m_matrix.end();
typename Graph::unfiltered_out_edge_iter
first(f, u, g.m_vertex_set.size())
, last(l, u, g.m_vertex_set.size());
detail::does_edge_exist pred;
typedef typename Graph::out_edge_iterator out_edge_iterator;
return std::make_pair(out_edge_iterator(pred, first, last),
out_edge_iterator(pred, last, last));
}
// O(N)
template <typename D, typename VP, typename EP, typename GP, typename A>
typename adjacency_matrix<D,VP,EP,GP,A>::degree_size_type
out_degree(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor u,
const adjacency_matrix<D,VP,EP,GP,A>& g)
{
typename adjacency_matrix<D,VP,EP,GP,A>::degree_size_type n = 0;
typename adjacency_matrix<D,VP,EP,GP,A>::out_edge_iterator f, l;
for (boost::tie(f, l) = out_edges(u, g); f != l; ++f)
++n;
return n;
}
// O(1)
template <typename D, typename VP, typename EP, typename GP, typename A,
typename Dir, typename Vertex>
typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor
source(const detail::matrix_edge_desc_impl<Dir,Vertex>& e,
const adjacency_matrix<D,VP,EP,GP,A>&)
{
return e.m_source;
}
// O(1)
template <typename D, typename VP, typename EP, typename GP, typename A,
typename Dir, typename Vertex>
typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor
target(const detail::matrix_edge_desc_impl<Dir,Vertex>& e,
const adjacency_matrix<D,VP,EP,GP,A>&)
{
return e.m_target;
}
//=========================================================================
// Functions required by the BidirectionalGraph concept
// O(1)
template <typename VP, typename EP, typename GP, typename A>
std::pair<typename adjacency_matrix<directedS,VP,EP,GP,A>::in_edge_iterator,
typename adjacency_matrix<directedS,VP,EP,GP,A>::in_edge_iterator>
in_edges
(typename adjacency_matrix<directedS,VP,EP,GP,A>::vertex_descriptor u,
const adjacency_matrix<directedS,VP,EP,GP,A>& g_)
{
typedef adjacency_matrix<directedS,VP,EP,GP,A> Graph;
Graph& g = const_cast<Graph&>(g_);
typename Graph::MatrixIter f = g.m_matrix.begin() + u;
typename Graph::MatrixIter l = g.m_matrix.end();
typename Graph::unfiltered_in_edge_iter
first(f, l, u, g.m_vertex_set.size())
, last(l, l, u, g.m_vertex_set.size());
detail::does_edge_exist pred;
typedef typename Graph::in_edge_iterator in_edge_iterator;
return std::make_pair(in_edge_iterator(pred, first, last),
in_edge_iterator(pred, last, last));
}
// O(1)
template <typename VP, typename EP, typename GP, typename A>
std::pair<
typename adjacency_matrix<undirectedS,VP,EP,GP,A>::in_edge_iterator,
typename adjacency_matrix<undirectedS,VP,EP,GP,A>::in_edge_iterator>
in_edges
(typename adjacency_matrix<undirectedS,VP,EP,GP,A>::vertex_descriptor u,
const adjacency_matrix<undirectedS,VP,EP,GP,A>& g_)
{
typedef adjacency_matrix<undirectedS,VP,EP,GP,A> Graph;
Graph& g = const_cast<Graph&>(g_);
typename Graph::vertices_size_type offset = u * (u + 1) / 2;
typename Graph::MatrixIter f = g.m_matrix.begin() + offset;
typename Graph::MatrixIter l = g.m_matrix.end();
typename Graph::unfiltered_in_edge_iter
first(f, u, g.m_vertex_set.size())
, last(l, u, g.m_vertex_set.size());
detail::does_edge_exist pred;
typedef typename Graph::in_edge_iterator in_edge_iterator;
return std::make_pair(in_edge_iterator(pred, first, last),
in_edge_iterator(pred, last, last));
}
// O(N)
template <typename D, typename VP, typename EP, typename GP, typename A>
typename adjacency_matrix<D,VP,EP,GP,A>::degree_size_type
in_degree(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor u,
const adjacency_matrix<D,VP,EP,GP,A>& g)
{
typename adjacency_matrix<D,VP,EP,GP,A>::degree_size_type n = 0;
typename adjacency_matrix<D,VP,EP,GP,A>::in_edge_iterator f, l;
for (boost::tie(f, l) = in_edges(u, g); f != l; ++f)
++n;
return n;
}
//=========================================================================
// Functions required by the AdjacencyGraph concept
template <typename D, typename VP, typename EP, typename GP, typename A>
std::pair<typename adjacency_matrix<D,VP,EP,GP,A>::adjacency_iterator,
typename adjacency_matrix<D,VP,EP,GP,A>::adjacency_iterator>
adjacent_vertices
(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor u,
const adjacency_matrix<D,VP,EP,GP,A>& g_)
{
typedef adjacency_matrix<D,VP,EP,GP,A> Graph;
const Graph& cg = static_cast<const Graph&>(g_);
Graph& g = const_cast<Graph&>(cg);
typedef typename Graph::adjacency_iterator adjacency_iterator;
typename Graph::out_edge_iterator first, last;
boost::tie(first, last) = out_edges(u, g);
return std::make_pair(adjacency_iterator(first, &g),
adjacency_iterator(last, &g));
}
//=========================================================================
// Functions required by the VertexListGraph concept
template <typename D, typename VP, typename EP, typename GP, typename A>
std::pair<typename adjacency_matrix<D,VP,EP,GP,A>::vertex_iterator,
typename adjacency_matrix<D,VP,EP,GP,A>::vertex_iterator>
vertices(const adjacency_matrix<D,VP,EP,GP,A>& g_) {
typedef adjacency_matrix<D,VP,EP,GP,A> Graph;
Graph& g = const_cast<Graph&>(g_);
return std::make_pair(g.m_vertex_set.begin(), g.m_vertex_set.end());
}
template <typename D, typename VP, typename EP, typename GP, typename A>
typename adjacency_matrix<D,VP,EP,GP,A>::vertices_size_type
num_vertices(const adjacency_matrix<D,VP,EP,GP,A>& g) {
return g.m_vertex_set.size();
}
//=========================================================================
// Functions required by the EdgeListGraph concept
template <typename D, typename VP, typename EP, typename GP, typename A>
std::pair<typename adjacency_matrix<D,VP,EP,GP,A>::edge_iterator,
typename adjacency_matrix<D,VP,EP,GP,A>::edge_iterator>
edges(const adjacency_matrix<D,VP,EP,GP,A>& g_)
{
typedef adjacency_matrix<D,VP,EP,GP,A> Graph;
Graph& g = const_cast<Graph&>(g_);
typename Graph::unfiltered_edge_iter
first(g.m_matrix.begin(), g.m_matrix.begin(),
g.m_vertex_set.size()),
last(g.m_matrix.end(), g.m_matrix.begin(),
g.m_vertex_set.size());
detail::does_edge_exist pred;
typedef typename Graph::edge_iterator edge_iterator;
return std::make_pair(edge_iterator(pred, first, last),
edge_iterator(pred, last, last));
}
// O(1)
template <typename D, typename VP, typename EP, typename GP, typename A>
typename adjacency_matrix<D,VP,EP,GP,A>::edges_size_type
num_edges(const adjacency_matrix<D,VP,EP,GP,A>& g)
{
return g.m_num_edges;
}
//=========================================================================
// Functions required by the MutableGraph concept
// O(1)
template <typename D, typename VP, typename EP, typename GP, typename A,
typename EP2>
std::pair<typename adjacency_matrix<D,VP,EP,GP,A>::edge_descriptor, bool>
add_edge(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor u,
typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor v,
const EP2& ep,
adjacency_matrix<D,VP,EP,GP,A>& g)
{
typedef typename adjacency_matrix<D,VP,EP,GP,A>::edge_descriptor
edge_descriptor;
if (detail::get_edge_exists(g.get_edge(u,v), 0) == false) {
++(g.m_num_edges);
detail::set_edge_property(g.get_edge(u,v), EP(ep), 0);
detail::set_edge_exists(g.get_edge(u,v), true, 0);
return std::make_pair
(edge_descriptor(true, u, v, &detail::get_edge_property(g.get_edge(u,v))),
true);
} else
return std::make_pair
(edge_descriptor(true, u, v, &detail::get_edge_property(g.get_edge(u,v))),
false);
}
// O(1)
template <typename D, typename VP, typename EP, typename GP, typename A>
std::pair<typename adjacency_matrix<D,VP,EP,GP,A>::edge_descriptor, bool>
add_edge(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor u,
typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor v,
adjacency_matrix<D,VP,EP,GP,A>& g)
{
EP ep;
return add_edge(u, v, ep, g);
}
// O(1)
template <typename D, typename VP, typename EP, typename GP, typename A>
void
remove_edge(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor u,
typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor v,
adjacency_matrix<D,VP,EP,GP,A>& g)
{
// Don'remove the edge unless it already exists.
if(detail::get_edge_exists(g.get_edge(u,v), 0)) {
--(g.m_num_edges);
detail::set_edge_exists(g.get_edge(u,v), false, 0);
}
}
// O(1)
template <typename D, typename VP, typename EP, typename GP, typename A>
void
remove_edge(typename adjacency_matrix<D,VP,EP,GP,A>::edge_descriptor e,
adjacency_matrix<D,VP,EP,GP,A>& g)
{
remove_edge(source(e, g), target(e, g), g);
}
template <typename D, typename VP, typename EP, typename GP, typename A>
inline typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor
add_vertex(adjacency_matrix<D,VP,EP,GP,A>& g) {
// UNDER CONSTRUCTION
BOOST_ASSERT(false);
return *vertices(g).first;
}
template <typename D, typename VP, typename EP, typename GP, typename A,
typename VP2>
inline typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor
add_vertex(const VP2& /*vp*/, adjacency_matrix<D,VP,EP,GP,A>& g) {
// UNDER CONSTRUCTION
BOOST_ASSERT(false);
return *vertices(g).first;
}
template <typename D, typename VP, typename EP, typename GP, typename A>
inline void
remove_vertex(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor /*u*/,
adjacency_matrix<D,VP,EP,GP,A>& /*g*/)
{
// UNDER CONSTRUCTION
BOOST_ASSERT(false);
}
// O(V)
template <typename VP, typename EP, typename GP, typename A>
void
clear_vertex
(typename adjacency_matrix<directedS,VP,EP,GP,A>::vertex_descriptor u,
adjacency_matrix<directedS,VP,EP,GP,A>& g)
{
typename adjacency_matrix<directedS,VP,EP,GP,A>::vertex_iterator
vi, vi_end;
for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
remove_edge(u, *vi, g);
for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
remove_edge(*vi, u, g);
}
// O(V)
template <typename VP, typename EP, typename GP, typename A>
void
clear_vertex
(typename adjacency_matrix<undirectedS,VP,EP,GP,A>::vertex_descriptor u,
adjacency_matrix<undirectedS,VP,EP,GP,A>& g)
{
typename adjacency_matrix<undirectedS,VP,EP,GP,A>::vertex_iterator
vi, vi_end;
for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
remove_edge(u, *vi, g);
}
//=========================================================================
// Functions required by the PropertyGraph concept
// O(1)
template <typename D, typename VP, typename EP, typename GP, typename A,
typename Tag, typename Value>
inline void
set_property(adjacency_matrix<D,VP,EP,GP,A>& g, Tag, const Value& value)
{
get_property_value(g.m_property, Tag()) = value;
}
template <typename D, typename VP, typename EP, typename GP, typename A,
typename Tag>
inline typename graph_property<adjacency_matrix<D,VP,EP,GP,A>, Tag>::type&
get_property(adjacency_matrix<D,VP,EP,GP,A>& g, Tag)
{
return get_property_value(g.m_property, Tag());
}
template <typename D, typename VP, typename EP, typename GP, typename A,
typename Tag>
inline const typename graph_property<adjacency_matrix<D,VP,EP,GP,A>, Tag>::type&
get_property(const adjacency_matrix<D,VP,EP,GP,A>& g, Tag)
{
return get_property_value(g.m_property, Tag());
}
//=========================================================================
// Vertex Property Map
template <typename GraphPtr, typename Vertex, typename T, typename R,
typename Tag>
class adj_matrix_vertex_property_map
: public put_get_helper<R,
adj_matrix_vertex_property_map<GraphPtr, Vertex, T, R, Tag> >
{
public:
typedef T value_type;
typedef R reference;
typedef Vertex key_type;
typedef boost::lvalue_property_map_tag category;
adj_matrix_vertex_property_map() { }
adj_matrix_vertex_property_map(GraphPtr g) : m_g(g) { }
inline reference operator[](key_type v) const {
return get_property_value(m_g->m_vertex_properties[v], Tag());
}
GraphPtr m_g;
};
template <class Property, class Vertex>
struct adj_matrix_vertex_id_map
: public boost::put_get_helper<Vertex,
adj_matrix_vertex_id_map<Property, Vertex> >
{
typedef Vertex value_type;
typedef Vertex reference;
typedef Vertex key_type;
typedef boost::readable_property_map_tag category;
adj_matrix_vertex_id_map() { }
template <class Graph>
inline adj_matrix_vertex_id_map(const Graph&) { }
inline value_type operator[](key_type v) const { return v; }
};
namespace detail {
struct adj_matrix_any_vertex_pa {
template <class Tag, class Graph, class Property>
struct bind_ {
typedef typename property_value<Property,Tag>::type Value;
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
typedef adj_matrix_vertex_property_map<Graph*, Vertex, Value, Value&,
Tag> type;
typedef adj_matrix_vertex_property_map<const Graph*, Vertex, Value,
const Value&, Tag> const_type;
};
};
struct adj_matrix_id_vertex_pa {
template <class Tag, class Graph, class Property>
struct bind_ {
typedef typename Graph::vertex_descriptor Vertex;
typedef adj_matrix_vertex_id_map<Property, Vertex> type;
typedef adj_matrix_vertex_id_map<Property, Vertex> const_type;
};
};
template <class Tag>
struct adj_matrix_choose_vertex_pa_helper {
typedef adj_matrix_any_vertex_pa type;
};
template <>
struct adj_matrix_choose_vertex_pa_helper<vertex_index_t> {
typedef adj_matrix_id_vertex_pa type;
};
template <class Tag, class Graph, class Property>
struct adj_matrix_choose_vertex_pa {
typedef typename adj_matrix_choose_vertex_pa_helper<Tag>::type Helper;
typedef typename Helper::template bind_<Tag,Graph,Property> Bind;
typedef typename Bind::type type;
typedef typename Bind::const_type const_type;
};
struct adj_matrix_vertex_property_selector {
template <class Graph, class Property, class Tag>
struct bind_ {
typedef adj_matrix_choose_vertex_pa<Tag,Graph,Property> Choice;
typedef typename Choice::type type;
typedef typename Choice::const_type const_type;
};
};
} // namespace detail
template <>
struct vertex_property_selector<adjacency_matrix_class_tag> {
typedef detail::adj_matrix_vertex_property_selector type;
};
//=========================================================================
// Edge Property Map
template <typename Directed, typename Property, typename Vertex,
typename T, typename R, typename Tag>
class adj_matrix_edge_property_map
: public put_get_helper<R,
adj_matrix_edge_property_map<Directed, Property, Vertex, T, R, Tag> >
{
public:
typedef T value_type;
typedef R reference;
typedef detail::matrix_edge_desc_impl<Directed, Vertex> key_type;
typedef boost::lvalue_property_map_tag category;
inline reference operator[](key_type e) const {
Property& p = *(Property*)e.get_property();
return get_property_value(p, Tag());
}
};
struct adj_matrix_edge_property_selector {
template <class Graph, class Property, class Tag>
struct bind_ {
typedef typename property_value<Property,Tag>::type T;
typedef typename Graph::vertex_descriptor Vertex;
typedef adj_matrix_edge_property_map<typename Graph::directed_category,
Property, Vertex, T, T&, Tag> type;
typedef adj_matrix_edge_property_map<typename Graph::directed_category,
Property, Vertex, T, const T&, Tag> const_type;
};
};
template <>
struct edge_property_selector<adjacency_matrix_class_tag> {
typedef adj_matrix_edge_property_selector type;
};
//=========================================================================
// Functions required by PropertyGraph
namespace detail {
template <typename Property, typename D, typename VP, typename EP,
typename GP, typename A>
typename boost::property_map<adjacency_matrix<D,VP,EP,GP,A>,
Property>::type
get_dispatch(adjacency_matrix<D,VP,EP,GP,A>& g, Property,
vertex_property_tag)
{
typedef adjacency_matrix<D,VP,EP,GP,A> Graph;
typedef typename boost::property_map<adjacency_matrix<D,VP,EP,GP,A>,
Property>::type PA;
return PA(&g);
}
template <typename Property, typename D, typename VP, typename EP,
typename GP, typename A>
typename boost::property_map<adjacency_matrix<D,VP,EP,GP,A>,
Property>::type
get_dispatch(adjacency_matrix<D,VP,EP,GP,A>&, Property,
edge_property_tag)
{
typedef typename boost::property_map<adjacency_matrix<D,VP,EP,GP,A>,
Property>::type PA;
return PA();
}
template <typename Property, typename D, typename VP, typename EP,
typename GP, typename A>
typename boost::property_map<adjacency_matrix<D,VP,EP,GP,A>,
Property>::const_type
get_dispatch(const adjacency_matrix<D,VP,EP,GP,A>& g, Property,
vertex_property_tag)
{
typedef adjacency_matrix<D,VP,EP,GP,A> Graph;
typedef typename boost::property_map<adjacency_matrix<D,VP,EP,GP,A>,
Property>::const_type PA;
return PA(&g);
}
template <typename Property, typename D, typename VP, typename EP,
typename GP, typename A>
typename boost::property_map<adjacency_matrix<D,VP,EP,GP,A>,
Property>::const_type
get_dispatch(const adjacency_matrix<D,VP,EP,GP,A>&, Property,
edge_property_tag)
{
typedef typename boost::property_map<adjacency_matrix<D,VP,EP,GP,A>,
Property>::const_type PA;
return PA();
}
} // namespace detail
template <typename Property, typename D, typename VP, typename EP,
typename GP, typename A>
inline
typename property_map<adjacency_matrix<D,VP,EP,GP,A>, Property>::type
get(Property p, adjacency_matrix<D,VP,EP,GP,A>& g)
{
typedef typename property_kind<Property>::type Kind;
return detail::get_dispatch(g, p, Kind());
}
template <typename Property, typename D, typename VP, typename EP,
typename GP, typename A>
inline
typename property_map<adjacency_matrix<D,VP,EP,GP,A>, Property>::const_type
get(Property p, const adjacency_matrix<D,VP,EP,GP,A>& g)
{
typedef typename property_kind<Property>::type Kind;
return detail::get_dispatch(g, p, Kind());
}
template <typename Property, typename D, typename VP, typename EP,
typename GP, typename A, typename Key>
inline
typename property_traits<
typename property_map<adjacency_matrix<D,VP,EP,GP,A>, Property>::const_type
>::value_type
get(Property p, const adjacency_matrix<D,VP,EP,GP,A>& g,
const Key& key)
{
return get(get(p, g), key);
}
template <typename Property, typename D, typename VP, typename EP,
typename GP, typename A, typename Key, typename Value>
inline void
put(Property p, adjacency_matrix<D,VP,EP,GP,A>& g,
const Key& key, const Value& value)
{
typedef adjacency_matrix<D,VP,EP,GP,A> Graph;
typedef typename boost::property_map<Graph, Property>::type Map;
Map pmap = get(p, g);
put(pmap, key, value);
}
//=========================================================================
// Other Functions
template <typename D, typename VP, typename EP, typename GP, typename A>
typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor
vertex(typename adjacency_matrix<D,VP,EP,GP,A>::vertices_size_type n,
const adjacency_matrix<D,VP,EP,GP,A>&)
{
return n;
}
// Support for bundled properties
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
template <typename Directed, typename VertexProperty, typename EdgeProperty, typename GraphProperty,
typename Allocator, typename T, typename Bundle>
inline
typename property_map<adjacency_matrix<Directed, VertexProperty, EdgeProperty, GraphProperty, Allocator>,
T Bundle::*>::type
get(T Bundle::* p, adjacency_matrix<Directed, VertexProperty, EdgeProperty, GraphProperty, Allocator>& g)
{
typedef typename property_map<adjacency_matrix<Directed, VertexProperty, EdgeProperty, GraphProperty, Allocator>,
T Bundle::*>::type
result_type;
return result_type(&g, p);
}
template <typename Directed, typename VertexProperty, typename EdgeProperty, typename GraphProperty,
typename Allocator, typename T, typename Bundle>
inline
typename property_map<adjacency_matrix<Directed, VertexProperty, EdgeProperty, GraphProperty, Allocator>,
T Bundle::*>::const_type
get(T Bundle::* p, adjacency_matrix<Directed, VertexProperty, EdgeProperty, GraphProperty, Allocator> const & g)
{
typedef typename property_map<adjacency_matrix<Directed, VertexProperty, EdgeProperty, GraphProperty, Allocator>,
T Bundle::*>::const_type
result_type;
return result_type(&g, p);
}
template <typename Directed, typename VertexProperty, typename EdgeProperty, typename GraphProperty,
typename Allocator, typename T, typename Bundle, typename Key>
inline T
get(T Bundle::* p, adjacency_matrix<Directed, VertexProperty, EdgeProperty, GraphProperty, Allocator> const & g,
const Key& key)
{
return get(get(p, g), key);
}
template <typename Directed, typename VertexProperty, typename EdgeProperty, typename GraphProperty,
typename Allocator, typename T, typename Bundle, typename Key>
inline void
put(T Bundle::* p, adjacency_matrix<Directed, VertexProperty, EdgeProperty, GraphProperty, Allocator>& g,
const Key& key, const T& value)
{
put(get(p, g), key, value);
}
#endif
#define ADJMAT_PARAMS \
typename D, typename VP, typename EP, typename GP, typename A
#define ADJMAT adjacency_matrix<D,VP,EP,GP,A>
template <ADJMAT_PARAMS>
struct graph_mutability_traits<ADJMAT> {
typedef mutable_edge_property_graph_tag category;
};
#undef ADJMAT_PARAMS
#undef ADJMAT
} // namespace boost
#endif // BOOST_ADJACENCY_MATRIX_HPP