C++ Boost

Using the BGL Algorithms

This material is out of date and needs to be rewritten!!

All of the BGL algorithms have a lot in common when it comes to the appearance of the interface and the setup the user must do in order to call them. These common points are discussed here while the details of the algorithms are discussed in the reference section for each algorithm. We will used Dijsktra's single-source shortest paths algorithm as our first example. The following is the declaration of the algorithm.

namespace boost {

  template <class VertexListGraph, class P, class T, class R>
  void
  dijkstra_shortest_paths(VertexListGraph& g,
    typename graph_traits<VertexListGraph>::vertex_descriptor s,
    const bgl_named_params<P, T, R>& params);

}

The Graph Parameter

Of course the most important parameter of the function is the graph object g. The name of the template type VertexListGraph is used to remind the user that graph classes used with Dijkstra's algorithm must model the VertexListGraph concept. This basically means that the graph class must provide vertices(), out_edges(), and the other functions and associated types required by VertexListGraph. Most BGL graph classes support these operations, though edge_list is a notable exception. You can look in the Model Of section of the graph class documentation to find out which operations are supported by the graph.

It is also important to note whether the algorithm works on only undirected graphs or whether it also applies to directed graphs (undirected graphs are a special kind of directed graph). This information always appears in the description of the graph parameter in the reference section for the algorithm.

The Vertex Parameter

The next parameter, Vertex s, is the source vertex from which we want to calculate the shortests paths. The object s must be a vertex desriptor of the graph object. The following code snippet shows how one would declare a vertex descriptor object.

  typedef ... Graph;
  Graph G;
  // fill in G with vertices and edges ...

  boost::graph_traits<Graph>::vertex_descriptor s;

The vertex s needs to be initialized so that it points to some vertex in the graph. There are several ways to obtain a vertex descriptor object from the graph, and which method you use will often depend on the situation. The vertices() function provides access to all the vertices in the graph through iterators, and the source() and target() functions give the vertices incident to an edge. Here we will simply grab the vertex at the beginning of the graph's vertex set. The tie() function provides a convenient way to assign the pair of iterators returned by vertices() to the viter and viter_end variables. The vertex iterator dereferences to give a vertex descriptor object.

  boost::graph_traits<Graph>::vertex_iterator viter, viter_end;
  boost::tie(viter, viter_end) = vertices(G);
  s = *viter;

Named Parameters

The Property Map Parameters

Much of the flexibility of BGL comes from property maps, so this deserves some discussion. As the name implies, a property map provides a mechanism for reading and writing to properties that are attached to vertices or edges of a graph. internal properties are stored inside of a graph object while external properties are not.

Internal Properties

Property maps for internal properties are always obtained via the interface defined in PropertyGraph. This interface defines a traits class property_map and a function get(property, g) which returns a property map object. The traits classes are used to obtain the type of the property map given some graph type and a property tag. The property tag determines which property will be accessed (more than one property can be attached to the vertices or edges of the graph). The functions are used to obtain the property map objects. The following code snippet shows how to create a property map for the distance and weight properties of graph G.

  boost::property_map<Graph, vertex_distance_t>::type
    d = get(vertex_distance, G);

  boost::property_map<Graph, edge_weight_t>::type
    w = get(edge_weight, G);

The BGL graph classes all have VertexProperty and EdgeProperty template parameters that let the user specify internal properties. If the graph G has properties for all four of the properties needed by Dijksta's algorithm, then we could invoke the algorithm in the following way.

  boost::dijkstra_shortest_paths(G, s, 
                                 distance_map(get(vertex_distance, G)),
                                 weight_map(get(edge_weight, G)),
                                 color_map(get(vertex_color, G)),
                                 vertex_index_map(get(vertex_index, G)),
                                 null_visitor());

Since it is somewhat cumbersome to provide arguments for all of the properties needed by an algorithm, BGL also provides variants of the algorithm (shortcuts) that assume that some or all of the properties are internal to the graph. The following call invokes variant (1) of Dijkstra's algorithm.

  boost::dijkstra_shortest_paths(G, s);

External Properties

There are at least two kinds of situations when internal properties can not or should not be used, and an external property should be used instead. The first situation is when a property is only needed for a short time relative to the lifetime of the graph (perhaps only for the duration of a single algorithm call). In this case it is more efficient to keep the property storage in memory for only the time that it is needed. The second situation is when the properties are already stored somewhere else due to some pragmatic or historical reason (yes, programs can and do have histories!).

For the most part, it is up to the user to create the appropriate property map for their extrnal properties. A typical property map class requires only a few lines of code, so this is not difficult to do.

BGL does provide one builtin external property map, the random_access_iterator_property_map which provides a convient way to wrap up a random access iterator for use as a property map. This adaptor uses the vertex or edge ID property as an index with the random access iterator. Normal builtin arrays and pointers to arrays are examples of storage that naturally have random access iterators. Many of the BGL examples use arrays for property storage because they are fast and convenient.

For the adjacency_list with template parameter VertexList=vecS the random access iterator adaptor is not necessary and the random access iterators can be passed as-is into the algorithm. This is because the vertex descriptors of those classes are vertex ID's.

The Visitor Parameter

The visitor parameter gives the user the oportunity to insert their own operations into the graph algorithm, similar to the function objects used in the STL. How to use visitors is described in Section Visitor Concepts.


Copyright © 2000 Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu)