Advanced Functional Programming Tim Sheard 1 Lecture 17 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture 17: Erwig style - Functional Graphs DFS – style of depth first search
Advanced Functional Programming Tim Sheard 2 Lecture 17 References The style of representing graphs, and most of the examples, come from the work of Martin Erwig Functional Programming with Graphs 2nd ACM SIGPLAN Int. Conf. on Functional Programming (ICFP'97), 52-65, 1997(ICFP'97) Inductive Graphs and Functional Graph AlgorithmsInductive Graphs and Functional Graph Algorithms, Martin Erwig Journal of Functional Programming,
Advanced Functional Programming Tim Sheard 3 Lecture 17 Graphs Nodes = 1,2,3 Edges = (1,2),(2,1),(3,1),(2,3) Node Labels = a,b,c Edge Labels = right,left,up,down 1 a c b 2 3 right left down up
Advanced Functional Programming Tim Sheard 4 Lecture 17 Types type Node = Int type LNode a = (Node,a) type UNode = LNode () type Edge = (Node,Node) type LEdge b = (Node,Node,b) type UEdge = LEdge ()
Advanced Functional Programming Tim Sheard 5 Lecture 17 More Types data Graph a b -- Abstract Type --unlabled Graph type UGraph = Graph () () type Path = [Node] type LPath a = [LNode a] type UPath = [UNode]
Advanced Functional Programming Tim Sheard 6 Lecture 17 Making Graphs ex1 = mkGraph [(1,"a"),(2,"b"),(3,"c")] [(1,2,"right"),(2,1,"left"), (2,3,"down"),(3,1,"up")] Main> ex1 1:"a"->[("right",2)] 2:"b"->[("left",1),("down",3)] 3:"c"->[("up",1)] 1 a c b 2 3 right left down up
Advanced Functional Programming Tim Sheard 7 Lecture 17 Looking inside noNodes :: Graph a b -> Int nodes :: Graph a b -> [Node] labNodes :: Graph a b -> [LNode a] -- [(Node,a)] edges :: Graph a b -> [Edge] --[(Node,Node)] labEdges :: Graph a b -> [LEdge b] -– [(Node,Node,b)]
Advanced Functional Programming Tim Sheard 8 Lecture 17 Examples Main> noNodes ex1 3 Main> nodes ex1 [1,2,3] Main> labEdges ex1 [(1,2,"right"),(2,1,"left"), (2,3,"down"),(3,1,"up")] 1 a c b 2 3 right left down up
Advanced Functional Programming Tim Sheard 9 Lecture 17 Decomposing Graphs type Adj b = [(b,Node)] type Context a b = (Adj b,Node,a,Adj b) type MContext a b = Maybe (Context a b) type Decomp a b = (MContext a b,Graph a b) type GDecomp a b = (Context a b,Graph a b) type UContext = ([Node],Node,[Node]) type UDecomp = (Maybe UContext,UGraph) match :: Node -> Graph a b -> Decomp a b edge label Its predecessors Its succesors The node Its label
Advanced Functional Programming Tim Sheard 10 Lecture 17 (Just(ps,n,lab,ss),ex2) = match 2 ex1 Main> ps [("right",1)] --predecessors Main> ss --successors [("left",1),("down",3)] Main> n –- the node 2 Main> lab -- its label "b" Main> ex2 1:"a"->[] 3:"c"->[("up",1)] 1 a c b 2 3 right left down up
Advanced Functional Programming Tim Sheard 11 Lecture 17 (Just(ps2,n2,lab2,ss2),ex3) = match 3 ex2 Main> ps2 [] Main> n2 3 Main> lab2 "c" Main> ss2 [("up",1)] Main> ex3 1:"a"->[] 1 a c 3 up
Advanced Functional Programming Tim Sheard 12 Lecture 17 Constructing Graphs Inductively empty :: Graph a b embed :: Context a b -> Graph a b -> Graph a b infixr & c & g = embed c g ex4 = (ps2,n2,lab2,ss2) & ex3 Main> ex4 1:"a"->[] 3:"c"->[("up",1)] 1 a c 3 up
Advanced Functional Programming Tim Sheard 13 Lecture 17 Operations on graphs -- maps on nodes nmap :: (a->c) -> Graph a b -> Graph c b -- maps on edges emap :: (b->c) -> Graph a b -> Graph a c -- graph reversal grev :: Graph a b -> Graph a b
Advanced Functional Programming Tim Sheard 14 Lecture 17 Example ex5 = nmap (ord. head) ex1 Main> ex5 1:97->[("right",2)] 2:98->[("down",3),("left",1)] 3:99->[("up",1)] Main> ex1 1:"a"->[("right",2)] 2:"b"->[("left",1),("down",3)] 3:"c"->[("up",1)]
Advanced Functional Programming Tim Sheard 15 Lecture 17 Example 2 ex6 = emap length ex1 Main> ex6 1:"a"->[(5,2)] 2:"b"->[(4,3),(4,1)] 3:"c"->[(2,1)] Main> ex1 1:"a"->[("right",2)] 2:"b"->[("left",1),("down",3)] 3:"c"->[("up",1)]
Advanced Functional Programming Tim Sheard 16 Lecture 17 Roll your own mymap f g | isEmpty g = empty | otherwise = let ns = nodes g (Just(ps,n,lab,ss),g2) = match (head ns) g in (ps,n,f lab,ss) & (mymap f g2)
Advanced Functional Programming Tim Sheard 17 Lecture 17 Depth First Search data Tree a = Branch a [Tree a] deriving Show df :: Node -> Graph b a -> (Tree b,Graph b a) df root g = let (Just(_,v,lab,ss), g') = match root g (r,g1) = dff ss g' in (Branch lab r,g1) dff :: [(c,Node)] -> Graph b c -> ([Tree b],Graph b c) dff [] g = ([],g) dff ((lab,v):l) g = let (x,g1) = df v g (y,g2) = dff l g1 in (x:y,g2)
Advanced Functional Programming Tim Sheard 18 Lecture 17 Example ex7 = fst (df 1 ex1) Main> ex7 Branch "c" [Branch "b" [Branch "a" []]]
Advanced Functional Programming Tim Sheard 19 Lecture 17 Launchbury & King “Structuring Depth-First Search Algorithms in Haskell” David King and John Launchbury - POPL ’95 – pp Graph algorithms based upon Depth First Search. Asymtotically efficient – uses lazy state
Advanced Functional Programming Tim Sheard 20 Lecture 17 Representing Graphs import ST import qualified Array as A type Vertex = Int -- Representing graphs: type Table a = A.Array Vertex a type Graph = Table [Vertex] -- Array Int [Int] Index for each node Edges (out of) that index [2,3] 2[7,4] 3[5] 4[6,9,7] 5[8] 6[9] 7 8[10] 9 10[]
Advanced Functional Programming Tim Sheard 21 Lecture 17 Functions on graphs type Vertex = Int type Edge = (Vertex,Vertex) vertices :: Graph -> [Vertex] indices :: Graph -> [Int] edges :: Graph -> [Edge]
Advanced Functional Programming Tim Sheard 22 Lecture 17 Building Graphs buildG :: Bounds -> [Edge] -> Graph graph = buildG (1,10) [ (1, 2), (1, 6), (2, 3), (2, 5), (3, 1), (3, 4), (5, 4), (7, 8), (7, 10), (8, 6), (8, 9), (8, 10) ]
Advanced Functional Programming Tim Sheard 23 Lecture 17 DFS and Forests data Tree a = Node a (Forest a) type Forest a = [Tree a] nodesTree (Node a f) ans = nodesForest f (a:ans) nodesForest [] ans = ans nodesForest (t : f) ans = nodesTree t (nodesForest f ans) Note how any tree can be spanned by a Forest. The Forest is not always unique
Advanced Functional Programming Tim Sheard 24 Lecture 17 DFS The DFS algorithm finds a spanning forest for a graph, from a set of roots. dfs :: Graph -> [Vertex] -> Forest Vertex dfs g vs = prune (A.bounds g) (map (generate g) vs) generate :: Graph -> Vertex -> Tree Vertex generate g v = Node v (map (generate g) (g `aat` v))
Advanced Functional Programming Tim Sheard 25 Lecture 17 Sets of nodes already visited type Set s = STArray s Vertex Bool mkEmpty :: Bounds -> ST s (Set s) mkEmpty bnds = newSTArray bnds False contains :: Set s -> Vertex -> ST s Bool contains m v = readSTArray m v include :: Set s -> Vertex -> ST s () include m v = writeSTArray m v True
Advanced Functional Programming Tim Sheard 26 Lecture 17 Pruning already visited paths prune :: Bounds -> Forest Vertex -> Forest Vertex prune bnds ts = runST (do { m <- mkEmpty bnds; chop m ts }) chop :: Set s -> Forest Vertex -> ST s (Forest Vertex) chop m [] = return [] chop m (Node v ts : us) do { visited <- contains m v ; if visited then chop m us else do { include m v ; as <- chop m ts ; bs <- chop m us ; return(Node v as : bs) }
Advanced Functional Programming Tim Sheard 27 Lecture 17 Topological Sort postorder :: Tree a -> [a] postorder (Node a ts) = postorderF ts ++ [a] postorderF :: Forest a -> [a] postorderF ts = concat (map postorder ts) postOrd :: Graph -> [Vertex] postOrd = postorderF. Dff dff :: Graph -> Forest Vertex dff g = dfs g (vertices g)