leda_conversion.html 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <HTML>
  2. <!--
  3. Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. -->
  8. <Head>
  9. <Title>Boost Graph Library: Converting Existing Graphs to BGL</Title>
  10. <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
  11. ALINK="#ff0000">
  12. <IMG SRC="../../../boost.png"
  13. ALT="C++ Boost" width="277" height="86">
  14. <BR Clear>
  15. <H1><a name="sec:leda-conversion">How to Convert Existing Graphs to BGL</H1>
  16. <P>
  17. Though the main goal of BGL is to aid the development of new
  18. applications and graph algorithms, there are quite a few existing codes
  19. that could benefit from using BGL algorithms. One way to use the BGL
  20. algorithms with existing graph data structures is to copy data from
  21. the older graph format into a BGL graph which could then be used in
  22. the BGL algorithms. The problem with this approach is that it can be
  23. expensive to make this copy. Another approach is to wrap the existing
  24. graph data structure with a BGL interface.
  25. <P>
  26. The Adaptor pattern&nbsp;[<A
  27. HREF="bibliography.html#gamma95:_design_patterns">12</A>] typically requires
  28. that the adaptee object be contained inside a new class that provides the
  29. desired interface. This containment is not required when wrapping a
  30. graph for BGL because the BGL graph interface consists solely of
  31. free (global) functions. Instead of creating a new graph class, you
  32. need to overload all the free functions required by the interface. We
  33. call this free function wrapper approach <I>external adaptation</I>.
  34. <P>
  35. One of the more commonly used graph classes is the LEDA parameterized
  36. <a
  37. href="https://algorithmic-solutions.info/leda_guide/graphs/param_graph.html"><TT>GRAPH</TT></a>
  38. class&nbsp;[<A HREF="bibliography.html#mehlhorn99:_leda">22</A>]. In
  39. this section we will show how to create a BGL interface for this
  40. class. The first question is which BGL interfaces (or concepts) we
  41. should implement. The following concepts are straightforward and easy
  42. to implement on top of LEDA: <a
  43. href="./VertexListGraph.html">VertexListGraph</a>, <a
  44. href="./BidirectionalGraph.html">BidirectionalGraph</a>, and <a
  45. href="./MutableGraph.html">MutableGraph</a>.
  46. <P>
  47. All types associated with a BGL graph class are accessed though the
  48. <TT>graph_traits</TT> class. We can partially specialize this traits
  49. class for the LEDA <TT>GRAPH</TT> class in the following way. The
  50. <TT>node</TT> and <TT>edge</TT> are the LEDA types for representing
  51. vertices and edges. The LEDA <TT>GRAPH</TT> is for directed graphs, so
  52. we choose <TT>directed_tag</TT> for the <TT>directed_category</TT>.
  53. The LEDA <TT>GRAPH</TT> does not automatically prevent the insertion
  54. of parallel edges, so we choose <TT>allow_parallel_edge_tag</TT> for
  55. the <TT>edge_parallel_category</TT>. The return type for the LEDA
  56. function <TT>number_of_nodes()</TT> and <TT>number_of_edges()</TT> is
  57. <TT>int</TT>, so we choose that type for the
  58. <TT>vertices_size_type</TT> and <tt>edges_size_type</tt> of the
  59. graph. The iterator types will be more complicated, so we leave that
  60. for later.
  61. <P>
  62. <PRE>
  63. namespace boost {
  64. template &lt;class vtype, class etype&gt;
  65. struct graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt; {
  66. typedef node vertex_descriptor;
  67. typedef edge edge_descriptor;
  68. // iterator typedefs...
  69. typedef directed_tag directed_category;
  70. typedef allow_parallel_edge_tag edge_parallel_category;
  71. typedef int vertices_size_type;
  72. typedef int edges_size_type;
  73. };
  74. } // namespace boost
  75. </PRE>
  76. <P>
  77. First we will write the <TT>source()</TT> and <TT>target()</TT>
  78. functions of the <a href="./IncidenceGraph.html">IncidenceGraph</a>
  79. concept, which is part of the <a
  80. href="./VertexListGraph.html">VertexListGraph</a> concept. We use the
  81. LEDA <TT>GRAPH</TT> type for the graph parameter, and use
  82. <TT>graph_traits</TT> to specify the edge parameter and the vertex
  83. return type. We could also just use the LEDA types <TT>node</TT> and
  84. <TT>edge</TT> here, but it is better practice to always use
  85. <TT>graph_traits</TT>. If there is a need to change the associated
  86. vertex or edge type, you will only need to do it in one place, inside
  87. the specialization of <TT>graph_traits</TT> instead of throughout your
  88. code. LEDA provides <TT>source()</TT> and <TT>target()</TT> functions,
  89. so we merely call them.
  90. <P>
  91. <PRE>
  92. namespace boost {
  93. template &lt;class vtype, class etype&gt;
  94. typename graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt;::vertex_descriptor
  95. source(
  96. typename graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt;::edge_descriptor e,
  97. const GRAPH&lt;vtype,etype&gt;&amp; g)
  98. {
  99. return source(e);
  100. }
  101. template &lt;class vtype, class etype&gt;
  102. typename graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt;::vertex_descriptor
  103. target(
  104. typename graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt;::edge_descriptor e,
  105. const GRAPH&lt;vtype,etype&gt;&amp; g)
  106. {
  107. return target(e);
  108. }
  109. } // namespace boost
  110. </PRE>
  111. <P>
  112. The next function from <a
  113. href="./IncidenceGraph.html">IncidenceGraph</a> that we need to
  114. implement is <TT>out_edges()</TT>. This function returns a pair of
  115. out-edge iterators. Since LEDA does not use STL-style iterators we
  116. need to implement some. There is a very handy boost utility for
  117. implementing iterators, called <TT>iterator_adaptor</TT>. Writing a
  118. standard conforming iterator classes is actually quite difficult,
  119. harder than you may think. With the <TT>iterator_adaptor</TT> class,
  120. you just implement a policy class and the rest is taken care of. The
  121. following code is the policy class for our out-edge iterator. In LEDA,
  122. the edge object itself is used like an iterator. It has functions
  123. <TT>Succ_Adj_Edge()</TT> and <TT>Pred_Adj_Edge()</TT> to move to the
  124. next and previous (successor and predecessor) edge. One gotcha in
  125. using the LEDA <TT>edge</TT> as an iterator comes up in the
  126. <TT>dereference()</TT> function, which merely returns the edge
  127. object. The dereference operator for standard compliant iterators must
  128. be a const member function, which is why the edge argument is
  129. const. However, the return type should not be const, hence the need
  130. for <TT>const_cast</TT>.
  131. <P>
  132. <PRE>
  133. namespace boost {
  134. struct out_edge_iterator_policies
  135. {
  136. static void increment(edge&amp; e)
  137. { e = Succ_Adj_Edge(e,0); }
  138. static void decrement(edge&amp; e)
  139. { e = Pred_Adj_Edge(e,0); }
  140. template &lt;class Reference&gt;
  141. static Reference dereference(type&lt;Reference&gt;, const edge&amp; e)
  142. { return const_cast&lt;Reference&gt;(e); }
  143. static bool equal(const edge&amp; x, const edge&amp; y)
  144. { return x == y; }
  145. };
  146. } // namespace boost
  147. </PRE>
  148. <P>
  149. Now we go back to the <TT>graph_traits</TT> class, and use
  150. <TT>iterator_adaptor</TT> to fill in the
  151. <TT>out_edge_iterator</TT>. We use the <TT>iterator</TT> type
  152. to specify the associated types of the iterator, including iterator
  153. category and value type.
  154. <P>
  155. <PRE>
  156. namespace boost {
  157. template &lt;class vtype, class etype&gt;
  158. struct graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt; {
  159. // ...
  160. typedef iterator_adaptor&lt;edge,
  161. out_edge_iterator_policies,
  162. iterator&lt;std::bidirectional_iterator_tag,edge&gt;
  163. &gt; out_edge_iterator;
  164. // ...
  165. };
  166. } // namespace boost
  167. </PRE>
  168. <P>
  169. With the <TT>out_edge_iterator</TT> defined in <TT>graph_traits</TT> we
  170. are ready to define the <TT>out_edges()</TT> function. The following
  171. definition looks complicated at first glance, but it is really quite
  172. simple. The return type should be a pair of out-edge iterators, so we
  173. use <TT>std::pair</TT> and then <TT>graph_traits</TT> to access the
  174. out-edge iterator types. In the body of the function we construct the
  175. out-edge iterators by passing in the first adjacenct edge for the
  176. begin iterator, and 0 for the end iterator (which is used in LEDA as
  177. the end sentinel). The 0 argument to <TT>First_Adj_Edge</TT> tells
  178. LEDA we want out-edges (and not in-edges).
  179. <P>
  180. <PRE>
  181. namespace boost {
  182. template &lt;class vtype, class etype&gt;
  183. inline std::pair&lt;
  184. typename graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt;::out_edge_iterator,
  185. typename graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt;::out_edge_iterator &gt;
  186. out_edges(
  187. typename graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt;::vertex_descriptor u,
  188. const GRAPH&lt;vtype,etype&gt;&amp; g)
  189. {
  190. typedef typename graph_traits&lt; GRAPH&lt;vtype,etype&gt; &gt;
  191. ::out_edge_iterator Iter;
  192. return std::make_pair( Iter(First_Adj_Edge(u,0)), Iter(0) );
  193. }
  194. } // namespace boost
  195. </PRE>
  196. <P>
  197. The rest of the iterator types and interface functions are constructed
  198. using the same techniques as above. The complete code for the LEDA
  199. wrapper interface is in <a
  200. href="../../../boost/graph/leda_graph.hpp"><TT>boost/graph/leda_graph.hpp</TT></a>. In
  201. the following code we use the BGL concept checks to make sure that we
  202. correctly implemented the BGL interface. These checks do not test the
  203. run-time behaviour of the implementation; that is tested in <a
  204. href="../test/graph.cpp"><TT>test/graph.cpp</TT></a>.
  205. <P>
  206. <PRE>
  207. #include &lt;boost/graph/graph_concepts.hpp&gt;
  208. #include &lt;boost/graph/leda_graph.hpp&gt;
  209. int
  210. main(int,char*[])
  211. {
  212. typedef GRAPH&lt;int,int&gt; Graph;
  213. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept&lt;Graph&gt; ));
  214. BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept&lt;Graph&gt; ));
  215. BOOST_CONCEPT_ASSERT(( MutableGraphConcept&lt;Graph&gt; ));
  216. return 0;
  217. }
  218. </PRE>
  219. <br>
  220. <HR>
  221. <TABLE>
  222. <TR valign=top>
  223. <TD nowrap>Copyright &copy; 2000-2001</TD><TD>
  224. <A HREF="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</A>,
  225. Indiana University (<A
  226. HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)<br>
  227. <A HREF="http://www.boost.org/people/liequan_lee.htm">Lie-Quan Lee</A>, Indiana University (<A HREF="mailto:llee@cs.indiana.edu">llee@cs.indiana.edu</A>)<br>
  228. <A HREF="https://homes.cs.washington.edu/~al75">Andrew Lumsdaine</A>,
  229. Indiana University (<A
  230. HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
  231. </TD></TR></TABLE>
  232. </BODY>
  233. </HTML>