Skip to content

Commit

Permalink
fix graph tests
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangjunphy committed Jun 13, 2024
1 parent b7f8170 commit c758d3c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 44 deletions.
21 changes: 11 additions & 10 deletions src/Util/Graph.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ module Util.Graph
, build
, strictlyDominate
, strictlyPostDominate
, traverseM_
, topologicalTraverse
) where

import Control.Lens ((%=))
import Control.Monad
import Control.Monad.Except
import Control.Monad.State
import Data.Monoid
import Data.Functor
import Data.Generics.Labels
import Data.List qualified as List
Expand Down Expand Up @@ -144,8 +145,8 @@ update bd init =
build :: (Eq ni, Ord ni) => GraphBuilder ni nd ed a -> Either Text (Graph ni nd ed)
build bd = update bd empty

traverseM_ :: (Eq ni, Ord ni, Monad m) => (ni -> nd -> m a) -> Graph ni nd ed -> m ()
traverseM_ f g@Graph {nodes = nodes} = recurse initIndegree g
topologicalTraverse :: (Eq ni, Ord ni, Monoid (f a)) => (ni -> nd -> f a) -> Graph ni nd ed -> f a
topologicalTraverse f g@Graph {nodes = nodes} = recurse initIndegree g
where
initIndegree = Map.mapWithKey (\i d -> length $ inBound i g) nodes
findZeroIndegree :: Map ni Int -> [ni]
Expand All @@ -154,14 +155,14 @@ traverseM_ f g@Graph {nodes = nodes} = recurse initIndegree g
let m' = List.foldl' (\m (_, ni, _) -> Map.adjust (\x -> x - 1) ni m) m $ outBound i g
m'' = Map.delete i m'
in m''
recurse indegree g = do
recurse indegree g =
let zeroIndegree = findZeroIndegree indegree
case zeroIndegree of
[] -> return ()
(n : ns) -> do
f n (Maybe.fromJust $ lookupNode n g)
let indegree' = updateIndegree n indegree g
recurse indegree' g
in case zeroIndegree of
[] -> mempty
(n : ns) ->
let ele = f n (Maybe.fromJust $ lookupNode n g)
indegree' = updateIndegree n indegree g
in ele <> recurse indegree' g

newtype Memoize ni m a = Memoize
{ unmem :: State m a
Expand Down
57 changes: 23 additions & 34 deletions test/GraphSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,25 @@ specTrivialGraph = do
in Map.size (Graph.nodes trivialGraph) == 2
where
constructTrivialGraph = do
Graph.addNode "1" "d1"
Graph.addNode "2" "d2"
Graph.addEdge "1" "2" "1-2"
Graph.addNode 1 "d1"
Graph.addNode 2 "d2"
Graph.addEdge 1 2 "1-2"

specCyclicGraph :: SpecWith ()
specCyclicGraph = do
it "construct a cyclic graph" $
let constructG = do
Graph.addNode "1" "d1"
Graph.addNode "2" "d2"
Graph.addNode "3" "d3"
Graph.addEdge "1" "2" "1-2"
Graph.addEdge "2" "3" "2-3"
Graph.addEdge "3" "1" "3-1"
Graph.addNode 1 "d1"
Graph.addNode 2 "d2"
Graph.addNode 3 "d3"
Graph.addEdge 1 2 "1-2"
Graph.addEdge 2 3 "2-3"
Graph.addEdge 3 1 "3-1"
(Right cyclicGraph) = Graph.build constructG
in Map.size (Graph.nodes cyclicGraph) == 3
&& Map.size (Graph.edges cyclicGraph) == 3
&& ( let inEdges = Graph.inBound "3" cyclicGraph
outEdges = Graph.outBound "3" cyclicGraph
&& ( let inEdges = Graph.inBound 3 cyclicGraph
outEdges = Graph.outBound 3 cyclicGraph
in length inEdges == 1
&& getNodeData ((\(src, _, _) -> src) (head inEdges) ) cyclicGraph == Just "d2"
&& length outEdges == 1
Expand All @@ -71,32 +71,21 @@ specCyclicGraph = do
where
getNodeData n g = Map.lookup n (Graph.nodes g)

newtype TraverseMonad ni a = TraverseMonad
{runTraverse :: State [ni] a}
deriving
( Functor,
Applicative,
Monad,
MonadState [ni]
)

sortedList :: (Ord ni) => Graph ni nd ed -> [ni]
sortedList g =
let (_, s) = (runState $ runTraverse (Graph.traverseM_ (\ni _ -> modify' (\l -> l ++ [ni])) g)) []
in s
topologicalSort :: (Ord ni) => Graph ni nd ed -> [ni]
topologicalSort = Graph.topologicalTraverse (\ni _ -> [ni])

traverseGraph :: SpecWith ()
traverseGraph = do
it "traverse graph in topological order" $
let constructG = do
Graph.addNode "1" "d1"
Graph.addNode "2" "d2"
Graph.addNode "3" "d3"
Graph.addNode "4" "d4"
Graph.addEdge "4" "2" "4-2"
Graph.addEdge "4" "3" "4-3"
Graph.addEdge "2" "1" "2-1"
Graph.addEdge "3" "1" "3-1"
Graph.addNode 1 "d1"
Graph.addNode 2 "d2"
Graph.addNode 3 "d3"
Graph.addNode 4 "d4"
Graph.addEdge 4 2 "4-2"
Graph.addEdge 4 3 "4-3"
Graph.addEdge 2 1 "2-1"
Graph.addEdge 3 1 "3-1"
(Right graph) = Graph.build constructG
lst = sortedList graph
in head lst == "4" && last lst == "1"
lst = topologicalSort graph
in head lst == 4 && last lst == 1

0 comments on commit c758d3c

Please sign in to comment.