Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/graph/doc/quick_tour.html @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 28.4 KB
Line 
1<html>
2
3<!--
4  -- Copyright (c) Jeremy Siek 2000
5  --
6  -- Distributed under the Boost Software License, Version 1.0.
7  -- (See accompanying file LICENSE_1_0.txt or copy at
8  -- http://www.boost.org/LICENSE_1_0.txt)
9  -->
10
11<head>
12<title>Quick Tour of Boost Graph Library</title>
13<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
14<meta name="ProgId" content="FrontPage.Editor.Document">
15</head>
16
17<body bgcolor="#ffffff" link="#0000ee" text="#000000" vlink="#551a8b" alink="#ff0000">
18
19<img src="../../../boost.png" alt="C++ Boost" width="277" height="86"><br clear>
20<h1>A Quick Tour of the Boost Graph Library</h1>
21<p>The domain of graph data structures and algorithms is in some respects more
22complicated than that of containers. The abstract iterator interface used by STL
23is not sufficiently rich to encompass the numerous ways that graph algorithms
24may traverse a graph. Instead, we formulate an abstract interface that serves
25the same purpose for graphs that iterators do for basic containers (though
26iterators still play a large role). <a href="#fig:analogy">Figure 1</a> depicts
27the analogy between the STL and the BGL.
28<p>&nbsp;</p>
29<div align="CENTER">
30  <a name="fig:analogy"></a><a name="752"></a>
31  <table>
32    <caption valign="bottom"><strong>Figure 1:</strong> The analogy between the
33      STL and the BGL.</caption>
34    <tr>
35      <td><img src="figs/analogy.gif" width="518" height="335"></td>
36    </tr>
37  </table>
38</div>
39<p>&nbsp;</p>
40The graph abstraction consists of a set of vertices (or nodes), and a set of
41edges (or arcs) that connect the vertices. <a href="#fig:quick-start">Figure 2</a>
42depicts a directed graph with five vertices (labeled 0 through 4) and 11 edges.
43The edges leaving a vertex are called the <i>out-edges</i> of the vertex. The
44edges <tt>{(0,1),(0,2),(0,3),(0,4)}</tt> are all out-edges of vertex 0. The
45edges entering a vertex are called the <i>in-edges</i> of the vertex. The edges <tt>{(0,4),(2,4),(3,4)}</tt>
46are all in-edges of vertex 4.
47<p>&nbsp;</p>
48<div align="CENTER">
49  <a name="fig:quick-start"></a>
50  <table>
51    <caption valign="bottom"><strong>Figure 2:</strong> An example of a directed
52      graph.</caption>
53    <tr>
54      <td><img src="figs/quick_start.gif" width="103" height="124"></td>
55    </tr>
56  </table>
57</div>
58<p>&nbsp;</p>
59<p>In the following sections we will use the BGL to construct this example graph
60and manipulate it in various ways. The complete source code for this example can
61be found in <a href="../example/quick_tour.cpp"><tt>examples/quick_tour.cpp</tt></a>.
62Each of the following sections discusses a &quot;slice&quot; of this example
63file. Excerpts from the output of the example program will also be listed.
64<p>&nbsp;
65<h2>Constructing a Graph</h2>
66<p>In this example we will use the BGL <a href="adjacency_list.html"><tt>adjacency_list</tt></a>
67class to demonstrate the main ideas in the BGL interface. The <tt>adjacency_list</tt>
68class provides a generalized version of the classic &quot;adjacency list&quot;
69data structure. The <tt>adjacency_list</tt> is a template class with six
70template parameters, though here we only fill in the first three parameters and
71use the defaults for the remaining three. The first two template arguments (<tt>vecS,
72vecS</tt>) determine the data structure used to represent the out-edges for each
73vertex in the graph and the data structure used to represent the graph's vertex
74set (see section <a href="using_adjacency_list.html#sec:choosing-graph-type">Choosing
75the <tt>Edgelist</tt> and <tt>VertexList</tt></a> for information about the
76tradeoffs of the different data structures). The third argument, <tt>bidirectionalS</tt>,
77selects a directed graph that provides access to both out and in-edges. The
78other options for the third argument are <tt>directedS</tt> which selects a
79directed graph with only out-edges, and <tt>undirectedS</tt> which selects an
80undirected graph.
81<p>Once we have the graph type selected, we can create the graph in <a href="#fig:quick-start">Figure
822</a> by declaring a graph object and filling in edges using the <a href="MutableGraph.html#sec:add-edge"><tt>add_edge()</tt></a>
83function of the <a href="MutableGraph.html">MutableGraph</a> interface (which <tt>adjacency_list</tt>
84implements). We use the array of pairs <tt>edge_array</tt> merely as a
85convenient way to explicitly create the edges for this example.
86<p>&nbsp;
87<pre>
88  #include &lt;iostream&gt;                  // for std::cout
89  #include &lt;utility&gt;                   // for std::pair
90  #include &lt;algorithm&gt;                 // for std::for_each
91  #include &lt;boost/graph/graph_traits.hpp&gt;
92  #include &lt;boost/graph/adjacency_list.hpp&gt;
93  #include &lt;boost/graph/dijkstra_shortest_paths.hpp&gt;
94
95  using namespace boost;
96 
97  int main(int,char*[])
98  {
99    // create a typedef for the Graph type
100    typedef adjacency_list&lt;vecS, vecS, bidirectionalS&gt; Graph;
101
102    // Make convenient labels for the vertices
103    enum { A, B, C, D, E, N };
104    const int num_vertices = N;
105    const char* name = "ABCDE";
106
107    // writing out the edges in the graph
108    typedef std::pair&lt;int, int&gt; Edge;
109    Edge edge_array[] =
110    { Edge(A,B), Edge(A,D), Edge(C,A), Edge(D,C),
111      Edge(C,E), Edge(B,D), Edge(D,E) };
112    const int num_edges = sizeof(edge_array)/sizeof(edge_array[0]);
113
114    // declare a graph object
115    Graph g(num_vertices);
116
117    // add the edges to the graph object
118    for (int i = 0; i &lt; num_edges; ++i)
119      add_edge(edge_array[i].first, edge_array[i].second, g);
120    ...
121    return 0;
122  }
123</pre>
124<p>Instead of calling the <tt>add_edge()</tt> function for each edge, we could
125use the <a href="adjacency_list.html#sec:iterator-constructor">edge iterator
126constructor</a> of the graph. This is typically more efficient than using <tt>add_edge()</tt>.
127Pointers to the <tt>edge_array</tt> can be viewed as iterators, so we can call
128the iterator constructor by passing pointers to the beginning and end of the
129array.
130<pre>
131    Graph g(edge_array, edge_array + sizeof(edge_array) / sizeof(Edge), num_vertices);
132</pre>
133<p>Instead of creating a graph with a certain number of vertices to begin with,
134it is also possible to add and remove vertices with the <a href="MutableGraph.html#sec:add-vertex"><tt>add_vertex()</tt></a>
135and <a href="MutableGraph.html#sec:remove-vertex"><tt>remove_vertex()</tt></a>
136functions, also of the <a href="MutableGraph.html">MutableGraph</a> interface.
137<h2>Accessing the Vertex Set</h2>
138<p>Now that we have created a graph, we can use the graph interface to access
139the graph data in different ways. First we can access all of the vertices in the
140graph using the <a href="VertexListGraph.html#sec:vertices"><tt>vertices()</tt></a>
141function of the <a href="VertexListGraph.html">VertexListGraph</a> interface.
142This function returns a <tt>std::pair</tt> of <i>vertex iterators</i> (the <tt>first</tt>
143iterator points to the &quot;beginning&quot; of the vertices and the <tt>second</tt>
144iterator points &quot;past the end&quot;). Dereferencing a vertex iterator gives
145a vertex object. The type of the vertex iterator is given by the <a href="graph_traits.html"><tt>graph_traits</tt></a>
146class. Note that different graph classes can have different associated vertex
147iterator types, which is why we need the <tt>graph_traits</tt> class. Given some
148graph type, the <tt>graph_traits</tt> class will provide access to the <tt>vertex_iterator</tt>
149type.
150<p>The following example prints out the index for each of the vertices in the
151graph. All vertex and edge properties, including index, are accessed via
152property map objects. The <a href="property_map.html"><tt>property_map</tt></a>
153class is used to obtain the property map type for a specific property (specified
154by <tt>vertex_index_t</tt>, one of the BGL predefined properties) and function
155call <tt>get(vertex_index, g)</tt> returns the actual property map object.
156<p>&nbsp;
157<pre>
158  // ...
159  int main(int,char*[])
160  {
161    // ...
162
163    // get the property map for vertex indices
164    typedef property_map&lt;Graph, vertex_index_t&gt;::type IndexMap;
165    IndexMap index = get(vertex_index, g);
166
167    std::cout &lt;&lt; &quot;vertices(g) = &quot;;
168    typedef graph_traits&lt;Graph&gt;::vertex_iterator vertex_iter;
169    std::pair&lt;vertex_iter, vertex_iter&gt; vp;
170    for (vp = vertices(g); vp.first != vp.second; ++vp.first)
171      std::cout &lt;&lt; index[*vp.first] &lt;&lt;  &quot; &quot;;
172    std::cout &lt;&lt; std::endl;
173    // ...
174    return 0;
175  }
176</pre>
177The output is:
178<pre>
179  vertices(g) = 0 1 2 3 4
180</pre>
181<p>&nbsp;
182<h2>Accessing the Edge Set</h2>
183<p>The set of edges for a graph can be accessed with the <a href="EdgeListGraph.html#sec:edges"><tt>edges()</tt></a>
184function of the <a href="EdgeListGraph.html">EdgeListGraph</a> interface.
185Similar to the <tt>vertices()</tt> function, this returns a pair of iterators,
186but in this case the iterators are <i>edge iterators</i>. Dereferencing an edge
187iterator gives an edge object. The <tt>source()</tt> and <tt>target()</tt>
188functions return the two vertices that are connected by the edge. Instead of
189explicitly creating a <tt>std::pair</tt> for the iterators, this time we will
190use the <a href="../../tuple/doc/tuple_users_guide.html#tiers"><tt>tie()</tt></a> helper function.
191This handy function can be used to assign the parts of a <tt>std::pair</tt> into
192two separate variables, in this case <tt>ei</tt> and <tt>ei_end</tt>. This is
193usually more convenient than creating a <tt>std::pair</tt> and is our method of
194choice for the BGL.
195<p>&nbsp;
196<pre>
197  // ...
198  int main(int,char*[])
199  {
200    // ...
201    std::cout &lt;&lt; &quot;edges(g) = &quot;;
202    graph_traits&lt;Graph&gt;::edge_iterator ei, ei_end;
203    for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
204        std::cout &lt;&lt; &quot;(&quot; &lt;&lt; index[source(*ei, g)]
205                  &lt;&lt; &quot;,&quot; &lt;&lt; index[target(*ei, g)] &lt;&lt; &quot;) &quot;;
206    std::cout &lt;&lt; std::endl;
207    // ...
208    return 0;
209  }
210</pre>
211The output is:
212<pre>
213  edges(g) = (0,1) (0,2) (0,3) (0,4) (2,0) (2,4) (3,0)
214    (3,1) (3,4) (4,0) (4,1)
215</pre>
216<p>&nbsp;
217<h2>The Adjacency Structure</h2>
218<p>In the next few examples we will explore the adjacency structure of the graph
219from the point of view of a particular vertex. We will look at the vertices'
220in-edges, out-edges, and its adjacent vertices. We will encapsulate this in an
221&quot;exercise vertex&quot; function, and apply it to each vertex in the graph.
222To demonstrate the STL-interoperability of BGL, we will use the STL <tt>for_each()</tt>
223function to iterate through the vertices and apply the function.
224<p>&nbsp;
225<pre>
226  //...
227  int main(int,char*[])
228  {
229    //...
230    std::for_each(vertices(g).first, vertices(g).second,
231                  exercise_vertex&lt;Graph&gt;(g));
232    return 0;
233  }
234</pre>
235<p>We use a functor for <tt>exercise_vertex</tt> instead of just a function
236because the graph object will be needed when we access information about each
237vertex; using a functor gives us a place to keep a reference to the graph object
238during the execution of the <tt>std::for_each()</tt>. Also we template the
239functor on the graph type so that it is reusable with different graph classes.
240Here is the start of the <tt>exercise_vertex</tt> functor:
241<p>&nbsp;
242<pre>
243  template &lt;class Graph&gt; struct exercise_vertex {
244    exercise_vertex(Graph&amp; g_) : g(g_) {}
245    //...
246    Graph&amp; g;
247  };
248</pre>
249<p>&nbsp;
250<h3>Vertex Descriptors</h3>
251<p>The first thing we need to know in order to write the <tt>operator()</tt>
252method of the functor is the type for the vertex objects of the graph. The
253vertex type will be the parameter to the <tt>operator()</tt> method. To be
254precise, we do not deal with actual vertex objects, but rather with <i>vertex
255descriptors</i>. Many graph representations (such as adjacency lists) do not
256store actual vertex objects, while others do (e.g., pointer-linked graphs). This
257difference is hidden underneath the &quot;black-box&quot; of the vertex
258descriptor object. The vertex descriptor is something provided by each graph
259type that can be used to access information about the graph via the <tt>out_edges()</tt>,
260<tt>in_edges()</tt>, <tt>adjacent_vertices()</tt>, and property map functions
261that are described in the following sections. The <tt>vertex_descriptor</tt>
262type is obtained through the <tt>graph_traits</tt> class. The <tt>typename</tt>
263keyword used below is necessary because the type on the left hand side of the
264scope <tt>::</tt> operator (the <tt>graph_traits&lt;Graph&gt;</tt> type) is
265dependent on a template parameter (the <tt>Graph</tt> type). Here is how we
266define the functor's apply method:
267<p>&nbsp;
268<pre>
269  template &lt;class Graph&gt; struct exercise_vertex {
270    //...
271    typedef typename graph_traits&lt;Graph&gt;
272      ::vertex_descriptor Vertex;
273
274    void operator()(const Vertex&amp; v) const
275    {
276      //...
277    }
278    //...
279  };
280</pre>
281<p>&nbsp;
282<h3>Out-Edges, In-Edges, and Edge Descriptors</h3>
283<p>The out-edges of a vertex are accessed with the <a href="IncidenceGraph.html#sec:out-edges"><tt>out_edges()</tt></a>
284function of the <a href="IncidenceGraph.html">IncidenceGraph</a> interface. The <tt>out_edges()</tt>
285function takes two arguments: the first argument is the vertex and the second is
286the graph object. The function returns a pair of iterators which provide access
287to all of the out-edges of a vertex (similar to how the <tt>vertices()</tt>
288function returned a pair of iterators). The iterators are called <i>out-edge
289iterators</i> and dereferencing one of these iterators gives an <i>edge
290descriptor</i> object. An edge descriptor plays the same kind of role as the
291vertex descriptor object, it is a &quot;black box&quot; provided by the graph
292type. The following code snippet prints the source-target pairs for each
293out-edge of vertex <tt>v</tt>.
294<p>&nbsp;
295<pre>
296  template &lt;class Graph&gt; struct exercise_vertex {
297    //...
298    void operator()(const Vertex&amp; v) const
299    {
300      typedef graph_traits&lt;Graph&gt; GraphTraits;
301      typename property_map&lt;Graph, vertex_index_t&gt;::type
302        index = get(vertex_index, g);
303
304      std::cout &lt;&lt; &quot;out-edges: &quot;;
305      typename GraphTraits::out_edge_iterator out_i, out_end;
306      typename GraphTraits::edge_descriptor e;
307      for (tie(out_i, out_end) = out_edges(v, g);
308           out_i != out_end; ++out_i) {
309        e = *out_i;
310        Vertex src = source(e, g), targ = target(e, g);
311        std::cout &lt;&lt; &quot;(&quot; &lt;&lt; index[src] &lt;&lt; &quot;,&quot; 
312                  &lt;&lt; index[targ] &lt;&lt; &quot;) &quot;;
313      }
314      std::cout &lt;&lt; std::endl;
315      //...
316    }
317    //...
318  };
319</pre>
320For vertex 0 the output is:
321<pre>
322  out-edges: (0,1) (0,2) (0,3) (0,4)
323</pre>
324<p>The <a href="BidirectionalGraph.html#sec:in-edges"><tt>in_edges()</tt></a>
325function of the <a href="BidirectionalGraph.html">BidirectionalGraph</a>
326interface provides access to all the in-edges of a vertex through <i>in-edge
327iterators</i>. The <tt>in_edges()</tt> function is only available for the <tt>adjacency_list</tt>
328if <tt>bidirectionalS</tt> is supplied for the <tt>Directed</tt> template
329parameter. There is an extra cost in space when <tt>bidirectionalS</tt> is
330specified instead of <tt>directedS</tt>.
331<p>&nbsp;
332<pre>
333  template &lt;class Graph&gt; struct exercise_vertex {
334    //...
335    void operator()(const Vertex&amp; v) const
336    {
337      //...
338      std::cout &lt;&lt; &quot;in-edges: &quot;;
339      typedef typename graph_traits&lt;Graph&gt; GraphTraits;
340      typename GraphTraits::in_edge_iterator in_i, in_end;
341      for (tie(in_i, in_end) = in_edges(v,g);
342           in_i != in_end; ++in_i) {
343        e = *in_i;
344        Vertex src = source(e, g), targ = target(e, g);
345        std::cout &lt;&lt; &quot;(&quot; &lt;&lt; index[src] &lt;&lt; &quot;,&quot; &lt;&lt; index[targ] &lt;&lt; &quot;) &quot;;
346      }
347      std::cout &lt;&lt; std::endl;
348      //...
349    }
350    //...
351  };
352</pre>
353For vertex 0 the output is:
354<pre>
355  in-edges: (2,0) (3,0) (4,0)
356</pre>
357<p>&nbsp;
358<h3>Adjacent Vertices</h3>
359<p>Given the out-edges of a vertex, the target vertices of these edges are <i>adjacent</i>
360to the source vertex. Sometimes an algorithm does not need to look at the edges
361of the graph and only cares about the vertices. Therefore the graph interface
362also includes the <a href="AdjacencyGraph.html#sec:adjacent-vertices"><tt>adjacent_vertices()</tt></a>
363function of the <a href="AdjacencyGraph.html">AdjacencyGraph</a> interface which
364provides direct access to the adjacent vertices. This function returns a pair of
365<i>adjacency iterators</i>. Dereferencing an adjacency iterator gives a vertex
366descriptor for an adjacent vertex.
367<p>&nbsp;
368<pre>
369  template &lt;class Graph&gt; struct exercise_vertex {
370    //...
371    void operator()(Vertex v) const
372    {
373      //...
374      std::cout &lt;&lt; &quot;adjacent vertices: &quot;;
375      typename graph_traits&lt;Graph&gt;::adjacency_iterator ai;
376      typename graph_traits&lt;Graph&gt;::adjacency_iterator ai_end;
377      for (tie(ai, ai_end) = adjacent_vertices(v, g);
378           ai != ai_end; ++ai)
379        std::cout &lt;&lt; index[*ai] &lt;&lt;  &quot; &quot;;
380      std::cout &lt;&lt; std::endl;
381    }
382    //...
383  };
384</pre>
385For vertex 4 the output is:
386<pre>
387  adjacent vertices: 0 1
388</pre>
389<p>&nbsp;
390<h2>Adding Some Color to your Graph</h2>
391<p>BGL attempts to be as flexible as possible in terms of accommodating how
392properties are attached to a graph. For instance, a property such as edge weight
393may need to be used throughout a graph object's lifespan and therefore it would
394be convenient to have the graph object also manage the property storage. On the
395other hand, a property like vertex color may only be needed for the duration of
396a single algorithm, and it would be better to have the property stored
397separately from the graph object. The first kind of property is called an <i>internally
398stored property</i> while the second kind is called an <i>externally stored
399property</i>. BGL uses a uniform mechanism to access both kinds of properties
400inside its graph algorithms called the <i>property map</i> interface, described
401in Section <a href="property_map.html">Property Map Concepts</a>. In addition,
402the <a href="PropertyGraph.html">PropertyGraph</a> concept defines the interface
403for obtaining a property map object for an internally stored property.
404<p>The BGL <tt>adjacency_list</tt> class allows users to specify internally
405stored properties through plug-in template parameters of the graph class. How to
406do this is discussed in detail in Section <a href="using_adjacency_list.html#sec:adjacency-list-properties">Internal
407Properties</a>. Externally stored properties can be created in many different
408ways, although they are ultimately passed as separate arguments to the graph
409algorithms. One straightforward way to store properties is to create an array
410indexed by vertex or edge index. In the <tt>adjacency_list</tt> with <tt>vecS</tt>
411specified for the <tt>VertexList</tt> template parameter, vertices are
412automatically assigned indices, which can be accessed via the property map for
413the <tt>vertex_index_t</tt>. Edges are not automatically assigned indices.
414However the property mechanism can be used to attach indices to the edges which
415can be used to index into other externally stored properties.
416<p>In the following example, we construct a graph and apply <a href="dijkstra_shortest_paths.html"><tt>dijkstra_shortest_paths()</tt></a>.
417The complete source code for the example is in <a href="../example/dijkstra-example.cpp"><tt>examples/dijkstra-example.cpp</tt></a>.
418Dijkstra's algorithm computes the shortest distance from the starting vertex to
419every other vertex in the graph.
420<p>Dijkstra's algorithm requires that a weight property is associated with each
421edge and a distance property with each vertex. Here we use an internal property
422for the weight and an external property for the distance. For the weight
423property we use the <tt>property</tt> class and specify <tt>int</tt> as the type
424used to represent weight values and <tt>edge_weight_t</tt> for the property tag
425(which is one of the BGL predefined property tags). The weight property is then
426used as a template argument for <tt>adjacency_list</tt>.
427<p>The <tt>listS</tt> and <tt>vecS</tt> types are selectors that determine the
428data structure used inside the <tt>adjacency_list</tt> (see Section <a href="using_adjacency_list.html#sec:choosing-graph-type">Choosing
429the <tt>Edgelist</tt> and <tt>VertexList</tt></a>). The <tt>directedS</tt> type
430specifies that the graph should be directed (versus undirected). The following
431code shows the specification of the graph type and then the initialization of
432the graph. The edges and weights are passed to the graph constructor in the form
433of iterators (a pointer qualifies as a <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
434<p>&nbsp;
435<pre>
436  typedef adjacency_list&lt;listS, vecS, directedS,
437                         no_property, property&lt;edge_weight_t, int&gt; &gt; Graph;
438  typedef graph_traits&lt;Graph&gt;::vertex_descriptor Vertex;
439  typedef std::pair&lt;int,int&gt; E;
440
441  const int num_nodes = 5;
442  E edges[] = { E(0,2),
443                E(1,1), E(1,3), E(1,4),
444                E(2,1), E(2,3),
445                E(3,4),
446                E(4,0), E(4,1) };
447  int weights[] = { 1, 2, 1, 2, 7, 3, 1, 1, 1};
448
449  Graph G(edges + sizeof(edges) / sizeof(E), weights, num_nodes);
450</pre>
451<p>For the external distance property we will use a <tt>std::vector</tt> for
452storage. BGL algorithms treat random access iterators as property maps, so we
453can just pass the beginning iterator of the distance vector to Dijkstra's
454algorithm. Continuing the above example, the following code shows the creation
455of the distance vector, the call to Dijkstra's algorithm (implicitly using the
456internal edge weight property), and then the output of the results.
457<p>&nbsp;
458<pre>
459  // vector for storing distance property
460  std::vector&lt;int&gt; d(num_vertices(G));
461
462  // get the first vertex
463  Vertex s = *(vertices(G).first);
464  // invoke variant 2 of Dijkstra's algorithm
465  dijkstra_shortest_paths(G, s, distance_map(&amp;d[0]));
466
467  std::cout &lt;&lt; &quot;distances from start vertex:&quot; &lt;&lt; std::endl;
468  graph_traits&lt;Graph&gt;::vertex_iterator vi;
469  for(vi = vertices(G).first; vi != vertices(G).second; ++vi)
470    std::cout &lt;&lt; &quot;distance(&quot; &lt;&lt; index(*vi) &lt;&lt; &quot;) = &quot; 
471              &lt;&lt; d[*vi] &lt;&lt; std::endl;
472  std::cout &lt;&lt; std::endl;
473</pre>
474The output is:
475<pre>
476  distances from start vertex:
477  distance(0) = 0
478  distance(1) = 6
479  distance(2) = 1
480  distance(3) = 4
481  distance(4) = 5
482</pre>
483<p>&nbsp;
484<h2>Extending Algorithms with Visitors</h2>
485<p>Often times an algorithm in a library <i>almost</i> does what you need, but
486not quite. For example, in the previous section we used Dijkstra's algorithm to
487calculate the shortest distances to each vertex, but perhaps we also wanted to
488record the tree of shortest paths. One way to do this is to record the
489predecessor (parent) for each node in the shortest-paths tree.
490<p>It would be nice if we could avoid rewriting Dijkstra's algorithm, and just
491add that little bit extra needed to record the predecessors <a href="#1">[1]</a>. In the STL, this
492kind of extensibility is provided by functors, which are optional parameters to
493each algorithm. In the BGL this role is fulfilled by <i>visitors</i>.
494<p>A visitor is like a functor, but instead of having just one &quot;apply&quot;
495method, it has several. Each of these methods get invoked at certain
496well-defined points within the algorithm. The visitor methods are explained in
497detail in Section <a href="visitor_concepts.html">Visitor Concepts</a>. The BGL
498provides a number of visitors for some common tasks including a predecessor
499recording visitor. The user is encouraged to write his or her own visitors as a
500way of extending the BGL. Here we will take a quick look at the implementation
501and use of the predecessor recorder. Since we will be using the <a href="dijkstra_shortest_paths.html">dijkstra_shortest_paths()</a>
502algorithm, the visitor we create must be a <a href="DijkstraVisitor.html">Dijkstra Visitor</a>.
503<p>The functionality of the <tt>record_predecessors</tt> visitor is separated
504into two parts. For the storage and access of the predecessor property, we will
505use a <a href="../../property_map/property_map.html">property map</a>. The
506predecessor visitor will then only be responsible for what parent to record. To
507implement this, we create a <tt>record_predecessors</tt> class and template it
508on the predecessor property map <tt>PredecessorMap</tt>. Since this visitor will
509only be filling in one of the visitor methods, we will inherit from <a href="dijkstra_visitor.html"><tt>dijkstra_visitor</tt></a>
510which will provide empty methods for the rest. The constructor of the <tt>predecessor_recorder</tt>
511will take the property map object and save it away in a data member.
512<p>&nbsp;
513<pre>
514  template &lt;class PredecessorMap&gt;
515  class record_predecessors : public dijkstra_visitor&lt;&gt;
516  {
517  public:
518    record_predecessors(PredecessorMap p)
519      : m_predecessor(p) { }
520
521    template &lt;class Edge, class Graph&gt;
522    void edge_relaxed(Edge e, Graph&amp; g) {
523      // set the parent of the target(e) to source(e)
524      put(m_predecessor, target(e, g), source(e, g));
525    }
526  protected:
527    PredecessorMap m_predecessor;
528  };
529</pre>
530<p>The job of recording the predecessors is quite simple. When Dijkstra's
531algorithm relaxes an edge (potentially adding it to the shortest-paths tree) we
532record the source vertex as the predecessor of the target vertex. Later, if the
533edge is relaxed again the predecessor property will be overwritten by the new
534predecessor. Here we use the <tt>put()</tt> function associated with the
535property map to record the predecessor. The <tt>edge_filter</tt> of the visitor
536tells the algorithm when to invoke the <tt>explore()</tt> method. In this case
537we only want to be notified about edges in the shortest-paths tree so we specify
538<tt>tree_edge_tag</tt>.
539<p>As a finishing touch, we create a helper function to make it more convenient
540to create predecessor visitors. All BGL visitors have a helper function like
541this.
542<p>&nbsp;
543<pre>
544  template &lt;class PredecessorMap&gt;
545  record_predecessors&lt;PredecessorMap&gt;
546  make_predecessor_recorder(PredecessorMap p) {
547    return record_predecessors&lt;PredecessorMap&gt;(p);
548  }
549</pre>
550<p>We are now ready to use the <tt>record_predecessors</tt> in
551Dijkstra's algorithm. Luckily, BGL's Dijkstra's algorithm is already
552equipped to handle visitors, so we just pass in our new visitor. In
553this example we only need to use one visitor, but the BGL is also
554equipped to handle the use of multiple visitors in the same algorithm
555(see Section <a href="visitor_concepts.html">Visitor Concepts</a>).
556<p>&nbsp;
557<pre>
558  using std::vector;
559  using std::cout;
560  using std::endl;
561  vector&lt;Vertex&gt; p(num_vertices(G)); //the predecessor array
562  dijkstra_shortest_paths(G, s, distance_map(&amp;d[0]).
563                          visitor(make_predecessor_recorder(&amp;p[0])));
564
565  cout &lt;&lt; &quot;parents in the tree of shortest paths:&quot; &lt;&lt; endl;
566  for(vi = vertices(G).first; vi != vertices(G).second; ++vi) {
567    cout &lt;&lt; &quot;parent(&quot; &lt;&lt; *vi;
568    if (p[*vi] == Vertex())
569      cout &lt;&lt; &quot;) = no parent&quot; &lt;&lt; endl;
570    else
571      cout &lt;&lt; &quot;) = &quot; &lt;&lt; p[*vi] &lt;&lt; endl;
572  }
573</pre>
574The output is:
575<pre>
576  parents in the tree of shortest paths:
577  parent(0) = no parent
578  parent(1) = 4
579  parent(2) = 0
580  parent(3) = 2
581  parent(4) = 3
582</pre>
583
584<br>
585
586<h3>Notes</h3>
587
588<a name="1">[1]</a> The new version of Dijkstra's algorithm now includes
589a named parameter for recording predecessors, so a predecessor visitor
590is no long necessary, though this still makes for a good example.
591
592<br>
593<hr>
594<table>
595  <tr valign="top">
596    <td nowrap>Copyright © 2000</td>
597    <td><a href="../../../people/jeremy_siek.htm">Jeremy Siek</a>,
598      Indiana University (<a href="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>)</td>
599  </tr>
600</table>
601
602</body>
603
604</html>
605<!--  LocalWords:  STL BGL cpp vecS bidirectionalS directedS undirectedS hpp vp
606 -->
607<!--  LocalWords:  iostream namespace int const num sizeof map ID's gif typedef
608 -->
609<!--  LocalWords:  iter ei interoperability struct typename GraphTraits src ai
610 -->
611<!--  LocalWords:  targ PropertyGraph  Properties property iterator iterators
612 -->
613<!--  LocalWords:  VertexList dijkstra listS Edgelist RandomAccessIterator cout
614 -->
615<!--  LocalWords:  weightp  adjacency tradeoffs undirected MutableGraph indices
616 -->
617<!--  LocalWords:  VertexListGraph Dereferencing IndexMap EdgeListGraph functor
618 -->
619<!--  LocalWords:  functor's IncidenceGraph dereferencing BidirectionalGraph
620 -->
621<!--  LocalWords:  AdjacencyGraph Dijkstra's extensibility functors BGL's endl
622 -->
623<!--  LocalWords:  DijkstraVisitor PredecessorMap siek htm Univ Notre
624 -->
Note: See TracBrowser for help on using the repository browser.