undirected_graph.hh
Go to the documentation of this file.
00001 //  (C) Copyright Sylvain Joyeux 2006
00002 //
00003 // Original code from reverse_graph adaptor
00004 //  (C) Copyright David Abrahams 2000.
00005 //
00006 // Distributed under the Boost Software License, Version 1.0. (See
00007 // accompanying file LICENSE_1_0.txt or copy at
00008 // http://www.boost.org/LICENSE_1_0.txt)
00009 
00010 #ifndef UNDIRECTED_GRAPH_HPP
00011 #define UNDIRECTED_GRAPH_HPP
00012 
00013 #include <boost/graph/adjacency_iterator.hpp>
00014 #include <boost/graph/properties.hpp>
00015 #include <boost/static_assert.hpp>
00016 #include <utilmm/iterator_sequence.hh>
00017 #include <boost/iterator/transform_iterator.hpp>
00018 
00019 #include <boost/type_traits.hpp>
00020 
00021 namespace utilmm {
00022     struct undirected_graph_tag { };
00023 
00027     template <class BidirectionalGraph, class GraphRef = const BidirectionalGraph&>
00028     class undirected_graph {
00029         typedef undirected_graph<BidirectionalGraph, GraphRef> Self;
00030         typedef boost::graph_traits<BidirectionalGraph> Traits;
00031 
00032         BOOST_STATIC_ASSERT(( boost::is_same<boost::bidirectional_tag, typename BidirectionalGraph::directed_category>::value ));
00033 
00034      public:
00035         typedef BidirectionalGraph base_type;
00036 
00037         // Constructor
00038         undirected_graph(GraphRef g) : m_g(g) {}
00039 
00040         // Graph requirements
00041         typedef typename Traits::vertex_descriptor vertex_descriptor;
00042         typedef boost::undirected_tag directed_category;
00043         typedef typename Traits::edge_parallel_category edge_parallel_category;
00044         typedef typename Traits::traversal_category traversal_category;
00045 
00046         // Add a 'reverse' flag to edge descriptors, so that source() and target() know what
00047         // needs to be done
00048         typedef std::pair<typename Traits::edge_descriptor, bool> edge_descriptor;
00049         typedef edge_descriptor (*make_undirected_edge_descriptor)(typename Traits::edge_descriptor);
00050 
00051         // Out edges do not need to be swapped
00052         static edge_descriptor make_out_edge_descriptor(typename Traits::edge_descriptor e)
00053         { return make_pair(e, false); }
00054         class base_out_edge_iterator : 
00055             public boost::transform_iterator<make_undirected_edge_descriptor, typename Traits::out_edge_iterator>
00056         {
00057             typedef boost::transform_iterator<make_undirected_edge_descriptor, typename Traits::out_edge_iterator>
00058                 base_type;
00059 
00060         public:
00061             base_out_edge_iterator() {}
00062             base_out_edge_iterator(typename Traits::out_edge_iterator e)
00063                 : base_type(e, make_out_edge_descriptor) {}
00064         };
00065 
00066         static edge_descriptor make_in_edge_descriptor(typename Traits::edge_descriptor e)
00067         { return make_pair(e, true); }
00068         class base_in_edge_iterator : 
00069             public boost::transform_iterator<make_undirected_edge_descriptor, typename Traits::in_edge_iterator>
00070         {
00071             typedef boost::transform_iterator<make_undirected_edge_descriptor, typename Traits::in_edge_iterator>
00072                 base_type;
00073 
00074         public:
00075             base_in_edge_iterator() {}
00076             base_in_edge_iterator(typename Traits::in_edge_iterator e)
00077                 : base_type(e, make_in_edge_descriptor) {}
00078         };
00079 
00080         // Do not swap plain edge iterators
00081         class edge_iterator : 
00082             public boost::transform_iterator<make_undirected_edge_descriptor, typename Traits::edge_iterator>
00083         {
00084             typedef boost::transform_iterator<make_undirected_edge_descriptor, typename Traits::edge_iterator>
00085                 base_type;
00086         public:
00087             edge_iterator() {}
00088             edge_iterator(typename Traits::edge_iterator e)
00089                 : base_type(e, make_out_edge_descriptor) {}
00090         };
00091 
00092         // IncidenceGraph requirements
00093         typedef typename Traits::degree_size_type degree_size_type;
00094         typedef iterator_sequence
00095             < base_in_edge_iterator
00096             , base_out_edge_iterator
00097             > in_edge_iterator;
00098         typedef in_edge_iterator out_edge_iterator;
00099 
00100         // AdjacencyGraph requirements
00101         typedef iterator_sequence
00102             < typename Traits::adjacency_iterator
00103             , typename BidirectionalGraph::inv_adjacency_iterator
00104             > adjacency_iterator;
00105         typedef adjacency_iterator inv_adjacency_iterator;
00106 
00107         // VertexListGraph requirements
00108         typedef typename Traits::vertex_iterator vertex_iterator;
00109 
00110         // EdgeListGraph requirements
00111         typedef typename Traits::edge_iterator   edge_iterator;
00112         typedef typename Traits::vertices_size_type vertices_size_type;
00113         typedef typename Traits::edges_size_type edges_size_type;
00114 
00115         // More typedefs used by detail::edge_property_map, vertex_property_map
00116         typedef typename BidirectionalGraph::edge_property_type
00117           edge_property_type;
00118         typedef typename BidirectionalGraph::vertex_property_type
00119           vertex_property_type;
00120         typedef undirected_graph_tag graph_tag;
00121 
00122         static vertex_descriptor null_vertex()
00123         { return Traits::null_vertex(); }
00124 
00125         // Bundled properties support
00126         typename boost::graph::detail::bundled_result<BidirectionalGraph,
00127                  edge_descriptor>::type&
00128         operator[](edge_descriptor x)
00129         { return m_g[x.first]; }
00130 
00131         typename boost::graph::detail::bundled_result<BidirectionalGraph,
00132                  edge_descriptor>::type const&
00133         operator[](edge_descriptor x) const
00134         { return m_g[x.first]; }
00135 
00136 
00137 
00138         typename boost::graph::detail::bundled_result<BidirectionalGraph,
00139                  vertex_descriptor>::type&
00140         operator[](vertex_descriptor x)
00141         { return m_g[x]; }
00142 
00143         typename boost::graph::detail::bundled_result<BidirectionalGraph,
00144                  vertex_descriptor>::type const&
00145         operator[](vertex_descriptor x) const
00146         { return m_g[x]; }
00147 
00148 
00149         // would be private, but template friends aren't portable enough.
00150      // private:
00151         GraphRef m_g;
00152     };
00153 
00154     template <class BidirectionalGraph>
00155     inline undirected_graph<BidirectionalGraph>
00156     make_undirected_graph(const BidirectionalGraph& g)
00157     {
00158         return undirected_graph<BidirectionalGraph>(g);
00159     }
00160 
00161     template <class BidirectionalGraph>
00162     inline undirected_graph<BidirectionalGraph, BidirectionalGraph&>
00163     make_undirected_graph(BidirectionalGraph& g)
00164     {
00165         return undirected_graph<BidirectionalGraph, BidirectionalGraph&>(g);
00166     }
00167 
00168     template <class BidirectionalGraph, class GRef>
00169     std::pair<typename undirected_graph<BidirectionalGraph>::vertex_iterator,
00170               typename undirected_graph<BidirectionalGraph>::vertex_iterator>
00171     vertices(const undirected_graph<BidirectionalGraph,GRef>& g)
00172     {
00173         return vertices(g.m_g);
00174     }
00175 
00176     template <class BidirectionalGraph, class GRef>
00177     std::pair<typename undirected_graph<BidirectionalGraph>::edge_iterator,
00178               typename undirected_graph<BidirectionalGraph>::edge_iterator>
00179     edges(const undirected_graph<BidirectionalGraph,GRef>& g)
00180     {
00181         return edges(g.m_g);
00182     }
00183 
00184     template <class BidirectionalGraph, class GRef>
00185     inline std::pair<typename undirected_graph<BidirectionalGraph,GRef>::out_edge_iterator,
00186                      typename undirected_graph<BidirectionalGraph,GRef>::out_edge_iterator>
00187     out_edges(const typename BidirectionalGraph::vertex_descriptor u,
00188               const undirected_graph<BidirectionalGraph,GRef>& g)
00189     {
00190         std::pair<typename BidirectionalGraph::out_edge_iterator,
00191                   typename BidirectionalGraph::out_edge_iterator>
00192                       out_edges = boost::out_edges(u, g.m_g);
00193         std::pair<typename BidirectionalGraph::in_edge_iterator,
00194                   typename BidirectionalGraph::in_edge_iterator> 
00195                       in_edges = boost::in_edges(u, g.m_g);
00196 
00197         typedef typename undirected_graph<BidirectionalGraph,GRef>::out_edge_iterator edge_iterator;
00198         return make_pair(
00199                 edge_iterator(in_edges.first, in_edges.second, out_edges.first, out_edges.first),
00200                 edge_iterator(in_edges.second, in_edges.second, out_edges.second, out_edges.second));
00201     }
00202 
00203     template <class BidirectionalGraph, class GRef>
00204     inline typename BidirectionalGraph::vertices_size_type
00205     num_vertices(const undirected_graph<BidirectionalGraph,GRef>& g)
00206     {
00207         return num_vertices(g.m_g);
00208     }
00209 
00210     template <class BidirectionalGraph, class GRef>
00211     inline typename undirected_graph<BidirectionalGraph>::edges_size_type
00212     num_edges(const undirected_graph<BidirectionalGraph,GRef>& g)
00213     {
00214         return num_edges(g.m_g);
00215     }
00216 
00217     template <class BidirectionalGraph, class GRef>
00218     inline typename BidirectionalGraph::degree_size_type
00219     out_degree(const typename BidirectionalGraph::vertex_descriptor u,
00220                const undirected_graph<BidirectionalGraph,GRef>& g)
00221     {
00222         return in_degree(u, g.m_g) + out_degree(u, g.m_g);
00223     }
00224 
00225     template <class BidirectionalGraph, class GRef>
00226     inline std::pair<typename BidirectionalGraph::edge_descriptor, bool>
00227     edge(const typename BidirectionalGraph::vertex_descriptor u,
00228          const typename BidirectionalGraph::vertex_descriptor v,
00229          const undirected_graph<BidirectionalGraph,GRef>& g)
00230     {
00231         return edge(v, u, g.m_g);
00232     }
00233 
00234     template <class BidirectionalGraph, class GRef>
00235     inline std::pair<typename BidirectionalGraph::out_edge_iterator,
00236         typename BidirectionalGraph::out_edge_iterator>
00237     in_edges(const typename BidirectionalGraph::vertex_descriptor u,
00238              const undirected_graph<BidirectionalGraph,GRef>& g)
00239     { return out_edges(u, g); }
00240 
00241     template <class BidirectionalGraph, class GRef>
00242     inline std::pair<typename undirected_graph<BidirectionalGraph,GRef>::adjacency_iterator,
00243                      typename undirected_graph<BidirectionalGraph,GRef>::adjacency_iterator>
00244     adjacent_vertices(const typename BidirectionalGraph::vertex_descriptor u,
00245                       const undirected_graph<BidirectionalGraph,GRef>& g)
00246     {
00247         std::pair<typename BidirectionalGraph::adjacency_iterator,
00248                   typename BidirectionalGraph::adjacency_iterator> 
00249                       adjacency = boost::adjacent_vertices(u, g.m_g);
00250         std::pair<typename BidirectionalGraph::inv_adjacency_iterator,
00251                   typename BidirectionalGraph::inv_adjacency_iterator>
00252                       inv_adjacency = boost::inv_adjacent_vertices(u, g.m_g);
00253 
00254         typedef typename undirected_graph<BidirectionalGraph,GRef>::adjacency_iterator adjacency_iterator;
00255         return std::make_pair(
00256                 adjacency_iterator(adjacency.first, adjacency.second, inv_adjacency.first, inv_adjacency.first),
00257                 adjacency_iterator(adjacency.second, adjacency.second, inv_adjacency.second, inv_adjacency.second));
00258     }
00259 
00260     template <class BidirectionalGraph, class GRef>
00261     inline typename BidirectionalGraph::degree_size_type
00262     in_degree(const typename BidirectionalGraph::vertex_descriptor u,
00263               const undirected_graph<BidirectionalGraph,GRef>& g)
00264     { return out_degree(u, g); }
00265 
00266     template <class Edge, class BidirectionalGraph, class GRef>
00267     inline typename boost::graph_traits<BidirectionalGraph>::vertex_descriptor
00268     source(const Edge& e, const undirected_graph<BidirectionalGraph,GRef>& g)
00269     {
00270         if (e.second)
00271             return target(e.first, g.m_g);
00272         else
00273             return source(e.first, g.m_g);
00274     }
00275 
00276     template <class Edge, class BidirectionalGraph, class GRef>
00277     inline typename boost::graph_traits<BidirectionalGraph>::vertex_descriptor
00278     target(const Edge& e, const undirected_graph<BidirectionalGraph,GRef>& g)
00279     {
00280         if (e.second)
00281             return source(e.first, g.m_g);
00282         else
00283             return target(e.first, g.m_g);
00284     }
00285 
00286 
00287     namespace detail {
00288 
00289       struct undirected_graph_vertex_property_selector {
00290         template <class UndirectedGraph, class Property, class Tag>
00291         struct bind_ {
00292           typedef typename UndirectedGraph::base_type Graph;
00293           typedef boost::property_map<Graph, Tag> PMap;
00294           typedef typename PMap::type type;
00295           typedef typename PMap::const_type const_type;
00296         };
00297       };
00298 
00299       struct undirected_graph_edge_property_selector {
00300         template <class UndirectedGraph, class Property, class Tag>
00301         struct bind_ {
00302           typedef typename UndirectedGraph::base_type Graph;
00303           typedef boost::property_map<Graph, Tag> PMap;
00304           typedef typename PMap::type type;
00305           typedef typename PMap::const_type const_type;
00306         };
00307       };
00308 
00309     } // namespace detail
00310 
00313     template<typename PropertyMap>
00314     class undirected_property_map 
00315     { 
00316     public:
00317         undirected_property_map(PropertyMap pmap)
00318             : m_map(pmap) {}
00319 
00320         PropertyMap& map() { return m_map; }
00321         PropertyMap const& map() const { return m_map; }
00322 
00323     private:
00324         PropertyMap m_map;
00325     };
00326 
00327     template<typename PropertyMap, typename EdgeDescriptor, typename ValueType>
00328     void put(undirected_property_map<PropertyMap>& map, 
00329             EdgeDescriptor e, ValueType value)
00330     { put(map.map(), e.first, value); }
00331     template<typename PropertyMap, typename EdgeDescriptor>
00332     typename boost::property_traits<PropertyMap>::value_type
00333         get(undirected_property_map<PropertyMap> const& map, 
00334             EdgeDescriptor e)
00335     { return get(map.map(), e.first); }
00336 
00337     template<typename PropertyMap>
00338     undirected_property_map<PropertyMap> make_undirected_edge_map(PropertyMap pmap)
00339     { return undirected_property_map<PropertyMap>(pmap); }
00340 
00341 
00342 } // namespace utilmm
00343 
00344 // Include specialization in the boost namespace
00345 namespace boost {
00346     template<typename PropertyMap>
00347     struct property_traits< utilmm::undirected_property_map<PropertyMap> >
00348         : property_traits<PropertyMap> {};
00349 
00350     template <>
00351     struct vertex_property_selector<utilmm::undirected_graph_tag> {
00352         typedef utilmm::detail::undirected_graph_vertex_property_selector type;
00353     };
00354 
00355     template <>
00356     struct edge_property_selector<utilmm::undirected_graph_tag> {
00357         typedef utilmm::detail::undirected_graph_edge_property_selector type;
00358     };
00359 
00360     namespace detail {
00361         template<typename BidirGraph, typename GRef, typename Property>
00362         struct get_property_map_type { };
00363         template<typename BidirGraph, typename Property>
00364         struct get_property_map_type<BidirGraph, const BidirGraph&, Property>
00365         { typedef typename property_map<BidirGraph, Property>::const_type type; };
00366         template<typename BidirGraph, typename Property>
00367         struct get_property_map_type<BidirGraph, BidirGraph&, Property>
00368         { typedef typename property_map<BidirGraph, Property>::type type; };
00369     }
00370 
00371     template <class BidirGraph, class GRef, class Property>
00372     typename detail::get_property_map_type<BidirGraph, GRef, Property>::type
00373     get(Property p, utilmm::undirected_graph<BidirGraph,GRef>& g)
00374     {
00375       return get(p, g.m_g);
00376     }
00377 
00378     template <class BidirGraph, class GRef, class Property>
00379     typename detail::get_property_map_type<BidirGraph, GRef, Property>::type
00380     get(Property p, const utilmm::undirected_graph<BidirGraph,GRef>& g)
00381     {
00382       return get(p, g.m_g);
00383     }
00384 
00385     template <class BidirectionalGraph, class GRef, class Property, class Key>
00386     typename property_traits<
00387       typename property_map<BidirectionalGraph, Property>::const_type
00388     >::value_type
00389     get(Property p, const utilmm::undirected_graph<BidirectionalGraph,GRef>& g, const Key& k)
00390     {
00391       return get(p, g.m_g, k);
00392     }
00393 
00394     template <class BidirectionalGraph, class GRef, class Property, class Key, class Value>
00395     void
00396     put(Property p, const utilmm::undirected_graph<BidirectionalGraph,GRef>& g, const Key& k,
00397         const Value& val)
00398     {
00399       put(p, g.m_g, k, val);
00400     }
00401 
00402     template<typename BidirectionalGraph, typename GRef, typename Tag,
00403              typename Value>
00404     inline void
00405     set_property(const utilmm::undirected_graph<BidirectionalGraph,GRef>& g, Tag tag, 
00406                  const Value& value)
00407     {
00408       set_property(g.m_g, tag, value);
00409     }
00410 
00411     template<typename BidirectionalGraph, typename GRef, typename Tag>
00412     inline
00413     typename graph_property<BidirectionalGraph, Tag>::type
00414     get_property(const utilmm::undirected_graph<BidirectionalGraph,GRef>& g, Tag tag)
00415     {
00416       return get_property(g.m_g, tag);
00417     }
00418 
00419 } // namespace boost
00420 
00421 #endif


utilmm
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Thu Jan 2 2014 11:38:31