fb-util-0.1.0.1: Util/Graph.hs
{-
Copyright (c) Meta Platforms, Inc. and affiliates.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree.
-}
module Util.Graph
( postorder
) where
import Data.Hashable
import qualified Data.HashSet as HashSet
import qualified Data.HashMap.Strict as HashMap
-- | Post-order traversal of a graph: guarantees that the dependents
-- of a node occur before it in the result list, while as far as
-- possible retaining the original order of the nodes.
postorder
:: (Hashable vertex, Eq vertex)
=> [node]
-- ^ Nodes in the order of traversal
-> (node -> vertex)
-- ^ Extract a hashable vertex from the node
-> (node -> [vertex])
-- ^ Out-edges from a node. Vertices that aren't in the set of
-- nodes are ignored.
-> [node]
-- ^ Result of post-order traversal
postorder nodes vert out = go HashSet.empty nodes (\_ -> [])
where
m = HashMap.fromList [ (vert n, n) | n <- nodes ]
go seen [] cont = cont seen
go seen (n : nodes) cont
| v `HashSet.member` seen = go seen nodes cont
| otherwise = go (HashSet.insert v seen) deps
(\seen -> n : go seen nodes cont)
where
v = vert n
deps = [ n | v <- out n, Just n <- [HashMap.lookup v m] ]