{Record G:make}
Where
Let (make MAP)
Let compare MAP.compare
In
Let ADJ
{Record
vertex:Func item. item.0
neighbors:Func item. item.1}
Let SET (SEARCH.SET compare)
In
Let (min a b) If (a < b) a b
In
Define (traverse g adj i stack preorder assigned components)
Let v (ADJ.vertex adj)
Let neighbors (ADJ.neighbors adj)
In
Let preorder (MAP.insert preorder {v i})
Let stack (v :: stack)
In
Let {link i' stack preorder assigned components}
(LIST.reduce neighbors
{i (i + 1) stack preorder assigned components}
Func state w.
Let {link i stack preorder assigned components} state
In
Match (SET.search assigned w)
| `just._ state
| `nothing
Match (MAP.search preorder w)
| `just.{_ j}
Let link (min link j)
In
{link i stack preorder assigned components}
| `nothing
Let adj
Match (MAP.search g w)
| `nothing {w []}
| `just.adj adj
;
In
Let {link' i stack preorder assigned components}
(traverse g adj i stack preorder assigned
components)
In
Let link (min link link')
In
{link i stack preorder assigned components}
;
;)
In
If (i = link)
Block
Let {c stack assigned}
Iterate {c stack assigned} From {[] stack assigned}
Match stack
| `cons.{w stack}
Let assigned (SET.insert assigned w)
In
Match (compare w v)
| `equal {(v :: c) stack assigned}
| _ Continue {(w :: c) stack assigned}
;
;
In
{link i' stack preorder assigned (c :: components)}
{link i' stack preorder assigned components}
In
Let (strongly_connected_components g)
Iterate {g adjs i stack preorder assigned components}
From {g (MAP.list g) 0 [] MAP.empty SET.empty []}
Match adjs
| `nil (LIST.reverse components)
| `cons.{adj adjs}
Match (SET.search assigned (ADJ.vertex adj))
| `just._
Continue {g adjs i stack preorder assigned components}
| `nothing
Let {link i stack preorder assigned components}
(traverse g adj i stack preorder assigned components)
In
Continue {g adjs i stack preorder assigned components}
;
;
In
Let (layers g)
Iterate {layers adjs} From {[] (MAP.list g)}
Let {layer adjs}
(LIST.fold adjs {[] []}
Func {v neighbors} {layer adjs}.
Match neighbors
| `nil {(v :: layer) adjs}
| `cons._ {layer ({v neighbors} :: adjs)}
;)
In
Match layer
| `nil layers
| `cons._
Let removed (LIST.reduce layer SET.empty SET.insert)
In
Let adjs
(LIST.map adjs
Func {v neighbors}.
Let neighbors
(SET.list
(SET.diff (SET.new neighbors) removed))
In
{v neighbors})
In
Continue {(layer :: layers) adjs}
;
In
{Record strongly_connected_components layers}
Where
Let die OS.die
Where
Let LIST Package "list"
Let OS Package "os"
Let SEARCH Package "search"
Let STDIO Package "stdio"