// Copyright (C) 2009 Andrew Sutton // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GRAPH_LABELED_GRAPH_HPP #define BOOST_GRAPH_LABELED_GRAPH_HPP #include <boost/config.hpp> #include <vector> #include <map> #include <boost/static_assert.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/bool.hpp> #include <boost/unordered_map.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_unsigned.hpp> #include <boost/pending/container_traits.hpp> #include <boost/graph/graph_traits.hpp> // This file implements a utility for creating mappings from arbitrary // identifiers to the vertices of a graph. namespace boost { // A type selector that denotes the use of some default value. struct defaultS { }; /** @internal */ namespace graph_detail { /** Returns true if the selector is the default selector. */ template < typename Selector > struct is_default : mpl::bool_< is_same< Selector, defaultS >::value > { }; /** * Choose the default map instance. If Label is an unsigned integral type * the we can use a vector to store the information. */ template < typename Label, typename Vertex > struct choose_default_map { typedef typename mpl::if_< is_unsigned< Label >, std::vector< Vertex >, std::map< Label, Vertex > // TODO: Should use unordered_map? >::type type; }; /** * @name Generate Label Map * These type generators are responsible for instantiating an associative * container for the the labeled graph. Note that the Selector must be * select a pair associative container or a vecS, which is only valid if * Label is an integral type. */ //@{ template < typename Selector, typename Label, typename Vertex > struct generate_label_map { }; template < typename Label, typename Vertex > struct generate_label_map< vecS, Label, Vertex > { typedef std::vector< Vertex > type; }; template < typename Label, typename Vertex > struct generate_label_map< mapS, Label, Vertex > { typedef std::map< Label, Vertex > type; }; template < typename Label, typename Vertex > struct generate_label_map< multimapS, Label, Vertex > { typedef std::multimap< Label, Vertex > type; }; template < typename Label, typename Vertex > struct generate_label_map< hash_mapS, Label, Vertex > { typedef boost::unordered_map< Label, Vertex > type; }; template < typename Label, typename Vertex > struct generate_label_map< hash_multimapS, Label, Vertex > { typedef boost::unordered_multimap< Label, Vertex > type; }; template < typename Selector, typename Label, typename Vertex > struct choose_custom_map { typedef typename generate_label_map< Selector, Label, Vertex >::type type; }; //@} /** * Choose and instantiate an "associative" container. Note that this can * also choose vector. */ template < typename Selector, typename Label, typename Vertex > struct choose_map { typedef typename mpl::eval_if< is_default< Selector >, choose_default_map< Label, Vertex >, choose_custom_map< Selector, Label, Vertex > >::type type; }; /** @name Insert Labeled Vertex */ //@{ // Tag dispatch on random access containers (i.e., vectors). This function // basically requires a) that Container is vector<Label> and that Label // is an unsigned integral value. Note that this will resize the vector // to accommodate indices. template < typename Container, typename Graph, typename Label, typename Prop > std::pair< typename graph_traits< Graph >::vertex_descriptor, bool > insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p, random_access_container_tag) { typedef typename graph_traits< Graph >::vertex_descriptor Vertex; // If the label is out of bounds, resize the vector to accommodate. // Resize by 2x the index so we don't cause quadratic insertions over // time. if (l >= c.size()) { c.resize((l + 1) * 2); } Vertex v = add_vertex(p, g); c[l] = v; return std::make_pair(c[l], true); } // Tag dispatch on multi associative containers (i.e. multimaps). template < typename Container, typename Graph, typename Label, typename Prop > std::pair< typename graph_traits< Graph >::vertex_descriptor, bool > insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p, multiple_associative_container_tag const&) { // Note that insertion always succeeds so we can add the vertex first // and then the mapping to the label. typedef typename graph_traits< Graph >::vertex_descriptor Vertex; Vertex v = add_vertex(p, g); c.insert(std::make_pair(l, v)); return std::make_pair(v, true); } // Tag dispatch on unique associative containers (i.e. maps). template < typename Container, typename Graph, typename Label, typename Prop > std::pair< typename graph_traits< Graph >::vertex_descriptor, bool > insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p, unique_associative_container_tag) { // Here, we actually have to try the insertion first, and only add // the vertex if we get a new element. typedef typename graph_traits< Graph >::vertex_descriptor Vertex; typedef typename Container::iterator Iterator; std::pair< Iterator, bool > x = c.insert(std::make_pair(l, Vertex())); if (x.second) { x.first->second = add_vertex(g); put(boost::vertex_all, g, x.first->second, p); } return std::make_pair(x.first->second, x.second); } // Dispatcher template < typename Container, typename Graph, typename Label, typename Prop > std::pair< typename graph_traits< Graph >::vertex_descriptor, bool > insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p) { return insert_labeled_vertex(c, g, l, p, container_category(c)); } //@} /** @name Find Labeled Vertex */ //@{ // Tag dispatch for sequential maps (i.e., vectors). template < typename Container, typename Graph, typename Label > typename graph_traits< Graph >::vertex_descriptor find_labeled_vertex( Container const& c, Graph const&, Label const& l, random_access_container_tag) { return l < c.size() ? c[l] : graph_traits< Graph >::null_vertex(); } // Tag dispatch for pair associative maps (more or less). template < typename Container, typename Graph, typename Label > typename graph_traits< Graph >::vertex_descriptor find_labeled_vertex( Container const& c, Graph const&, Label const& l, associative_container_tag) { typename Container::const_iterator i = c.find(l); return i != c.end() ? i->second : graph_traits< Graph >::null_vertex(); } // Dispatcher template < typename Container, typename Graph, typename Label > typename graph_traits< Graph >::vertex_descriptor find_labeled_vertex( Container const& c, Graph const& g, Label const& l) { return find_labeled_vertex(c, g, l, container_category(c)); } //@} /** @name Put Vertex Label */ //@{ // Tag dispatch on vectors. template < typename Container, typename Label, typename Graph, typename Vertex > bool put_vertex_label(Container& c, Graph const&, Label const& l, Vertex v, random_access_container_tag) { // If the element is already occupied, then we probably don't want to // overwrite it. if (c[l] == graph_traits< Graph >::null_vertex()) return false; c[l] = v; return true; } // Attempt the insertion and return its result. template < typename Container, typename Label, typename Graph, typename Vertex > bool put_vertex_label(Container& c, Graph const&, Label const& l, Vertex v, unique_associative_container_tag) { return c.insert(std::make_pair(l, v)).second; } // Insert the pair and return true. template < typename Container, typename Label, typename Graph, typename Vertex > bool put_vertex_label(Container& c, Graph const&, Label const& l, Vertex v, multiple_associative_container_tag) { c.insert(std::make_pair(l, v)); return true; } // Dispatcher template < typename Container, typename Label, typename Graph, typename Vertex > bool put_vertex_label( Container& c, Graph const& g, Label const& l, Vertex v) { return put_vertex_label(c, g, l, v, container_category(c)); } //@} } // namespace detail struct labeled_graph_class_tag { }; /** @internal * This class is responsible for the deduction and declaration of type names * for the labeled_graph class template. */ template < typename Graph, typename Label, typename Selector > struct labeled_graph_types { typedef Graph graph_type; // Label and maps typedef Label label_type; typedef typename graph_detail::choose_map< Selector, Label, typename graph_traits< Graph >::vertex_descriptor >::type map_type; }; /** * The labeled_graph class is a graph adaptor that maintains a mapping between * vertex labels and vertex descriptors. * * @todo This class is somewhat redundant for adjacency_list<*, vecS> if * the intended label is an unsigned int (and perhaps some other cases), but * it does avoid some weird ambiguities (i.e. adding a vertex with a label that * does not match its target index). * * @todo This needs to be reconciled with the named_graph, but since there is * no documentation or examples, its not going to happen. */ template < typename Graph, typename Label, typename Selector = defaultS > class labeled_graph : protected labeled_graph_types< Graph, Label, Selector > { typedef labeled_graph_types< Graph, Label, Selector > Base; public: typedef labeled_graph_class_tag graph_tag; typedef typename Base::graph_type graph_type; typedef typename graph_traits< graph_type >::vertex_descriptor vertex_descriptor; typedef typename graph_traits< graph_type >::edge_descriptor edge_descriptor; typedef typename graph_traits< graph_type >::directed_category directed_category; typedef typename graph_traits< graph_type >::edge_parallel_category edge_parallel_category; typedef typename graph_traits< graph_type >::traversal_category traversal_category; typedef typename graph_traits< graph_type >::out_edge_iterator out_edge_iterator; typedef typename graph_traits< graph_type >::in_edge_iterator in_edge_iterator; typedef typename graph_traits< graph_type >::adjacency_iterator adjacency_iterator; typedef typename graph_traits< graph_type >::degree_size_type degree_size_type; typedef typename graph_traits< graph_type >::vertex_iterator vertex_iterator; typedef typename graph_traits< graph_type >::vertices_size_type vertices_size_type; typedef typename graph_traits< graph_type >::edge_iterator edge_iterator; typedef typename graph_traits< graph_type >::edges_size_type edges_size_type; typedef typename graph_type::graph_property_type graph_property_type; typedef typename graph_type::graph_bundled graph_bundled; typedef typename graph_type::vertex_property_type vertex_property_type; typedef typename graph_type::vertex_bundled vertex_bundled; typedef typename graph_type::edge_property_type edge_property_type; typedef typename graph_type::edge_bundled edge_bundled; typedef typename Base::label_type label_type; typedef typename Base::map_type map_type; public: labeled_graph(graph_property_type const& gp = graph_property_type()) : _graph(gp), _map() { } labeled_graph(labeled_graph const& x) : _graph(x._graph), _map(x._map) {} // This constructor can only be used if map_type supports positional // range insertion (i.e. its a vector). This is the only case where we can // try to guess the intended labels for graph. labeled_graph(vertices_size_type n, graph_property_type const& gp = graph_property_type()) : _graph(n, gp), _map() { std::pair< vertex_iterator, vertex_iterator > rng = vertices(_graph); _map.insert(_map.end(), rng.first, rng.second); } // Construct a graph over n vertices, each of which receives a label from // the range [l, l + n). Note that the graph is not directly constructed // over the n vertices, but added sequentially. This constructor is // necessarily slower than the underlying counterpart. template < typename LabelIter > labeled_graph(vertices_size_type n, LabelIter l, graph_property_type const& gp = graph_property_type()) : _graph(gp) { while (n-- > 0) add_vertex(*l++); } // Construct the graph over n vertices each of which has a label in the // range [l, l + n) and a property in the range [p, p + n). template < typename LabelIter, typename PropIter > labeled_graph(vertices_size_type n, LabelIter l, PropIter p, graph_property_type const& gp = graph_property_type()) : _graph(gp) { while (n-- > 0) add_vertex(*l++, *p++); } labeled_graph& operator=(labeled_graph const& x) { _graph = x._graph; _map = x._map; return *this; } /** @name Graph Accessors */ //@{ graph_type& graph() { return _graph; } graph_type const& graph() const { return _graph; } //@} /** * Create a new label for the given vertex, returning false, if the label * cannot be created. */ bool label_vertex(vertex_descriptor v, Label const& l) { return graph_detail::put_vertex_label(_map, _graph, l, v); } /** @name Add Vertex * Add a vertex to the graph, returning the descriptor. If the vertices * are uniquely labeled and the label already exists within the graph, * then no vertex is added, and the returned descriptor refers to the * existing vertex. A vertex property can be given as a parameter, if * needed. */ //@{ vertex_descriptor add_vertex(Label const& l) { return graph_detail::insert_labeled_vertex( _map, _graph, l, vertex_property_type()) .first; } vertex_descriptor add_vertex(Label const& l, vertex_property_type const& p) { return graph_detail::insert_labeled_vertex(_map, _graph, l, p).first; } //@} /** @name Insert Vertex * Insert a vertex into the graph, returning a pair containing the * descriptor of a vertex and a boolean value that describes whether or not * a new vertex was inserted. If vertices are not uniquely labeled, then * insertion will always succeed. */ //@{ std::pair< vertex_descriptor, bool > insert_vertex(Label const& l) { return graph_detail::insert_labeled_vertex( _map, _graph, l, vertex_property_type()); } std::pair< vertex_descriptor, bool > insert_vertex( Label const& l, vertex_property_type const& p) { return graph_detail::insert_labeled_vertex(_map, _graph, l, p); } //@} /** Remove the vertex with the given label. */ void remove_vertex(Label const& l) { return boost::remove_vertex(vertex(l), _graph); } /** Return a descriptor for the given label. */ vertex_descriptor vertex(Label const& l) const { return graph_detail::find_labeled_vertex(_map, _graph, l); } #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES /** @name Bundled Properties */ //@{ // Lookup the requested vertex and return the bundle. vertex_bundled& operator[](Label const& l) { return _graph[vertex(l)]; } vertex_bundled const& operator[](Label const& l) const { return _graph[vertex(l)]; } // Delegate edge lookup to the underlying graph. edge_bundled& operator[](edge_descriptor e) { return _graph[e]; } edge_bundled const& operator[](edge_descriptor e) const { return _graph[e]; } //@} #endif /** Return a null descriptor */ static vertex_descriptor null_vertex() { return graph_traits< graph_type >::null_vertex(); } private: graph_type _graph; map_type _map; }; /** * The partial specialization over graph pointers allows the construction * of temporary labeled graph objects. In this case, the labels are destructed * when the wrapper goes out of scope. */ template < typename Graph, typename Label, typename Selector > class labeled_graph< Graph*, Label, Selector > : protected labeled_graph_types< Graph, Label, Selector > { typedef labeled_graph_types< Graph, Label, Selector > Base; public: typedef labeled_graph_class_tag graph_tag; typedef typename Base::graph_type graph_type; typedef typename graph_traits< graph_type >::vertex_descriptor vertex_descriptor; typedef typename graph_traits< graph_type >::edge_descriptor edge_descriptor; typedef typename graph_traits< graph_type >::directed_category directed_category; typedef typename graph_traits< graph_type >::edge_parallel_category edge_parallel_category; typedef typename graph_traits< graph_type >::traversal_category traversal_category; typedef typename graph_traits< graph_type >::out_edge_iterator out_edge_iterator; typedef typename graph_traits< graph_type >::in_edge_iterator in_edge_iterator; typedef typename graph_traits< graph_type >::adjacency_iterator adjacency_iterator; typedef typename graph_traits< graph_type >::degree_size_type degree_size_type; typedef typename graph_traits< graph_type >::vertex_iterator vertex_iterator; typedef typename graph_traits< graph_type >::vertices_size_type vertices_size_type; typedef typename graph_traits< graph_type >::edge_iterator edge_iterator; typedef typename graph_traits< graph_type >::edges_size_type edges_size_type; typedef typename graph_type::vertex_property_type vertex_property_type; typedef typename graph_type::edge_property_type edge_property_type; typedef typename graph_type::graph_property_type graph_property_type; typedef typename graph_type::vertex_bundled vertex_bundled; typedef typename graph_type::edge_bundled edge_bundled; typedef typename Base::label_type label_type; typedef typename Base::map_type map_type; labeled_graph(graph_type* g) : _graph(g) {} /** @name Graph Access */ //@{ graph_type& graph() { return *_graph; } graph_type const& graph() const { return *_graph; } //@} /** * Create a new label for the given vertex, returning false, if the label * cannot be created. */ bool label_vertex(vertex_descriptor v, Label const& l) { return graph_detail::put_vertex_label(_map, *_graph, l, v); } /** @name Add Vertex */ //@{ vertex_descriptor add_vertex(Label const& l) { return graph_detail::insert_labeled_vertex( _map, *_graph, l, vertex_property_type()) .first; } vertex_descriptor add_vertex(Label const& l, vertex_property_type const& p) { return graph_detail::insert_labeled_vertex(_map, *_graph, l, p).first; } std::pair< vertex_descriptor, bool > insert_vertex(Label const& l) { return graph_detail::insert_labeled_vertex( _map, *_graph, l, vertex_property_type()); } //@} /** Try to insert a vertex with the given label. */ std::pair< vertex_descriptor, bool > insert_vertex( Label const& l, vertex_property_type const& p) { return graph_detail::insert_labeled_vertex(_map, *_graph, l, p); } /** Remove the vertex with the given label. */ void remove_vertex(Label const& l) { return boost::remove_vertex(vertex(l), *_graph); } /** Return a descriptor for the given label. */ vertex_descriptor vertex(Label const& l) const { return graph_detail::find_labeled_vertex(_map, *_graph, l); } #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES /** @name Bundled Properties */ //@{ // Lookup the requested vertex and return the bundle. vertex_bundled& operator[](Label const& l) { return (*_graph)[vertex(l)]; } vertex_bundled const& operator[](Label const& l) const { return (*_graph)[vertex(l)]; } // Delegate edge lookup to the underlying graph. edge_bundled& operator[](edge_descriptor e) { return (*_graph)[e]; } edge_bundled const& operator[](edge_descriptor e) const { return (*_graph)[e]; } //@} #endif static vertex_descriptor null_vertex() { return graph_traits< graph_type >::null_vertex(); } private: graph_type* _graph; map_type _map; }; #define LABELED_GRAPH_PARAMS typename G, typename L, typename S #define LABELED_GRAPH labeled_graph< G, L, S > /** @name Labeled Graph */ //@{ template < LABELED_GRAPH_PARAMS > inline bool label_vertex(typename LABELED_GRAPH::vertex_descriptor v, typename LABELED_GRAPH::label_type const l, LABELED_GRAPH& g) { return g.label_vertex(v, l); } template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::vertex_descriptor vertex_by_label( typename LABELED_GRAPH::label_type const l, LABELED_GRAPH& g) { return g.vertex(l); } //@} /** @name Graph */ //@{ template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > edge( typename LABELED_GRAPH::vertex_descriptor const& u, typename LABELED_GRAPH::vertex_descriptor const& v, LABELED_GRAPH const& g) { return edge(u, v, g.graph()); } // Labeled Extensions template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > edge_by_label( typename LABELED_GRAPH::label_type const& u, typename LABELED_GRAPH::label_type const& v, LABELED_GRAPH const& g) { return edge(g.vertex(u), g.vertex(v), g); } //@} /** @name Incidence Graph */ //@{ template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::out_edge_iterator, typename LABELED_GRAPH::out_edge_iterator > out_edges(typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) { return out_edges(v, g.graph()); } template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::degree_size_type out_degree( typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) { return out_degree(v, g.graph()); } template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::vertex_descriptor source( typename LABELED_GRAPH::edge_descriptor e, LABELED_GRAPH const& g) { return source(e, g.graph()); } template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::vertex_descriptor target( typename LABELED_GRAPH::edge_descriptor e, LABELED_GRAPH const& g) { return target(e, g.graph()); } //@} /** @name Bidirectional Graph */ //@{ template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::in_edge_iterator, typename LABELED_GRAPH::in_edge_iterator > in_edges(typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) { return in_edges(v, g.graph()); } template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::degree_size_type in_degree( typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) { return in_degree(v, g.graph()); } template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::degree_size_type degree( typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) { return degree(v, g.graph()); } //@} /** @name Adjacency Graph */ //@{ template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::adjacency_iterator, typename LABELED_GRAPH::adjacency_iterator > adjacenct_vertices( typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) { return adjacent_vertices(v, g.graph()); } //@} /** @name VertexListGraph */ //@{ template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::vertex_iterator, typename LABELED_GRAPH::vertex_iterator > vertices(LABELED_GRAPH const& g) { return vertices(g.graph()); } template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::vertices_size_type num_vertices( LABELED_GRAPH const& g) { return num_vertices(g.graph()); } //@} /** @name EdgeListGraph */ //@{ template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::edge_iterator, typename LABELED_GRAPH::edge_iterator > edges(LABELED_GRAPH const& g) { return edges(g.graph()); } template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::edges_size_type num_edges(LABELED_GRAPH const& g) { return num_edges(g.graph()); } //@} /** @internal @name Property Lookup */ //@{ namespace graph_detail { struct labeled_graph_vertex_property_selector { template < class LabeledGraph, class Property, class Tag > struct bind_ { typedef typename LabeledGraph::graph_type Graph; typedef property_map< Graph, Tag > PropertyMap; typedef typename PropertyMap::type type; typedef typename PropertyMap::const_type const_type; }; }; struct labeled_graph_edge_property_selector { template < class LabeledGraph, class Property, class Tag > struct bind_ { typedef typename LabeledGraph::graph_type Graph; typedef property_map< Graph, Tag > PropertyMap; typedef typename PropertyMap::type type; typedef typename PropertyMap::const_type const_type; }; }; } template <> struct vertex_property_selector< labeled_graph_class_tag > { typedef graph_detail::labeled_graph_vertex_property_selector type; }; template <> struct edge_property_selector< labeled_graph_class_tag > { typedef graph_detail::labeled_graph_edge_property_selector type; }; //@} /** @name Property Graph */ //@{ template < LABELED_GRAPH_PARAMS, typename Prop > inline typename property_map< LABELED_GRAPH, Prop >::type get( Prop p, LABELED_GRAPH& g) { return get(p, g.graph()); } template < LABELED_GRAPH_PARAMS, typename Prop > inline typename property_map< LABELED_GRAPH, Prop >::const_type get( Prop p, LABELED_GRAPH const& g) { return get(p, g.graph()); } template < LABELED_GRAPH_PARAMS, typename Prop, typename Key > inline typename property_traits< typename property_map< typename LABELED_GRAPH::graph_type, Prop >::const_type >::value_type get(Prop p, LABELED_GRAPH const& g, const Key& k) { return get(p, g.graph(), k); } template < LABELED_GRAPH_PARAMS, typename Prop, typename Key, typename Value > inline void put(Prop p, LABELED_GRAPH& g, Key const& k, Value const& v) { put(p, g.graph(), k, v); } //@} /** @name Mutable Graph */ //@{ template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > add_edge( typename LABELED_GRAPH::vertex_descriptor const& u, typename LABELED_GRAPH::vertex_descriptor const& v, LABELED_GRAPH& g) { return add_edge(u, v, g.graph()); } template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > add_edge( typename LABELED_GRAPH::vertex_descriptor const& u, typename LABELED_GRAPH::vertex_descriptor const& v, typename LABELED_GRAPH::edge_property_type const& p, LABELED_GRAPH& g) { return add_edge(u, v, p, g.graph()); } template < LABELED_GRAPH_PARAMS > inline void clear_vertex( typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH& g) { return clear_vertex(v, g.graph()); } template < LABELED_GRAPH_PARAMS > inline void remove_edge( typename LABELED_GRAPH::edge_descriptor e, LABELED_GRAPH& g) { return remove_edge(e, g.graph()); } template < LABELED_GRAPH_PARAMS > inline void remove_edge(typename LABELED_GRAPH::vertex_descriptor u, typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH& g) { return remove_edge(u, v, g.graph()); } // Labeled extensions template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > add_edge_by_label(typename LABELED_GRAPH::label_type const& u, typename LABELED_GRAPH::label_type const& v, LABELED_GRAPH& g) { return add_edge(g.vertex(u), g.vertex(v), g); } template < LABELED_GRAPH_PARAMS > inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > add_edge_by_label(typename LABELED_GRAPH::label_type const& u, typename LABELED_GRAPH::label_type const& v, typename LABELED_GRAPH::edge_property_type const& p, LABELED_GRAPH& g) { return add_edge(g.vertex(u), g.vertex(v), p, g); } template < LABELED_GRAPH_PARAMS > inline void clear_vertex_by_label( typename LABELED_GRAPH::label_type const& l, LABELED_GRAPH& g) { clear_vertex(g.vertex(l), g.graph()); } template < LABELED_GRAPH_PARAMS > inline void remove_edge_by_label(typename LABELED_GRAPH::label_type const& u, typename LABELED_GRAPH::label_type const& v, LABELED_GRAPH& g) { remove_edge(g.vertex(u), g.vertex(v), g.graph()); } //@} /** @name Labeled Mutable Graph * The labeled mutable graph hides the add_ and remove_ vertex functions from * the mutable graph concept. Note that the remove_vertex is hidden because * removing the vertex without its key could leave a dangling reference in * the map. */ //@{ template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::vertex_descriptor add_vertex( typename LABELED_GRAPH::label_type const& l, LABELED_GRAPH& g) { return g.add_vertex(l); } // MutableLabeledPropertyGraph::add_vertex(l, vp, g) template < LABELED_GRAPH_PARAMS > inline typename LABELED_GRAPH::vertex_descriptor add_vertex( typename LABELED_GRAPH::label_type const& l, typename LABELED_GRAPH::vertex_property_type const& p, LABELED_GRAPH& g) { return g.add_vertex(l, p); } template < LABELED_GRAPH_PARAMS > inline void remove_vertex( typename LABELED_GRAPH::label_type const& l, LABELED_GRAPH& g) { g.remove_vertex(l); } //@} #undef LABELED_GRAPH_PARAMS #undef LABELED_GRAPH } // namespace boost // Pull the labeled graph traits #include <boost/graph/detail/labeled_graph_traits.hpp> #endif // BOOST_GRAPH_LABELED_GRAPH_HPP