code: func (g *AcyclicGraph) depthFirstWalk(start []Vertex, sorted bool, f DepthWalkFunc) error {
  	defer g.debug.BeginOperation(typeDepthFirstWalk, "").End("")
  
  	seen := make(map[Vertex]struct{})
  	frontier := make([]*vertexAtDepth, len(start))
  	for i, v := range start {
  		frontier[i] = &vertexAtDepth{
  			Vertex: v,
  			Depth:  0,
  		}
  	}
  	for len(frontier) > 0 {
  		// Pop the current vertex
  		n := len(frontier)
  		current := frontier[n-1]
  		frontier = frontier[:n-1]
  
  		// Check if we've seen this already and return...
  		if _, ok := seen[current.Vertex]; ok {
  			continue
  		}
  		seen[current.Vertex] = struct{}{}
  
  		// Visit the current node
  		if err := f(current.Vertex, current.Depth); err != nil {
  			return err
  		}
  
  		// Visit targets of this in a consistent order.
  		targets := AsVertexList(g.DownEdges(current.Vertex))
  
  		if sorted {
  			sort.Sort(byVertexName(targets))
  		}
  
  		for _, t := range targets {
  			frontier = append(frontier, &vertexAtDepth{
  				Vertex: t,
  				Depth:  current.Depth + 1,
  			})
  		}
  	}
  
  	return nil
  }
docs: // This internal method provides the option of not sorting the vertices during
  // the walk, which we use for the Transitive reduction.
  // Some configurations can lead to fully-connected subgraphs, which makes our
  // transitive reduction algorithm O(n^3). This is still passable for the size
  // of our graphs, but the additional n^2 sort operations would make this
  // uncomputable in a reasonable amount of time.