0 | module Libraries.Data.Graph
3 | import Data.SortedMap
4 | import Data.SortedSet
9 | record TarjanVertex where
16 | record TarjanState cuid where
18 | vertices : SortedMap cuid TarjanVertex
21 | components : List (List1 cuid)
22 | impossibleHappened : Bool
24 | initial : Ord cuid => TarjanState cuid
25 | initial = TS empty [] 0 [] False
32 | tarjan : Ord cuid => SortedMap cuid (SortedSet cuid) -> List (List1 cuid)
33 | tarjan {cuid} deps = loop initial (SortedMap.keys deps)
35 | strongConnect : TarjanState cuid -> cuid -> TarjanState cuid
36 | strongConnect ts v =
37 | let ts'' = case SortedMap.lookup v deps of
39 | Just edgeSet => loop ts' (Prelude.toList edgeSet)
40 | in case SortedMap.lookup v ts''.vertices of
41 | Nothing => { impossibleHappened := True } ts''
43 | if vtv.index == vtv.lowlink
44 | then createComponent ts'' v []
47 | createComponent : TarjanState cuid -> cuid -> List cuid -> TarjanState cuid
48 | createComponent ts v acc =
50 | [] => { impossibleHappened := True } ts
52 | let ts' : TarjanState cuid = {
53 | vertices $= updateExisting { inStack := False } w,
57 | then { components $= ((v ::: acc) ::) } ts'
58 | else createComponent ts' v (w :: acc)
60 | loop : TarjanState cuid -> List cuid -> TarjanState cuid
64 | case SortedMap.lookup w ts.vertices of
65 | Nothing => let ts' = strongConnect ts w in
66 | case SortedMap.lookup w ts'.vertices of
67 | Nothing => { impossibleHappened := True } ts'
68 | Just wtv => { vertices $= updateExisting { lowlink $= min wtv.lowlink } v } ts'
70 | Just wtv => case wtv.inStack of
72 | True => { vertices $= updateExisting { lowlink $= min wtv.index } v } ts
75 | ts' : TarjanState cuid
77 | vertices $= SortedMap.insert v (TV ts.nextIndex ts.nextIndex True),
82 | loop : TarjanState cuid -> List cuid -> List (List1 cuid)
84 | if ts.impossibleHappened
88 | case SortedMap.lookup v ts.vertices of
89 | Just _ => loop ts vs
90 | Nothing => loop (strongConnect ts v) vs