Skip to content

Commit

Permalink
added profiling to bench Makefile + haddock comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Raeez Lorgat committed Sep 1, 2011
1 parent 2f85444 commit 75a6c6e
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 143 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -6,5 +6,8 @@ dist
*.chs.h
*.csv
*.html
*.prof

bench/bench
bench/prof
bench/lgl
9 changes: 0 additions & 9 deletions Data/Graph/Linear/Basic.hs
Expand Up @@ -21,10 +21,6 @@ module Data.Graph.Linear.Basic
where

import Data.Graph.Linear.Graph
-- import Data.Graph.Linear.Representation.Array
-- import Data.Graph.Linear.Representation.Vector
-- import Data.Graph.Linear.Representation.HashMap
-- import Data.Graph.Linear.Representation.Map

-------------------------------------------------------------------------------
-- Basic traversals/projections
Expand All @@ -47,8 +43,3 @@ outdegree = mapT numEdges

indegree :: IntGraph -> Table Int
indegree = outdegree . transpose

graphEmpty :: IntGraph -> Bool
graphEmpty g = lo > hi
where (lo, hi) = bounds g

77 changes: 50 additions & 27 deletions Data/Graph/Linear/Graph.hs
Expand Up @@ -24,17 +24,11 @@ module Data.Graph.Linear.Graph
)
where

#ifdef USE_MAPS
import Data.Graph.Linear.Representation.Map
#endif

#ifdef USE_VECTOR
{- #ifdef USE_VECTOR
import Data.Graph.Linear.Representation.Vector as Rep
#endif

#ifdef USE_ARRAY
#else-}
import Data.Graph.Linear.Representation.Array as Rep
#endif
-- #endif

import Data.Maybe(mapMaybe)
import Data.List
Expand All @@ -45,20 +39,22 @@ import Data.List
-- | A single Vertex represented in an InternalGraph.
type Vertex = Int

-- | A single edge represented in an InternalGraph
type Edge = (Vertex, Vertex)
-- | A single edge between any two representations of points in a graph.
type Edge n = (n, n)

-- | An internal-only adjacency list mapping from Vertices to neighboring vertices.
type InternalGraph = Rep.Mapping [Vertex]

-------------------------------------------------------------------------------
-- External Graph Representation

-- | A single 'Node' represents an addressable vertex within a 'Graph'
-- | A single 'Node' represents an addressable vertex within a 'Graph'. The choice
-- of information stored at the node, as well as the label addressing each node is
-- kept polymorphic.
data Node payload label = Node
{ payload :: payload
, label :: !label
, successors :: ![label]
{ payload :: payload -- ^ The information stored at this point in the graph
, label :: !label -- ^ The label for this node
, successors :: ![label] -- ^ List of labeled edges rechable from this node.
}

instance Eq l => Eq (Node p l) where
Expand All @@ -70,22 +66,42 @@ instance Ord l => Ord (Node p l) where
| l1 == l2 = EQ
| l1 <= l2 = LT
| otherwise = GT

instance (Show p, Show l) => Show (Node p l) where
show (Node p l ls) = show p ++ "[" ++ show l ++ "]"
-------------------------------------------------------------------------------
-- Constructors

-- | Given an arbitrary representation we can construct a graph.
-- | Given an arbitrary representation of a set of nodes, we can construct a graph.
class Ord node => GraphRepresentation node where
-- | The Graph data type, polymorphic in the type of node.
data Graph node :: *

-- |The empty graph.
empty :: Graph node

-- |Given a list of nodes, we can construct a graph.
mkGraph :: [node] -> Graph node
bounds :: Graph node -> Bounds

-- |List of nodes in this graph.
nodes :: Graph node -> [node]

-- |List of vertices in this graph.
vertices :: Graph node -> [Vertex]
edges :: Graph node -> [Edge]

-- |List of edges between nodes in this graph.
edges :: Graph node -> [Edge node]

-- |List of edges between vertices in this graph.
vedges :: Graph node -> [Edge Vertex]

-- |Return the vertices adjacent to a given node in this graph.
adjacentTo :: Graph node -> Vertex -> [Vertex]

-- |Return the upper and lower bounds on the vertex-numbering of this graph's
-- representation
bounds :: Graph node -> Bounds

instance Ord l => GraphRepresentation (Node p l) where
data Graph (Node p l) = Graph
{ grAdjacencyList :: {-# UNPACK #-} !InternalGraph
Expand All @@ -96,17 +112,20 @@ instance Ord l => GraphRepresentation (Node p l) where
empty = Graph Rep.empty (error "emptyGraph") (const Nothing)
mkGraph nodes = Graph intgraph vertex_fn (label_vertex . label)
where
(vertex_fn, label_vertex, numbered_nodes) = reduceNodesIntoVertices nodes label
(bounds, vertex_fn, label_vertex, numbered_nodes) = reduceNodesIntoVertices nodes label

reduceNodesIntoVertices nodes label_extractor = ((!) vertex_map, label_vertex, numbered_nodes)
reduceNodesIntoVertices nodes label_extractor = (bounds, (!) vertex_map, label_vertex, numbered_nodes)
where
max_v = length nodes - 1
bounds = (0, max_v)

sorted_nodes = let n1 `le` n2 = (label_extractor n1 `compare` label_extractor n2)
in sortBy le nodes

numbered_nodes = [0..] `zip` sorted_nodes

key_map = Rep.fromList [(v, label_extractor node) | (v, node) <- numbered_nodes]
vertex_map = Rep.fromList numbered_nodes
key_map = Rep.mkMap bounds [(v, label_extractor node) | (v, node) <- numbered_nodes]
vertex_map = Rep.mkMap bounds numbered_nodes

--label_vertex :: label -> Maybe Vertex
-- returns Nothing for non-interesting vertices
Expand All @@ -119,16 +138,20 @@ instance Ord l => GraphRepresentation (Node p l) where
EQ -> Just mid
GT -> find (mid + 1) b

intgraph = Rep.fromList [(v, mapMaybe label_vertex ks) | (v, Node _ _ ks) <- numbered_nodes]

vertices (Graph g _ _) = domain g
edges (Graph g _ _) = [ (v, w) | v <- domain g, w <- g ! v ]
bounds (Graph g _ _) = domainBounds g
intgraph = Rep.mkMap bounds [(v, mapMaybe label_vertex ks) | (v, Node _ _ ks) <- numbered_nodes]

nodes (Graph g vm _) = map vm (domain g)
vertices (Graph g vm _) = domain g
edges (Graph g vm _) = [ (vm v, vm w) | v <- domain g, w <- g ! v ]
vedges (Graph g _ _) = [ (v, w) | v <- domain g, w <- g ! v ]
adjacentTo (Graph g _ _) = (!) g
bounds (Graph g _ _) = domainBounds g


-- |Helper function for constructing graphs out of lists of tuples.
graphFromEdgedVertices :: Ord label => [(payload, label, [label])] -> Graph (Node payload label)
graphFromEdgedVertices = mkGraph . map nodeConstructor

-- |A helper function for constructing Node representations out of tuples.
nodeConstructor :: Ord l => (p, l, [l]) -> Node p l
nodeConstructor = \(p, l, ls) -> Node p l ls
17 changes: 10 additions & 7 deletions Data/Graph/Linear/Query/BCC.hs
Expand Up @@ -33,7 +33,7 @@ import Control.Applicative

-- |A list of biconnected components, structured as a tuple of
-- (component id, component edge list)
type BCCList = [(Int, [Edge])]
type BCCList = [(Int, [Edge Vertex])]

-- |A mapping from internal graph vertices to biconnected component id
type BCCMap = Vertex -> Int
Expand All @@ -43,21 +43,23 @@ type BCCMap = Vertex -> Int
-- inclusion within this biconnected component
data BCC node = BCC
{ bccID :: !Int
, bccVertices :: [Edge] -- ^ List of edges in the component
, bccVertices :: [Edge Vertex] -- ^ List of edges in the component
, bccMap :: node -> Maybe Bool
}

instance Show payload => Show (BCC payload) where
show (BCC _ vertices _) = show vertices


-- |Structure holding the state of threaded through the execution of Tarjan's
-- strongly connected components algorithm.
data TarjanState = TS
{ nextN :: {-# UNPACK #-} !Int -- ^ Next node number
, nextC :: {-# UNPACK #-} !Int -- ^ next BCC number
, stack :: ![Edge] -- ^ Traversal Stack
, stack :: ![Edge Vertex] -- ^ Traversal Stack
, bccs :: BCCList -- ^ bcc list
}

-- |Run Tarjan's biconnected components algorithm.
bcc :: GraphRepresentation node
=> Graph node
-> (BCCList, BCCMap)
Expand Down Expand Up @@ -129,11 +131,12 @@ biConnect g marks lowpoints st v u =


{-# INLINE processStack #-}
processStack :: STMapping s Int -> Vertex -> Vertex -> [Edge] -> ST s ([Edge], [Edge])
processStack :: STMapping s Int -> Vertex -> Vertex -> [Edge Vertex] -> ST s ([Edge Vertex], [Edge Vertex])
processStack marks v w stck = do (bcc', stck') <- buildBCC marks w [] stck
return ((v, w):bcc', delete (v, w) stck')

buildBCC :: STMapping s Int -> Vertex -> [Edge] -> [Edge] -> ST s ([Edge], [Edge])
{-# INLINE buildBCC #-}
buildBCC :: STMapping s Int -> Vertex -> [Edge Vertex] -> [Edge Vertex] -> ST s ([Edge Vertex], [Edge Vertex])
buildBCC marks w cs [] = return (cs, [])
buildBCC marks w cs ((u1, u2):stck) =
ifM (readSTMap marks u1 .>=. readSTMap marks w)
Expand All @@ -142,7 +145,7 @@ buildBCC marks w cs ((u1, u2):stck) =
-- else
(return (cs, (u1, u2):stck)) -- otherwise return the constructed component

-- | Construct a graph from a list of edged vertices, and compute the biconnected
-- | Construct a graph from a list of tuples, and compute the biconnected
-- components∙
biConnectedComp :: Ord label
=> [(payload, label, [label])]
Expand Down
38 changes: 29 additions & 9 deletions Data/Graph/Linear/Query/SCC.hs
Expand Up @@ -29,59 +29,75 @@ import Control.Monad(forM_, ap)
import Control.Monad.ST
import Control.Applicative

-- | Strongly connected component.
-- |Strongly connected component.
data SCC vertex = AcyclicSCC vertex -- ^ A single vertex that is not in any cycle.
| CyclicSCC [vertex] -- ^ A maximal set of mutually reachable vertices.

instance Functor SCC where
fmap f (AcyclicSCC v) = AcyclicSCC (f v)
fmap f (CyclicSCC vs) = CyclicSCC (fmap f vs)

instance Show s => Show (SCC s) where
show (AcyclicSCC v) = show v
show (CyclicSCC vs) = show vs

-- |Convert a list of SCCs to its list representation.
flattenSCCs :: [SCC a] -> [a]
flattenSCCs = concatMap flattenSCC

-- |Convert a single SCC to its list representation.
flattenSCC :: SCC a -> [a]
flattenSCC (AcyclicSCC v) = [v]
flattenSCC (CyclicSCC vs) = vs

-- |Output of Tarjan's strongly connected components algorithm; returns a list
-- of tuples, indexed by (component id, list of vertices in component).
type SCCList = [(Int, [Vertex])]

-- |Output of Tarjan's strongly connected components algorithm; returns a map from
-- vertices to strongly connected component id's.
type SCCMap = Vertex -> Int

-- |Structure holding the state threaded through the execution of Tarjan's
-- strongly connected components algorithm.
data TarjanState = TS
{ nextN :: {-# UNPACK #-} !Int -- ^ Next node number
, nextC :: {-# UNPACK #-} !Int -- ^ next SCC number
, stack :: ![Vertex] -- ^ Traversal Stack
, sccs :: !SCCList -- ^ Completed scc list
}

-- |Run Tarjan's strongly connected components algorithm.
scc :: GraphRepresentation node => Graph node -> (SCCList, SCCMap)
scc g = runST (
do marks <- newSTMap (bounds g) 0
lowlinks <- newSTMap (bounds g) 0
st <- newSTRef $ TS 1 1 [] []

forM_ (vertices g) $ \w ->
whenM (unvisited marks w) -- unvisited
whenM (unvisited marks w)
$ strongConnect g marks lowlinks st w

final <- readSTRef st
sccMap <- unsafeFreeze marks

return (sccs final, \i -> sccMap ! i)
)

{-# INLINE strongConnect #-}
-- |Find the strongly connected components rooted at vertex v
strongConnect :: GraphRepresentation node
=> Graph node -- original graph
-> STMapping s Int -- state of node (visited/unvisited)
-> STMapping s Int
-> STMapping s Int -- state of vertex {0 = unvisited, -ve = on the stack, +ve = in a component)
-> STMapping s Int -- vertex of node
-> STRef s TarjanState
-> Vertex
-> ST s ()
strongConnect g marks lowlinks st v =
do s <- readSTRef st
let n = nextN s
writeSTMap marks v (negate n)
writeSTMap lowlinks v n
writeSTMap marks v $ (negate n)
writeSTMap lowlinks v $ n
let s' = s { stack = v:stack s
, nextN = n + 1
}
Expand All @@ -98,7 +114,7 @@ strongConnect g marks lowlinks st v =
$ do ll' <- min <$> readSTMap lowlinks v <*> (negate <$> readSTMap marks w)
writeSTMap lowlinks v ll')

whenM (readSTMap lowlinks v .==. readSTMap marks v)
whenM (readSTMap lowlinks v .==. (negate <$> readSTMap marks v))
$ do s <- readSTRef st
let nextComponentID = nextC s
(newSCC, newStack) = span (>= v) (stack s)
Expand All @@ -111,7 +127,8 @@ strongConnect g marks lowlinks st v =

writeSTRef st s'


-- |Construct a graph from a list of tuples and compute the strongly connected
-- components.
stronglyConnComp :: Ord label
=> [(payload, label, [label])]
-> [SCC payload]
Expand All @@ -125,6 +142,9 @@ stronglyConnComp es = reverse $ map cvt cs
cvt (_,vs) = CyclicSCC [ payload | Node payload _ _ <- map (grVertexMap g) vs ]


-- |Wrapper function computing the strongly connected components present in the
-- graph represented as a list of tuples. Same as stronglyConnComp, but retains
-- full node information in the generated SCCs.
stronglyConnCompN :: Ord label
=> [(payload, label, [label])]
-> [SCC (Node payload label)]
Expand Down

0 comments on commit 75a6c6e

Please sign in to comment.