diff --git a/doc/kevin_bacon.html b/doc/kevin_bacon.html index 984a89b7..661c4986 100644 --- a/doc/kevin_bacon.html +++ b/doc/kevin_bacon.html @@ -64,12 +64,12 @@ href="../example/kevin-bacon.cpp">examples/kevin-bacon.cpp. We have supplied a file kevin-bacon.dat which contains a list of actor pairs who appeared in the same movie. Each line of the file contains an actor's name, a movie, and another actor that appeared in -the movie. The ``|'' character is used as a separator. Here is an +the movie. The ``;'' character is used as a separator. Here is an excerpt.

-Patrick Stewart|Prince of Egypt, The (1998)|Steve Martin
+Patrick Stewart;Prince of Egypt, The (1998);Steve Martin
 

@@ -81,7 +81,7 @@ it. We use a std::ifstream to input the file. std::ifstream datafile("./kevin-bacon.dat"); if (!datafile) { cerr << "No ./kevin-bacon.dat file" << endl; - return -1; + return EXIT_FAILURE; } @@ -97,7 +97,7 @@ actors appearing together in a movie is symmetric. using namespace boost; typedef adjacency_list<vecS, vecS, undirectedS, property<vertex_name_t, string>, - property<edge_name_t, string, property<edge_weight_t, int> > + property<edge_name_t, string > > > Graph; @@ -107,22 +107,20 @@ objects from the graph. The following code shows how this is done.

-  boost::property_map<Graph, vertex_name_t>::type actor_name = get(vertex_name, g);
-  boost::property_map<Graph, edge_name_t>::type connecting_movie = get(edge_name, g);
-  boost::property_map<Graph, edge_weight_t>::type weight = get(edge_weight, g);
+  property_map<Graph, vertex_name_t>::type actor_name = get(vertex_name, g);
+  property_map<Graph, edge_name_t>::type connecting_movie = get(edge_name, g);
 

Next we can start to loop through the file, parsing each line into a -list of tokens. stringtok is a C++ version of the old -strtok standard C function. +sequence of tokens using the Boost +Tokenizer Library.

-  std::string line;
-  while (std::getline(datafile,line)) {
-    std::list<std::string> line_toks;
-    boost::stringtok(line_toks, line, "|");
+  for (std::string line; std::getline(datafile, line);) {
+    char_delimiters_separator<char> sep(false, "", ";");
+    tokenizer<> line_toks(line, sep);
     ...
   }
 
@@ -150,7 +148,7 @@ can be used to implement this mapping. The first token will be an actor's name. If the actor is not already in our actor's map we will add a vertex to the graph, set the name property of the vertex, and record the vertex descriptor in the map. -If the actor is already in the graph, we will retreive the vertex +If the actor is already in the graph, we will retrieve the vertex descriptor from the map's pos iterator.

@@ -159,16 +157,16 @@ descriptor from the map's pos iterator. bool inserted; Vertex u, v; - std::list<std::string>::iterator i = line_toks.begin(); + tokenizer<>::iterator i = line_toks.begin(); + std::string actors_name = *i++; - boost::tie(pos, inserted) = actors.insert(make_pair(*i, Vertex())); + tie(pos, inserted) = actors.insert(std::make_pair(actors_name, Vertex())); if (inserted) { u = add_vertex(g); - actor_name[u] = *i; + actor_name[u] = actors_name; pos->second = u; } else u = pos->second; - ++i;

@@ -180,7 +178,7 @@ actor into the graph.

   std::string movie_name = *i++;
       
-  boost::tie(pos, inserted) = actors.insert(make_pair(*i, Vertex()));
+  tie(pos, inserted) = actors.insert(std::make_pair(*i, Vertex()));
   if (inserted) {
     v = add_vertex(g);
     actor_name[v] = *i;
@@ -190,72 +188,81 @@ actor into the graph.
 

-The final step is to add an edge connecting the two actors, and -record the name of the connecting movie. We also set the weight -of the edge to one. Since we chose setS for the EdgeList -type of the adjacency_list, any parallel edges in the input -will not be inserted into the graph. +The final step is to add an edge connecting the two actors, and record +the name of the connecting movie.

-  Edge e;
-  boost::tie(e, inserted) = add_edge(u, v, g);
-  if (inserted) {
+  graph_traits<Graph>::edge_descriptor e;
+  tie(e, inserted) = add_edge(u, v, g);
+  if (inserted)
     connecting_movie[e] = movie_name;
-    weight[e] = 1;
+
+ +

+ +

A Custom Visitor Class

+ +

+We create a custom visitor class to record the Kevin Bacon +numbers. The Kevin Bacon number will be the shortest distances from +each actor to Kevin Bacon. This distance has also been referred to as +the ``Bacon Number'' in memory of the ``Erdos Number'' used to rank +mathematicians according to how many publications separate them from +Paul Erdos. The shortest distance to from Kevin Bacon to each actor +will follow the breadth-first tree. The BFS algorithm identifies edges +that belong to the breadth-first tree and calls our visitor's +tree_edge function. We record the distance to the target +vertex as one plus the distance to the source vertex. + + +

+  template <typename DistanceMap>
+  class bacon_number_recorder : public default_bfs_visitor
+  {
+  public:
+    bacon_number_recorder(DistanceMap dist) : d(dist) { }
+
+    template <typename Edge, typename Graph>
+    void tree_edge(Edge e, const Graph& g) const
+    {
+      typename graph_traits<Graph>::vertex_descriptor
+	u = source(e, g), v = target(e, g);
+	d[v] = d[u] + 1;
+    }
+  private:
+      DistanceMap d;
+  };
+  // Convenience function
+  template <typename DistanceMap>
+  bacon_number_recorder<DistanceMap>
+  record_bacon_number(DistanceMap d)
+  {
+    return bacon_number_recorder<DistanceMap>(d);
   }
 

- -

Applying Breadth-First Search

- -

-The documentation for breadth_first_search() -algorithm shows that we will need to provide property maps for color -and vertex ID. In addition, we will be using visitors to record -predecessors and distances so we will need property maps for these as -well. The distance will be the shortest distances from each actor to -Kevin Bacon calculated by the algorithm. This distance has also been -referred to as the ``Bacon Number'' in memory of the ``Erdos Number'' -used to rank mathematicians according to how many publications -separate them from Paul Erdos. We will use a vector to store the bacon -numbers, and another vector to store the color property needed by -the BFS algorithm. The predecessor vector will be used to -record the shortest path from each actor to Kevin. For each vertex, -the predecessor vector will contain a pointer to the next -vertex on the shortest path towards Kevin Bacon. +We will use a vector to store the bacon numbers.

   std::vector<int> bacon_number(num_vertices(g));
-  std::vector<int> color(num_vertices(g));
-  std::vector<Vertex> predecessor(num_vertices(g));
 
+

Apply the Breadth-First Search

+

-The BFS algorithm also requires a source vertex as input; of course -this will be Kevin Bacon. We now call the BGL BFS algorithm, passing -in the graph, source vertex, the property maps, and a visitor composed -of a predecessor and distance recorder. We use the predecessor_recorder -to record the predecessors and the distance_recorder to -record distances. +The BFS algorithm requires a source vertex as input; of course this +will be Kevin Bacon. We now call the BGL BFS algorithm, passing in the +graph, source vertex, and the visitor.

-    Vertex src = actors["Kevin Bacon"];
-    
-    breadth_first_search
-      (g, src, 
-       visitor(make_bfs_visitor
-	       (make_list(record_predecessors(&predecessor[0], 
-					      on_examine_edge()),
-			  record_distances(&bacon_number[0],
-					   on_examine_edge()))))
-       );
+  Vertex src = actors["Kevin Bacon"];
+  bacon_number[src] = 0;
+
+  breadth_first_search(g, src, visitor(record_bacon_number(&bacon_number[0])));
 

@@ -265,10 +272,10 @@ through all the vertices in the graph and use them to index into the

-    graph_traits<Graph>::vertex_iterator i, end;
-    for (boost::tie(i, end) = vertices(g); i != end; ++i)
-      std::cout << actor_name[*i] << "'s bacon number is " 
-                << bacon_number[*i] << std::endl;
+  graph_traits<Graph>::vertex_iterator i, end;
+  for (boost::tie(i, end) = vertices(g); i != end; ++i)
+    std::cout << actor_name[*i] << "'s bacon number is " 
+              << bacon_number[*i] << std::endl;
 

@@ -283,10 +290,6 @@ HREF="../../property_map/iterator_property_map.html">iterator_property_map Here are some excepts from the output of the program.

-William Shatner was in Loaded Weapon 1 (1993) with Denise Richards
-Denise Richards was in Wild Things (1998) with Kevin Bacon
-Patrick Stewart was in Prince of Egypt, The (1998) with Steve Martin
-...
 William Shatner's bacon number is 2
 Denise Richards's bacon number is 1
 Kevin Bacon's bacon number is 0