public static IGraphNavigator BFSpanningTree(IEnumerable roots, IGraphNavigator navigator, 
      DNodePredicate avoid) 
    {
      BFSpanningBuilder bfb = new BFSpanningBuilder();

      bfs(roots, navigator, avoid, null, new DEdgeVisitor(bfb.VisitEdge));

      return bfb;
    }
    /// <summary>
    /// Does a breadth first traversal of the given graph
    /// </summary>
    /// <param name="roots">The roots of the traversal.</param>
    /// <param name="avoid">If not null, is a predicate to avoid certain nodes</param>
    /// <param name="visitRoot">If not null, called for each root that is not avoided.</param>
    /// <param name="visitEdge">Called for each edges in the bf traversal, i.e., only for edges going to unvisited nodes.</param>
    public static void bfs(IEnumerable roots, IGraphNavigator navigator,
      DNodePredicate avoid,
      DNodeVisitor visitRoot,
      DEdgeVisitor visitEdge)
    {
      Queue queue = new Queue();
      IMutableSet seen = new HashSet();

      // initialize queue with roots
      foreach(object o in roots) 
      {
        if (avoid==null || !avoid(o)) 
        {
          queue.Enqueue(o);
          seen.Add(o);
          if (visitRoot != null) visitRoot(o);
        }
      }

      while(queue.Count > 0) 
      {
        object node = queue.Dequeue();
        foreach(object succ in navigator.NextNodes(node)) 
        {
          if ((avoid == null || !avoid(succ)) && !seen.Contains(succ)) 
          {
            seen.Add(succ);
            queue.Enqueue(succ);
            visitEdge(node, succ);
          }
        }
      }
    }
    /// <summary>
    /// DFS traversal of the (sub)graph rooted in a set of nodes.
    /// </summary>
    /// <param name="roots">Roots of the traversed subgraph. The subgraph
    /// rooted in the first root will be traversed in DFS order; next, if
    /// the second root wasn't reached yet, the subgraph rooted in it will
    /// be traversed in DFS order and so on. The order of
    /// the roots is given by the corresponding <c>IEnumerator</c>.</param>
    /// <param name="navigator">Navigator that describes the graph structure.</param>
    /// <param name="avoid">Encountered nodes that satisfy this predicate will be
    /// ignored by the DFS traversal (together with their attached arcs). <c>null</c>
    /// corresponds to the predicate that is always false (i.e., no encountered node
    /// will be ignored).</param>
    /// <param name="new_subgraph_visitor">Visitor for the root node of each
    /// new subgraph: the roots (see the roots parameter)
    /// are explored in order; if a root node has not been already reached
    /// by the DFS traversal of the previous roots, <c>new_subgraph_visitor</c>
    /// will be called on it, and next the subgraph rooted in it will be DFS
    /// traversed.</param>
    /// <param name="begin_visitor">Node visitor to be called when a node is reached
    /// for the first time by the DFS traversal. <c>null</c> corresponds to no
    /// visitor.</param>
    /// <param name="end_visitor">Node visitor to be called when the exploration of
    /// a node has finished. <c>null</c> corresponds to no visitor.</param>
    public static void SearchDepthFirst (
      IEnumerable roots, 
      IGraphNavigator navigator,
      DNodePredicate avoid,
      DNodeVisitor new_subgraph_visitor,
      DNodeVisitor begin_visitor,
      DNodeVisitor end_visitor
      )
    {
      // set of already seen nodes
      IMutableSet seen_nodes = new HashSet();
      // DFS Stack: holds the currently explored path; simulates the call
      // stack of a recursive implementation of DFS.
      Stack/*<NodeInfo>*/ stack = new Stack();

      foreach(object root in roots)
      {
        if( ((avoid != null) && avoid(root)) ||
          seen_nodes.Contains(root)) continue;

        call_visitor(new_subgraph_visitor, root);

        seen_nodes.Add(root);
        call_visitor(begin_visitor, root);
        stack.Push(new NodeInfo(root, navigator));
        while(stack.Count != 0)
        {
          NodeInfo info = (NodeInfo) stack.Peek();
          if(info.enext.MoveNext())
          {
            object next_node = info.enext.Current;
            // ignore nodes as dictated by "avoid"
            if((avoid != null) && avoid(next_node))
              continue;
						
            if(!seen_nodes.Contains(next_node))
            {
              // new and non-avoidable node!
              // mark it as seen,
              seen_nodes.Add(next_node);
              // call the begin visitor,
              call_visitor(begin_visitor, next_node);
              // and put the node on the DFS stack
              stack.Push(new NodeInfo(next_node, navigator));
            }
          }
          else 
          {
            // the visit of info.node has finished
            // apply end visitor
            call_visitor(end_visitor, info.node);
            // remove the top of the stack
            stack.Pop();
          }
        }
      }
    }
 /// <summary>
 /// Convenient <c>DFS</c> function.  Call the full <c>dfs</c> function
 /// with new_subgraph_visitor set to <c>null</c>.
 /// </summary>
 public static void dfs (
   IEnumerable roots, 
   IGraphNavigator navigator,
   DNodePredicate avoid,
   DNodeVisitor begin_visitor,
   DNodeVisitor end_visitor)
 {
   SearchDepthFirst(roots, navigator, avoid, null, begin_visitor, end_visitor);
 }
 public static ISet ReachableNodes (DSetFactory setfactory, IEnumerable roots, IGraphNavigator navigator, DNodePredicate avoid)
 {
   ReachableNodesData data = new ReachableNodesData(setfactory);
   SearchDepthFirst(roots, navigator, avoid, null,
     new DNodeVisitor(data.reachable_visitor), null);
   return data.all_nodes;
 }