fgl (empty) → 5.3
raw patch · 31 files changed
+3577/−0 lines, 31 filesdep +basedep +mtlbuild-type:Customsetup-changed
Dependencies added: base, mtl
Files
- Data/Graph/Inductive.hs +33/−0
- Data/Graph/Inductive/Basic.hs +126/−0
- Data/Graph/Inductive/Example.hs +187/−0
- Data/Graph/Inductive/Graph.hs +476/−0
- Data/Graph/Inductive/Graphviz.hs +69/−0
- Data/Graph/Inductive/Internal/FiniteMap.hs +209/−0
- Data/Graph/Inductive/Internal/Heap.hs +91/−0
- Data/Graph/Inductive/Internal/Queue.hs +26/−0
- Data/Graph/Inductive/Internal/RootPath.hs +51/−0
- Data/Graph/Inductive/Internal/Thread.hs +149/−0
- Data/Graph/Inductive/Monad.hs +227/−0
- Data/Graph/Inductive/Monad/IOArray.hs +112/−0
- Data/Graph/Inductive/NodeMap.hs +248/−0
- Data/Graph/Inductive/Query.hs +29/−0
- Data/Graph/Inductive/Query/ArtPoint.hs +122/−0
- Data/Graph/Inductive/Query/BCC.hs +75/−0
- Data/Graph/Inductive/Query/BFS.hs +131/−0
- Data/Graph/Inductive/Query/DFS.hs +222/−0
- Data/Graph/Inductive/Query/Dominators.hs +40/−0
- Data/Graph/Inductive/Query/GVD.hs +51/−0
- Data/Graph/Inductive/Query/Indep.hs +24/−0
- Data/Graph/Inductive/Query/MST.hs +41/−0
- Data/Graph/Inductive/Query/MaxFlow.hs +127/−0
- Data/Graph/Inductive/Query/MaxFlow2.hs +263/−0
- Data/Graph/Inductive/Query/Monad.hs +227/−0
- Data/Graph/Inductive/Query/SP.hs +32/−0
- Data/Graph/Inductive/Query/TransClos.hs +21/−0
- Data/Graph/Inductive/Tree.hs +99/−0
- LICENSE +28/−0
- Setup.hs +2/−0
- fgl.cabal +39/−0
+ Data/Graph/Inductive.hs view
@@ -0,0 +1,33 @@+------------------------------------------------------------------------------+-- +-- Inductive.hs -- Functional Graph Library +--+-- (c) 1999-2006 by Martin Erwig [see file COPYRIGHT]+--+------------------------------------------------------------------------------++module Data.Graph.Inductive(+ module Data.Graph.Inductive.Graph,+ module Data.Graph.Inductive.Tree,+ module Data.Graph.Inductive.Basic,+ module Data.Graph.Inductive.Monad,+ module Data.Graph.Inductive.Monad.IOArray,+ module Data.Graph.Inductive.Query,+ module Data.Graph.Inductive.Graphviz,+ module Data.Graph.Inductive.NodeMap,+ -- * Version Information+ version+) where++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Tree+import Data.Graph.Inductive.Basic+import Data.Graph.Inductive.Monad+import Data.Graph.Inductive.Monad.IOArray+import Data.Graph.Inductive.Query+import Data.Graph.Inductive.Graphviz+import Data.Graph.Inductive.NodeMap++-- | Version info+version :: IO ()+version = putStrLn "\nFGL - Functional Graph Library, June 2006"
+ Data/Graph/Inductive/Basic.hs view
@@ -0,0 +1,126 @@+-- (c) 1999 - 2002 by Martin Erwig [see file COPYRIGHT]+-- | Basic Graph Algorithms+module Data.Graph.Inductive.Basic+(+ -- * Graph Operations+ grev,+ undir,unlab,+ gsel, gfold,+ -- * Filter Operations+ efilter,elfilter,+ -- * Predicates and Classifications+ hasLoop,isSimple,+ -- * Tree Operations+ postorder, postorderF, preorder, preorderF+) +where+++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Internal.Thread (threadMaybe,threadList)++import Data.List (nub)+import Data.Tree++-- | Reverse the direction of all edges.+grev :: DynGraph gr => gr a b -> gr a b +grev = gmap (\(p,v,l,s)->(s,v,l,p))++-- | Make the graph undirected, i.e. for every edge from A to B, there+-- exists an edge from B to A.+undir :: (Eq b,DynGraph gr) => gr a b -> gr a b+undir = gmap (\(p,v,l,s)->let ps = nub (p++s) in (ps,v,l,ps))+-- this version of undir considers edge lables and keeps edges with+-- different labels, an alternative is the definition below:+-- undir = gmap (\(p,v,l,s)->+-- let ps = nubBy (\x y->snd x==snd y) (p++s) in (ps,v,l,ps))++-- | Remove all labels.+unlab :: DynGraph gr => gr a b -> gr () ()+unlab = gmap (\(p,v,_,s)->(unlabAdj p,v,(),unlabAdj s))+ where unlabAdj = map (\(_,v)->((),v))+-- alternative:+-- unlab = nmap (\_->()) . emap (\_->())++-- | Return all 'Context's for which the given function returns 'True'.+gsel :: Graph gr => (Context a b -> Bool) -> gr a b -> [Context a b]+gsel p = ufold (\c cs->if p c then c:cs else cs) []+++-- filter operations+--+-- efilter : filter based on edge property+-- elfilter : filter based on edge label property+--++-- | Filter based on edge property.+efilter :: DynGraph gr => (LEdge b -> Bool) -> gr a b -> gr a b+efilter f = ufold cfilter empty+ where cfilter (p,v,l,s) g = (p',v,l,s') & g+ where p' = filter (\(b,u)->f (u,v,b)) p+ s' = filter (\(b,w)->f (v,w,b)) s++-- | Filter based on edge label property.+elfilter :: DynGraph gr => (b -> Bool) -> gr a b -> gr a b+elfilter f = efilter (\(_,_,b)->f b)+++-- some predicates and classifications+--++-- | 'True' if the graph has any edges of the form (A, A).+hasLoop :: Graph gr => gr a b -> Bool+hasLoop = not . null . (gsel (\c->(node' c `elem` suc' c)))++-- | The inverse of 'hasLoop'.+isSimple :: Graph gr => gr a b -> Bool+isSimple = not . hasLoop+++threadGraph f c = threadMaybe f c match++-- gfold1 f d b u = threadGraph (\c->d (labNode' c)) (\c->gfoldn f d b u (f c))+gfold1 f d b = threadGraph d (\c->gfoldn f d b (f c))+gfoldn f d b = threadList b (gfold1 f d b)++-- gfold :: ((Context a b) -> [Node]) -> ((Node,a) -> c -> d) -> +-- (Maybe d -> c -> c) -> c -> [Node] -> Graph a b -> c+-- gfold f d b u l g = fst (gfoldn f d b u l g)++-- type Dir a b = (Context a b) -> [Node] -- direction of fold+-- type Dagg a b c = (Node,a) -> b -> c -- depth aggregation+-- type Bagg a b = (Maybe a -> b -> b,b) -- breadth/level aggregation+-- +-- gfold :: (Dir a b) -> (Dagg a c d) -> (Bagg d c) -> [Node] -> Graph a b -> c+-- gfold f d (b,u) l g = fst (gfoldn f d b u l g)++-- | Directed graph fold.+gfold :: Graph gr => ((Context a b) -> [Node]) -- ^ direction of fold+ -> ((Context a b) -> c -> d) -- ^ depth aggregation+ -> (Maybe d -> c -> c, c) -- ^ breadth\/level aggregation+ -> [Node]+ -> gr a b+ -> c+gfold f d b l g = fst (gfoldn f d b l g)++-- not finished yet ...+--+-- undirBy :: (b -> b -> b) -> Graph a b -> Graph a b+-- undirBy = gmap (\(p,v,l,s)->let ps = nub (p++s) in (ps,v,l,ps))++-- | Flatten a 'Tree', returning the elements in post-order.+postorder :: Tree a -> [a]+postorder (Node v ts) = postorderF ts ++ [v]++-- | Flatten multiple 'Tree's in post-order.+postorderF :: [Tree a] -> [a]+postorderF = concatMap postorder++-- | Flatten a 'Tree', returning the elements in pre-order. Equivalent to+--'flatten' in 'Data.Tree'.+preorder :: Tree a -> [a]+preorder = flatten++-- | Flatten multiple 'Tree's in pre-order.+preorderF :: [Tree a] -> [a]+preorderF = concatMap preorder
+ Data/Graph/Inductive/Example.hs view
@@ -0,0 +1,187 @@+-- | Example Graphs+module Data.Graph.Inductive.Example(+ -- * Auxiliary Functions+ genUNodes, genLNodes, labUEdges, noEdges,+ -- * Small Dynamic Graphs+ a, b, c, e, loop, ab, abb, dag3, e3, cyc3, g3, g3b, dag4, d1, d3,+ -- * Small Static Graphs+ a', b', c', e', loop', ab', abb', dag3', e3', dag4', d1', d3',+ -- * Functions to Create (Regular) Graphs+ ucycle, star, ucycleM, starM,+ -- * More Graphs+ -- | clr : Cormen\/Leiserson\/Rivest++ -- | kin : Kingston++ -- ** Dynamic Versions+ clr479, clr489, clr486, clr508, clr528, clr595, gr1, kin248, vor,+ -- ** Static Versions+ clr479', clr489', clr486', clr508', clr528', kin248', vor'+)where+++import Data.Graph.Inductive+import Data.Graph.Inductive.Tree+import Data.Graph.Inductive.Monad+import Data.Graph.Inductive.Monad.IOArray++-- | generate list of unlabeled nodes+genUNodes :: Int -> [UNode]+genUNodes n = zip [1..n] (repeat ())++-- | generate list of labeled nodes+genLNodes :: Enum a => a -> Int -> [LNode a]+genLNodes q i = take i (zip [1..] [q..])++-- | denote unlabeled edges+labUEdges :: [Edge] -> [UEdge]+labUEdges = map (\(i,j) -> (i,j,()))++-- | empty (unlabeled) edge list+noEdges :: [UEdge]+noEdges = [] +++a,b,c,e,loop,ab,abb,dag3 :: Gr Char ()+e3 :: Gr () String+cyc3,g3,g3b :: Gr Char String+dag4 :: Gr Int ()+d1,d3 :: Gr Int Int++a = ([],1,'a',[]) & empty -- just a node+b = mkGraph (zip [1..2] "ab") noEdges -- just two nodes+c = mkGraph (zip [1..3] "abc") noEdges -- just three nodes+e = ([((),1)],2,'b',[]) & a -- just one edge a-->b+e3 = mkGraph (genUNodes 2) + [(1,2,"a"),(1,2,"b"),(1,2,"a")] -- three edges (two labels) a-->b+loop = ([],1,'a',[((),1)]) & empty -- loop on single node+ab = ([((),1)],2,'b',[((),1)]) & a -- cycle of two nodes: a<-->b+abb = mkGraph (zip [1..2] "ab") (labUEdges [(2,2)]) -- a and loop on b++cyc3 = buildGr -- cycle of three nodes+ [([("ca",3)],1,'a',[("ab",2)]),+ ([],2,'b',[("bc",3)]),+ ([],3,'c',[])]++dag3 = mkGraph (zip [1..3] "abc") (labUEdges [(1,3)])+dag4 = mkGraph (genLNodes 1 4) (labUEdges [(1,2),(1,4),(2,3),(2,4),(4,3)])++d1 = mkGraph (genLNodes 1 2) [(1,2,1)]+d3 = mkGraph (genLNodes 1 3) [(1,2,1),(1,3,4),(2,3,2)] ++g3 = ([("left",2),("up",3)],1,'a',[("right",2)]) & (+ ([],2,'b',[("down",3)]) & (+ ([],3,'c',[]) & empty ))+g3b = ([("down",2)], 3,'c',[("up",1)]) & (+ ([("right",1)],2,'b',[("left",1)]) & (+ ([],1,'a',[]) & empty ))+++a',b',c',e',loop',ab',abb',dag3' :: IO (SGr Char ())+e3' :: IO (SGr () String)+dag4' :: IO (SGr Int ())+d1',d3' :: IO (SGr Int Int)++a' = mkGraphM [(1,'a')] noEdges -- just a node+b' = mkGraphM (zip [1..2] "ab") noEdges -- just two nodes+c' = mkGraphM (zip [1..3] "abc") noEdges -- just three nodes+e' = mkGraphM (zip [1..2] "ab") [(1,2,())] -- just one edge a-->b+e3' = mkGraphM (genUNodes 2) + [(1,2,"a"),(1,2,"b"),(1,2,"a")] -- three edges (two labels) a-->b+loop' = mkGraphM [(1,'a')] [(1,1,())] -- loop on single node+ab' = mkGraphM (zip [1..2] "ab") + [(1,2,()),(2,1,())] -- cycle of two nodes: a<-->b+abb' = mkGraphM (zip [1..2] "ab") (labUEdges [(2,2)]) -- a and loop on b++dag3' = mkGraphM (zip [1..3] "abc") (labUEdges [(1,3)])+dag4' = mkGraphM (genLNodes 1 4) (labUEdges [(1,2),(1,4),(2,3),(2,4),(4,3)])++d1' = mkGraphM (genLNodes 1 2) [(1,2,1)]+d3' = mkGraphM (genLNodes 1 3) [(1,2,1),(1,3,4),(2,3,2)] ++ucycle :: Graph gr => Int -> gr () ()+ucycle n = mkUGraph vs (map (\v->(v,v `mod` n+1)) vs)+ where vs = [1..n]++star :: Graph gr => Int -> gr () ()+star n = mkUGraph [1..n] (map (\v->(1,v)) [2..n])++ucycleM :: GraphM m gr => Int -> m (gr () ())+ucycleM n = mkUGraphM vs (map (\v->(v,v `mod` n+1)) vs)+ where vs = [1..n]++starM :: GraphM m gr => Int -> m (gr () ())+starM n = mkUGraphM [1..n] (map (\v->(1,v)) [2..n])+++clr479,clr489 :: Gr Char ()+clr486 :: Gr String ()+clr508,clr528 :: Gr Char Int+clr595,gr1 :: Gr Int Int+kin248 :: Gr Int ()+vor :: Gr String Int++clr479 = mkGraph (genLNodes 'u' 6) + (labUEdges [(1,2),(1,4),(2,5),(3,5),(3,6),(4,2),(5,4),(6,6)])+clr486 = mkGraph (zip [1..9] ["shorts","socks","watch","pants","shoes",+ "shirt","belt","tie","jacket"])+ (labUEdges [(1,4),(1,5),(2,5),(4,5),(4,7),(6,7),(6,8),(7,9),(8,9)])+clr489 = mkGraph (genLNodes 'a' 8)+ (labUEdges [(1,2),(2,3),(2,5),(2,6),(3,4),(3,7),(4,3),(4,8),+ (5,1),(5,6),(6,7),(7,6),(7,8),(8,8)])+clr508 = mkGraph (genLNodes 'a' 9)+ [(1,2,4),(1,8,8),(2,3,8),(2,8,11),(3,4,7),(3,6,4),(3,9,2),+ (4,5,9),(4,6,14),(5,6,10),(6,7,2),(7,8,1),(7,9,6),(8,9,7)]+clr528 = mkGraph [(1,'s'),(2,'u'),(3,'v'),(4,'x'),(5,'y')]+ [(1,2,10),(1,4,5),(2,3,1),(2,4,2),(3,5,4),+ (4,2,3),(4,3,9),(4,5,2),(5,1,7),(5,3,6)]+clr595 = mkGraph (zip [1..6] [1..6]) + [(1,2,16),(1,3,13),(2,3,10),(2,4,12),(3,2,4),+ (3,5,14),(4,3,9),(4,6,20),(5,4,7),(5,6,4)]+gr1 = mkGraph (zip [1..10] [1..10]) + [(1,2,12),(1,3,1),(1,4,2),(2,3,1),(2,5,7),(2,6,5),(3,6,1),+ (3,7,7),(4,3,3),(4,6,2),(4,7,5),(5,3,2),(5,6,3),(5,8,3),+ (6,7,2),(6,8,3),(6,9,1),(7,9,9),(8,9,1),(8,10,4),(9,10,11)]+kin248 = mkGraph (genLNodes 1 10)+ (labUEdges [(1,2),(1,4),(1,7),(2,4),(2,5),(3,4),(3,10),+ (4,5),(4,8),(5,2),(5,3),(6,7),(7,6),(7,8),+ (8,10),(9,9),(9,10),(10,8),(10,9)])+ -- this is the inverse graph shown on the bottom of the page++vor = mkGraph (zip [1..8] ["A","B","C","H1","H2","D","E","F"])+ [(1,4,3),(2,3,3),(2,4,3),(4,2,4),(4,6,2),+ (5,2,5),(5,3,6),(5,7,5),(5,8,6),+ (6,5,3),(6,7,2),(7,8,3),(8,7,3)]+++clr479',clr489' :: IO (SGr Char ())+clr486' :: IO (SGr String ())+clr508',clr528' :: IO (SGr Char Int)+kin248' :: IO (SGr Int ())+vor' :: IO (SGr String Int)++clr479' = mkGraphM (genLNodes 'u' 6) + (labUEdges [(1,2),(1,4),(2,5),(3,5),(3,6),(4,2),(5,4),(6,6)])+clr486' = mkGraphM (zip [1..9] ["shorts","socks","watch","pants","shoes",+ "shirt","belt","tie","jacket"])+ (labUEdges [(1,4),(1,5),(2,5),(4,5),(4,7),(6,7),(6,8),(7,9),(8,9)])+clr489' = mkGraphM (genLNodes 'a' 8)+ (labUEdges [(1,2),(2,3),(2,5),(2,6),(3,4),(3,7),(4,3),(4,8),+ (5,1),(5,6),(6,7),(7,6),(7,8),(8,8)])+clr508' = mkGraphM (genLNodes 'a' 9)+ [(1,2,4),(1,8,8),(2,3,8),(2,8,11),(3,4,7),(3,6,4),(3,9,2),+ (4,5,9),(4,6,14),(5,6,10),(6,7,2),(7,8,1),(7,9,6),(8,9,7)]+clr528' = mkGraphM [(1,'s'),(2,'u'),(3,'v'),(4,'x'),(5,'y')]+ [(1,2,10),(1,4,5),(2,3,1),(2,4,2),(3,5,4),+ (4,2,3),(4,3,9),(4,5,2),(5,1,7),(5,3,6)]+kin248' = mkGraphM (genLNodes 1 10)+ (labUEdges [(1,2),(1,4),(1,7),(2,4),(2,5),(3,4),(3,10),+ (4,5),(4,8),(5,2),(5,3),(6,7),(7,6),(7,8),+ (8,10),(9,9),(9,10),(10,8),(10,9)])+ -- this is the inverse graph shown on the bottom of the page++vor' = mkGraphM (zip [1..8] ["A","B","C","H1","H2","D","E","F"])+ [(1,4,3),(2,3,3),(2,4,3),(4,2,4),(4,6,2),+ (5,2,5),(5,3,6),(5,7,5),(5,8,6),+ (6,5,3),(6,7,2),(7,8,3),(8,7,3)]+
+ Data/Graph/Inductive/Graph.hs view
@@ -0,0 +1,476 @@+-- (c) 1999-2005 by Martin Erwig [see file COPYRIGHT]+-- | Static and Dynamic Inductive Graphs +module Data.Graph.Inductive.Graph (+ -- * General Type Defintions+ -- ** Node and Edge Types+ Node,LNode,UNode,+ Edge,LEdge,UEdge,+ -- ** Types Supporting Inductive Graph View+ Adj,Context,MContext,Decomp,GDecomp,UDecomp,+ Path,LPath(..),UPath,+ -- * Graph Type Classes+ -- | We define two graph classes:+ --+ -- Graph: static, decomposable graphs.+ -- Static means that a graph itself cannot be changed+ -- + -- DynGraph: dynamic, extensible graphs.+ -- Dynamic graphs inherit all operations from static graphs+ -- but also offer operations to extend and change graphs.+ --+ -- Each class contains in addition to its essential operations those+ -- derived operations that might be overwritten by a more efficient+ -- implementation in an instance definition.+ -- + -- Note that labNodes is essentially needed because the default definition+ -- for matchAny is based on it: we need some node from the graph to define+ -- matchAny in terms of match. Alternatively, we could have made matchAny + -- essential and have labNodes defined in terms of ufold and matchAny. + -- However, in general, labNodes seems to be (at least) as easy to define + -- as matchAny. We have chosen labNodes instead of the function nodes since + -- nodes can be easily derived from labNodes, but not vice versa.+ Graph(..), + DynGraph(..),+ -- * Operations+ -- ** Graph Folds and Maps+ ufold,gmap,nmap,emap,+ -- ** Graph Projection+ nodes,edges,newNodes,gelem,+ -- ** Graph Construction and Destruction+ insNode,insEdge,delNode,delEdge,delLEdge,+ insNodes,insEdges,delNodes,delEdges,+ buildGr,mkUGraph,+ -- ** Graph Inspection+ context,lab,neighbors,+ suc,pre,lsuc,lpre,+ out,inn,outdeg,indeg,deg,+ equal,+ -- ** Context Inspection+ node',lab',labNode',neighbors',+ suc',pre',lpre',lsuc',+ out',inn',outdeg',indeg',deg',+) where+++import Data.List (sortBy)+++{- Signatures:++-- basic operations+empty :: Graph gr => gr a b+isEmpty :: Graph gr => gr a b -> Bool+match :: Graph gr => Node -> gr a b -> Decomp gr a b+mkGraph :: Graph gr => [LNode a] -> [LEdge b] -> gr a b+(&) :: DynGraph gr => Context a b -> gr a b -> gr a b++-- graph folds and maps+ufold :: Graph gr => ((Context a b) -> c -> c) -> c -> gr a b -> c+gmap :: Graph gr => (Context a b -> Context c d) -> gr a b -> gr c d+nmap :: Graph gr => (a -> c) -> gr a b -> gr c b+emap :: Graph gr => (b -> c) -> gr a b -> gr a c++-- graph projection+matchAny :: Graph gr => gr a b -> GDecomp g a b+nodes :: Graph gr => gr a b -> [Node]+edges :: Graph gr => gr a b -> [Edge]+labNodes :: Graph gr => gr a b -> [LNode a]+labEdges :: Graph gr => gr a b -> [LEdge b]+newNodes :: Graph gr => Int -> gr a b -> [Node]+noNodes :: Graph gr => gr a b -> Int+nodeRange :: Graph gr => gr a b -> (Node,Node)+gelem :: Graph gr => Node -> gr a b -> Bool++-- graph construction & destruction+insNode :: DynGraph gr => LNode a -> gr a b -> gr a b+insEdge :: DynGraph gr => LEdge b -> gr a b -> gr a b+delNode :: Graph gr => Node -> gr a b -> gr a b+delEdge :: DynGraph gr => Edge -> gr a b -> gr a b+delLEdge :: (DynGraph gr, Eq b) =>+ LEdge b -> gr a b -> gr a b+insNodes :: DynGraph gr => [LNode a] -> gr a b -> gr a b+insEdges :: DynGraph gr => [LEdge b] -> gr a b -> gr a b+delNodes :: Graph gr => [Node] -> gr a b -> gr a b+delEdges :: DynGraph gr => [Edge] -> gr a b -> gr a b+buildGr :: DynGraph gr => [Context a b] -> gr a b+mkUGraph :: DynGraph gr => [Node] -> [Edge] -> gr () ()++-- graph inspection+context :: Graph gr => gr a b -> Node -> Context a b+lab :: Graph gr => gr a b -> Node -> Maybe a+neighbors :: Graph gr => gr a b -> Node -> [Node] +suc :: Graph gr => gr a b -> Node -> [Node]+pre :: Graph gr => gr a b -> Node -> [Node] +lsuc :: Graph gr => gr a b -> Node -> [(Node,b)]+lpre :: Graph gr => gr a b -> Node -> [(Node,b)] +out :: Graph gr => gr a b -> Node -> [LEdge b] +inn :: Graph gr => gr a b -> Node -> [LEdge b] +outdeg :: Graph gr => gr a b -> Node -> Int+indeg :: Graph gr => gr a b -> Node -> Int+deg :: Graph gr => gr a b -> Node -> Int++-- context inspection+node' :: Context a b -> Node+lab' :: Context a b -> a+labNode' :: Context a b -> LNode a+neighbors' :: Context a b -> [Node] +suc' :: Context a b -> [Node]+pre' :: Context a b -> [Node] +lpre' :: Context a b -> [(Node,b)] +lsuc' :: Context a b -> [(Node,b)]+out' :: Context a b -> [LEdge b] +inn' :: Context a b -> [LEdge b] +outdeg' :: Context a b -> Int+indeg' :: Context a b -> Int+deg' :: Context a b -> Int++-}++-- | Unlabeled node+type Node = Int +-- | Labeled node+type LNode a = (Node,a) +-- | Quasi-unlabeled node+type UNode = LNode () ++-- | Unlabeled edge+type Edge = (Node,Node) +-- | Labeled edge+type LEdge b = (Node,Node,b) +-- | Quasi-unlabeled edge+type UEdge = LEdge () ++-- | Unlabeled path+type Path = [Node] +-- | Labeled path+newtype LPath a = LP [LNode a]++instance Show a => Show (LPath a) where+ show (LP xs) = show xs++-- | Quasi-unlabeled path+type UPath = [UNode] ++-- | Labeled links to or from a 'Node'.+type Adj b = [(b,Node)]+-- | Links to the 'Node', the 'Node' itself, a label, links from the 'Node'.+type Context a b = (Adj b,Node,a,Adj b) -- Context a b "=" Context' a b "+" Node+type MContext a b = Maybe (Context a b)+-- | 'Graph' decomposition - the context removed from a 'Graph', and the rest+-- of the 'Graph'.+type Decomp g a b = (MContext a b,g a b)+-- | The same as 'Decomp', only more sure of itself.+type GDecomp g a b = (Context a b,g a b)++-- | Unlabeled context.+type UContext = ([Node],Node,[Node])+-- | Unlabeled decomposition.+type UDecomp g = (Maybe UContext,g)++-- | Minimum implementation: 'empty', 'isEmpty', 'match', 'mkGraph', 'labNodes'+class Graph gr where+ -- essential operations+ -- | An empty 'Graph'.+ empty :: gr a b+ -- | True if the given 'Graph' is empty.+ isEmpty :: gr a b -> Bool+ -- | Decompose a 'Graph' into the 'MContext' found for the given node and the+ -- remaining 'Graph'.+ match :: Node -> gr a b -> Decomp gr a b+ -- | Create a 'Graph' from the list of 'LNode's and 'LEdge's.+ mkGraph :: [LNode a] -> [LEdge b] -> gr a b+ -- | A list of all 'LNode's in the 'Graph'.+ labNodes :: gr a b -> [LNode a]+ -- derived operations+ -- | Decompose a graph into the 'Context' for an arbitrarily-chosen 'Node'+ -- and the remaining 'Graph'.+ matchAny :: gr a b -> GDecomp gr a b+ -- | The number of 'Node's in a 'Graph'.+ noNodes :: gr a b -> Int+ -- | The minimum and maximum 'Node' in a 'Graph'.+ nodeRange :: gr a b -> (Node,Node)+ -- | A list of all 'LEdge's in the 'Graph'.+ labEdges :: gr a b -> [LEdge b]+ -- default implementation of derived operations+ matchAny g = case labNodes g of+ [] -> error "Match Exception, Empty Graph"+ (v,_):_ -> (c,g') where (Just c,g') = match v g + noNodes = length . labNodes + nodeRange g = (minimum vs,maximum vs) where vs = map fst (labNodes g)+ labEdges = ufold (\(_,v,_,s)->((map (\(l,w)->(v,w,l)) s)++)) []+++class Graph gr => DynGraph gr where+ -- | Merge the 'Context' into the 'DynGraph'.+ (&) :: Context a b -> gr a b -> gr a b+++-- | Fold a function over the graph.+ufold :: Graph gr => ((Context a b) -> c -> c) -> c -> gr a b -> c+ufold f u g | isEmpty g = u+ | otherwise = f c (ufold f u g') + where (c,g') = matchAny g++-- | Map a function over the graph.+gmap :: DynGraph gr => (Context a b -> Context c d) -> gr a b -> gr c d+gmap f = ufold (\c->(f c&)) empty++-- | Map a function over the 'Node' labels in a graph.+nmap :: DynGraph gr => (a -> c) -> gr a b -> gr c b+nmap f = gmap (\(p,v,l,s)->(p,v,f l,s))++-- | Map a function over the 'Edge' labels in a graph.+emap :: DynGraph gr => (b -> c) -> gr a b -> gr a c+emap f = gmap (\(p,v,l,s)->(map1 f p,v,l,map1 f s))+ where map1 g = map (\(l,v)->(g l,v))++-- | List all 'Node's in the 'Graph'.+nodes :: Graph gr => gr a b -> [Node]+nodes = map fst . labNodes++-- | List all 'Edge's in the 'Graph'.+edges :: Graph gr => gr a b -> [Edge]+edges = map (\(v,w,_)->(v,w)) . labEdges++-- | List N available 'Node's, i.e. 'Node's that are not used in the 'Graph'.+newNodes :: Graph gr => Int -> gr a b -> [Node]+newNodes i g = [n+1..n+i] where (_,n) = nodeRange g++-- | 'True' if the 'Node' is present in the 'Graph'.+gelem :: Graph gr => Node -> gr a b -> Bool+gelem v g = case match v g of {(Just _,_) -> True; _ -> False}++-- | Insert a 'LNode' into the 'Graph'.+insNode :: DynGraph gr => LNode a -> gr a b -> gr a b+insNode (v,l) = (([],v,l,[])&)++-- | Insert a 'LEdge' into the 'Graph'.+insEdge :: DynGraph gr => LEdge b -> gr a b -> gr a b+insEdge (v,w,l) g = (pr,v,la,(l,w):su) & g'+ where (Just (pr,_,la,su),g') = match v g++-- | Remove a 'Node' from the 'Graph'.+delNode :: Graph gr => Node -> gr a b -> gr a b+delNode v = delNodes [v]++-- | Remove an 'Edge' from the 'Graph'.+delEdge :: DynGraph gr => Edge -> gr a b -> gr a b+delEdge (v,w) g = case match v g of+ (Nothing,_) -> g+ (Just (p,v',l,s),g') -> (p,v',l,filter ((/=w).snd) s) & g'++-- | Remove an 'LEdge' from the 'Graph'.+delLEdge :: (DynGraph gr, Eq b) => LEdge b -> gr a b -> gr a b+delLEdge (v,w,b) g = case match v g of+ (Nothing,_) -> g+ (Just (p,v',l,s),g') -> (p,v',l,filter (\(x,n) -> x /= b || n /= w) s) & g'++-- | Insert multiple 'LNode's into the 'Graph'.+insNodes :: DynGraph gr => [LNode a] -> gr a b -> gr a b+insNodes vs g = foldr insNode g vs++-- | Insert multiple 'LEdge's into the 'Graph'.+insEdges :: DynGraph gr => [LEdge b] -> gr a b -> gr a b+insEdges es g = foldr insEdge g es++-- | Remove multiple 'Node's from the 'Graph'.+delNodes :: Graph gr => [Node] -> gr a b -> gr a b+delNodes [] g = g+delNodes (v:vs) g = delNodes vs (snd (match v g)) ++-- | Remove multiple 'Edge's from the 'Graph'.+delEdges :: DynGraph gr => [Edge] -> gr a b -> gr a b+delEdges es g = foldr delEdge g es++-- | Build a 'Graph' from a list of 'Context's.+buildGr :: DynGraph gr => [Context a b] -> gr a b+buildGr = foldr (&) empty++-- mkGraph :: DynGraph gr => [LNode a] -> [LEdge b] -> gr a b+-- mkGraph vs es = (insEdges es . insNodes vs) empty++-- | Build a quasi-unlabeled 'Graph'.+mkUGraph :: Graph gr => [Node] -> [Edge] -> gr () ()+mkUGraph vs es = mkGraph (labUNodes vs) (labUEdges es) ++labUEdges = map (\(v,w)->(v,w,()))+labUNodes = map (\v->(v,()))+ +-- | Find the context for the given 'Node'. Causes an error if the 'Node' is+-- not present in the 'Graph'.+context :: Graph gr => gr a b -> Node -> Context a b+context g v = case match v g of+ (Nothing,_) -> error ("Match Exception, Node: "++show v)+ (Just c,_) -> c ++-- | Find the label for a 'Node'.+lab :: Graph gr => gr a b -> Node -> Maybe a+lab g v = fst (match v g) >>= return.lab' ++-- | Find the neighbors for a 'Node'.+neighbors :: Graph gr => gr a b -> Node -> [Node] +neighbors = (\(p,_,_,s) -> map snd (p++s)) .: context++-- | Find all 'Node's that have a link from the given 'Node'.+suc :: Graph gr => gr a b -> Node -> [Node]+suc = map snd .: context4++-- | Find all 'Node's that link to to the given 'Node'.+pre :: Graph gr => gr a b -> Node -> [Node] +pre = map snd .: context1++-- | Find all 'Node's that are linked from the given 'Node' and the label of+-- each link.+lsuc :: Graph gr => gr a b -> Node -> [(Node,b)]+lsuc = map flip2 .: context4++-- | Find all 'Node's that link to the given 'Node' and the label of each link.+lpre :: Graph gr => gr a b -> Node -> [(Node,b)] +lpre = map flip2 .: context1++-- | Find all outward-bound 'LEdge's for the given 'Node'.+out :: Graph gr => gr a b -> Node -> [LEdge b] +out g v = map (\(l,w)->(v,w,l)) (context4 g v)++-- | Find all inward-bound 'LEdge's for the given 'Node'.+inn :: Graph gr => gr a b -> Node -> [LEdge b] +inn g v = map (\(l,w)->(w,v,l)) (context1 g v)++-- | The outward-bound degree of the 'Node'.+outdeg :: Graph gr => gr a b -> Node -> Int+outdeg = length .: context4++-- | The inward-bound degree of the 'Node'.+indeg :: Graph gr => gr a b -> Node -> Int+indeg = length .: context1++-- | The degree of the 'Node'.+deg :: Graph gr => gr a b -> Node -> Int+deg = (\(p,_,_,s) -> length p+length s) .: context++-- | The 'Node' in a 'Context'.+node' :: Context a b -> Node+node' (_,v,_,_) = v++-- | The label in a 'Context'.+lab' :: Context a b -> a+lab' (_,_,l,_) = l++-- | The 'LNode' from a 'Context'.+labNode' :: Context a b -> LNode a+labNode' (_,v,l,_) = (v,l)++-- | All 'Node's linked to or from in a 'Context'.+neighbors' :: Context a b -> [Node] +neighbors' (p,_,_,s) = map snd p++map snd s++-- | All 'Node's linked to in a 'Context'.+suc' :: Context a b -> [Node]+suc' (_,_,_,s) = map snd s++-- | All 'Node's linked from in a 'Context'.+pre' :: Context a b -> [Node] +pre' (p,_,_,_) = map snd p++-- | All 'Node's linked from in a 'Context', and the label of the links.+lpre' :: Context a b -> [(Node,b)] +lpre' (p,_,_,_) = map flip2 p++-- | All 'Node's linked from in a 'Context', and the label of the links.+lsuc' :: Context a b -> [(Node,b)]+lsuc' (_,_,_,s) = map flip2 s++-- | All outward-directed 'LEdge's in a 'Context'.+out' :: Context a b -> [LEdge b] +out' (_,v,_,s) = map (\(l,w)->(v,w,l)) s++-- | All inward-directed 'LEdge's in a 'Context'.+inn' :: Context a b -> [LEdge b] +inn' (p,v,_,_) = map (\(l,w)->(w,v,l)) p++-- | The outward degree of a 'Context'.+outdeg' :: Context a b -> Int+outdeg' (_,_,_,s) = length s++-- | The inward degree of a 'Context'.+indeg' :: Context a b -> Int+indeg' (p,_,_,_) = length p++-- | The degree of a 'Context'.+deg' :: Context a b -> Int+deg' (p,_,_,s) = length p+length s+++-- graph equality+--+nodeComp :: Eq b => LNode b -> LNode b -> Ordering+nodeComp n@(v,_) n'@(w,_) | n == n' = EQ+ | v<w = LT+ | otherwise = GT++slabNodes :: (Eq a,Graph gr) => gr a b -> [LNode a]+slabNodes = sortBy nodeComp . labNodes++edgeComp :: Eq b => LEdge b -> LEdge b -> Ordering+edgeComp e@(v,w,_) e'@(x,y,_) | e == e' = EQ+ | v<x || (v==x && w<y) = LT+ | otherwise = GT++slabEdges :: (Eq b,Graph gr) => gr a b -> [LEdge b]+slabEdges = sortBy edgeComp . labEdges++-- instance (Eq a,Eq b,Graph gr) => Eq (gr a b) where+-- g == g' = slabNodes g == slabNodes g' && slabEdges g == slabEdges g'++equal :: (Eq a,Eq b,Graph gr) => gr a b -> gr a b -> Bool+equal g g' = slabNodes g == slabNodes g' && slabEdges g == slabEdges g'+++----------------------------------------------------------------------+-- UTILITIES+----------------------------------------------------------------------+++-- auxiliary functions used in the implementation of the +-- derived class members+-- +(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)+-- f .: g = \x y->f (g x y)+-- f .: g = (f .) . g+-- (.:) f = ((f .) .)+-- (.:) = (.) (.) (.)+(.:) = (.) . (.)++fst4 (x,_,_,_) = x+{- not used+snd4 (_,x,_,_) = x+thd4 (_,_,x,_) = x+-}+fth4 (_,_,_,x) = x++{- not used+fst3 (x,_,_) = x+snd3 (_,x,_) = x+thd3 (_,_,x) = x+-}++flip2 (x,y) = (y,x)+++-- projecting on context elements+--+-- context1 g v = fst4 (contextP g v)+context1 :: Graph gr => gr a b -> Node -> Adj b+{- not used+context2 :: Graph gr => gr a b -> Node -> Node+context3 :: Graph gr => gr a b -> Node -> a+-}+context4 :: Graph gr => gr a b -> Node -> Adj b++context1 = fst4 .: context+{- not used+context2 = snd4 .: context+context3 = thd4 .: context+-}+context4 = fth4 .: context+
+ Data/Graph/Inductive/Graphviz.hs view
@@ -0,0 +1,69 @@+-- | Simple graphviz output.+module Data.Graph.Inductive.Graphviz(+ Orient(..),+ graphviz, graphviz'+) where++import Data.Graph.Inductive.Graph++data Orient = Portrait | Landscape deriving (Eq, Show)++o2s :: Orient -> String+o2s Portrait = "\trotate = \"0\"\n"+o2s Landscape = "\trotate = \"90\"\n"++-- | Formats a graph for use in graphviz.+graphviz :: (Graph g, Show a, Show b) => g a b -- ^ The graph to format+ -> String -- ^ The title of the graph+ -> (Double, Double) -- ^ The size+ -- of the page+ -> (Int, Int) -- ^ The width and+ -- height of the page+ -- grid+ -> Orient -- ^ The orientation of+ -- the graph.+ -> String++i2d :: Int -> Double+i2d = fromInteger . toInteger++graphviz g t (w, h) p@(pw', ph') o =+ let n = labNodes g+ e = labEdges g+ ns = concatMap sn n+ es = concatMap se e+ sz w' h' = if o == Portrait then show w'++","++show h' else show h'++","++show w'+ ps = show w++","++show h+ (pw, ph) = if o == Portrait then p else (ph', pw')+ --gs = show ((w*(i2d pw))-m)++","++show ((h*(i2d ph))-m)+ gs = sz (w*(i2d pw)) (h*(i2d ph))+ in "digraph "++t++" {\n"+ ++"\tmargin = \"0\"\n"+ ++"\tpage = \""++ps++"\"\n"+ ++"\tsize = \""++gs++"\"\n"+ ++o2s o+ ++"\tratio = \"fill\"\n"+ ++ns+ ++es+ ++"}"+ where sn (n, a) | sa == "" = ""+ | otherwise = '\t':(show n ++ sa ++ "\n")+ where sa = sl a+ se (n1, n2, b) = '\t':(show n1 ++ " -> " ++ show n2 ++ sl b ++ "\n")++-- | Format a graph for graphviz with reasonable defaults: title of \"fgl\",+-- 8.5x11 pages, one page, landscape orientation+graphviz' :: (Graph g, Show a, Show b) => g a b -> String+graphviz' g = graphviz g "fgl" (8.5,11.0) (1,1) Landscape++sq :: String -> String+sq ('"':s) | last s == '"' = init s+ | otherwise = s+sq ('\'':s) | last s == '\'' = init s+ | otherwise = s+sq s = s++sl :: (Show a) => a -> String+sl a =+ let l = sq (show a)+ in if (l /= "()") then (" [label = \""++l++"\"]") else ""
+ Data/Graph/Inductive/Internal/FiniteMap.hs view
@@ -0,0 +1,209 @@+-- | Simple Finite Maps.+-- This implementation provides several useful methods that Data.FiniteMap+-- does not.++module Data.Graph.Inductive.Internal.FiniteMap(+ -- * Type+ FiniteMap(..),+ -- * Operations+ emptyFM,addToFM,delFromFM,+ updFM,+ accumFM,+ splitFM,+ isEmptyFM,sizeFM,lookupFM,elemFM,+ rangeFM,+ minFM,maxFM,predFM,succFM,+ splitMinFM,+ fmToList+) where++import Data.Maybe (isJust) ++data Ord a => FiniteMap a b =+ Empty | Node Int (FiniteMap a b) (a,b) (FiniteMap a b)+ deriving (Eq)+++----------------------------------------------------------------------+-- UTILITIES+----------------------------------------------------------------------+++-- pretty printing+--+showsMap :: (Show a,Show b,Ord a) => FiniteMap a b -> ShowS+showsMap Empty = id+showsMap (Node _ l (i,x) r) = showsMap l . (' ':) . + shows i . ("->"++) . shows x . showsMap r+ +instance (Show a,Show b,Ord a) => Show (FiniteMap a b) where+ showsPrec _ m = showsMap m+++-- other+--+splitMax :: Ord a => FiniteMap a b -> (FiniteMap a b,(a,b))+splitMax (Node _ l x Empty) = (l,x)+splitMax (Node _ l x r) = (avlBalance l x m,y) where (m,y) = splitMax r+splitMax Empty = error "splitMax on empty FiniteMap"++merge :: Ord a => FiniteMap a b -> FiniteMap a b -> FiniteMap a b+merge l Empty = l+merge Empty r = r+merge l r = avlBalance l' x r where (l',x) = splitMax l+++----------------------------------------------------------------------+-- MAIN FUNCTIONS+----------------------------------------------------------------------++emptyFM :: Ord a => FiniteMap a b+emptyFM = Empty++addToFM :: Ord a => FiniteMap a b -> a -> b -> FiniteMap a b+addToFM Empty i x = node Empty (i,x) Empty+addToFM (Node h l (j,y) r) i x+ | i<j = avlBalance (addToFM l i x) (j,y) r+ | i>j = avlBalance l (j,y) (addToFM r i x) + | otherwise = Node h l (j,x) r ++-- | applies function to stored entry+updFM :: Ord a => FiniteMap a b -> a -> (b -> b) -> FiniteMap a b+updFM Empty _ _ = Empty+updFM (Node h l (j,x) r) i f + | i<j = let l' = updFM l i f in l' `seq` Node h l' (j,x) r+ | i>j = let r' = updFM r i f in r' `seq` Node h l (j,x) r'+ | otherwise = Node h l (j,f x) r ++-- | defines or aggregates entries+accumFM :: Ord a => FiniteMap a b -> a -> (b -> b -> b) -> b -> FiniteMap a b+accumFM Empty i _ x = node Empty (i,x) Empty+accumFM (Node h l (j,y) r) i f x + | i<j = avlBalance (accumFM l i f x) (j,y) r+ | i>j = avlBalance l (j,y) (accumFM r i f x) + | otherwise = Node h l (j,f x y) r ++delFromFM :: Ord a => FiniteMap a b -> a -> FiniteMap a b+delFromFM Empty _ = Empty+delFromFM (Node _ l (j,x) r) i+ | i<j = avlBalance (delFromFM l i) (j,x) r+ | i>j = avlBalance l (j,x) (delFromFM r i) + | otherwise = merge l r ++isEmptyFM :: FiniteMap a b -> Bool+isEmptyFM Empty = True+isEmptyFM _ = False++sizeFM :: Ord a => FiniteMap a b -> Int+sizeFM Empty = 0+sizeFM (Node _ l _ r) = sizeFM l + 1 + sizeFM r++lookupFM :: Ord a => FiniteMap a b -> a -> Maybe b+lookupFM Empty _ = Nothing+lookupFM (Node _ l (j,x) r) i | i<j = lookupFM l i+ | i>j = lookupFM r i + | otherwise = Just x++-- | applies lookup to an interval+rangeFM :: Ord a => FiniteMap a b -> a -> a -> [b]+rangeFM m i j = rangeFMa m i j []+--+rangeFMa Empty _ _ a = a+rangeFMa (Node _ l (k,x) r) i j a+ | k<i = rangeFMa r i j a+ | k>j = rangeFMa l i j a+ | otherwise = rangeFMa l i j (x:rangeFMa r i j a)++minFM :: Ord a => FiniteMap a b -> Maybe (a,b)+minFM Empty = Nothing+minFM (Node _ Empty x _) = Just x+minFM (Node _ l _ _) = minFM l++maxFM :: Ord a => FiniteMap a b -> Maybe (a,b)+maxFM Empty = Nothing+maxFM (Node _ _ x Empty) = Just x+maxFM (Node _ _ _ r) = maxFM r++predFM :: Ord a => FiniteMap a b -> a -> Maybe (a,b)+predFM m i = predFM' m i Nothing+--+predFM' Empty _ p = p+predFM' (Node _ l (j,x) r) i p | i<j = predFM' l i p+ | i>j = predFM' r i (Just (j,x))+ | isJust ml = ml + | otherwise = p+ where ml = maxFM l+ +succFM :: Ord a => FiniteMap a b -> a -> Maybe (a,b)+succFM m i = succFM' m i Nothing+--+succFM' Empty _ p = p+succFM' (Node _ l (j,x) r) i p | i<j = succFM' l i (Just (j,x))+ | i>j = succFM' r i p+ | isJust mr = mr + | otherwise = p+ where mr = minFM r++elemFM :: Ord a => FiniteMap a b -> a -> Bool+elemFM m i = case lookupFM m i of {Nothing -> False; _ -> True}++-- | combines delFrom and lookup+splitFM :: Ord a => FiniteMap a b -> a -> Maybe (FiniteMap a b,(a,b))+splitFM Empty _ = Nothing+splitFM (Node _ l (j,x) r) i =+ if i<j then+ case splitFM l i of+ Just (l',y) -> Just (avlBalance l' (j,x) r,y)+ Nothing -> Nothing else+ if i>j then+ case splitFM r i of+ Just (r',y) -> Just (avlBalance l (j,x) r',y) + Nothing -> Nothing + else {- i==j -} Just (merge l r,(j,x)) ++-- | combines splitFM and minFM+splitMinFM :: Ord a => FiniteMap a b -> Maybe (FiniteMap a b,(a,b))+splitMinFM Empty = Nothing+splitMinFM (Node _ Empty x r) = Just (r,x)+splitMinFM (Node _ l x r) = Just (avlBalance l' x r,y) + where Just (l',y) = splitMinFM l++fmToList :: Ord a => FiniteMap a b -> [(a,b)]+fmToList m = scan m []+ where scan Empty xs = xs+ scan (Node _ l x r) xs = scan l (x:(scan r xs))++----------------------------------------------------------------------+-- AVL tree helper functions+----------------------------------------------------------------------++height :: Ord a => FiniteMap a b -> Int+height Empty = 0+height (Node h _ _ _) = h++node :: Ord a => FiniteMap a b -> (a,b) -> FiniteMap a b -> FiniteMap a b+node l val r = Node h l val r+ where h=1+(height l `max` height r)++avlBalance :: Ord a => FiniteMap a b -> (a,b) -> FiniteMap a b -> FiniteMap a b+avlBalance l (i,x) r+ | (hr + 1 < hl) && (bias l < 0) = rotr (node (rotl l) (i,x) r)+ | (hr + 1 < hl) = rotr (node l (i,x) r)+ | (hl + 1 < hr) && (0 < bias r) = rotl (node l (i,x) (rotr r))+ | (hl + 1 < hr) = rotl (node l (i,x) r)+ | otherwise = node l (i,x) r+ where hl=height l; hr=height r++bias :: Ord a => FiniteMap a b -> Int+bias (Node _ l _ r) = height l - height r+bias Empty = 0++rotr :: Ord a => FiniteMap a b -> FiniteMap a b+rotr Empty = Empty+rotr (Node _ (Node _ l1 v1 r1) v2 r2) = node l1 v1 (node r1 v2 r2)+rotr (Node _ Empty _ _) = error "rotr on invalid FiniteMap"++rotl :: Ord a => FiniteMap a b -> FiniteMap a b+rotl Empty = Empty+rotl (Node _ l1 v1 (Node _ l2 v2 r2)) = node (node l1 v1 l2) v2 r2+rotl (Node _ _ _ Empty) = error "rotl on invalid FiniteMap"
+ Data/Graph/Inductive/Internal/Heap.hs view
@@ -0,0 +1,91 @@+-- | Pairing heap implementation of dictionary+module Data.Graph.Inductive.Internal.Heap(+ -- * Type+ Heap(..),+ -- * Operations+ empty,unit,insert,merge,mergeAll,+ isEmpty,findMin,deleteMin,splitMin,+ build, toList, heapsort+) where+++data Ord a => Heap a b = Empty | Node a b [Heap a b]+ deriving Eq++showsHeap :: (Show a,Ord a,Show b) => Heap a b -> ShowS+showsHeap Empty = id+showsHeap (Node key val []) = shows key . (": "++) . shows val+showsHeap (Node key val hs) = shows key . (": "++) . shows val . (' ':) . shows hs+ +instance (Show a,Ord a,Show b) => Show (Heap a b) where+ showsPrec _ d = showsHeap d+++----------------------------------------------------------------------+-- MAIN FUNCTIONS+----------------------------------------------------------------------++empty :: Ord a => Heap a b+empty = Empty++unit :: Ord a => a -> b -> Heap a b+unit key val = Node key val []++insert :: Ord a => (a, b) -> Heap a b -> Heap a b+insert (key, val) h = merge (unit key val) h++merge :: Ord a => Heap a b -> Heap a b -> Heap a b+merge h Empty = h+merge Empty h = h+merge h@(Node key1 val1 hs) h'@(Node key2 val2 hs')+ | key1<key2 = Node key1 val1 (h':hs)+ | otherwise = Node key2 val2 (h:hs')++mergeAll:: Ord a => [Heap a b] -> Heap a b+mergeAll [] = Empty+mergeAll [h] = h+mergeAll (h:h':hs) = merge (merge h h') (mergeAll hs)++isEmpty :: Ord a => Heap a b -> Bool+isEmpty Empty = True+isEmpty _ = False+ +findMin :: Ord a => Heap a b -> (a, b)+findMin Empty = error "Heap.findMin: empty heap"+findMin (Node key val _) = (key, val)++deleteMin :: Ord a => Heap a b -> Heap a b+deleteMin Empty = Empty+deleteMin (Node _ _ hs) = mergeAll hs++splitMin :: Ord a => Heap a b -> (a,b,Heap a b)+splitMin Empty = error "Heap.splitMin: empty heap"+splitMin (Node key val hs) = (key,val,mergeAll hs)+++----------------------------------------------------------------------+-- APPLICATION FUNCTIONS, EXAMPLES+----------------------------------------------------------------------+++build :: Ord a => [(a,b)] -> Heap a b+build = foldr insert Empty++toList :: Ord a => Heap a b -> [(a,b)]+toList Empty = []+toList h = x:toList r+ where (x,r) = (findMin h,deleteMin h)++heapsort :: Ord a => [a] -> [a]+heapsort = (map fst) . toList . build . map (\x->(x,x))+{-+l :: (Num a) => [a]+l = [6,9,2,13,6,8,14,9,10,7,5]+l' = reverse l++h1 = build $ map (\x->(x,x)) l+h1' = build $ map (\x->(x,x)) l'++s1 = heapsort l+s1' = heapsort l'+-}
+ Data/Graph/Inductive/Internal/Queue.hs view
@@ -0,0 +1,26 @@+module Data.Graph.Inductive.Internal.Queue(+ -- * Type+ Queue(..),+ -- * Operations+ mkQueue, queuePut, queuePutList, queueGet, queueEmpty+) where+++data Queue a = MkQueue [a] [a]++mkQueue :: Queue a+mkQueue = MkQueue [] []++queuePut :: a -> Queue a -> Queue a+queuePut item (MkQueue ins outs) = MkQueue (item:ins) outs++queuePutList :: [a] -> Queue a -> Queue a+queuePutList [] q = q+queuePutList (x:xs) q = queuePutList xs (queuePut x q)++queueGet :: Queue a -> (a, Queue a)+queueGet (MkQueue ins (item:rest)) = (item, MkQueue ins rest)+queueGet (MkQueue ins []) = queueGet (MkQueue [] (reverse ins))++queueEmpty :: Queue a -> Bool+queueEmpty (MkQueue ins outs) = (null ins) && (null outs)
+ Data/Graph/Inductive/Internal/RootPath.hs view
@@ -0,0 +1,51 @@+-- (c) 2000-2005 by Martin Erwig [see file COPYRIGHT]+-- | Inward directed trees as lists of paths.+module Data.Graph.Inductive.Internal.RootPath (+ -- * Types+ RTree,LRTree,+ -- * Operations+ getPath,getLPath,+ getDistance,+ getLPathNodes+) where++import Data.Graph.Inductive.Graph+++instance Eq a => Eq (LPath a) where+ (LP []) == (LP []) = True+ (LP ((_,x):_)) == (LP ((_,y):_)) = x==y+ (LP _) == (LP _) = False++instance Ord a => Ord (LPath a) where+ compare (LP []) (LP []) = EQ+ compare (LP ((_,x):_)) (LP ((_,y):_)) = compare x y+ compare _ _ = error "LPath: cannot compare to empty paths"+++type LRTree a = [LPath a]+type RTree = [Path]++first :: ([a] -> Bool) -> [[a]] -> [a]+first p xss = case filter p xss of+ [] -> []+ x:_ -> x++-- | Find the first path in a tree that starts with the given node+findP :: Node -> LRTree a -> [LNode a]+findP _ [] = []+findP v ((LP []):ps) = findP v ps+findP v ((LP (p@((w,_):_))):ps) | v==w = p+ | otherwise = findP v ps++getPath :: Node -> RTree -> Path+getPath v = reverse . first (\(w:_)->w==v) ++getLPath :: Node -> LRTree a -> LPath a+getLPath v = LP . reverse . findP v++getDistance :: Node -> LRTree a -> a+getDistance v = snd . head . findP v++getLPathNodes :: Node -> LRTree a -> Path+getLPathNodes v = (\(LP p)->map fst p) . getLPath v
+ Data/Graph/Inductive/Internal/Thread.hs view
@@ -0,0 +1,149 @@+-- (c) 1999 by Martin Erwig+-- | Threading Combinators.+module Data.Graph.Inductive.Internal.Thread(+ -- * Types+ Split, SplitM, Thread, Collect,+ -- * Operations+ threadList', threadList, threadMaybe', threadMaybe, splitPar, splitParM+) where++-- import Graph+-- import GraphData+-- import qualified Diet as D++-- import ADT++----------------------------------------------------------------------+-- CLASSES AND TYPES+----------------------------------------------------------------------++{-+class Thread t a b where+ split :: a -> t -> (b,t)+ + +instance Thread (Graph a b) Node (MContext a b) where+ split = match+ +instance D.Discrete a => Thread (D.Diet a) a a where+ split x s = (x,D.delete x s)+-}++{-+ Make clear different notions:+ + "thread" = data structure + split operation+ ... = threadable data structure+ ... = split operation+ +-}+++----------------------------------------------------------------------+-- THREAD COMBINATORS+----------------------------------------------------------------------+++-- (A) split along a list of indexes and thread data structure+--+-- there are different ways to consume the returned elements:++{-+-- (1) simple collect in a list+-- +foldT1' ys [] d = ys+foldT1' ys (x:xs) d = foldT1' (y:ys) xs d' where (y,d') = split x d+foldT1 xs d = foldT1' [] xs d++-- (2) combine by a function+-- +foldT2' f ys [] d = ys+foldT2' f ys (x:xs) d = foldT2' f (f y ys) xs d' where (y,d') = split x d+foldT2 f u xs d = foldT2' f u xs d+-}+++-- Mnemonics:+--+-- t : thread type+-- i : index type+-- r : result type+-- c : collection type+--+type Split t i r = i -> t -> (r,t)+type Thread t i r = (t,Split t i r)+type Collect r c = (r -> c -> c,c)++-- (3) abstract from split+-- +threadList' :: (Collect r c) -> (Split t i r) -> [i] -> t -> (c,t)+threadList' (_,c) _ [] t = (c,t)+threadList' (f,c) split (i:is) t = threadList' (f,f r c) split is t'+ where (r,t') = split i t++{- + Note: threadList' works top-down (or, from left),+ whereas dfs,gfold,... have been defined bottom-up (or from right).+ + ==> therefore, we define a correpsonding operator for folding+ bottom-up/from right.+-}+threadList :: (Collect r c) -> (Split t i r) -> [i] -> t -> (c,t)+threadList (_,c) _ [] t = (c,t)+threadList (f,c) split (i:is) t = (f r c',t'')+ where (r,t') = split i t+ (c',t'') = threadList (f,c) split is t'++++-- (B) thread "maybes", ie, apply f to Just-values and continue+-- threading with "continuation" c, and ignore Nothing-values, ie,+-- stop threading and return current data structure.+--+-- threadMaybe' :: (r -> b) -> (Split t i r) -> (e -> f -> (Maybe i,t)) +-- -> e -> f -> (Maybe b,t)++type SplitM t i r = Split t i (Maybe r)++threadMaybe' :: (r->a)->Split t i r->Split t j (Maybe i)->Split t j (Maybe a)+threadMaybe' f cont split j t = + case mi of Just i -> (Just (f r),t'') where (r,t'') = cont i t'+ Nothing -> (Nothing,t')+ where (mi,t') = split j t++-- extension: grant f access also to y, the result of split.+--+-- threadMaybe :: (a -> b -> c) -> (a -> d -> (b,d)) -> (e -> f -> (Maybe a,d))+-- -> e -> f -> (Maybe c,d)+-- threadMaybe :: (i->r->a)->Split t i r->Split t j (Maybe i)->Split t j (Maybe a)+threadMaybe :: (i -> r -> a) -> Split t i r -> SplitM t j i -> SplitM t j a+threadMaybe f cont split j t = + case mi of Just i -> (Just (f i r),t'') where (r,t'') = cont i t'+ Nothing -> (Nothing,t')+ where (mi,t') = split j t+++-- (C) compose splits in parallel (is a kind of generalized zip)+--+-- splitPar :: (a -> b -> (c,d)) -> (e -> f -> (g,h)) +-- -> (a,e) -> (b,f) -> ((c,g),(d,h))+splitPar :: Split t i r -> Split u j s -> Split (t,u) (i,j) (r,s)+splitPar split split' (i,j) (t,u) = ((r,s),(t',u'))+ where (r,t') = split i t+ (s,u') = split' j u++splitParM :: SplitM t i r -> Split u j s -> SplitM (t,u) (i,j) (r,s)+splitParM splitm split (i,j) (t,u) =+ case mr of Just r -> (Just (r,s),(t',u'))+ Nothing -> (Nothing,(t',u)) -- ignore 2nd split + where (mr,t') = splitm i t+ (s,u') = split j u+++-- (D) merge a thread with/into a computation+--+{- + Example: assign consecutive numbers to the nodes of a tree+ + Input: type d, thread (t,split), fold operation on d+-}
+ Data/Graph/Inductive/Monad.hs view
@@ -0,0 +1,227 @@+-- (c) 2002 by Martin Erwig [see file COPYRIGHT]+-- | Monadic Graphs+module Data.Graph.Inductive.Monad(+ -- * Classes+ GraphM(..), + -- * Operations+ -- ** Graph Folds and Maps+ ufoldM,+ -- ** Graph Projection+ nodesM,edgesM,newNodesM,+ -- ** Graph Construction and Destruction+ delNodeM,delNodesM,+ mkUGraphM,+ -- ** Graph Inspection+ contextM,labM+) where+++import Data.Graph.Inductive.Graph+++----------------------------------------------------------------------+-- MONADIC GRAPH CLASS+----------------------------------------------------------------------++-- +-- Currently, we define just one monadic graph class:+--+-- GraphM: static, decomposable graphs+-- static means that a graph itself cannot be changed+-- +-- Later we might also define DynGraphM for dynamic, extensible graphs+-- ++++-- Monadic Graph+-- +class Monad m => GraphM m gr where+ -- essential operations+ emptyM :: m (gr a b)+ isEmptyM :: m (gr a b) -> m Bool+ matchM :: Node -> m (gr a b) -> m (Decomp gr a b)+ mkGraphM :: [LNode a] -> [LEdge b] -> m (gr a b)+ labNodesM :: m (gr a b) -> m [LNode a]+ -- derived operations+ matchAnyM :: m (gr a b) -> m (GDecomp gr a b)+ noNodesM :: m (gr a b) -> m Int+ nodeRangeM :: m (gr a b) -> m (Node,Node)+ labEdgesM :: m (gr a b) -> m [LEdge b]+ -- default implementation of derived operations+ matchAnyM g = do vs <- labNodesM g + case vs of+ [] -> error "Match Exception, Empty Graph"+ (v,_):_ -> do (Just c,g') <- matchM v g+ return (c,g') + noNodesM = labNodesM >>. length+ nodeRangeM g = do vs <- labNodesM g+ let vs' = map fst vs + return (minimum vs',maximum vs') + labEdgesM = ufoldM (\(p,v,_,s)->(((map (i v) p)++(map (o v) s))++)) []+ where o v = \(l,w)->(v,w,l)+ i v = \(l,w)->(w,v,l)+++-- composing a monadic function with a non-monadic one+--+(>>.) :: Monad m => (m a -> m b) -> (b -> c) -> (m a -> m c)+f >>. g = (>>= return . g) . f +++----------------------------------------------------------------------+-- DERIVED GRAPH OPERATIONS+----------------------------------------------------------------------++-- graph folds and maps+-- ++-- | graph fold+ufoldM :: GraphM m gr => ((Context a b) -> c -> c) -> c -> m (gr a b) -> m c+ufoldM f u g = do b <- isEmptyM g+ if b then return u+ else do (c,g') <- matchAnyM g+ x <- ufoldM f u (return g')+ return (f c x)+++-- (additional) graph projection+-- [noNodes, nodeRange, labNodes, labEdges are defined in class Graph]+-- +nodesM :: GraphM m gr => m (gr a b) -> m [Node]+nodesM = labNodesM >>. map fst++edgesM :: GraphM m gr => m (gr a b) -> m [Edge]+edgesM = labEdgesM >>. map (\(v,w,_)->(v,w))++newNodesM :: GraphM m gr => Int -> m (gr a b) -> m [Node]+newNodesM i g = do (_,n) <- nodeRangeM g+ return [n+1..n+i]+++-- graph construction & destruction+-- +delNodeM :: GraphM m gr => Node -> m (gr a b) -> m (gr a b)+delNodeM v = delNodesM [v]++delNodesM :: GraphM m gr => [Node] -> m (gr a b) -> m (gr a b)+delNodesM [] g = g+delNodesM (v:vs) g = do (_,g') <- matchM v g + delNodesM vs (return g') ++mkUGraphM :: GraphM m gr => [Node] -> [Edge] -> m (gr () ())+mkUGraphM vs es = mkGraphM (labUNodes vs) (labUEdges es) ++labUEdges = map (\(v,w)->(v,w,()))+labUNodes = map (\v->(v,()))+++-- graph inspection (for a particular node)+-- +onMatch :: GraphM m gr => (Context a b -> c) -> c -> m (gr a b) -> Node -> m c+onMatch f u g v = do (x,_) <- matchM v g+ return (case x of {Nothing -> u; Just c -> f c})++contextM :: GraphM m gr => m (gr a b) -> Node -> m (Context a b)+contextM g v = onMatch id (error ("Match Exception, Node: "++show v)) g v++labM :: GraphM m gr => m (gr a b) -> Node -> m (Maybe a)+labM = onMatch (Just . lab') Nothing++{-+neighbors :: GraphM m gr => m (gr a b) -> Node -> [Node] +neighbors = (\(p,_,_,s) -> map snd (p++s)) .: context++suc :: GraphM m gr => m (gr a b) -> Node -> [Node]+suc = map snd .: context4++pre :: GraphM m gr => m (gr a b) -> Node -> [Node] +pre = map snd .: context1++lsuc :: GraphM m gr => m (gr a b) -> Node -> [(Node,b)]+lsuc = map flip2 .: context4++lpre :: GraphM m gr => m (gr a b) -> Node -> [(Node,b)] +lpre = map flip2 .: context1++out :: GraphM m gr => m (gr a b) -> Node -> [LEdge b] +out g v = map (\(l,w)->(v,w,l)) (context4 g v)++inn :: GraphM m gr => m (gr a b) -> Node -> [LEdge b] +inn g v = map (\(l,w)->(w,v,l)) (context1 g v)++outdeg :: GraphM m gr => m (gr a b) -> Node -> Int+outdeg = length .: context4++indeg :: GraphM m gr => m (gr a b) -> Node -> Int+indeg = length .: context1++deg :: GraphM m gr => m (gr a b) -> Node -> Int+deg = (\(p,_,_,s) -> length p+length s) .: context+-- ++-- -- context inspection+-- -- +-- node' :: Context a b -> Node+-- node' (_,v,_,_) = v+-- +-- lab' :: Context a b -> a+-- lab' (_,_,l,_) = l+-- +-- labNode' :: Context a b -> LNode a+-- labNode' (_,v,l,_) = (v,l)+-- +-- neighbors' :: Context a b -> [Node] +-- neighbors' (p,_,_,s) = map snd p++map snd s+-- +-- suc' :: Context a b -> [Node]+-- suc' (_,_,_,s) = map snd s+-- +-- pre' :: Context a b -> [Node] +-- pre' (p,_,_,_) = map snd p+-- +-- lpre' :: Context a b -> [(Node,b)] +-- lpre' (p,_,_,_) = map flip2 p+-- +-- lsuc' :: Context a b -> [(Node,b)]+-- lsuc' (_,_,_,s) = map flip2 s+-- +-- out' :: Context a b -> [LEdge b] +-- out' (_,v,_,s) = map (\(l,w)->(v,w,l)) s+-- +-- inn' :: Context a b -> [LEdge b] +-- inn' (p,v,_,_) = map (\(l,w)->(w,v,l)) p+-- +-- outdeg' :: Context a b -> Int+-- outdeg' (_,_,_,s) = length s+-- +-- indeg' :: Context a b -> Int+-- indeg' (p,_,_,_) = length p+-- +-- deg' :: Context a b -> Int+-- deg' (p,_,_,s) = length p+length s+++-- graph equality+--+nodeComp :: Eq b => LNode b -> LNode b -> Ordering+nodeComp n@(v,a) n'@(w,b) | n == n' = EQ+ | v<w = LT+ | otherwise = GT++slabNodes :: (Eq a,Graph gr) => m (gr a b) -> [LNode a]+slabNodes = sortBy nodeComp . labNodes++edgeComp :: Eq b => LEdge b -> LEdge b -> Ordering+edgeComp e@(v,w,a) e'@(x,y,b) | e == e' = EQ+ | v<x || (v==x && w<y) = LT+ | otherwise = GT++slabEdges :: (Eq b,Graph gr) => m (gr a b) -> [LEdge b]+slabEdges = sortBy edgeComp . labEdges++instance (Eq a,Eq b,Graph gr) => Eq (m (gr a b)) where+ g == g' = slabNodes g == slabNodes g' && slabEdges g == slabEdges g'+++-}
+ Data/Graph/Inductive/Monad/IOArray.hs view
@@ -0,0 +1,112 @@+-- (c) 2002 by Martin Erwig [see file COPYRIGHT]+-- | Static IOArray-based Graphs +module Data.Graph.Inductive.Monad.IOArray(+ -- * Graph Representation+ SGr(..), GraphRep, Context', USGr,+ defaultGraphSize, emptyN,+ -- * Utilities+ removeDel,+) where++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Monad++import Control.Monad+import Data.Array+import Data.Array.IO+import System.IO.Unsafe+import Data.Maybe+++----------------------------------------------------------------------+-- GRAPH REPRESENTATION+----------------------------------------------------------------------++data SGr a b = SGr (GraphRep a b)++type GraphRep a b = (Int,Array Node (Context' a b),IOArray Node Bool)+type Context' a b = Maybe (Adj b,a,Adj b)++type USGr = SGr () ()+++----------------------------------------------------------------------+-- CLASS INSTANCES+----------------------------------------------------------------------++-- Show+--+showGraph :: (Show a,Show b) => GraphRep a b -> String+showGraph (_,a,m) = concatMap showAdj (indices a)+ where showAdj v | unsafePerformIO (readArray m v) = ""+ | otherwise = case a!v of+ Nothing -> ""+ Just (_,l,s) -> '\n':show v++":"++show l++"->"++show s'+ where s' = unsafePerformIO (removeDel m s)+ +instance (Show a,Show b) => Show (SGr a b) where+ show (SGr g) = showGraph g++instance (Show a,Show b) => Show (IO (SGr a b)) where+ show g = unsafePerformIO (do {(SGr g') <- g; return (showGraph g')})++{-+run :: Show (IO a) => IO a -> IO ()+run x = seq x (print x)+-}++-- GraphM+-- +instance GraphM IO SGr where+ emptyM = emptyN defaultGraphSize+ isEmptyM g = do {SGr (n,_,_) <- g; return (n==0)}+ matchM v g = do g'@(SGr (n,a,m)) <- g+ case a!v of + Nothing -> return (Nothing,g')+ Just (pr,l,su) -> + do b <- readArray m v+ if b then return (Nothing,g') else+ do s <- removeDel m su+ p' <- removeDel m pr+ let p = filter ((/=v).snd) p'+ writeArray m v True+ return (Just (p,v,l,s),SGr (n-1,a,m))+ mkGraphM vs es = do m <- newArray (1,n) False+ return (SGr (n,pr,m))+ where nod = array bnds (map (\(v,l)->(v,Just ([],l,[]))) vs)+ su = accum addSuc nod (map (\(v,w,l)->(v,(l,w))) es)+ pr = accum addPre su (map (\(v,w,l)->(w,(l,v))) es)+ bnds = (minimum vs',maximum vs')+ vs' = map fst vs+ n = length vs+ addSuc (Just (p,l',s)) (l,w) = Just (p,l',(l,w):s)+ addSuc Nothing _ = error "mkGraphM (SGr): addSuc Nothing"+ addPre (Just (p,l',s)) (l,w) = Just ((l,w):p,l',s)+ addPre Nothing _ = error "mkGraphM (SGr): addPre Nothing"+ labNodesM g = do (SGr (_,a,m)) <- g+ let getLNode vs (_,Nothing) = return vs+ getLNode vs (v,Just (_,l,_)) = + do b <- readArray m v + return (if b then vs else (v,l):vs)+ foldM getLNode [] (assocs a)+ +defaultGraphSize :: Int+defaultGraphSize = 100++emptyN :: Int -> IO (SGr a b) +emptyN n = do m <- newArray (1,n) False+ return (SGr (0,array (1,n) [(i,Nothing) | i <- [1..n]],m))++----------------------------------------------------------------------+-- UTILITIES+----------------------------------------------------------------------++++-- | filter list (of successors\/predecessors) through a boolean ST array+-- representing deleted marks+removeDel :: IOArray Node Bool -> Adj b -> IO (Adj b)+removeDel m = filterM (\(_,v)->do {b<-readArray m v;return (not b)})+++
+ Data/Graph/Inductive/NodeMap.hs view
@@ -0,0 +1,248 @@+-- | Utility methods to automatically generate and keep track of a mapping+-- between node labels and 'Node's.+module Data.Graph.Inductive.NodeMap(+ -- * Functional Construction+ NodeMap,+ -- ** Map Construction+ new, fromGraph, mkNode, mkNode_, mkNodes, mkNodes_, mkEdge, mkEdges,+ -- ** Graph Construction+ -- | These functions mirror the construction and destruction functions in+ -- 'Data.Graph.Inductive.Graph', but use the given 'NodeMap' to look up+ -- the appropriate 'Node's. Note that the 'insMapNode' family of functions+ -- will create new nodes as needed, but the other functions will not.+ insMapNode, insMapNode_, insMapEdge, delMapNode, delMapEdge, insMapNodes,+ insMapNodes_, insMapEdges, delMapNodes, delMapEdges, mkMapGraph,+ -- * Monadic Construction+ NodeMapM,+ -- | The following mirror the functional construction functions, but handle passing+ -- 'NodeMap's and 'Graph's behind the scenes.++ -- ** Map Construction+ run, run_, mkNodeM, mkNodesM, mkEdgeM, mkEdgesM,+ -- ** Graph Construction+ insMapNodeM, insMapEdgeM, delMapNodeM, delMapEdgeM, insMapNodesM,+ insMapEdgesM, delMapNodesM, delMapEdgesM+) where++import Prelude hiding (map)+import qualified Prelude as P (map)+import Control.Monad.State+import Data.Graph.Inductive.Graph+--import Data.Graph.Inductive.Tree+import Data.Graph.Inductive.Internal.FiniteMap++data (Ord a) => NodeMap a =+ NodeMap { map :: FiniteMap a Node,+ key :: Int }+ deriving Show++-- | Create a new, empty mapping.+new :: (Ord a) => NodeMap a+new = NodeMap { map = emptyFM, key = 0 }++-- LNode = (Node, a)++-- | Generate a mapping containing the nodes in the given graph.+fromGraph :: (Ord a, Graph g) => g a b -> NodeMap a+fromGraph g =+ let ns = labNodes g+ aux (n, a) (m', k') = (addToFM m' a n, max n k')+ (m, k) = foldr aux (emptyFM, 0) ns+ in NodeMap { map = m, key = k+1 }++-- | Generate a labelled node from the given label. Will return the same node+-- for the same label.+mkNode :: (Ord a) => NodeMap a -> a -> (LNode a, NodeMap a)+mkNode m@(NodeMap mp k) a =+ case lookupFM mp a of+ Just i -> ((i, a), m)+ Nothing ->+ let m' = NodeMap { map = addToFM mp a k, key = k+1 }+ in ((k, a), m')++-- | Generate a labelled node and throw away the modified 'NodeMap'.+mkNode_ :: (Ord a) => NodeMap a -> a -> LNode a+mkNode_ m a = fst $ mkNode m a++-- | Generate a 'LEdge' from the node labels.+mkEdge :: (Ord a) => NodeMap a -> (a, a, b) -> Maybe (LEdge b)+mkEdge (NodeMap m _) (a1, a2, b) =+ do n1 <- lookupFM m a1+ n2 <- lookupFM m a2+ return (n1, n2, b)++-- | Generates a list of 'LEdge's.+mkEdges :: (Ord a) => NodeMap a -> [(a, a, b)] -> Maybe [LEdge b]+mkEdges m es = mapM (mkEdge m) es++-- | Construct a list of nodes.+mkNodes :: (Ord a) => NodeMap a -> [a] -> ([LNode a], NodeMap a)+mkNodes = map' mkNode++map' :: (a -> b -> (c, a)) -> a -> [b] -> ([c], a)+map' _ a [] = ([], a)+map' f a (b:bs) =+ let (c, a') = f a b+ (cs, a'') = map' f a' bs+ in (c:cs, a'')++-- | Construct a list of nodes and throw away the modified 'NodeMap'.+mkNodes_ :: (Ord a) => NodeMap a -> [a] -> [LNode a]+mkNodes_ m as = fst $ mkNodes m as++insMapNode :: (Ord a, DynGraph g) => NodeMap a -> a -> g a b -> (g a b, NodeMap a, LNode a)+insMapNode m a g =+ let (n, m') = mkNode m a+ in (insNode n g, m', n)++insMapNode_ :: (Ord a, DynGraph g) => NodeMap a -> a -> g a b -> g a b+insMapNode_ m a g =+ let (g', _, _) = insMapNode m a g+ in g'++insMapEdge :: (Ord a, DynGraph g) => NodeMap a -> (a, a, b) -> g a b -> g a b+insMapEdge m e g =+ let (Just e') = mkEdge m e+ in insEdge e' g++delMapNode :: (Ord a, DynGraph g) => NodeMap a -> a -> g a b -> g a b+delMapNode m a g =+ let (n, _) = mkNode_ m a+ in delNode n g++delMapEdge :: (Ord a, DynGraph g) => NodeMap a -> (a, a) -> g a b -> g a b+delMapEdge m (n1, n2) g =+ let Just (n1', n2', _) = mkEdge m (n1, n2, ())+ in delEdge (n1', n2') g++insMapNodes :: (Ord a, DynGraph g) => NodeMap a -> [a] -> g a b -> (g a b, NodeMap a, [LNode a])+insMapNodes m as g =+ let (ns, m') = mkNodes m as+ in (insNodes ns g, m', ns)++insMapNodes_ :: (Ord a, DynGraph g) => NodeMap a -> [a] -> g a b -> g a b+insMapNodes_ m as g =+ let (g', _, _) = insMapNodes m as g+ in g'++insMapEdges :: (Ord a, DynGraph g) => NodeMap a -> [(a, a, b)] -> g a b -> g a b+insMapEdges m es g =+ let Just es' = mkEdges m es+ in insEdges es' g++delMapNodes :: (Ord a, DynGraph g) => NodeMap a -> [a] -> g a b -> g a b+delMapNodes m as g =+ let ns = P.map fst $ mkNodes_ m as+ in delNodes ns g++delMapEdges :: (Ord a, DynGraph g) => NodeMap a -> [(a, a)] -> g a b -> g a b+delMapEdges m ns g =+ let Just ns' = mkEdges m $ P.map (\(a, b) -> (a, b, ())) ns+ ns'' = P.map (\(a, b, _) -> (a, b)) ns'+ in delEdges ns'' g++mkMapGraph :: (Ord a, DynGraph g) => [a] -> [(a, a, b)] -> (g a b, NodeMap a)+mkMapGraph ns es =+ let (ns', m') = mkNodes new ns+ Just es' = mkEdges m' es+ in (mkGraph ns' es', m')++-- | Graph construction monad; handles passing both the 'NodeMap' and the+-- 'Graph'.+type NodeMapM a b g r = State (NodeMap a, g a b) r++-- | Run a construction; return the value of the computation, the modified+-- 'NodeMap', and the modified 'Graph'.+run :: (DynGraph g, Ord a) => g a b -> NodeMapM a b g r -> (r, (NodeMap a, g a b))+run g m = runState m (fromGraph g, g)++-- | Run a construction and only return the 'Graph'.+run_ :: (DynGraph g, Ord a) => g a b -> NodeMapM a b g r -> g a b+run_ g m = snd . snd $ run g m++{- not used+liftN1 :: (Ord a, DynGraph g) => (NodeMap a -> (c, NodeMap a)) -> NodeMapM a b g c+liftN1 f =+ do (m, g) <- get+ let (r, m') = f m+ put (m', g)+ return r++liftN1' :: (Ord a, DynGraph g) => (NodeMap a -> c) -> NodeMapM a b g c+liftN1' f =+ do (m, g) <- get+ return $ f m+-}+liftN2 :: (Ord a, DynGraph g) => (NodeMap a -> c -> (d, NodeMap a)) -> c -> NodeMapM a b g d+liftN2 f c =+ do (m, g) <- get+ let (r, m') = f m c+ put (m', g)+ return r++liftN2' :: (Ord a, DynGraph g) => (NodeMap a -> c -> d) -> c -> NodeMapM a b g d+liftN2' f c =+ do (m, _) <- get+ return $ f m c+{- not used+liftN3 :: (Ord a, DynGraph g) => (NodeMap a -> c -> d -> (e, NodeMap a)) -> c -> d -> NodeMapM a b g e+liftN3 f c d =+ do (m, g) <- get+ let (r, m') = f m c d+ put (m', g)+ return r++liftN3' :: (Ord a, DynGraph g) => (NodeMap a -> c -> d -> e) -> c -> d -> NodeMapM a b g e+liftN3' f c d =+ do (m, g) <- get+ return $ f m c d+-}+liftM1 :: (Ord a, DynGraph g) => (NodeMap a -> c -> g a b -> g a b) -> c -> NodeMapM a b g ()+liftM1 f c =+ do (m, g) <- get+ let g' = f m c g+ put (m, g')++liftM1' :: (Ord a, DynGraph g) => (NodeMap a -> c -> g a b -> (g a b, NodeMap a, d)) -> c -> NodeMapM a b g d+liftM1' f c =+ do (m, g) <- get+ let (g', m', r) = f m c g+ put (m', g')+ return r++-- | Monadic node construction.+mkNodeM :: (Ord a, DynGraph g) => a -> NodeMapM a b g (LNode a)+mkNodeM = liftN2 mkNode++mkNodesM :: (Ord a, DynGraph g) => [a] -> NodeMapM a b g [LNode a]+mkNodesM = liftN2 mkNodes++mkEdgeM :: (Ord a, DynGraph g) => (a, a, b) -> NodeMapM a b g (Maybe (LEdge b))+mkEdgeM = liftN2' mkEdge++mkEdgesM :: (Ord a, DynGraph g) => [(a, a, b)] -> NodeMapM a b g (Maybe [LEdge b])+mkEdgesM = liftN2' mkEdges++insMapNodeM :: (Ord a, DynGraph g) => a -> NodeMapM a b g (LNode a)+insMapNodeM = liftM1' insMapNode++insMapEdgeM :: (Ord a, DynGraph g) => (a, a, b) -> NodeMapM a b g ()+insMapEdgeM = liftM1 insMapEdge++delMapNodeM :: (Ord a, DynGraph g) => a -> NodeMapM a b g ()+delMapNodeM = liftM1 delMapNode++delMapEdgeM :: (Ord a, DynGraph g) => (a, a) -> NodeMapM a b g ()+delMapEdgeM = liftM1 delMapEdge++insMapNodesM :: (Ord a, DynGraph g) => [a] -> NodeMapM a b g [LNode a]+insMapNodesM = liftM1' insMapNodes++insMapEdgesM :: (Ord a, DynGraph g) => [(a, a, b)] -> NodeMapM a b g ()+insMapEdgesM = liftM1 insMapEdges++delMapNodesM :: (Ord a, DynGraph g) => [a] -> NodeMapM a b g ()+delMapNodesM = liftM1 delMapNodes++delMapEdgesM :: (Ord a, DynGraph g) => [(a, a)] -> NodeMapM a b g ()+delMapEdgesM = liftM1 delMapEdges
+ Data/Graph/Inductive/Query.hs view
@@ -0,0 +1,29 @@+module Data.Graph.Inductive.Query(+ module Data.Graph.Inductive.Query.DFS,+ module Data.Graph.Inductive.Query.BFS,+ module Data.Graph.Inductive.Query.SP,+ module Data.Graph.Inductive.Query.GVD,+ module Data.Graph.Inductive.Query.MST,+ module Data.Graph.Inductive.Query.Indep,+ module Data.Graph.Inductive.Query.MaxFlow,+ module Data.Graph.Inductive.Query.MaxFlow2,+ module Data.Graph.Inductive.Query.ArtPoint,+ module Data.Graph.Inductive.Query.BCC,+ module Data.Graph.Inductive.Query.Dominators,+ module Data.Graph.Inductive.Query.TransClos,+ module Data.Graph.Inductive.Query.Monad,+) where++import Data.Graph.Inductive.Query.DFS+import Data.Graph.Inductive.Query.BFS+import Data.Graph.Inductive.Query.SP+import Data.Graph.Inductive.Query.GVD+import Data.Graph.Inductive.Query.MST+import Data.Graph.Inductive.Query.Indep+import Data.Graph.Inductive.Query.MaxFlow+import Data.Graph.Inductive.Query.MaxFlow2+import Data.Graph.Inductive.Query.ArtPoint+import Data.Graph.Inductive.Query.BCC+import Data.Graph.Inductive.Query.Dominators+import Data.Graph.Inductive.Query.TransClos+import Data.Graph.Inductive.Query.Monad
+ Data/Graph/Inductive/Query/ArtPoint.hs view
@@ -0,0 +1,122 @@+module Data.Graph.Inductive.Query.ArtPoint(+ ap+) where++import Data.Graph.Inductive.Graph+++------------------------------------------------------------------------------+-- Tree for storing the DFS numbers and back edges for each node in the graph.+-- Each node in this tree is of the form (v,n,b) where v is the vertex number,+-- n is its DFS number and b is the list of nodes (and their DFS numbers) that+-- lead to back back edges for that vertex v.+------------------------------------------------------------------------------+data DFSTree a = B (a,a,[(a,a)]) [DFSTree a]+ deriving (Eq)++------------------------------------------------------------------------------+-- Tree for storing the DFS and low numbers for each node in the graph.+-- Each node in this tree is of the form (v,n,l) where v is the vertex number,+-- n is its DFS number and l is its low number.+------------------------------------------------------------------------------+data LOWTree a = Brc (a,a,a) [LOWTree a]+ deriving (Eq)++------------------------------------------------------------------------------+-- Finds the back edges for a given node.+------------------------------------------------------------------------------+getBackEdges :: Node -> [[(Node,Int)]] -> [(Node,Int)]+getBackEdges _ [] = []+getBackEdges v ls = map head (filter (elem (v,0)) (tail ls))++------------------------------------------------------------------------------+-- Builds a DFS tree for a given graph. Each element (v,n,b) in the tree+-- contains: the node number v, the DFS number n, and a list of backedges b.+------------------------------------------------------------------------------+dfsTree :: Graph gr => Int -> Node -> [Node] -> [[(Node,Int)]] -> + gr a b -> ([DFSTree Int],gr a b,Int)+dfsTree n _ [] _ g = ([],g,n)+dfsTree n _ _ _ g | isEmpty g = ([],g,n)+dfsTree n u (v:vs) ls g = case match v g of+ (Nothing, g1) -> dfsTree n u vs ls g1+ (Just c , g1) -> (B (v,n+1,bck) ts:ts', g3, k)+ where bck = getBackEdges v ls+ (ts, g2,m) = dfsTree (n+1) v sc ls' g1+ (ts',g3,k) = dfsTree m v vs ls g2+ ls' = ((v,n+1):sc'):ls+ sc' = map (\x->(x,0)) sc+ sc = suc' c++------------------------------------------------------------------------------+-- Finds the minimum between a dfs number and a list of back edges' dfs+-- numbers.+------------------------------------------------------------------------------+minbckEdge :: Int -> [(Node,Int)] -> Int+minbckEdge n [] = n+minbckEdge n bs = min n (minimum (map snd bs))++------------------------------------------------------------------------------+-- Returns the low number for a node in a subtree.+------------------------------------------------------------------------------+getLow :: LOWTree Int -> Int+getLow (Brc (_,_,l) _) = l++------------------------------------------------------------------------------+-- Builds a low tree from a DFS tree. Each element (v,n,low) in the tree+-- contains: the node number v, the DFS number n, and the low number low.+------------------------------------------------------------------------------+lowTree :: DFSTree Int -> LOWTree Int+lowTree (B (v,n,[] ) [] ) = Brc (v,n,n) [] +lowTree (B (v,n,bcks) [] ) = Brc (v,n,minbckEdge n bcks) [] +lowTree (B (v,n,bcks) trs) = Brc (v,n,lowv) ts+ where lowv = min (minbckEdge n bcks) lowChild+ lowChild = minimum (map getLow ts)+ ts = map lowTree trs++------------------------------------------------------------------------------+-- Builds a low tree for a given graph. Each element (v,n,low) in the tree+-- contains: the node number v, the DFS number n, and the low number low.+------------------------------------------------------------------------------+getLowTree :: Graph gr => gr a b -> Node -> LOWTree Int+getLowTree g v = lowTree (head dfsf)+ where (dfsf, _, _) = dfsTree 0 0 [v] [] g++------------------------------------------------------------------------------+-- Tests if a node in a subtree is an articulation point. An non-root node v+-- is an articulation point iff there exists at least one child w of v such+-- that lowNumber(w) >= dfsNumber(v). The root node is an articulation point+-- iff it has two or more children.+------------------------------------------------------------------------------+isap :: LOWTree Int -> Bool+isap (Brc (_,_,_) []) = False+isap (Brc (_,1,_) ts) = length ts > 1+isap (Brc (_,n,_) ts) = length ch >= 1+ where ch = filter ( >=n) (map getLow ts)++------------------------------------------------------------------------------+-- Finds the articulation points by traversing the low tree.+------------------------------------------------------------------------------+arp :: LOWTree Int -> [Node]+arp (Brc (v,1,_) ts) | length ts > 1 = v:concatMap arp ts+ | otherwise = concatMap arp ts+arp (Brc (v,n,l) ts) | isap (Brc (v,n,l) ts) = v:concatMap arp ts+ | otherwise = concatMap arp ts++------------------------------------------------------------------------------+-- Finds the articulation points of a graph starting at a given node.+------------------------------------------------------------------------------+artpoints :: Graph gr => gr a b -> Node -> [Node]+artpoints g v = arp (getLowTree g v)++{-|+ Finds the articulation points for a connected undirected graph,+ by using the low numbers criteria:++ a) The root node is an articulation point iff it has two or more children.++ b) An non-root node v is an articulation point iff there exists at least+ one child w of v such that lowNumber(w) >= dfsNumber(v).+-}+ap :: Graph gr => gr a b -> [Node]+ap g = artpoints g v where ((_,v,_,_),_) = matchAny g+
+ Data/Graph/Inductive/Query/BCC.hs view
@@ -0,0 +1,75 @@+module Data.Graph.Inductive.Query.BCC(+ bcc+) where+++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Query.DFS+import Data.Graph.Inductive.Query.ArtPoint+++------------------------------------------------------------------------------+-- Given a graph g, this function computes the subgraphs which are+-- g's connected components.+------------------------------------------------------------------------------+gComponents :: DynGraph gr => gr a b -> [gr a b]+gComponents g = map (\(x,y)-> mkGraph x y) (zip ln le)+ where ln = map (\x->[(u,l)|(u,l)<-vs,elem u x]) cc+ le = map (\x->[(u,v,l)|(u,v,l)<-es,elem u x]) cc+ (vs,es,cc) = (labNodes g,labEdges g,components g)+++embedContexts :: DynGraph gr => Context a b -> [gr a b] -> [gr a b]+embedContexts (_,v,l,s) gs = map (\(x,y)-> x & y) (zip lc gs)+ where lc = map (\e->(e,v,l,e)) lc'+ lc'= map (\g->[ e | e <- s, gelem (snd e) g]) gs++------------------------------------------------------------------------------+-- Given a node v and a list of graphs, this functions returns the graph which+-- v belongs to.+------------------------------------------------------------------------------+findGraph :: DynGraph gr => Node -> [gr a b] -> Decomp gr a b+findGraph _ [] = error "findGraph: empty graph list"+findGraph v (g:gs) = case match v g of+ (Nothing, _) -> findGraph v gs+ (Just c, g') -> (Just c, g')++------------------------------------------------------------------------------+-- Given a graph g and its articulation points, this function disconnects g+-- for each articulation point and returns the connected components of the+-- resulting disconnected graph.+------------------------------------------------------------------------------+splitGraphs :: DynGraph gr => [gr a b] -> [Node] -> [gr a b]+splitGraphs gs [] = gs+splitGraphs [] _ = error "splitGraphs: empty graph list"+splitGraphs (g:gs) (v:vs) = splitGraphs (gs''++gs) vs + where gs'' = embedContexts c gs'+ gs' = gComponents g'+ (Just c,g') = findGraph v (g:gs)++{-|+Finds the bi-connected components of an undirected connected graph.+It first finds the articulation points of the graph. Then it disconnects the+graph on each articulation point and computes the connected components.+-}+bcc :: DynGraph gr => gr a b -> [gr a b]+bcc g = splitGraphs [g] (ap g)+++++++++ ++++++++++
+ Data/Graph/Inductive/Query/BFS.hs view
@@ -0,0 +1,131 @@+-- (c) 2000-2005 by Martin Erwig [see file COPYRIGHT]+-- | Breadth-First Search Algorithms++module Data.Graph.Inductive.Query.BFS(+ -- * BFS Node List+ bfs,bfsn,bfsWith,bfsnWith,+ -- * Node List With Depth Info+ level,leveln,+ -- * BFS Edges+ bfe,bfen,+ -- * BFS Tree+ bft,lbft,+ -- * Shortest Path (Number of Edges)+ esp,lesp+) where+++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Internal.Queue+import Data.Graph.Inductive.Internal.RootPath++-- bfs (node list ordered by distance)+--+bfsnInternal :: Graph gr => (Context a b -> c) -> Queue Node -> gr a b -> [c]+bfsnInternal f q g | queueEmpty q || isEmpty g = []+ | otherwise =+ case match v g of+ (Just c, g') -> f c:bfsnInternal f (queuePutList (suc' c) q') g'+ (Nothing, g') -> bfsnInternal f q' g'+ where (v,q') = queueGet q++bfsnWith :: Graph gr => (Context a b -> c) -> [Node] -> gr a b -> [c]+bfsnWith f vs = bfsnInternal f (queuePutList vs mkQueue)++bfsn :: Graph gr => [Node] -> gr a b -> [Node]+bfsn = bfsnWith node'++bfsWith :: Graph gr => (Context a b -> c) -> Node -> gr a b -> [c]+bfsWith f v = bfsnInternal f (queuePut v mkQueue)++bfs :: Graph gr => Node -> gr a b -> [Node]+bfs = bfsWith node'+++-- level (extension of bfs giving the depth of each node)+--+level :: Graph gr => Node -> gr a b -> [(Node,Int)]+level v = leveln [(v,0)]++suci c i = zip (suc' c) (repeat i)++leveln :: Graph gr => [(Node,Int)] -> gr a b -> [(Node,Int)]+leveln [] _ = []+leveln _ g | isEmpty g = []+leveln ((v,j):vs) g = case match v g of+ (Just c,g') -> (v,j):leveln (vs++suci c (j+1)) g'+ (Nothing,g') -> leveln vs g' +++-- bfe (breadth first edges)+-- remembers predecessor information+--+bfenInternal :: Graph gr => Queue Edge -> gr a b -> [Edge]+bfenInternal q g | queueEmpty q || isEmpty g = []+ | otherwise = + case match v g of+ (Just c, g') -> (u,v):bfenInternal (queuePutList (outU c) q') g'+ (Nothing, g') -> bfenInternal q' g'+ where ((u,v),q') = queueGet q++bfen :: Graph gr => [Edge] -> gr a b -> [Edge]+bfen vs g = bfenInternal (queuePutList vs mkQueue) g++bfe :: Graph gr => Node -> gr a b -> [Edge]+bfe v = bfen [(v,v)]++outU c = map (\(v,w,_)->(v,w)) (out' c)+++-- bft (breadth first search tree)+-- here: with inward directed trees+--+-- bft :: Node -> gr a b -> IT.InTree Node+-- bft v g = IT.build $ map swap $ bfe v g+-- where swap (x,y) = (y,x)+-- +-- sp (shortest path wrt to number of edges)+--+-- sp :: Node -> Node -> gr a b -> [Node]+-- sp s t g = reverse $ IT.rootPath (bft s g) t+++-- faster shortest paths +-- here: with root path trees+-- +bft :: Graph gr => Node -> gr a b -> RTree+bft v = bf (queuePut [v] mkQueue)++bf :: Graph gr => Queue Path -> gr a b -> RTree+bf q g | queueEmpty q || isEmpty g = []+ | otherwise =+ case match v g of+ (Just c, g') -> p:bf (queuePutList (map (:p) (suc' c)) q') g'+ (Nothing, g') -> bf q' g'+ where (p@(v:_),q') = queueGet q++esp :: Graph gr => Node -> Node -> gr a b -> Path+esp s t = getPath t . bft s+++-- lesp is a version of esp that returns labeled paths+-- Note that the label of the first node in a returned path is meaningless;+-- all other nodes are paired with the label of their incoming edge. +--+lbft :: Graph gr => Node -> gr a b -> LRTree b+lbft v g = case (out g v) of + [] -> [LP []]+ (v',_,l):_ -> lbf (queuePut (LP [(v',l)]) mkQueue) g++lbf :: Graph gr => Queue (LPath b) -> gr a b -> LRTree b+lbf q g | queueEmpty q || isEmpty g = []+ | otherwise =+ case match v g of+ (Just c, g') ->+ LP p:lbf (queuePutList (map (\v' -> LP (v':p)) (lsuc' c)) q') g'+ (Nothing, g') -> lbf q' g'+ where ((LP (p@((v,_):_))),q') = queueGet q++lesp :: Graph gr => Node -> Node -> gr a b -> LPath b+lesp s t = getLPath t . lbft s+
+ Data/Graph/Inductive/Query/DFS.hs view
@@ -0,0 +1,222 @@+-- (c) 2000 - 2005 by Martin Erwig [see file COPYRIGHT]+-- | Depth-First Search ++module Data.Graph.Inductive.Query.DFS(+ CFun,+ dfs,dfs',dff,dff',+ dfsWith, dfsWith',dffWith,dffWith',+ -- * Undirected DFS+ udfs,udfs',udff,udff',+ -- * Reverse DFS+ rdff,rdff',rdfs,rdfs',+ -- * Applications of DFS\/DFF+ topsort,topsort',scc,reachable,+ -- * Applications of UDFS\/UDFF+ components,noComponents,isConnected+) where++import Data.Tree+import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Basic++----------------------------------------------------------------------+-- DFS AND FRIENDS+----------------------------------------------------------------------++{-++ Classification of all 32 dfs functions:++ dfs-function ::= [direction]"df"structure["With"]["'"]+ direction --> "x" | "u" | "r"+ structure --> "s" | "f"++ | structure+ direction | "s" "f"+ ------------------------ + optional With + optional '+ "x" | xdfs xdff + " " | dfs dff+ "u" | udfs udff+ "r" | rdfs rdff+ ------------------------++ Direction Parameter+ -------------------+ x : parameterized by a function that specifies which nodes + to be visited next++ " ": the "normal case: just follow successors+ + u : undirected, ie, follow predecesors and successors+ + r : reverse, ie, follow predecesors+++ Structure Parameter+ -------------------+ s : result is a list of + (a) objects computed from visited contexts ("With"-version)+ (b) nodes (normal version)++ f : result is a tree/forest of + (a) objects computed from visited contexts ("With"-version)+ (b) nodes (normal version)++ Optional Suffixes+ -----------------+ With : objects to be put into list/tree are given by a function+ on contexts, default for non-"With" versions: nodes++ ' : parameter node list is given implicitly by the nodes of the + graph to be traversed, default for non-"'" versions: nodes+ must be provided explicitly+++ Defined are only the following 18 most important function versions:++ xdfsWith+ dfsWith,dfsWith',dfs,dfs'+ udfs,udfs'+ rdfs,rdfs'+ xdffWith+ dffWith,dffWith',dff,dff'+ udff,udff'+ rdff,rdff'+ + Others can be added quite easily if needed.+ +-}++-- fixNodes fixes the nodes of the graph as a parameter+--+fixNodes :: Graph gr => ([Node] -> gr a b -> c) -> gr a b -> c+fixNodes f g = f (nodes g) g+++-- generalized depth-first search+-- (could also be simply defined as applying preorderF to the +-- result of xdffWith)+-- +type CFun a b c = Context a b -> c++xdfsWith :: Graph gr => CFun a b [Node] -> CFun a b c -> [Node] -> gr a b -> [c]+xdfsWith _ _ [] _ = []+xdfsWith _ _ _ g | isEmpty g = []+xdfsWith d f (v:vs) g = case match v g of+ (Just c,g') -> f c:xdfsWith d f (d c++vs) g'+ (Nothing,g') -> xdfsWith d f vs g' +++-- dfs+--+dfsWith :: Graph gr => CFun a b c -> [Node] -> gr a b -> [c]+dfsWith = xdfsWith suc'++dfsWith' :: Graph gr => CFun a b c -> gr a b -> [c]+dfsWith' f = fixNodes (dfsWith f)++dfs :: Graph gr => [Node] -> gr a b -> [Node]+dfs = dfsWith node'++dfs' :: Graph gr => gr a b -> [Node]+dfs' = dfsWith' node'+++-- undirected dfs, ie, ignore edge directions+--+udfs :: Graph gr => [Node] -> gr a b -> [Node]+udfs = xdfsWith neighbors' node' ++udfs' :: Graph gr => gr a b -> [Node]+udfs' = fixNodes udfs+++-- reverse dfs, ie, follow predecessors+--+rdfs :: Graph gr => [Node] -> gr a b -> [Node]+rdfs = xdfsWith pre' node' ++rdfs' :: Graph gr => gr a b -> [Node]+rdfs' = fixNodes rdfs+++-- generalized depth-first forest+-- +xdfWith :: Graph gr => CFun a b [Node] -> CFun a b c -> [Node] -> gr a b -> ([Tree c],gr a b)+xdfWith _ _ [] g = ([],g)+xdfWith _ _ _ g | isEmpty g = ([],g)+xdfWith d f (v:vs) g = case match v g of+ (Nothing,g1) -> xdfWith d f vs g1 + (Just c,g1) -> (Node (f c) ts:ts',g3) + where (ts,g2) = xdfWith d f (d c) g1+ (ts',g3) = xdfWith d f vs g2 ++xdffWith :: Graph gr => CFun a b [Node] -> CFun a b c -> [Node] -> gr a b -> [Tree c]+xdffWith d f vs g = fst (xdfWith d f vs g)+++-- dff+--+dffWith :: Graph gr => CFun a b c -> [Node] -> gr a b -> [Tree c]+dffWith = xdffWith suc'++dffWith' :: Graph gr => CFun a b c -> gr a b -> [Tree c]+dffWith' f = fixNodes (dffWith f)++dff :: Graph gr => [Node] -> gr a b -> [Tree Node]+dff = dffWith node'++dff' :: Graph gr => gr a b -> [Tree Node]+dff' = dffWith' node'+++-- undirected dff+--+udff :: Graph gr => [Node] -> gr a b -> [Tree Node]+udff = xdffWith neighbors' node'++udff' :: Graph gr => gr a b -> [Tree Node]+udff' = fixNodes udff+++-- reverse dff, ie, following predecessors+--+rdff :: Graph gr => [Node] -> gr a b -> [Tree Node]+rdff = xdffWith pre' node'++rdff' :: Graph gr => gr a b -> [Tree Node]+rdff' = fixNodes rdff+++----------------------------------------------------------------------+-- ALGORITHMS BASED ON DFS+----------------------------------------------------------------------++components :: Graph gr => gr a b -> [[Node]]+components = (map preorder) . udff'++noComponents :: Graph gr => gr a b -> Int+noComponents = length . components++isConnected :: Graph gr => gr a b -> Bool+isConnected = (==1) . noComponents++postflatten :: Tree a -> [a]+postflatten (Node v ts) = postflattenF ts ++ [v]++postflattenF :: [Tree a] -> [a]+postflattenF = concatMap postflatten++topsort :: Graph gr => gr a b -> [Node]+topsort = reverse . postflattenF . dff'++topsort' :: Graph gr => gr a b -> [a]+topsort' = reverse . postorderF . (dffWith' lab')++scc :: Graph gr => gr a b -> [[Node]]+scc g = map preorder (rdff (topsort g) g) -- optimized, using rdff+-- sccOrig g = map preorder (dff (topsort g) (grev g)) -- original by Sharir++reachable :: Graph gr => Node -> gr a b -> [Node]+reachable v g = preorderF (dff [v] g)+
+ Data/Graph/Inductive/Query/Dominators.hs view
@@ -0,0 +1,40 @@+module Data.Graph.Inductive.Query.Dominators(+ dom+) where++import Data.List+import Data.Graph.Inductive.Graph+++type DomSets = [(Node,[Node],[Node])]+++intersection :: [[Node]] -> [Node]+intersection cs = foldr intersect (head cs) cs++getdomv :: [Node] -> DomSets -> [[Node]]+getdomv vs ds = [z|(w,_,z)<-ds,v<-vs,v==w]++builddoms :: DomSets -> [Node] -> DomSets+builddoms ds [] = ds+builddoms ds (v:vs) = builddoms ((fs++[(n,p,sort(n:idv))])++(tail rs)) vs+ where idv = intersection (getdomv p ds)+ (n,p,_) = head rs+ (fs,rs) = span (\(x,_,_)->x/=v) ds++domr :: DomSets -> [Node] -> DomSets+domr ds vs|xs == ds = ds+ |otherwise = builddoms xs vs+ where xs = (builddoms ds vs)++{-|+Finds the dominators relationship for a given graph and an initial+node. For each node v, it returns the list of dominators of v.+-}+dom :: Graph gr => gr a b -> Node -> [(Node,[Node])]+dom g u = map (\(x,_,z)->(x,z)) (domr ld n')+ where ld = (u,[],[u]):map (\v->(v,pre g v,n)) (n')+ n' = n\\[u]+ n = nodes g++
+ Data/Graph/Inductive/Query/GVD.hs view
@@ -0,0 +1,51 @@+-- (c) 2000-2005 by Martin Erwig [see file COPYRIGHT]+-- | Graph Voronoi Diagram ++module Data.Graph.Inductive.Query.GVD (+ Voronoi,+ gvdIn,gvdOut,+ voronoiSet,nearestNode,nearestDist,nearestPath,+-- vd,nn,ns,+-- vdO,nnO,nsO+) where++import Data.Maybe (listToMaybe)+import Data.List (nub)++import qualified Data.Graph.Inductive.Internal.Heap as H++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Query.SP (dijkstra)+import Data.Graph.Inductive.Internal.RootPath+import Data.Graph.Inductive.Basic++type Voronoi a = LRTree a++gvdIn :: (DynGraph gr, Real b) => [Node] -> gr a b -> Voronoi b+gvdIn vs g = gvdOut vs (grev g)++gvdOut :: (Graph gr, Real b) => [Node] -> gr a b -> Voronoi b+gvdOut vs = dijkstra (H.build (zip (repeat 0) (map (\v->LP [(v,0)]) vs)))++voronoiSet :: Real b => Node -> Voronoi b -> [Node]+voronoiSet v = nub . concat . filter (\p->last p==v) . map (\(LP p)->map fst p)++maybePath :: Real b => Node -> Voronoi b -> Maybe (LPath b)+maybePath v = listToMaybe . filter (\(LP ((w,_):_))->w==v)++nearestNode :: Real b => Node -> Voronoi b -> Maybe Node+nearestNode v = fmap (\(LP ((w,_):_))->w) . maybePath v++nearestDist :: Real b => Node -> Voronoi b -> Maybe b+nearestDist v = fmap (\(LP ((_,l):_))->l) . maybePath v++nearestPath :: Real b => Node -> Voronoi b -> Maybe Path+nearestPath v = fmap (\(LP p)->map fst p) . maybePath v+++-- vd = gvdIn [4,5] vor+-- vdO = gvdOut [4,5] vor+-- nn = map (flip nearestNode vd) [1..8]+-- nnO = map (flip nearestNode vdO) [1..8]+-- ns = map (flip voronoiSet vd) [1..8]+-- nsO = map (flip voronoiSet vdO) [1..8]
+ Data/Graph/Inductive/Query/Indep.hs view
@@ -0,0 +1,24 @@+-- (c) 2000 - 2002 by Martin Erwig [see file COPYRIGHT]+-- | Maximum Independent Node Sets++module Data.Graph.Inductive.Query.Indep (+ indep+) where+++import Data.Graph.Inductive.Graph+++first :: (a -> Bool) -> [a] -> a+first p = head . filter p++indep :: DynGraph gr => gr a b -> [Node]+indep g | isEmpty g = []+indep g = if length i1>length i2 then i1 else i2+ where vs = nodes g + m = maximum (map (deg g) vs) + v = first (\v'->deg g v'==m) vs + (Just c,g') = match v g + i1 = indep g'+ i2 = v:indep (delNodes (neighbors' c) g')+
+ Data/Graph/Inductive/Query/MST.hs view
@@ -0,0 +1,41 @@+-- (c) 2000-2005 by Martin Erwig [see file COPYRIGHT]+-- | Minimum-Spanning-Tree Algorithms ++module Data.Graph.Inductive.Query.MST (+ msTreeAt,msTree,+ -- * Path in MST+ msPath+) where++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Internal.RootPath+import qualified Data.Graph.Inductive.Internal.Heap as H+++newEdges :: Ord b => LPath b -> Context a b -> [H.Heap b (LPath b)]+newEdges (LP p) (_,_,_,s) = map (\(l,v)->H.unit l (LP ((v,l):p))) s++prim :: (Graph gr,Real b) => H.Heap b (LPath b) -> gr a b -> LRTree b+prim h g | H.isEmpty h || isEmpty g = []+prim h g =+ case match v g of+ (Just c,g') -> p:prim (H.mergeAll (h':newEdges p c)) g'+ (Nothing,g') -> prim h' g' + where (_,p@(LP ((v,_):_)),h') = H.splitMin h++msTreeAt :: (Graph gr,Real b) => Node -> gr a b -> LRTree b+msTreeAt v g = prim (H.unit 0 (LP [(v,0)])) g++msTree :: (Graph gr,Real b) => gr a b -> LRTree b+msTree g = msTreeAt v g where ((_,v,_,_),_) = matchAny g++msPath :: Real b => LRTree b -> Node -> Node -> Path+msPath t a b = joinPaths (getLPathNodes a t) (getLPathNodes b t)+ +joinPaths :: Path -> Path -> Path +joinPaths p q = joinAt (head p) p q++joinAt :: Node -> Path -> Path -> Path+joinAt _ (v:vs) (w:ws) | v==w = joinAt v vs ws+joinAt x p q = reverse p++(x:q)+
+ Data/Graph/Inductive/Query/MaxFlow.hs view
@@ -0,0 +1,127 @@+-- | Maximum Flow algorithm+-- We are given a flow network G=(V,E) with source s and sink t where each+-- edge (u,v) in E has a nonnegative capacity c(u,v)>=0, and we wish to+-- find a flow of maximum value from s to t.+-- +-- A flow in G=(V,E) is a real-valued function f:VxV->R that satisfies:+--+-- @+-- For all u,v in V, f(u,v)\<=c(u,v)+-- For all u,v in V, f(u,v)=-f(v,u)+-- For all u in V-{s,t}, Sum{f(u,v):v in V } = 0+-- @+--+-- The value of a flow f is defined as |f|=Sum {f(s,v)|v in V}, i.e.,+-- the total net flow out of the source.+--+-- In this module we implement the Edmonds-Karp algorithm, which is the+-- Ford-Fulkerson method but using the shortest path from s to t as the+-- augmenting path along which the flow is incremented.++module Data.Graph.Inductive.Query.MaxFlow(+ getRevEdges, augmentGraph, updAdjList, updateFlow, mfmg, mf, maxFlowgraph,+ maxFlow+) where+++import Data.List++import Data.Graph.Inductive.Basic+import Data.Graph.Inductive.Graph+--import Data.Graph.Inductive.Tree+import Data.Graph.Inductive.Query.BFS++-- |+-- @+-- i 0+-- For each edge a--->b this function returns edge b--->a .+-- i+-- Edges a\<--->b are ignored+-- j+-- @+getRevEdges :: (Num b,Ord b) => [(Node,Node)] -> [(Node,Node,b)]+getRevEdges [] = []+getRevEdges ((u,v):es) | notElem (v,u) es = (v,u,0):getRevEdges es+ | otherwise = getRevEdges (delete (v,u) es)++-- |+-- @+-- i 0+-- For each edge a--->b insert into graph the edge a\<---b . Then change the+-- i (i,0,i)+-- label of every edge from a---->b to a------->b+-- @+-- +-- where label (x,y,z)=(Max Capacity, Current flow, Residual capacity)+augmentGraph :: (DynGraph gr,Num b,Ord b) => gr a b -> gr a (b,b,b)+augmentGraph g = emap (\i->(i,0,i)) (insEdges (getRevEdges (edges g)) g)+ +-- | Given a successor or predecessor list for node u and given node v, find+-- the label corresponding to edge (u,v) and update the flow and residual+-- capacity of that edge's label. Then return the updated list.+updAdjList::(Num b,Ord b) => [((b,b,b),Node)]->Node->b->Bool->[((b,b,b),Node)]+updAdjList s v cf fwd | fwd == True = ((x,y+cf,z-cf),w):rs+ | otherwise = ((x,y-cf,z+cf),w):rs+ where ((x,y,z),w) = head (filter (\(_,w')->v==w') s)+ rs = filter (\(_,w')->v/=w') s++-- | Update flow and residual capacity along augmenting path from s to t in+-- graph G. For a path [u,v,w,...] find the node u in G and its successor and+-- predecessor list, then update the corresponding edges (u,v) and (v,u) on+-- those lists by using the minimum residual capacity of the path.+updateFlow :: (DynGraph gr,Num b,Ord b) => Path -> b -> gr a (b,b,b) -> gr a (b,b,b)+updateFlow [] _ g = g+updateFlow [_] _ g = g+updateFlow (u:v:vs) cf g = case match u g of+ (Nothing,g') -> g'+ (Just (p,u',l,s),g') -> (p',u',l,s') & g2+ where g2 = updateFlow (v:vs) cf g'+ s' = updAdjList s v cf True+ p' = updAdjList p v cf False++-- | Compute the flow from s to t on a graph whose edges are labeled with+-- (x,y,z)=(max capacity,current flow,residual capacity) and all edges+-- are of the form a\<---->b. First compute the residual graph, that is,+-- delete those edges whose residual capacity is zero. Then compute the+-- shortest augmenting path from s to t, and finally update the flow and+-- residual capacity along that path by using the minimum capacity of+-- that path. Repeat this process until no shortest path from s to t exist.+mfmg :: (DynGraph gr,Num b,Ord b) => gr a (b,b,b) -> Node -> Node -> gr a (b,b,b)+mfmg g s t | augPath == [] = g+ | otherwise = mfmg (updateFlow augPath minC g) s t+ where minC = minimum (map ((\(_,_,z)->z).snd)(tail augLPath))+ augPath = map fst augLPath+ LP augLPath = lesp s t gf+ gf = elfilter (\(_,_,z)->z/=0) g++-- | Compute the flow from s to t on a graph whose edges are labeled with+-- x, which is the max capacity and where not all edges need to be of the+-- form a\<---->b. Return the flow as a grap whose edges are labeled with+-- (x,y,z)=(max capacity,current flow,residual capacity) and all edges+-- are of the form a\<---->b+mf :: (DynGraph gr,Num b,Ord b) => gr a b -> Node -> Node -> gr a (b,b,b)+mf g s t = mfmg (augmentGraph g) s t++-- | Compute the maximum flow from s to t on a graph whose edges are labeled+-- with x, which is the max capacity and where not all edges need to be of+-- the form a\<---->b. Return the flow as a grap whose edges are labeled with+-- (y,x) = (current flow, max capacity).+maxFlowgraph :: (DynGraph gr,Num b,Ord b) => gr a b -> Node -> Node -> gr a (b,b)+maxFlowgraph g s t = emap (\(u,v,_)->(v,u)) g2+ where g2 = elfilter (\(x,_,_)->x/=0) g1+ g1 = mf g s t++-- | Compute the value of a maximumflow+maxFlow :: (DynGraph gr,Num b,Ord b) => gr a b -> Node -> Node -> b+maxFlow g s t = foldr (+) 0 (map (\(_,_,(x,_))->x)(out (maxFlowgraph g s t) s))++------------------------------------------------------------------------------+-- Some test cases: clr595 is from the CLR textbook, page 595. The value of+-- the maximum flow for s=1 and t=6 (23) coincides with the example but the +-- flow itself is slightly different since the textbook does not compute the +-- shortest augmenting path from s to t, but just any path. However remember +-- that for a given flow graph the maximum flow is not unique.+-- (gr595 is defined in GraphData.hs)+------------------------------------------------------------------------------++
+ Data/Graph/Inductive/Query/MaxFlow2.hs view
@@ -0,0 +1,263 @@+-- | Alternative Maximum Flow+module Data.Graph.Inductive.Query.MaxFlow2(+ Network,+ ekSimple, ekFused, ekList,+) where++-- ekSimple, ekFused, ekList) where++import Data.List+import Data.Maybe++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Tree+import Data.Graph.Inductive.Internal.FiniteMap+import Data.Graph.Inductive.Internal.Queue+import Data.Graph.Inductive.Query.BFS (bft)+++------------------------------------------------------------------------------+-- Data types++-- Network data type+type Network = Gr () (Double, Double)++-- Data type for direction in which an edge is traversed+data Direction = Forward | Backward+ deriving (Eq, Show)++-- Data type for edge with direction of traversal+type DirEdge b = (Node, Node, b, Direction)++type DirPath=[(Node, Direction)]+type DirRTree=[DirPath]++pathFromDirPath = map (\(n,_)->n)++------------------------------------------------------------------------------+-- Example networks++-- Example number 1+-- This network has a maximum flow of 2000+{-+exampleNetwork1 :: Network+exampleNetwork1=mkGraph [ (1,()), (2,()), (3,()), (4,()) ]+ [ (1,2,(1000,0)), (1,3,(1000,0)),+ (2,3,(1,0)), (2,4,(1000,0)), (3,4,(1000,0)) ]++-- Example number 2+-- Taken from "Introduction to Algorithms" (Cormen, Leiserson, Rivest)+-- This network has a maximum flow of 23+exampleNetwork2 :: Network+-- Names of nodes in "Introduction to Algorithms":+-- 1: s+-- 2: v1+-- 3: v2+-- 4: v3+-- 5: v4+-- 6: t+exampleNetwork2=mkGraph [ (1,()), (2,()), (3,()), (4,()), (5,()), (6,()) ]+ [ (1, 2, (16, 0)),+ (1, 3, (13, 0)),+ (2, 3, (10, 0)),+ (3, 2, (4, 0)),+ (2, 4, (12, 0)),+ (3, 5, (14, 0)),+ (4, 3, (9, 0)),+ (5, 4, (7, 0)),+ (4, 6, (20, 0)),+ (5, 6, (4, 0)) ]+-}+------------------------------------------------------------------------------+-- Implementation of Edmonds-Karp algorithm++-- EXTRACT fglEdmondsFused.txt+-- Compute an augmenting path+augPathFused :: Network -> Node -> Node -> Maybe DirPath+augPathFused g s t = listToMaybe $ map reverse $ + filter (\((u,_):_) -> u==t) tree+ where tree = bftForEK s g++-- Breadth First Search wrapper function+bftForEK :: Node -> Network -> DirRTree+bftForEK v = bfForEK (queuePut [(v,Forward)] mkQueue)++-- Breadth First Search, tailored for Edmonds & Karp+bfForEK :: Queue DirPath -> Network -> DirRTree+bfForEK q g+ | queueEmpty q || isEmpty g = []+ | otherwise = case match v g of+ (Nothing, g') -> bfForEK q1 g'+ (Just (preAdj, _, _, sucAdj), g') -> p:bfForEK q2 g'+ where+ -- Insert successor nodes (with path to root) into queue+ q2 = queuePutList suc1 $ queuePutList suc2 q1+ -- Traverse edges in reverse if flow positive+ suc1 = [ (preNode, Backward):p+ | ((_, f), preNode) <- preAdj, f>0]+ -- Traverse edges forwards if flow less than capacity+ suc2 = [ (sucNode,Forward):p+ | ((c, f), sucNode) <- sucAdj, c>f]+ where (p@((v,_):_), q1)=queueGet q++-- Extract augmenting path from network; return path as a sequence of +-- edges with direction of traversal, and new network with augmenting +-- path removed.+extractPathFused :: Network -> DirPath + -> ([DirEdge (Double,Double)], Network)+extractPathFused g [] = ([], g)+extractPathFused g [(_,_)] = ([], g)+extractPathFused g ((u,_):rest@((v,Forward):_)) =+ ((u, v, l, Forward):tailedges, newerg)+ where (tailedges, newerg) = extractPathFused newg rest+ Just (l, newg) = extractEdge g u v (\(c,f)->(c>f))+extractPathFused g ((u,_):rest@((v,Backward):_)) =+ ((v, u, l, Backward):tailedges, newerg)+ where (tailedges, newerg) = extractPathFused newg rest+ Just (l, newg) = extractEdge g v u (\(_,f)->(f>0))++-- ekFusedStep :: EKStepFunc+ekFusedStep g s t = case maybePath of+ Just _ -> + Just ((insEdges (integrateDelta es delta) newg), delta)+ Nothing -> Nothing+ where maybePath = augPathFused g s t+ (es, newg) = extractPathFused g (fromJust maybePath)+ delta = minimum $ getPathDeltas es++ekFused :: Network -> Node -> Node -> (Network, Double)+ekFused = ekWith ekFusedStep+-- ENDEXTRACT++-----------------------------------------------------------------------------+-- Alternative implementation: Use an explicit residual graph++-- EXTRACT fglEdmondsSimple.txt+residualGraph :: Network -> Gr () Double+residualGraph g = + mkGraph (labNodes g) + ([(u, v, c-f) | (u, v, (c,f)) <- labEdges g, c>f ] ++ + [(v, u, f) | (u,v,(_,f)) <- labEdges g, f>0])++augPath :: Network -> Node -> Node -> Maybe Path+augPath g s t = listToMaybe $ map reverse $ filter (\(u:_) -> u==t) tree+ where tree = bft s (residualGraph g)++-- Extract augmenting path from network; return path as a sequence of+-- edges with direction of traversal, and new network with augmenting +-- path removed.+extractPath :: Network -> Path -> ([DirEdge (Double,Double)], Network)+extractPath g [] = ([], g)+extractPath g [_] = ([], g)+extractPath g (u:v:ws) =+ case fwdExtract of+ Just (l, newg) -> ((u, v, l, Forward):tailedges, newerg)+ where (tailedges, newerg) = extractPath newg (v:ws)+ Nothing ->+ case revExtract of+ Just (l, newg) -> + ((v, u, l, Backward):tailedges, newerg)+ where (tailedges, newerg) = extractPath newg (v:ws)+ Nothing -> error "extractPath: revExtract == Nothing"+ where fwdExtract = extractEdge g u v (\(c,f)->(c>f))+ revExtract = extractEdge g v u (\(_,f)->(f>0))++-- Extract an edge from the graph that satisfies a given predicate+-- Return the label on the edge and the graph without the edge+extractEdge :: Gr a b -> Node -> Node -> (b->Bool) -> Maybe (b, Gr a b)+extractEdge g u v p =+ case adj of+ Just (el, _) -> Just (el, (p', node, l, rest) & newg)+ Nothing -> Nothing+ where (Just (p', node, l, s), newg) = match u g+ (adj, rest)=extractAdj s + (\(l', dest) -> (dest==v) && (p l'))++-- Extract an item from an adjacency list that satisfies a given +-- predicate. Return the item and the rest of the adjacency list+extractAdj :: Adj b -> ((b,Node)->Bool) -> (Maybe (b,Node), Adj b)+extractAdj [] _ = (Nothing, [])+extractAdj (adj:adjs) p+ | p adj = (Just adj, adjs)+ | otherwise = (theone, adj:rest) + where (theone, rest)=extractAdj adjs p++getPathDeltas :: [DirEdge (Double,Double)] -> [Double]+getPathDeltas [] = []+getPathDeltas (e:es) = case e of+ (_, _, (c,f), Forward) -> (c-f) : (getPathDeltas es)+ (_, _, (_,f), Backward) -> f : (getPathDeltas es)++integrateDelta :: [DirEdge (Double,Double)] -> Double + -> [LEdge (Double, Double)]+integrateDelta [] _ = []+integrateDelta (e:es) delta = case e of+ (u, v, (c, f), Forward) -> + (u, v, (c, f+delta)) : (integrateDelta es delta)+ (u, v, (c, f), Backward) -> + (u, v, (c, f-delta)) : (integrateDelta es delta)++type EKStepFunc = Network -> Node -> Node -> Maybe (Network, Double)++ekSimpleStep :: EKStepFunc+ekSimpleStep g s t = case maybePath of+ Just _ -> + Just ((insEdges (integrateDelta es delta) newg), delta)+ Nothing -> Nothing+ where maybePath = augPath g s t+ (es, newg) = extractPath g (fromJust maybePath)+ delta = minimum $ getPathDeltas es++ekWith :: EKStepFunc -> Network -> Node -> Node -> (Network, Double)+ekWith stepfunc g s t = case stepfunc g s t of+ Just (newg, delta) -> (finalg, capacity+delta)+ where (finalg, capacity) = (ekWith stepfunc newg s t)+ Nothing -> (g, 0)++ekSimple :: Network -> Node -> Node -> (Network, Double)+ekSimple = ekWith ekSimpleStep+-- ENDEXTRACT++-----------------------------------------------------------------------------+-- Alternative implementation: Process list of edges to extract path instead+-- of operating on graph structure++-- EXTRACT fglEdmondsList.txt+setFromList :: Ord a => [a] -> FiniteMap a ()+setFromList [] = emptyFM+setFromList (x:xs) = addToFM (setFromList xs) x ()++setContains :: Ord a => FiniteMap a () -> a -> Bool+setContains m i = case (lookupFM m i) of+ Nothing -> False+ Just () -> True++extractPathList :: [LEdge (Double, Double)] -> FiniteMap (Node,Node) () + -> ([DirEdge (Double, Double)], [LEdge (Double, Double)])+extractPathList [] _ = ([], [])+extractPathList (edge@(u,v,l@(c,f)):es) set+ | (c>f) && (setContains set (u,v)) = + let (pathrest, notrest)=extractPathList es (delFromFM set (u,v))+ in ((u,v,l,Forward):pathrest, notrest)+ | (f>0) && (setContains set (v,u)) =+ let (pathrest, notrest)=extractPathList es (delFromFM set (u,v))+ in ((u,v,l,Backward):pathrest, notrest)+ | otherwise =+ let (pathrest, notrest)=extractPathList es set in+ (pathrest, edge:notrest)++ekStepList :: EKStepFunc+ekStepList g s t = case maybePath of+ Just _ -> Just (mkGraph (labNodes g) newEdges, delta)+ Nothing -> Nothing+ where newEdges = (integrateDelta es delta) ++ otheredges+ maybePath = augPathFused g s t+ (es, otheredges) = extractPathList (labEdges g) + (setFromList (zip justPath (tail justPath)))+ delta = minimum $ getPathDeltas es+ justPath = pathFromDirPath (fromJust maybePath)++ekList :: Network -> Node -> Node -> (Network, Double)+ekList = ekWith ekStepList+-- ENDEXTRACT+
+ Data/Graph/Inductive/Query/Monad.hs view
@@ -0,0 +1,227 @@+-- (c) 2002 by Martin Erwig [see file COPYRIGHT]+-- | Monadic Graph Algorithms++module Data.Graph.Inductive.Query.Monad(+ -- * Additional Graph Utilities+ mapFst, mapSnd, (><), orP,+ -- * Graph Transformer Monad+ GT(..), apply, apply', applyWith, applyWith', runGT, condMGT', recMGT',+ condMGT, recMGT,+ -- * Graph Computations Based on Graph Monads+ -- ** Monadic Graph Accessing Functions+ getNode, getContext, getNodes', getNodes, sucGT, sucM,+ -- ** Derived Graph Recursion Operators+ graphRec, graphRec', graphUFold,+ -- * Examples: Graph Algorithms as Instances of Recursion Operators+ -- ** Instances of graphRec+ graphNodesM0, graphNodesM, graphNodes, graphFilterM, graphFilter,+ -- * Example: Monadic DFS Algorithm(s)+ dfsGT, dfsM, dfsM', dffM, graphDff, graphDff',+) where+++-- Why all this?+--+-- graph monad ensures single-threaded access +-- ==> we can safely use imperative updates in the graph implementation+--++import Data.Tree+--import Control.Monad (liftM)++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Monad++-- some additional (graph) utilities+--+mapFst :: (a -> b) -> (a, c) -> (b, c)+mapFst f (x,y) = (f x,y)+mapSnd :: (a -> b) -> (c, a) -> (c, b)+mapSnd f (x,y) = (x,f y)++infixr 8 ><+(><) :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)+(f >< g) (x,y) = (f x,g y)++orP :: (a -> Bool) -> (b -> Bool) -> (a,b) -> Bool+orP p q (x,y) = p x || q y++----------------------------------------------------------------------+-- "wrapped" state transformer monad ==+-- monadic graph transformer monad+----------------------------------------------------------------------++data GT m g a = MGT (m g -> m (a,g))++apply :: GT m g a -> m g -> m (a,g)+apply (MGT f) mg = f mg++apply' :: Monad m => GT m g a -> g -> m (a,g)+apply' gt = apply gt . return++applyWith :: Monad m => (a -> b) -> GT m g a -> m g -> m (b,g)+applyWith h (MGT f) gm = do {(x,g) <- f gm; return (h x,g)}++applyWith' :: Monad m => (a -> b) -> GT m g a -> g -> m (b,g)+applyWith' h gt = applyWith h gt . return++runGT :: Monad m => GT m g a -> m g -> m a+runGT gt mg = do {(x,_) <- apply gt mg; return x}+++instance Monad m => Monad (GT m g) where+ return x = MGT (\mg->do {g<-mg; return (x,g)})+ f >>= h = MGT (\mg->do {(x,g)<-apply f mg; apply' (h x) g})++condMGT' :: Monad m => (s -> Bool) -> GT m s a -> GT m s a -> GT m s a+condMGT' p f g = MGT (\mg->do {h<-mg; if p h then apply f mg else apply g mg})+ +recMGT' :: Monad m => (s -> Bool) -> GT m s a -> (a -> b -> b) -> b -> GT m s b+recMGT' p mg f u = condMGT' p (return u) + (do {x<-mg;y<-recMGT' p mg f u;return (f x y)})++condMGT :: Monad m => (m s -> m Bool) -> GT m s a -> GT m s a -> GT m s a+condMGT p f g = MGT (\mg->do {b<-p mg; if b then apply f mg else apply g mg})++recMGT :: Monad m => (m s -> m Bool) -> GT m s a -> (a -> b -> b) -> b -> GT m s b+recMGT p mg f u = condMGT p (return u) + (do {x<-mg;y<-recMGT p mg f u;return (f x y)})+++----------------------------------------------------------------------+-- graph computations based on state monads/graph monads+----------------------------------------------------------------------+++-- some monadic graph accessing functions+-- +getNode :: GraphM m gr => GT m (gr a b) Node+getNode = MGT (\mg->do {((_,v,_,_),g) <- matchAnyM mg; return (v,g)})++getContext :: GraphM m gr => GT m (gr a b) (Context a b)+getContext = MGT matchAnyM++-- some functions defined by using the do-notation explicitly+-- Note: most of these can be expressed as an instance of graphRec+-- +getNodes' :: (Graph gr,GraphM m gr) => GT m (gr a b) [Node]+getNodes' = condMGT' isEmpty (return [])+ (do v <- getNode+ vs <- getNodes+ return (v:vs))++getNodes :: GraphM m gr => GT m (gr a b) [Node]+getNodes = condMGT isEmptyM (return [])+ (do v <- getNode+ vs <- getNodes+ return (v:vs))++sucGT :: GraphM m gr => Node -> GT m (gr a b) (Maybe [Node])+sucGT v = MGT (\mg->do (c,g) <- matchM v mg+ case c of+ Just (_,_,_,s) -> return (Just (map snd s),g)+ Nothing -> return (Nothing,g)+ )++sucM :: GraphM m gr => Node -> m (gr a b) -> m (Maybe [Node])+sucM v = runGT (sucGT v)++++----------------------------------------------------------------------+-- some derived graph recursion operators+----------------------------------------------------------------------++-- +-- graphRec :: GraphMonad a b c -> (c -> d -> d) -> d -> GraphMonad a b d+-- graphRec f g u = cond isEmpty (return u) +-- (do x <- f+-- y <- graphRec f g u+-- return (g x y))++-- | encapsulates a simple recursion schema on graphs+graphRec :: GraphM m gr => GT m (gr a b) c -> + (c -> d -> d) -> d -> GT m (gr a b) d+graphRec = recMGT isEmptyM++graphRec' :: (Graph gr,GraphM m gr) => GT m (gr a b) c -> + (c -> d -> d) -> d -> GT m (gr a b) d+graphRec' = recMGT' isEmpty++graphUFold :: GraphM m gr => (Context a b -> c -> c) -> c -> GT m (gr a b) c+graphUFold = graphRec getContext++++----------------------------------------------------------------------+-- Examples: graph algorithms as instances of recursion operators+----------------------------------------------------------------------++-- instances of graphRec+-- +graphNodesM0 :: GraphM m gr => GT m (gr a b) [Node]+graphNodesM0 = graphRec getNode (:) []++graphNodesM :: GraphM m gr => GT m (gr a b) [Node]+graphNodesM = graphUFold (\(_,v,_,_)->(v:)) []++graphNodes :: GraphM m gr => m (gr a b) -> m [Node]+graphNodes = runGT graphNodesM++graphFilterM :: GraphM m gr => (Context a b -> Bool) ->+ GT m (gr a b) [Context a b]+graphFilterM p = graphUFold (\c cs->if p c then c:cs else cs) []++graphFilter :: GraphM m gr => (Context a b -> Bool) -> m (gr a b) -> m [Context a b]+graphFilter p = runGT (graphFilterM p)+++++----------------------------------------------------------------------+-- Example: monadic dfs algorithm(s)+----------------------------------------------------------------------++-- | Monadic graph algorithms are defined in two steps:+--+-- (1) define the (possibly parameterized) graph transformer (e.g., dfsGT)+-- (2) run the graph transformer (applied to arguments) (e.g., dfsM)+--++dfsGT :: GraphM m gr => [Node] -> GT m (gr a b) [Node]+dfsGT [] = return []+dfsGT (v:vs) = MGT (\mg->+ do (mc,g') <- matchM v mg+ case mc of+ Just (_,_,_,s) -> applyWith' (v:) (dfsGT (map snd s++vs)) g'+ Nothing -> apply' (dfsGT vs) g' )++-- | depth-first search yielding number of nodes+dfsM :: GraphM m gr => [Node] -> m (gr a b) -> m [Node]+dfsM vs = runGT (dfsGT vs)++dfsM' :: GraphM m gr => m (gr a b) -> m [Node]+dfsM' mg = do {vs <- nodesM mg; runGT (dfsGT vs) mg}+++-- | depth-first search yielding dfs forest+dffM :: GraphM m gr => [Node] -> GT m (gr a b) [Tree Node]+dffM vs = MGT (\mg->+ do g<-mg+ b<-isEmptyM mg+ if b||null vs then return ([],g) else + let (v:vs') = vs in+ do (mc,g1) <- matchM v mg+ case mc of+ Nothing -> apply (dffM vs') (return g1)+ Just c -> do (ts, g2) <- apply (dffM (suc' c)) (return g1)+ (ts',g3) <- apply (dffM vs') (return g2)+ return (Node (node' c) ts:ts',g3)+ )++graphDff :: GraphM m gr => [Node] -> m (gr a b) -> m [Tree Node]+graphDff vs = runGT (dffM vs)++graphDff' :: GraphM m gr => m (gr a b) -> m [Tree Node]+graphDff' mg = do {vs <- nodesM mg; runGT (dffM vs) mg}+
+ Data/Graph/Inductive/Query/SP.hs view
@@ -0,0 +1,32 @@+-- (c) 2000-2005 by Martin Erwig [see file COPYRIGHT]++module Data.Graph.Inductive.Query.SP(+ spTree,spLength,sp,+ dijkstra+) where++import qualified Data.Graph.Inductive.Internal.Heap as H++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Internal.RootPath++expand :: Real b => b -> LPath b -> Context a b -> [H.Heap b (LPath b)]+expand d (LP p) (_,_,_,s) = map (\(l,v)->H.unit (l+d) (LP ((v,l+d):p))) s++-- | Implementation of Dijkstra's shortest path algorithm +dijkstra :: (Graph gr, Real b) => H.Heap b (LPath b) -> gr a b -> LRTree b+dijkstra h g | H.isEmpty h || isEmpty g = []+dijkstra h g =+ case match v g of+ (Just c,g') -> p:dijkstra (H.mergeAll (h':expand d p c)) g'+ (Nothing,g') -> dijkstra h' g' + where (_,p@(LP ((v,d):_)),h') = H.splitMin h+ +spTree :: (Graph gr, Real b) => Node -> gr a b -> LRTree b+spTree v = dijkstra (H.unit 0 (LP [(v,0)]))++spLength :: (Graph gr, Real b) => Node -> Node -> gr a b -> b+spLength s t = getDistance t . spTree s++sp :: (Graph gr, Real b) => Node -> Node -> gr a b -> Path+sp s t = getLPathNodes t . spTree s
+ Data/Graph/Inductive/Query/TransClos.hs view
@@ -0,0 +1,21 @@+module Data.Graph.Inductive.Query.TransClos(+ trc+) where++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Query.DFS (reachable)+++getNewEdges :: DynGraph gr => [LNode a] -> gr a b -> [LEdge ()]+getNewEdges vs g = concatMap (\(u,_)->r u g) vs+ where r = \u g' -> map (\v->(u,v,())) (reachable u g')++{-|+Finds the transitive closure of a directed graph.+Given a graph G=(V,E), its transitive closure is the graph:+G* = (V,E*) where E*={(i,j): i,j in V and there is a path from i to j in G}+-}+trc :: DynGraph gr => gr a b -> gr a ()+trc g = insEdges (getNewEdges ln g) (insNodes ln empty)+ where ln = labNodes g+
+ Data/Graph/Inductive/Tree.hs view
@@ -0,0 +1,99 @@+-- (c) 1999 - 2002 by Martin Erwig [see file COPYRIGHT]+-- | Tree-based implementation of 'Graph' and 'DynGraph'++module Data.Graph.Inductive.Tree (Gr,UGr) where++import Data.List (foldl')++import Data.Graph.Inductive.Graph+import Data.Graph.Inductive.Internal.FiniteMap++import Data.Maybe (fromJust)+++----------------------------------------------------------------------+-- GRAPH REPRESENTATION+----------------------------------------------------------------------++data Gr a b = Gr (GraphRep a b)++type GraphRep a b = FiniteMap Node (Context' a b)+type Context' a b = (Adj b,a,Adj b)++type UGr = Gr () ()+++----------------------------------------------------------------------+-- CLASS INSTANCES+----------------------------------------------------------------------+++-- Show+--+showsGraph :: (Show a,Show b) => GraphRep a b -> ShowS+showsGraph Empty = id+showsGraph (Node _ l (v,(_,l',s)) r) = showsGraph l . ('\n':) . + shows v . (':':) . shows l' . ("->"++) . shows s . showsGraph r+ +instance (Show a,Show b) => Show (Gr a b) where+ showsPrec _ (Gr g) = showsGraph g+++-- Graph+-- +instance Graph Gr where+ empty = Gr emptyFM+ isEmpty (Gr g) = case g of {Empty -> True; _ -> False}+ match = matchGr+ mkGraph vs es = (insEdges' . insNodes vs) empty+ where+ insEdges' g = foldl' (flip insEdge) g es++ labNodes (Gr g) = map (\(v,(_,l,_))->(v,l)) (fmToList g)+ -- more efficient versions of derived class members+ --+ matchAny (Gr Empty) = error "Match Exception, Empty Graph"+ matchAny g@(Gr (Node _ _ (v,_) _)) = (c,g') where (Just c,g') = matchGr v g+ noNodes (Gr g) = sizeFM g+ nodeRange (Gr Empty) = (0,0)+ nodeRange (Gr g) = (ix (minFM g),ix (maxFM g)) where ix = fst.fromJust+ labEdges (Gr g) = concatMap (\(v,(_,_,s))->map (\(l,w)->(v,w,l)) s) (fmToList g)+++matchGr v (Gr g) = + case splitFM g v of + Nothing -> (Nothing,Gr g)+ Just (g',(_,(p,l,s))) -> (Just (p',v,l,s),Gr g2)+ where s' = filter ((/=v).snd) s+ p' = filter ((/=v).snd) p+ g1 = updAdj g' s' (clearPred v)+ g2 = updAdj g1 p' (clearSucc v)+++-- DynGraph+-- +instance DynGraph Gr where+ (p,v,l,s) & (Gr g) | elemFM g v = error ("Node Exception, Node: "++show v)+ | otherwise = Gr g3+ where g1 = addToFM g v (p,l,s)+ g2 = updAdj g1 p (addSucc v)+ g3 = updAdj g2 s (addPred v)+++----------------------------------------------------------------------+-- UTILITIES+----------------------------------------------------------------------++addSucc v l (p,l',s) = (p,l',(l,v):s)+addPred v l (p,l',s) = ((l,v):p,l',s)++clearSucc v _ (p,l,s) = (p,l,filter ((/=v).snd) s)+clearPred v _ (p,l,s) = (filter ((/=v).snd) p,l,s)++updAdj :: GraphRep a b -> Adj b -> (b -> Context' a b -> Context' a b) -> GraphRep a b+updAdj g [] _ = g+updAdj g ((l,v):vs) f | elemFM g v = updAdj (updFM g v (f l)) vs f+ | otherwise = error ("Edge Exception, Node: "++show v)+++
+ LICENSE view
@@ -0,0 +1,28 @@+Copyright (c) 1999-2004, Martin Erwig+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice,+ this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of its contributors may be+ used to endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ fgl.cabal view
@@ -0,0 +1,39 @@+name: fgl+version: 5.3+license: BSD3+license-file: LICENSE+maintainer: Martin Erwig+homepage: http://web.engr.oregonstate.edu/~erwig/fgl/haskell+category: Data Structures+synopsis: Martin Erwig's Functional Graph Library+exposed-modules:+ Data.Graph.Inductive.Internal.FiniteMap,+ Data.Graph.Inductive.Internal.Heap,+ Data.Graph.Inductive.Internal.Queue,+ Data.Graph.Inductive.Internal.RootPath,+ Data.Graph.Inductive.Internal.Thread,+ Data.Graph.Inductive.Basic,+ Data.Graph.Inductive.Example,+ Data.Graph.Inductive.Graph,+ Data.Graph.Inductive.Graphviz,+ Data.Graph.Inductive.Monad,+ Data.Graph.Inductive.NodeMap,+ Data.Graph.Inductive.Query,+ Data.Graph.Inductive.Tree,+ Data.Graph.Inductive.Monad.IOArray,+ Data.Graph.Inductive.Query.ArtPoint,+ Data.Graph.Inductive.Query.BCC,+ Data.Graph.Inductive.Query.BFS,+ Data.Graph.Inductive.Query.DFS,+ Data.Graph.Inductive.Query.Dominators,+ Data.Graph.Inductive.Query.GVD,+ Data.Graph.Inductive.Query.Indep,+ Data.Graph.Inductive.Query.MST,+ Data.Graph.Inductive.Query.MaxFlow,+ Data.Graph.Inductive.Query.MaxFlow2,+ Data.Graph.Inductive.Query.Monad,+ Data.Graph.Inductive.Query.SP,+ Data.Graph.Inductive.Query.TransClos,+ Data.Graph.Inductive+build-depends: base, mtl+extensions: MultiParamTypeClasses, OverlappingInstances