       try callback(.finish(vertex), &self, &workList)
     }  // end while loop
   }
-}
-
-extension IncidenceGraph where Self: VertexListGraph, VertexId: IdIndexable {
+
+  /// Runs breadth first search on `graph` starting from `startVertices`; `callback` is invoked at
+  /// key events during the search.
+  ///
+  /// - Precondition: `startVertices` is non-empty.
+  public mutating func breadthFirstSearch<
+    StartVertices: Collection,
+    VertexVisitationState: PropertyMap
+  >(
+    startingAt startVertices: StartVertices,
+    vertexVisitationState: inout VertexVisitationState,
+    callback: BFSCallback
+  ) rethrows
+  where
+    StartVertices.Element == VertexId,
+    VertexVisitationState.Graph == Self,
+    VertexVisitationState.Key == VertexId,
+    VertexVisitationState.Value == VertexColor
+  {
+    var queue = Deque<VertexId>()
+    try self.breadthFirstSearch(
+      startingAt: startVertices,
+      workList: &queue,
+      vertexVisitationState: &vertexVisitationState
+    ) { e, g, q in
+      try callback(e, &g)
+    }
+  }
+}
+
+extension IncidenceGraph where Self: VertexListGraph, VertexId: IdIndexable & Hashable {
+  // Disambiguation of method call when VertexId is both IdIndexable and Hashable;
+  // uses a table for the color map.
+  /// Runs breadth first search on `graph` starting from `startVertices`; `callback` is invoked at
+  /// key events during the search.
+  ///
+  /// - Precondition: `startVertices` is non-empty.
+  public mutating func breadthFirstSearch<
+    StartVertices: Collection
+  >(
+    startingAt startVertices: StartVertices,
+    callback: BFSCallback
+  ) rethrows
+  where
+    StartVertices.Element == VertexId
+  {
+    var vertexVisitationState = TablePropertyMap(repeating: VertexColor.white, forVerticesIn: self)
+    try self.breadthFirstSearch(
+      startingAt: startVertices,
+      vertexVisitationState: &vertexVisitationState,
+      callback: callback)
+  }
+
   /// Runs breadth first search on `graph` starting from `startVertex`; `callback` is invoked at
   /// key events during the search.
   public mutating func breadthFirstSearch(

  /// modify the work list of vertices.
  public typealias BFSCallbackWithWorkList<WorkList: Queue> =
    (BFSEvent<Self>, inout Self, inout WorkList) throws -> Void

  /// Runs breadth first search on `graph` starting from `startVertices`; `callback` is invoked at
  /// key events during the search.
  ///
  /// - Precondition: `startVertices` is non-empty.
  public mutating func breadthFirstSearch<
    StartVertices: Collection
  >(
    startingAt startVertices: StartVertices,
    callback: BFSCallback
  ) rethrows
  where
    StartVertices.Element == VertexId,
    VertexId: IdIndexable
  {
    var vertexVisitationState = TablePropertyMap(repeating: VertexColor.white, forVerticesIn: self)
    var queue = Deque<VertexId>()
    try self.breadthFirstSearch(
      startingAt: startVertices,
      workList: &queue,
      vertexVisitationState: &vertexVisitationState
    ) { e, g, q in
      try callback(e, &g)
    }
  }

  /// Runs breadth first search on `graph` using `vertexVisitationState` to keep track of search
  /// progress; `callback` is invoked at key events during the search.

  case finish(Vertex)
}

extension IncidenceGraph {
  /// A hook to observe events that occur during depth first search.
  public typealias BFSCallback = (BFSEvent<Self>, inout Self) throws -> Void

