packages feed

ghc-9.14.1: GHC/Data/Graph/Directed/Internal.hs

module GHC.Data.Graph.Directed.Internal where

import GHC.Prelude
import GHC.Utils.Outputable

import Data.Array
import qualified Data.Graph as G
import Data.Graph ( Vertex, SCC(..) ) -- Used in the underlying representation
import Data.Tree

data Graph node = Graph {
    gr_int_graph      :: IntGraph,
    gr_vertex_to_node :: Vertex -> node,
    gr_node_to_vertex :: node -> Maybe Vertex
}

data Edge node = Edge node node

------------------------------------------------------------
-- Nodes and Edges
------------------------------------------------------------

verticesG :: Graph node -> [node]
verticesG graph = map (gr_vertex_to_node graph) $ G.vertices (gr_int_graph graph)

edgesG :: Graph node -> [Edge node]
edgesG graph = map (\(v1, v2) -> Edge (v2n v1) (v2n v2)) $ G.edges (gr_int_graph graph)
  where v2n = gr_vertex_to_node graph

------------------------------------------------------------
-- Showing Graphs
------------------------------------------------------------

instance Outputable node => Outputable (Graph node) where
    ppr graph = vcat [
                  hang (text "Vertices:") 2 (vcat (map ppr $ verticesG graph)),
                  hang (text "Edges:") 2 (vcat (map ppr $ edgesG graph))
                ]

instance Outputable node => Outputable (Edge node) where
    ppr (Edge from to) = ppr from <+> text "->" <+> ppr to

{-
************************************************************************
*                                                                      *
*      IntGraphs
*                                                                      *
************************************************************************
-}

type IntGraph = G.Graph

------------------------------------------------------------
-- Depth first search numbering
------------------------------------------------------------

-- Data.Tree has flatten for Tree, but nothing for Forest
preorderF           :: Forest a -> [a]
preorderF ts         = concatMap flatten ts

------------------------------------------------------------
-- Finding reachable vertices
------------------------------------------------------------

-- This generalizes reachable which was found in Data.Graph
reachable    :: IntGraph -> [Vertex] -> [Vertex]
reachable g vs = preorderF (G.dfs g vs)

scc :: IntGraph -> [SCC Vertex]
scc graph = map decode forest
  where
    forest = {-# SCC "Digraph.scc" #-} G.scc graph

    decode (Node v []) | mentions_itself v = CyclicSCC [v]
                       | otherwise         = AcyclicSCC v
    decode other = CyclicSCC (dec other [])
      where dec (Node v ts) vs = v : foldr dec vs ts
    mentions_itself v = v `elem` (graph ! v)