import StdEnv, StdMaybe
import Data.Map => qualified updateAt
-:: St a = {nextindex :: Int, stack :: [a], map :: Map a Annot, sccs :: [[a]]}
+:: St a = {nextindex :: Int, stack :: [a], map :: Map a Annot, sccs :: [[a]]}
:: Annot = {index :: Int, lowlink :: Int, onstack :: Bool}
scc :: [(a, [a])] -> [[a]] | Eq, Ord a
-scc nodes = reverse (foldr strongconnect {nextindex=0,stack=[],map=newMap,sccs=[]} nodes).sccs
+scc nodes = reverse (foldr (strongconnect nodes) {nextindex=zero,stack=[],map=newMap,sccs=[]} nodes).sccs
where
-// strongconnect :: (a, [a]) (St a) -> St a | Eq, Ord a
- strongconnect (v, suc) s
+ strongconnect :: [(a, [a])] (a, [a]) (St a) -> St a | Eq, Ord a
+ strongconnect nodes (v, suc) s
| isJust (get v s.map) = s
- # s = foldr processSucc
+ # s = foldr (processSucc nodes v)
{ s & map = put v {index=s.nextindex, lowlink=s.nextindex, onstack=True} s.map
, stack = [v:s.stack]
- , nextindex = s.nextindex + 1
+ , nextindex = inc s.nextindex
} suc
# (Just a) = get v s.map
- | a.index == a.lowlink
- # (scc, [sl:stack]) = span ((<>) v) s.stack
- # scc = scc ++ [sl]
- = { s & sccs = [scc:s.sccs]
- , stack = stack
- , map = foldr (alter \(Just s)->Just {s & onstack=False}) s.map scc
- }
- = s
+ | a.index <> a.lowlink = s
+ # (scc, [sl:stack]) = span ((<>) v) s.stack
+ # scc = scc ++ [sl]
+ = { s & sccs = [scc:s.sccs]
+ , stack = stack
+ , map = foldr (alter \(Just s)->Just {s & onstack=False}) s.map scc
+ }
where
-// processSucc :: a (St a) -> St a | Eq, Ord a
- processSucc w s = case get w s.map of
+ processSucc :: [(a, [a])] a a (St a) -> St a | Eq, Ord a
+ processSucc nodes v w s = case get w s.map of
Nothing
- # n = [l\\l=:(n, _)<-nodes | n == w]
+ # n = filter ((==)w o fst) nodes
| n =: [] = s
- # s = strongconnect (hd n) s
+ # s = strongconnect nodes (hd n) s
# (Just aw) = get w s.map
# (Just av) = get v s.map
= {s & map=put v {av & lowlink=min av.lowlink aw.lowlink} s.map}