11module Data.Graph (
22 Edge (..),
33 Graph (..),
4+ SCC (..),
5+
6+ vertices ,
47
58 scc ,
69 scc' ,
@@ -27,10 +30,26 @@ data Graph k v = Graph [v] [Edge k]
2730
2831type Index = Number
2932
30- scc :: forall v . (Eq v , Ord v ) => Graph v v -> [[v ]]
33+ data SCC v = AcyclicSCC v | CyclicSCC [v ]
34+
35+ instance showSCC :: (Show v ) => Show (SCC v ) where
36+ show (AcyclicSCC v) = " AcyclicSCC (" ++ show v ++ " )"
37+ show (CyclicSCC vs) = " CyclicSCC " ++ show vs
38+
39+ instance eqSCC :: (Eq v ) => Eq (SCC v ) where
40+ (==) (AcyclicSCC v1) (AcyclicSCC v2) = v1 == v2
41+ (==) (CyclicSCC vs1) (CyclicSCC vs2) = vs1 == vs2
42+ (==) _ _ = false
43+ (/=) scc1 scc2 = not (scc1 == scc2)
44+
45+ vertices :: forall v . SCC v -> [v ]
46+ vertices (AcyclicSCC v) = [v]
47+ vertices (CyclicSCC vs) = vs
48+
49+ scc :: forall v . (Eq v , Ord v ) => Graph v v -> [SCC v ]
3150scc = scc' id id
3251
33- scc' :: forall k v . (Eq k , Ord k ) => (v -> k ) -> (k -> v ) -> Graph k v -> [[ v ] ]
52+ scc' :: forall k v . (Eq k , Ord k ) => (v -> k ) -> (k -> v ) -> Graph k v -> [SCC v ]
3453scc' makeKey makeVert (Graph vs es) = runPure (runST (do
3554 index <- newSTRef 0
3655 path <- newSTRef []
@@ -90,10 +109,15 @@ scc' makeKey makeVert (Graph vs es) = runPure (runST (do
90109 when (vIndex == vLowlink) $ do
91110 currentPath <- readSTRef path
92111 let newPath = popUntil makeKey v currentPath []
93- modifySTRef components $ flip (++) [newPath.component]
112+ modifySTRef components $ flip (++) [makeComponent newPath.component]
94113 writeSTRef path newPath.path
95114 return {}
96- in go vs)))
115+
116+ makeComponent [v] | not (isCycle (makeKey v)) = AcyclicSCC v
117+ makeComponent vs = CyclicSCC vs
118+
119+ isCycle k = any (\(Edge k1 k2) -> k1 == k && k2 == k) es
120+ in go vs)))
97121
98122popUntil :: forall k v . (Eq k ) => (v -> k ) -> v -> [v ] -> [v ] -> { path :: [v ], component :: [v ] }
99123popUntil _ _ [] popped = { path: [] , component: popped }
@@ -111,4 +135,4 @@ topSort :: forall v. (Eq v, Ord v) => Graph v v -> [v]
111135topSort = topSort' id id
112136
113137topSort' :: forall k v . (Eq k , Ord k ) => (v -> k ) -> (k -> v ) -> Graph k v -> [v ]
114- topSort' makeKey makeVert = reverse <<< concatMap id <<< scc' makeKey makeVert
138+ topSort' makeKey makeVert = reverse <<< concatMap vertices <<< scc' makeKey makeVert
0 commit comments