Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.

Commit 6ac5833

Browse files
committed
Generalise scc and topSort
1 parent 73d1804 commit 6ac5833

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/output/
12
/js/
23
/externs/
34
/node_modules/

src/Data/Graph.purs.hs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ module Data.Graph (
33
Graph(..),
44

55
scc,
6-
topSort
6+
scc',
7+
8+
topSort,
9+
topSort'
710
) where
811

912
import Data.Maybe
10-
import Data.Array (reverse, concatMap)
13+
import Data.Array (map, reverse, concatMap)
1114
import Data.Foldable
1215
import Data.Traversable
1316

@@ -25,7 +28,10 @@ data Graph v = Graph [v] [Edge v]
2528
type Index = Number
2629

2730
scc :: forall v. (Eq v, Ord v) => Graph v -> [[v]]
28-
scc (Graph vs es) = runPure (runST (do
31+
scc = scc' id
32+
33+
scc' :: forall k v. (Eq k, Ord k) => (v -> k) -> Graph v -> [[v]]
34+
scc' makeKey (Graph vs es) = runPure (runST (do
2935
index <- newSTRef 0
3036
path <- newSTRef []
3137
indexMap <- newSTRef M.empty
@@ -35,11 +41,11 @@ scc (Graph vs es) = runPure (runST (do
3541
(let
3642
indexOf v = do
3743
m <- readSTRef indexMap
38-
return $ M.lookup v m
44+
return $ M.lookup (makeKey v) m
3945

4046
lowlinkOf v = do
4147
m <- readSTRef lowlinkMap
42-
return $ M.lookup v m
48+
return $ M.lookup (makeKey v) m
4349

4450
go [] = readSTRef components
4551
go (v : vs) = do
@@ -50,13 +56,13 @@ scc (Graph vs es) = runPure (runST (do
5056
strongConnect v = do
5157
i <- readSTRef index
5258

53-
modifySTRef indexMap $ M.insert v i
54-
modifySTRef lowlinkMap $ M.insert v i
59+
modifySTRef indexMap $ M.insert (makeKey v) i
60+
modifySTRef lowlinkMap $ M.insert (makeKey v) i
5561

5662
writeSTRef index $ i + 1
5763
modifySTRef path $ (:) v
5864

59-
for es $ \(Edge v' w) -> when (v == v') $ do
65+
for es $ \(Edge v' w) -> when (makeKey v == makeKey v') $ do
6066
wIndex <- indexOf w
6167
currentPath <- readSTRef path
6268

@@ -65,27 +71,27 @@ scc (Graph vs es) = runPure (runST (do
6571
strongConnect w
6672
wLowlink <- lowlinkOf w
6773
for_ wLowlink $ \lowlink ->
68-
modifySTRef lowlinkMap $ M.alter (maybeMin lowlink) v
69-
_ -> when (w `elem` currentPath) $ do
74+
modifySTRef lowlinkMap $ M.alter (maybeMin lowlink) (makeKey v)
75+
_ -> when (makeKey w `elem` map makeKey currentPath) $ do
7076
wIndex <- indexOf w
7177
for_ wIndex $ \index ->
72-
modifySTRef lowlinkMap $ M.alter (maybeMin index) v
78+
modifySTRef lowlinkMap $ M.alter (maybeMin index) (makeKey v)
7379

7480
vIndex <- indexOf v
7581
vLowlink <- lowlinkOf v
7682

7783
when (vIndex == vLowlink) $ do
7884
currentPath <- readSTRef path
79-
let newPath = popUntil v currentPath []
85+
let newPath = popUntil makeKey v currentPath []
8086
modifySTRef components $ flip (++) [newPath.component]
8187
writeSTRef path newPath.path
8288
return {}
8389
in go vs)))
8490

85-
popUntil :: forall v. (Eq v) => v -> [v] -> [v] -> { path :: [v], component :: [v] }
86-
popUntil _ [] popped = { path: [], component: popped }
87-
popUntil v (w : path) popped | v == w = { path: path, component: w : popped }
88-
popUntil v (w : ws) popped = popUntil v ws (w : popped)
91+
popUntil :: forall k v. (Eq k) => (v -> k) -> v -> [v] -> [v] -> { path :: [v], component :: [v] }
92+
popUntil _ _ [] popped = { path: [], component: popped }
93+
popUntil makeKey v (w : path) popped | makeKey v == makeKey w = { path: path, component: w : popped }
94+
popUntil makeKey v (w : ws) popped = popUntil makeKey v ws (w : popped)
8995

9096
maybeMin :: Index -> Maybe Index -> Maybe Index
9197
maybeMin i Nothing = Just i
@@ -95,4 +101,7 @@ maybeMin i (Just j) = Just $ Math.min i j
95101
-- Topological sort
96102
--
97103
topSort :: forall v. (Eq v, Ord v) => Graph v -> [v]
98-
topSort = reverse <<< concatMap id <<< scc
104+
topSort = topSort' id
105+
106+
topSort' :: forall k v. (Eq k, Ord k) => (v -> k) -> Graph v -> [v]
107+
topSort' makeKey = reverse <<< concatMap id <<< scc' makeKey

0 commit comments

Comments
 (0)