#ifndef UE2_GRAPH_H
#define UE2_GRAPH_H
#include "ue2common.h"
#include "util/graph_range.h"
#include "util/noncopyable.h"
#include "util/operators.h"
#include <boost/graph/properties.hpp>
#include <boost/pending/property.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <functional>
#include <tuple>
#include <type_traits>
#include <utility>
namespace ue2 {
namespace graph_detail {
class graph_base : noncopyable {
};
struct default_edge_property {
size_t index;
};
struct default_vertex_property {
size_t index;
};
template<typename Graph>
class vertex_descriptor : totally_ordered<vertex_descriptor<Graph>> {
using vertex_node = typename Graph::vertex_node;
public:
vertex_descriptor() : p(nullptr), serial(0) {}
explicit vertex_descriptor(vertex_node *pp) : p(pp), serial(pp->serial) {}
operator bool() const { return p; }
bool operator<(const vertex_descriptor b) const {
if (p && b.p) {
assert(p == b.p || serial != b.serial);
return serial < b.serial;
} else {
return p < b.p;
}
}
bool operator==(const vertex_descriptor b) const { return p == b.p; }
size_t hash() const {
return std::hash<u64a>()(serial);
}
private:
vertex_node *raw(void) { return p; }
vertex_node *p;
u64a serial;
friend Graph;
};
template<typename Graph>
class edge_descriptor : totally_ordered<edge_descriptor<Graph>> {
using edge_node = typename Graph::edge_node;
public:
edge_descriptor() : p(nullptr), serial(0) {}
explicit edge_descriptor(edge_node *pp) : p(pp), serial(pp->serial) {}
edge_descriptor(const std::pair<edge_descriptor, bool> &tup)
: p(tup.first.p), serial(tup.first.serial) {
assert(tup.second == (bool)tup.first);
}
operator bool() const { return p; }
bool operator<(const edge_descriptor b) const {
if (p && b.p) {
assert(p == b.p || serial != b.serial);
return serial < b.serial;
} else {
return p < b.p;
}
}
bool operator==(const edge_descriptor b) const { return p == b.p; }
size_t hash() const {
return std::hash<u64a>()(serial);
}
private:
edge_node *raw(void) { return p; }
edge_node *p;
u64a serial;
friend Graph;
};
}
template<typename Graph,
typename VertexPropertyType = graph_detail::default_vertex_property,
typename EdgePropertyType = graph_detail::default_edge_property>
class ue2_graph : graph_detail::graph_base {
private:
struct in_edge_tag { };
struct out_edge_tag { };
struct vertex_node;
using out_edge_hook
= boost::intrusive::list_base_hook<boost::intrusive::tag<out_edge_tag> >;
using in_edge_hook
= boost::intrusive::list_base_hook<boost::intrusive::tag<in_edge_tag>,
boost::intrusive::link_mode<boost::intrusive::normal_link> >;
struct edge_node : public out_edge_hook, public in_edge_hook {
explicit edge_node(u64a serial_in) : serial(serial_in) { }
vertex_node *source = nullptr;
vertex_node *target = nullptr;
const u64a serial;
EdgePropertyType props;
};
template<typename hook_type> using vertex_edge_list
= boost::intrusive::list<edge_node,
boost::intrusive::base_hook<hook_type> >;
struct vertex_node : public boost::intrusive::list_base_hook<> {
explicit vertex_node(u64a serial_in) : serial(serial_in) { }
VertexPropertyType props;
const u64a serial;
vertex_edge_list<in_edge_hook> in_edge_list;
vertex_edge_list<out_edge_hook> out_edge_list;
~vertex_node() {
out_edge_list.clear_and_dispose(delete_disposer());
}
};
struct delete_disposer {
template<typename T> void operator()(const T *d) const { delete d; }
};
struct in_edge_disposer {
void operator()(edge_node *e) const {
vertex_node *u = e->source;
u->out_edge_list.erase(u->out_edge_list.iterator_to(*e));
delete e;
}
};
struct out_edge_disposer {
void operator()(edge_node *e) const {
vertex_node *v = e->target;
v->in_edge_list.erase(v->in_edge_list.iterator_to(*e));
delete e;
}
};
using vertices_list_type
= boost::intrusive::list<vertex_node,
boost::intrusive::base_hook<boost::intrusive::list_base_hook<> > >;
vertices_list_type vertices_list;
protected:
static const size_t N_SPECIAL_VERTICES = 0;
size_t next_vertex_index = 0;
size_t next_edge_index = 0;
private:
size_t graph_edge_count = 0;
u64a next_serial = 0;
u64a new_serial() {
u64a serial = next_serial++;
if (!next_serial) {
throw std::overflow_error("too many graph edges/vertices created");
}
return serial;
}
public:
using vertex_descriptor = graph_detail::vertex_descriptor<ue2_graph>;
using edge_descriptor = graph_detail::edge_descriptor<ue2_graph>;
friend vertex_descriptor;
friend edge_descriptor;
using vertices_size_type = typename vertices_list_type::size_type;
using degree_size_type
= typename vertex_edge_list<out_edge_hook>::size_type;
using edges_size_type = size_t;
using vertex_property_type = VertexPropertyType;
using edge_property_type = EdgePropertyType;
using graph_bundled = boost::no_property;
using vertex_bundled = VertexPropertyType;
using edge_bundled = EdgePropertyType;
private:
template<typename BundleType, typename dummy = void>
struct bundle_key_type {
};
template<typename dummy>
struct bundle_key_type<VertexPropertyType, dummy> {
using type = vertex_descriptor;
};
template<typename dummy>
struct bundle_key_type<EdgePropertyType, dummy> {
using type = edge_descriptor;
};
public:
class out_edge_iterator : public boost::iterator_adaptor<
out_edge_iterator,
typename vertex_edge_list<out_edge_hook>::const_iterator,
edge_descriptor,
boost::bidirectional_traversal_tag,
edge_descriptor> {
using super = typename out_edge_iterator::iterator_adaptor_;
public:
out_edge_iterator() : super() { }
explicit out_edge_iterator(
typename vertex_edge_list<out_edge_hook>::const_iterator it)
: super(it) { }
edge_descriptor dereference() const {
return edge_descriptor(const_cast<edge_node *>(&*super::base()));
}
};
class in_edge_iterator : public boost::iterator_adaptor<
in_edge_iterator,
typename vertex_edge_list<in_edge_hook>::const_iterator,
edge_descriptor,
boost::bidirectional_traversal_tag,
edge_descriptor> {
using super = typename in_edge_iterator::iterator_adaptor_;
public:
in_edge_iterator() : super() { }
explicit in_edge_iterator(
typename vertex_edge_list<in_edge_hook>::const_iterator it)
: super(it) { }
edge_descriptor dereference() const {
return edge_descriptor(const_cast<edge_node *>(&*super::base()));
}
};
class adjacency_iterator : public boost::iterator_adaptor<
adjacency_iterator,
out_edge_iterator,
vertex_descriptor,
boost::bidirectional_traversal_tag,
vertex_descriptor> {
using super = typename adjacency_iterator::iterator_adaptor_;
public:
adjacency_iterator(out_edge_iterator a) : super(std::move(a)) { }
adjacency_iterator() { }
vertex_descriptor dereference() const {
return vertex_descriptor(super::base()->p->target);
}
};
class inv_adjacency_iterator : public boost::iterator_adaptor<
inv_adjacency_iterator,
in_edge_iterator,
vertex_descriptor,
boost::bidirectional_traversal_tag,
vertex_descriptor> {
using super = typename inv_adjacency_iterator::iterator_adaptor_;
public:
inv_adjacency_iterator(in_edge_iterator a) : super(std::move(a)) { }
inv_adjacency_iterator() { }
vertex_descriptor dereference() const {
return vertex_descriptor(super::base()->p->source);
}
};
class vertex_iterator : public boost::iterator_adaptor<
vertex_iterator,
typename vertices_list_type::const_iterator,
vertex_descriptor,
boost::bidirectional_traversal_tag,
vertex_descriptor> {
using super = typename vertex_iterator::iterator_adaptor_;
public:
vertex_iterator() : super() { }
explicit vertex_iterator(typename vertices_list_type::const_iterator it)
: super(it) { }
vertex_descriptor dereference() const {
return vertex_descriptor(
const_cast<vertex_node *>(&*super::base()));
}
};
class edge_iterator : public boost::iterator_facade<
edge_iterator,
edge_descriptor,
boost::forward_traversal_tag,
edge_descriptor> {
public:
using main_base_iter_type = vertex_iterator;
using aux_base_iter_type = out_edge_iterator;
edge_iterator(main_base_iter_type b, main_base_iter_type e)
: main(std::move(b)), main_end(std::move(e)) {
if (main == main_end) {
return;
}
std::tie(aux, aux_end) = out_edges_impl(*main);
while (aux == aux_end) {
++main;
if (main == main_end) {
break;
}
std::tie(aux, aux_end) = out_edges_impl(*main);
}
}
edge_iterator() { }
friend class boost::iterator_core_access;
void increment() {
++aux;
while (aux == aux_end) {
++main;
if (main == main_end) {
break;
}
std::tie(aux, aux_end) = out_edges_impl(*main);
}
}
bool equal(const edge_iterator &other) const {
return main == other.main && (main == main_end || aux == other.aux);
}
edge_descriptor dereference() const {
return *aux;
}
main_base_iter_type main;
main_base_iter_type main_end;
aux_base_iter_type aux;
aux_base_iter_type aux_end;
};
public:
static
vertex_descriptor null_vertex() { return vertex_descriptor(); }
vertex_descriptor add_vertex_impl() {
vertex_node *v = new vertex_node(new_serial());
v->props.index = next_vertex_index++;
vertices_list.push_back(*v);
return vertex_descriptor(v);
}
void remove_vertex_impl(vertex_descriptor v) {
vertex_node *vv = v.raw();
assert(vv->in_edge_list.empty());
assert(vv->out_edge_list.empty());
vertices_list.erase_and_dispose(vertices_list.iterator_to(*vv),
delete_disposer());
}
void clear_in_edges_impl(vertex_descriptor v) {
graph_edge_count -= v.raw()->in_edge_list.size();
v.raw()->in_edge_list.clear_and_dispose(in_edge_disposer());
}
void clear_out_edges_impl(vertex_descriptor v) {
graph_edge_count -= v.raw()->out_edge_list.size();
v.raw()->out_edge_list.clear_and_dispose(out_edge_disposer());
}
static
vertex_descriptor source_impl(edge_descriptor e) {
return vertex_descriptor(e.raw()->source);
}
static
vertex_descriptor target_impl(edge_descriptor e) {
return vertex_descriptor(e.raw()->target);
}
static
degree_size_type out_degree_impl(vertex_descriptor v) {
return v.raw()->out_edge_list.size();
}
static
std::pair<out_edge_iterator, out_edge_iterator>
out_edges_impl(vertex_descriptor v) {
return {out_edge_iterator(v.raw()->out_edge_list.begin()),
out_edge_iterator(v.raw()->out_edge_list.end())};
}
static
degree_size_type in_degree_impl(vertex_descriptor v) {
return v.raw()->in_edge_list.size();
}
static
std::pair<in_edge_iterator, in_edge_iterator>
in_edges_impl(vertex_descriptor v) {
return {in_edge_iterator(v.raw()->in_edge_list.begin()),
in_edge_iterator(v.raw()->in_edge_list.end())};
}
static
degree_size_type degree_impl(vertex_descriptor v) {
return in_degree_impl(v) + out_degree_impl(v);
}
static
std::pair<adjacency_iterator, adjacency_iterator>
adjacent_vertices_impl(vertex_descriptor v) {
auto out_edge_its = out_edges_impl(v);
return {adjacency_iterator(out_edge_its.first),
adjacency_iterator(out_edge_its.second)};
}
std::pair<edge_descriptor, bool> edge_impl(vertex_descriptor u,
vertex_descriptor v) const {
if (in_degree_impl(v) < out_degree_impl(u)) {
for (const edge_descriptor &e : in_edges_range(v, *this)) {
if (source_impl(e) == u) {
return {e, true};
}
}
} else {
for (const edge_descriptor &e : out_edges_range(u, *this)) {
if (target_impl(e) == v) {
return {e, true};
}
}
}
return {edge_descriptor(), false};
}
static
edge_descriptor null_edge() { return edge_descriptor(); }
static
std::pair<inv_adjacency_iterator, inv_adjacency_iterator>
inv_adjacent_vertices_impl(vertex_descriptor v) {
auto in_edge_its = in_edges_impl(v);
return {inv_adjacency_iterator(in_edge_its.first),
inv_adjacency_iterator(in_edge_its.second)};
}
std::pair<edge_descriptor, bool>
add_edge_impl(vertex_descriptor u, vertex_descriptor v) {
bool added = true;
edge_node *e = new edge_node(new_serial());
e->source = u.raw();
e->target = v.raw();
e->props.index = next_edge_index++;
u.raw()->out_edge_list.push_back(*e);
v.raw()->in_edge_list.push_back(*e);
graph_edge_count++;
return {edge_descriptor(e), added};
}
void remove_edge_impl(edge_descriptor e) {
graph_edge_count--;
vertex_node *u = e.raw()->source;
vertex_node *v = e.raw()->target;
v->in_edge_list.erase(v->in_edge_list.iterator_to(*e.raw()));
u->out_edge_list.erase(u->out_edge_list.iterator_to(*e.raw()));
delete e.raw();
}
template<class Predicate>
void remove_out_edge_if_impl(vertex_descriptor v, Predicate pred) {
out_edge_iterator it, ite;
std::tie(it, ite) = out_edges_impl(v);
while (it != ite) {
auto jt = it;
++it;
if (pred(*jt)) {
this->remove_edge_impl(*jt);
}
}
}
template<class Predicate>
void remove_in_edge_if_impl(vertex_descriptor v, Predicate pred) {
in_edge_iterator it, ite;
std::tie(it, ite) = in_edges_impl(v);
while (it != ite) {
auto jt = it;
++it;
if (pred(*jt)) {
remove_edge_impl(*jt);
}
}
}
template<class Predicate>
void remove_edge_if_impl(Predicate pred) {
edge_iterator it, ite;
std::tie(it, ite) = edges_impl();
while (it != ite) {
auto jt = it;
++it;
if (pred(*jt)) {
remove_edge_impl(*jt);
}
}
}
private:
struct source_match {
explicit source_match(const vertex_descriptor &uu) : u(uu) { }
bool operator()(edge_descriptor e) const { return source_impl(e) == u; }
const vertex_descriptor &u;
};
struct target_match {
explicit target_match(const vertex_descriptor &vv) : v(vv) { }
bool operator()(edge_descriptor e) const { return target_impl(e) == v; }
const vertex_descriptor &v;
};
public:
void remove_edge_impl(const vertex_descriptor &u,
const vertex_descriptor &v) {
if (in_degree_impl(v) < out_degree_impl(u)) {
remove_in_edge_if_impl(v, source_match(u));
} else {
remove_out_edge_if_impl(u, target_match(v));
}
}
vertices_size_type num_vertices_impl() const {
return vertices_list.size();
}
std::pair<vertex_iterator, vertex_iterator> vertices_impl() const {
return {vertex_iterator(vertices_list.begin()),
vertex_iterator(vertices_list.end())};
}
edges_size_type num_edges_impl() const {
return graph_edge_count;
}
std::pair<edge_iterator, edge_iterator> edges_impl() const {
vertex_iterator vi, ve;
std::tie(vi, ve) = vertices_impl();
return {edge_iterator(vi, ve), edge_iterator(ve, ve)};
}
vertex_property_type &operator[](vertex_descriptor v) {
return v.raw()->props;
}
const vertex_property_type &operator[](vertex_descriptor v) const {
return v.raw()->props;
}
edge_property_type &operator[](edge_descriptor e) {
return e.raw()->props;
}
const edge_property_type &operator[](edge_descriptor e) const {
return e.raw()->props;
}
template<typename R, typename P_of>
struct prop_map : public boost::put_get_helper<R, prop_map<R, P_of> > {
using value_type = typename std::decay<R>::type;
using reference = R;
using key_type = typename bundle_key_type<P_of>::type;
typedef typename boost::lvalue_property_map_tag category;
prop_map(value_type P_of::*m_in) : member(m_in) { }
reference operator[](key_type k) const {
return k.raw()->props.*member;
}
reference operator()(key_type k) const { return (*this)[k]; }
private:
value_type P_of::*member;
};
template<typename R>
struct prop_map_all : public boost::put_get_helper<R, prop_map_all<R> > {
using value_type = typename std::decay<R>::type;
using reference = R;
using key_type = typename bundle_key_type<value_type>::type;
typedef typename boost::lvalue_property_map_tag category;
reference operator[](key_type k) const {
return k.raw()->props;
}
reference operator()(key_type k) const { return (*this)[k]; }
};
template<typename P_type, typename P_of>
friend
prop_map<P_type &, P_of> get(P_type P_of::*t, Graph &) {
return prop_map<P_type &, P_of>(t);
}
template<typename P_type, typename P_of>
friend
prop_map<const P_type &, P_of> get(P_type P_of::*t, const Graph &) {
return prop_map<const P_type &, P_of>(t);
}
friend
prop_map<size_t &, VertexPropertyType>
get(boost::vertex_index_t, Graph &g) {
return get(&VertexPropertyType::index, g);
}
friend
prop_map<const size_t &, VertexPropertyType>
get(boost::vertex_index_t, const Graph &g) {
return get(&VertexPropertyType::index, g);
}
friend
prop_map<size_t &, EdgePropertyType>
get(boost::edge_index_t, Graph &g) {
return get(&EdgePropertyType::index, g);
}
friend
prop_map<const size_t &, EdgePropertyType>
get(boost::edge_index_t, const Graph &g) {
return get(&EdgePropertyType::index, g);
}
friend
prop_map_all<VertexPropertyType &> get(boost::vertex_all_t, Graph &) {
return {};
}
friend
prop_map_all<const VertexPropertyType &> get(boost::vertex_all_t,
const Graph &) {
return {};
}
friend
prop_map_all<EdgePropertyType &> get(boost::edge_all_t, Graph &) {
return {};
}
friend
prop_map_all<const EdgePropertyType &> get(boost::edge_all_t,
const Graph &) {
return {};
}
friend
prop_map_all<VertexPropertyType &> get(boost::vertex_bundle_t, Graph &) {
return {};
}
friend
prop_map_all<const VertexPropertyType &> get(boost::vertex_bundle_t,
const Graph &) {
return {};
}
friend
prop_map_all<EdgePropertyType &> get(boost::edge_bundle_t, Graph &) {
return {};
}
friend
prop_map_all<const EdgePropertyType &> get(boost::edge_bundle_t,
const Graph &) {
return {};
}
template<typename Prop, typename K>
friend
auto get(Prop p, Graph &g, K key) -> decltype(get(p, g)[key]) {
return get(p, g)[key];
}
template<typename Prop, typename K>
friend
auto get(Prop p, const Graph &g, K key) -> decltype(get(p, g)[key]) {
return get(p, g)[key];
}
template<typename Prop, typename K, typename V>
friend
void put(Prop p, Graph &g, K key, const V &value) {
get(p, g)[key] = value;
}
vertex_descriptor add_vertex_impl(const VertexPropertyType &vp) {
vertex_descriptor v = add_vertex_impl();
auto i = (*this)[v].index;
(*this)[v] = vp;
(*this)[v].index = i;
return v;
}
std::pair<edge_descriptor, bool>
add_edge_impl(vertex_descriptor u, vertex_descriptor v,
const EdgePropertyType &ep) {
auto e = add_edge_impl(u, v);
auto i = (*this)[e.first].index;
(*this)[e.first] = ep;
(*this)[e.first].index = i;
return e;
}
void renumber_edges_impl() {
next_edge_index = 0;
edge_iterator it;
edge_iterator ite;
for (std::tie(it, ite) = edges_impl(); it != ite; ++it) {
(*this)[*it].index = next_edge_index++;
}
}
void renumber_vertices_impl() {
DEBUG_PRINTF("renumbering above %zu\n", Graph::N_SPECIAL_VERTICES);
next_vertex_index = Graph::N_SPECIAL_VERTICES;
vertex_iterator it;
vertex_iterator ite;
for (std::tie(it, ite) = vertices_impl(); it != ite; ++it) {
if ((*this)[*it].index < Graph::N_SPECIAL_VERTICES) {
continue;
}
(*this)[*it].index = next_vertex_index++;
}
}
vertices_size_type vertex_index_upper_bound_impl() const {
return next_vertex_index;
}
vertices_size_type edge_index_upper_bound_impl() const {
return next_edge_index;
}
using directed_category = boost::directed_tag;
using edge_parallel_category = boost::allow_parallel_edge_tag;
struct traversal_category :
public virtual boost::bidirectional_graph_tag,
public virtual boost::adjacency_graph_tag,
public virtual boost::vertex_list_graph_tag,
public virtual boost::edge_list_graph_tag { };
ue2_graph() = default;
ue2_graph(ue2_graph &&old)
: next_vertex_index(old.next_vertex_index),
next_edge_index(old.next_edge_index),
graph_edge_count(old.graph_edge_count),
next_serial(old.next_serial) {
using std::swap;
swap(vertices_list, old.vertices_list);
}
ue2_graph &operator=(ue2_graph &&old) {
next_vertex_index = old.next_vertex_index;
next_edge_index = old.next_edge_index;
graph_edge_count = old.graph_edge_count;
next_serial = old.next_serial;
using std::swap;
swap(vertices_list, old.vertices_list);
return *this;
}
~ue2_graph() {
vertices_list.clear_and_dispose(delete_disposer());
}
};
template<typename Graph>
struct is_ue2_graph
: public ::std::integral_constant<
bool, std::is_base_of<graph_detail::graph_base, Graph>::value> {};
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::vertex_descriptor>::type
add_vertex(Graph &g) {
return g.add_vertex_impl();
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
remove_vertex(typename Graph::vertex_descriptor v, Graph &g) {
g.remove_vertex_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
clear_in_edges(typename Graph::vertex_descriptor v, Graph &g) {
g.clear_in_edges_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
clear_out_edges(typename Graph::vertex_descriptor v, Graph &g) {
g.clear_out_edges_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
clear_vertex(typename Graph::vertex_descriptor v, Graph &g) {
g.clear_in_edges_impl(v);
g.clear_out_edges_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::vertex_descriptor>::type
source(typename Graph::edge_descriptor e, const Graph &) {
return Graph::source_impl(e);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::vertex_descriptor>::type
target(typename Graph::edge_descriptor e, const Graph &) {
return Graph::target_impl(e);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::degree_size_type>::type
out_degree(typename Graph::vertex_descriptor v, const Graph &) {
return Graph::out_degree_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::out_edge_iterator,
typename Graph::out_edge_iterator>>::type
out_edges(typename Graph::vertex_descriptor v, const Graph &) {
return Graph::out_edges_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::degree_size_type>::type
in_degree(typename Graph::vertex_descriptor v, const Graph &) {
return Graph::in_degree_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::in_edge_iterator,
typename Graph::in_edge_iterator>>::type
in_edges(typename Graph::vertex_descriptor v, const Graph &) {
return Graph::in_edges_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::degree_size_type>::type
degree(typename Graph::vertex_descriptor v, const Graph &) {
return Graph::degree_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::adjacency_iterator,
typename Graph::adjacency_iterator>>::type
adjacent_vertices(typename Graph::vertex_descriptor v, const Graph &) {
return Graph::adjacent_vertices_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::edge_descriptor, bool>>::type
edge(typename Graph::vertex_descriptor u, typename Graph::vertex_descriptor v,
const Graph &g) {
return g.edge_impl(u, v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::inv_adjacency_iterator,
typename Graph::inv_adjacency_iterator>>::type
inv_adjacent_vertices(typename Graph::vertex_descriptor v, const Graph &) {
return Graph::inv_adjacent_vertices_impl(v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::edge_descriptor, bool>>::type
add_edge(typename Graph::vertex_descriptor u,
typename Graph::vertex_descriptor v, Graph &g) {
return g.add_edge_impl(u, v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
remove_edge(typename Graph::edge_descriptor e, Graph &g) {
g.remove_edge_impl(e);
}
template<typename Graph, typename Iter>
typename std::enable_if<
!std::is_convertible<Iter, typename Graph::edge_descriptor>::value &&
is_ue2_graph<Graph>::value>::type
remove_edge(Iter it, Graph &g) {
g.remove_edge_impl(*it);
}
template<typename Graph, typename Predicate>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
remove_out_edge_if(typename Graph::vertex_descriptor v, Predicate pred,
Graph &g) {
g.remove_out_edge_if_impl(v, pred);
}
template<typename Graph, typename Predicate>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
remove_in_edge_if(typename Graph::vertex_descriptor v, Predicate pred,
Graph &g) {
g.remove_in_edge_if_impl(v, pred);
}
template<typename Graph, typename Predicate>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
remove_edge_if(Predicate pred, Graph &g) {
g.remove_edge_if_impl(pred);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
remove_edge(const typename Graph::vertex_descriptor &u,
const typename Graph::vertex_descriptor &v, Graph &g) {
g.remove_edge_impl(u, v);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::vertices_size_type>::type
num_vertices(const Graph &g) {
return g.num_vertices_impl();
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::vertex_iterator,
typename Graph::vertex_iterator>>::type
vertices(const Graph &g) {
return g.vertices_impl();
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::edges_size_type>::type
num_edges(const Graph &g) {
return g.num_edges_impl();
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::edge_iterator,
typename Graph::edge_iterator>>::type
edges(const Graph &g) {
return g.edges_impl();
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::vertex_descriptor>::type
add_vertex(const typename Graph::vertex_property_type &vp, Graph &g) {
return g.add_vertex_impl(vp);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
std::pair<typename Graph::edge_descriptor, bool>>::type
add_edge(typename Graph::vertex_descriptor u,
typename Graph::vertex_descriptor v,
const typename Graph::edge_property_type &ep, Graph &g) {
return g.add_edge_impl(u, v, ep);
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
renumber_edges(Graph &g) {
g.renumber_edges_impl();
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value>::type
renumber_vertices(Graph &g) {
g.renumber_vertices_impl();
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::vertices_size_type>::type
vertex_index_upper_bound(const Graph &g) {
return g.vertex_index_upper_bound_impl();
}
template<typename Graph>
typename std::enable_if<is_ue2_graph<Graph>::value,
typename Graph::edges_size_type>::type
edge_index_upper_bound(const Graph &g) {
return g.edge_index_upper_bound_impl();
}
template<typename T> struct pointer_to_member_traits {};
template<typename Return, typename Class>
struct pointer_to_member_traits<Return(Class::*)> {
using member_type = Return;
using class_type = Class;
};
template<typename Graph, typename Property, typename Enable = void>
struct is_ue2_vertex_or_edge_property {
static constexpr bool value = false;
};
template<typename Graph, typename Property>
struct is_ue2_vertex_or_edge_property<
Graph, Property, typename std::enable_if<is_ue2_graph<Graph>::value &&
std::is_member_object_pointer<
Property>::value>::type> {
private:
using class_type = typename pointer_to_member_traits<Property>::class_type;
using vertex_type = typename Graph::vertex_property_type;
using edge_type = typename Graph::edge_property_type;
public:
static constexpr bool value =
std::is_same<class_type, vertex_type>::value ||
std::is_same<class_type, edge_type>::value;
};
using boost::vertex_index;
using boost::edge_index;
}
namespace boost {
template<typename Graph, typename Prop>
struct property_map<Graph, Prop,
typename std::enable_if<ue2::is_ue2_graph<Graph>::value &&
ue2::is_ue2_vertex_or_edge_property<
Graph, Prop>::value>::type> {
private:
using prop_traits = ue2::pointer_to_member_traits<Prop>;
using member_type = typename prop_traits::member_type;
using class_type = typename prop_traits::class_type;
public:
using type = typename Graph::template prop_map<member_type &, class_type>;
using const_type = typename Graph::template prop_map<const member_type &,
class_type>;
};
template<typename Graph>
struct property_map<Graph, vertex_index_t,
typename std::enable_if<ue2::is_ue2_graph<Graph>::value>::type> {
using v_prop_type = typename Graph::vertex_property_type;
using type = typename Graph::template prop_map<size_t &, v_prop_type>;
using const_type =
typename Graph::template prop_map<const size_t &, v_prop_type>;
};
template<typename Graph>
struct property_map<Graph, edge_index_t,
typename std::enable_if<ue2::is_ue2_graph<Graph>::value>::type> {
using e_prop_type = typename Graph::edge_property_type;
using type = typename Graph::template prop_map<size_t &, e_prop_type>;
using const_type =
typename Graph::template prop_map<const size_t &, e_prop_type>;
};
template<typename Graph>
struct property_map<Graph, vertex_all_t,
typename std::enable_if<ue2::is_ue2_graph<Graph>::value>::type> {
using v_prop_type = typename Graph::vertex_property_type;
using type = typename Graph::template prop_map_all<v_prop_type &>;
using const_type =
typename Graph::template prop_map_all<const v_prop_type &>;
};
template<typename Graph>
struct property_map<Graph, edge_all_t,
typename std::enable_if<ue2::is_ue2_graph<Graph>::value>::type> {
using e_prop_type = typename Graph::edge_property_type;
using type = typename Graph::template prop_map_all<e_prop_type &>;
using const_type =
typename Graph::template prop_map_all<const e_prop_type &>;
};
}
namespace std {
template<typename Graph>
struct hash<ue2::graph_detail::vertex_descriptor<Graph>> {
using vertex_descriptor = ue2::graph_detail::vertex_descriptor<Graph>;
std::size_t operator()(const vertex_descriptor &v) const {
return v.hash();
}
};
template<typename Graph>
struct hash<ue2::graph_detail::edge_descriptor<Graph>> {
using edge_descriptor = ue2::graph_detail::edge_descriptor<Graph>;
std::size_t operator()(const edge_descriptor &e) const {
return e.hash();
}
};
} #endif