Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Synopsis
- data Graph edge node edgeLabel nodeLabel
- type LabeledNode n label = (n, label)
- type LabeledEdge edge node label = (edge node, label)
- class (Foldable edge, Ord1 edge) => Edge edge where
- defaultEdgeFoldMap :: (Edge edge, Monoid a) => edge a -> a
- data DirEdge node = DirEdge node node
- data UndirEdge node = UndirEdge node node
- undirEdge :: Ord node => node -> node -> UndirEdge node
- data EitherEdge node
- = EDirEdge (DirEdge node)
- | EUndirEdge (UndirEdge node)
- empty :: Graph edge node edgeLabel nodeLabel
- fromList :: (Edge e, Ord n) => [LabeledNode n nl] -> [LabeledEdge e n el] -> Graph e n el nl
- fromMap :: (Edge e, Ord n) => Map n nl -> Map (e n) el -> Graph e n el nl
- graphMap :: Graph edge node edgeLabel nodeLabel -> Map node (InOutMap edge node edgeLabel nodeLabel)
- nodeLabels :: (Edge e, Ord n) => Graph e n el nl -> Map n nl
- nodeSet :: Graph e n el nl -> Set n
- nodes :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> [node]
- nodeEdges :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Map node (Set (edge node), nodeLabel, Set (edge node))
- edgeLabels :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Map (edge node) edgeLabel
- edgeSet :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Set (edge node)
- edges :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> [edge node]
- isEmpty :: Graph e n el nl -> Bool
- lookupNode :: Ord n => n -> Graph e n el nl -> Maybe nl
- lookupEdge :: (Edge e, Ord n) => e n -> Graph e n el nl -> Maybe el
- predecessors :: (Edge e, Ord n) => Graph e n el nl -> n -> [n]
- successors :: (Edge e, Ord n) => Graph e n el nl -> n -> [n]
- adjacentEdgeSet :: (Edge e, Ord n) => Graph e n el nl -> n -> Set (e n)
- adjacentEdges :: (Edge e, Ord n) => Graph e n el nl -> n -> Set (e n)
- isLoop :: (Edge edge, Eq node) => edge node -> Bool
- pathExists :: (Edge edge, Ord node) => node -> node -> Graph edge node edgeLabel nodeLabel -> Bool
- depthFirstSearch :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Forest node
- topologicalSort :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> ([node], Graph edge node edgeLabel nodeLabel)
- components :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> [Graph edge node edgeLabel nodeLabel]
- isConsistent :: (Ord n, Eq el) => Graph DirEdge n el nl -> Bool
- stronglyConnectedComponents :: Ord node => Graph DirEdge node edgeLabel nodeLabel -> [Set node]
- mapNode :: (nl0 -> nl1) -> Graph e n el nl0 -> Graph e n el nl1
- mapNodeWithKey :: (n -> nl0 -> nl1) -> Graph e n el nl0 -> Graph e n el nl1
- mapEdge :: (el0 -> el1) -> Graph e n el0 nl -> Graph e n el1 nl
- mapEdgeWithKey :: (e n -> el0 -> el1) -> Graph e n el0 nl -> Graph e n el1 nl
- mapNodeWithInOut :: (Edge e, Ord n) => (InOut e n el nl0 -> nl1) -> Graph e n el nl0 -> Graph e n el nl1
- type InOut e n el nl = ([LabeledEdge e n el], LabeledNode n nl, [LabeledEdge e n el])
- filterEdgeWithKey :: (Edge e, Ord n) => (e n -> el -> Bool) -> Graph e n el nl -> Graph e n el nl
- traverseNode :: (Applicative f, Edge e, Ord n) => (nl0 -> f nl1) -> Graph e n el nl0 -> f (Graph e n el nl1)
- traverseEdge :: (Applicative f, Edge e, Ord n) => (el0 -> f el1) -> Graph e n el0 nl -> f (Graph e n el1 nl)
- traverse :: (Applicative f, Edge e, Ord n) => (nl0 -> f nl1) -> (el0 -> f el1) -> Graph e n el0 nl0 -> f (Graph e n el1 nl1)
- checkedZipWith :: (Edge edge, Ord node) => Caller -> (nodeLabel0 -> nodeLabel1 -> nodeLabel2) -> (edgeLabel0 -> edgeLabel1 -> edgeLabel2) -> Graph edge node edgeLabel0 nodeLabel0 -> Graph edge node edgeLabel1 nodeLabel1 -> Graph edge node edgeLabel2 nodeLabel2
- union :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel
- class Edge edge => Reverse edge
- reverse :: (Reverse e, Ord n) => Graph e n el nl -> Graph e n el nl
- reverseEdge :: Reverse edge => edge node -> edge node
- mapKeys :: (Edge edge1, Ord node0, Ord node1) => (node0 -> node1) -> (edge0 node0 -> edge1 node1) -> Graph edge0 node0 edgeLabel nodeLabel -> Graph edge1 node1 edgeLabel nodeLabel
- mapMaybeEdgeKeys :: (Edge e1, Ord n) => (e0 n -> Maybe (e1 n)) -> Graph e0 n el nl -> Graph e1 n el nl
- mapEdgeKeys :: (Edge e1, Ord n) => (e0 n -> e1 n) -> Graph e0 n el nl -> Graph e1 n el nl
- deleteNode :: (Edge e, Ord n) => n -> Graph e n el nl -> Graph e n el nl
- deleteNodeSet :: (Edge e, Ord n) => Set n -> Graph e n el nl -> Graph e n el nl
- deleteEdge :: (Edge e, Ord n) => e n -> Graph e n el nl -> Graph e n el nl
- insertNode :: Ord n => n -> nl -> Graph e n el nl -> Graph e n el nl
- insertEdge :: (Edge e, Ord n) => e n -> el -> Graph e n el nl -> Graph e n el nl
- insertEdgeSet :: (Edge e, Ord n) => Map (e n) el -> Graph e n el nl -> Graph e n el nl
Types
data Graph edge node edgeLabel nodeLabel Source #
Instances
(Edge edge, Ord node) => Monoid (Graph edge node edgeLabel nodeLabel) Source # | |
(Edge edge, Ord node) => Semigroup (Graph edge node edgeLabel nodeLabel) Source # | |
Defined in Data.Graph.Comfort (<>) :: Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel # sconcat :: NonEmpty (Graph edge node edgeLabel nodeLabel) -> Graph edge node edgeLabel nodeLabel # stimes :: Integral b => b -> Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel # | |
(Edge e, Ord n, Show1 e, Show n, Show el, Show nl) => Show (Graph e n el nl) Source # | |
(Eq1 edge, Eq node, Eq edgeLabel, Eq nodeLabel) => Eq (Graph edge node edgeLabel nodeLabel) Source # | |
(Ord1 edge, Ord node, Ord edgeLabel, Ord nodeLabel) => Ord (Graph edge node edgeLabel nodeLabel) Source # | |
Defined in Data.Graph.Comfort compare :: Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Ordering # (<) :: Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Bool # (<=) :: Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Bool # (>) :: Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Bool # (>=) :: Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Bool # max :: Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel # min :: Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel # |
type LabeledNode n label = (n, label) Source #
type LabeledEdge edge node label = (edge node, label) Source #
class (Foldable edge, Ord1 edge) => Edge edge where Source #
defaultEdgeFoldMap :: (Edge edge, Monoid a) => edge a -> a Source #
DirEdge node node |
Instances
Danger:
Do not use the data constructor UndirEdge
because it does not ensure ordering of members.
Use the smart constructor undirEdge
instead.
UndirEdge
is not really an undirected edge.
It is more like a directed edge with a canonical direction.
Working with UndirEdge
requires caution.
In Graph UndirEdge
predecessors
are all edges to lower nodes
with respect to Ord node
,
whereas successors
are all edges to higher nodes.
Thus you get all connection only when merging predecessors
and successors
.
UndirEdge node node |
Instances
data EitherEdge node Source #
EDirEdge (DirEdge node) | |
EUndirEdge (UndirEdge node) |
Instances
Construction
empty :: Graph edge node edgeLabel nodeLabel Source #
Graph.isEmpty (Graph.empty :: MonoGraph)
Graph.isConsistent (Graph.empty :: MonoGraph)
fromList :: (Edge e, Ord n) => [LabeledNode n nl] -> [LabeledEdge e n el] -> Graph e n el nl Source #
fromMap :: (Edge e, Ord n) => Map n nl -> Map (e n) el -> Graph e n el nl Source #
\(TestGraph gr) -> gr == Graph.fromMap (Graph.nodeLabels gr) (Graph.edgeLabels gr)
Extract large portions of the graph
graphMap :: Graph edge node edgeLabel nodeLabel -> Map node (InOutMap edge node edgeLabel nodeLabel) Source #
nodeEdges :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Map node (Set (edge node), nodeLabel, Set (edge node)) Source #
edgeLabels :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Map (edge node) edgeLabel Source #
Queries
lookupNode :: Ord n => n -> Graph e n el nl -> Maybe nl Source #
\(TestGraph gr) n -> Graph.lookupNode n gr == Map.lookup n (Graph.nodeLabels gr)
lookupEdge :: (Edge e, Ord n) => e n -> Graph e n el nl -> Maybe el Source #
\(GraphAndEdge gr e) -> Graph.lookupEdge e gr == Map.lookup e (Graph.edgeLabels gr)
predecessors :: (Edge e, Ord n) => Graph e n el nl -> n -> [n] Source #
Direct predecessors of a node, i.e. nodes with an outgoing edge to the queried node.
It is a checked error, if the queried node is not contained in the graph.
successors :: (Edge e, Ord n) => Graph e n el nl -> n -> [n] Source #
Direct successors of a node, i.e. nodes with an incoming edge from the queried node.
It is a checked error, if the queried node is not contained in the graph.
adjacentEdges :: (Edge e, Ord n) => Graph e n el nl -> n -> Set (e n) Source #
Deprecated: Use adjacentEdgeSet instead.
pathExists :: (Edge edge, Ord node) => node -> node -> Graph edge node edgeLabel nodeLabel -> Bool Source #
depthFirstSearch :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Forest node Source #
topologicalSort :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> ([node], Graph edge node edgeLabel nodeLabel) Source #
>>>
mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['a'*->'a']
("","a")>>>
mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['a'*->'h', 'a'*->'p', 'g'*->'r', 'p'*->'h', 'r'*->'a']
("graph","")>>>
mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['h'*->'a', 'a'*->'p', 'g'*->'r', 'p'*->'h', 'r'*->'a']
("gr","ahp")
components :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> [Graph edge node edgeLabel nodeLabel] Source #
>>>
map Graph.nodes $ Graph.components $ unlabGraph ['d'] ['a'*->'p', 'g'*->'r', 'p'*->'h']
["ahp","d","gr"]>>>
map Graph.nodes $ Graph.components $ unlabGraph ['d'] ['a'*-*'p', 'g'*-*'r', 'p'*-*'h']
["ahp","d","gr"]
stronglyConnectedComponents :: Ord node => Graph DirEdge node edgeLabel nodeLabel -> [Set node] Source #
>>>
map Set.toAscList $ Graph.stronglyConnectedComponents $ unlabGraph ['d'] ['g'*->'r', 'r'*->'a', 'a'*->'g', 'a'*->'p', 'p'*->'h', 'h'*->'p']
["d","hp","agr"]
\(TestGraph gr) -> Set.fromList (map Graph.nodeSet (Graph.components gr)) == Set.fromList (Graph.stronglyConnectedComponents (addReversedEdges gr))
Manipulate labels
mapNode :: (nl0 -> nl1) -> Graph e n el nl0 -> Graph e n el nl1 Source #
\(TestGraph gr) -> Graph.mapNode id gr == gr
mapNodeWithKey :: (n -> nl0 -> nl1) -> Graph e n el nl0 -> Graph e n el nl1 Source #
mapEdge :: (el0 -> el1) -> Graph e n el0 nl -> Graph e n el1 nl Source #
\(TestGraph gr) -> Graph.mapEdge id gr == gr
mapEdgeWithKey :: (e n -> el0 -> el1) -> Graph e n el0 nl -> Graph e n el1 nl Source #
mapNodeWithInOut :: (Edge e, Ord n) => (InOut e n el nl0 -> nl1) -> Graph e n el nl0 -> Graph e n el nl1 Source #
type InOut e n el nl = ([LabeledEdge e n el], LabeledNode n nl, [LabeledEdge e n el]) Source #
filterEdgeWithKey :: (Edge e, Ord n) => (e n -> el -> Bool) -> Graph e n el nl -> Graph e n el nl Source #
\(GraphAndEdge gr e) -> Graph.filterEdgeWithKey (\ei _ -> e/=ei) gr == Graph.deleteEdge e gr
traverseNode :: (Applicative f, Edge e, Ord n) => (nl0 -> f nl1) -> Graph e n el nl0 -> f (Graph e n el nl1) Source #
Same restrictions as in traverse
.
\(TestGraph gr) nl -> Graph.isConsistent $ evalTraverseNode nl gr
\(TestGraph gr) -> runIdentity (Graph.traverseNode (Identity . Char.toUpper) gr) == Graph.mapNode Char.toUpper gr
traverseEdge :: (Applicative f, Edge e, Ord n) => (el0 -> f el1) -> Graph e n el0 nl -> f (Graph e n el1 nl) Source #
Same restrictions as in traverse
.
\(TestGraph gr) el -> Graph.isConsistent $ evalTraverseEdge el gr
\(TestGraph gr) el -> runIdentity (Graph.traverseEdge (Identity . (el+)) gr) == Graph.mapEdge (el+) gr
traverse :: (Applicative f, Edge e, Ord n) => (nl0 -> f nl1) -> (el0 -> f el1) -> Graph e n el0 nl0 -> f (Graph e n el1 nl1) Source #
Don't rely on a particular order of traversal!
\(TestGraph gr) nl el -> Graph.isConsistent $ evalTraverse nl el gr
\(TestGraph gr) nl el -> evalTraverse nl el gr == evalTraverseNode nl (evalTraverseEdge el gr)
\(TestGraph gr) nl el -> evalTraverse nl el gr == evalTraverseEdge el (evalTraverseNode nl gr)
\(TestGraph gr) nl -> flip MS.evalState nl (Graph.traverseNode nodeAction gr) == flip MS.evalState nl (Graph.traverse nodeAction pure gr)
\(TestGraph gr) el -> flip MS.evalState el (Graph.traverseEdge edgeAction gr) == flip MS.evalState el (Graph.traverse pure edgeAction gr)
Combine graphs
checkedZipWith :: (Edge edge, Ord node) => Caller -> (nodeLabel0 -> nodeLabel1 -> nodeLabel2) -> (edgeLabel0 -> edgeLabel1 -> edgeLabel2) -> Graph edge node edgeLabel0 nodeLabel0 -> Graph edge node edgeLabel1 nodeLabel1 -> Graph edge node edgeLabel2 nodeLabel2 Source #
Node and edge sets must be equal.
union :: (Edge edge, Ord node) => Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel -> Graph edge node edgeLabel nodeLabel Source #
The node sets must be disjoint.
Manipulate indices
class Edge edge => Reverse edge Source #
Instances
Reverse DirEdge Source # | |
Defined in Data.Graph.Comfort reverseEdge :: DirEdge node -> DirEdge node Source # |
reverse :: (Reverse e, Ord n) => Graph e n el nl -> Graph e n el nl Source #
\(TestGraph gr) -> Graph.isConsistent (Graph.reverse gr)
\(TestGraph gr) -> Graph.reverse (Graph.reverse gr) == gr
reverseEdge :: Reverse edge => edge node -> edge node Source #
mapKeys :: (Edge edge1, Ord node0, Ord node1) => (node0 -> node1) -> (edge0 node0 -> edge1 node1) -> Graph edge0 node0 edgeLabel nodeLabel -> Graph edge1 node1 edgeLabel nodeLabel Source #
The index map must be an injection, that is, nodes must not collaps. Also the node and edge index maps must be consistent, i.e.
from (edgeMap e) == nodeMap (from e) to (edgeMap e) == nodeMap (to e)
Strictly spoken, we would need the node map only for isolated nodes, but we use it for all nodes for simplicity.
mapMaybeEdgeKeys :: (Edge e1, Ord n) => (e0 n -> Maybe (e1 n)) -> Graph e0 n el nl -> Graph e1 n el nl Source #
You may only use this for filtering edges and use more specialised types as a result. You must not alter source and target nodes of edges.
mapEdgeKeys :: (Edge e1, Ord n) => (e0 n -> e1 n) -> Graph e0 n el nl -> Graph e1 n el nl Source #
Same restrictions as in mapMaybeEdgeKeys
.
Insertion and removal
deleteNode :: (Edge e, Ord n) => n -> Graph e n el nl -> Graph e n el nl Source #
Node to be deleted must be contained in the graph.
\(TestGraph gr) n -> Graph.isConsistent $ deleteNodeIfExists n gr
\(TestGraph gr) n nl -> Graph.deleteNode n (Graph.insertNode n nl gr) == deleteNodeIfExists n gr
\(TestGraph gr) -> let isolatedNodes = filter (isolated gr) $ Graph.nodes gr in not (null isolatedNodes) ==> QC.forAll (QC.elements isolatedNodes) $ \n nl -> Graph.insertNode n nl gr == Graph.insertNode n nl (Graph.deleteNode n gr)
deleteNodeSet :: (Edge e, Ord n) => Set n -> Graph e n el nl -> Graph e n el nl Source #
Could be implemented more efficiently.
deleteEdge :: (Edge e, Ord n) => e n -> Graph e n el nl -> Graph e n el nl Source #
\(GraphAndEdge gr e) -> Graph.isConsistent $ Graph.deleteEdge e gr
\(GraphAndEdge gr e) el -> Graph.deleteEdge e (Graph.insertEdge e el gr) == Graph.deleteEdge e gr
\(GraphAndEdge gr e) el -> Graph.insertEdge e el gr == Graph.insertEdge e el (Graph.deleteEdge e gr)
insertNode :: Ord n => n -> nl -> Graph e n el nl -> Graph e n el nl Source #
In the current implementation existing nodes are replaced with new labels and existing edges are maintained. However, I think we should better have an extra function for this purpose and you should not rely on this behavior.
\(TestGraph gr) n nl -> Graph.isConsistent $ Graph.insertNode n nl gr
\(TestGraph gr) n nl -> Graph.lookupNode n (Graph.insertNode n nl gr) == Just nl
insertEdge :: (Edge e, Ord n) => e n -> el -> Graph e n el nl -> Graph e n el nl Source #
\(GraphAndEdge gr e) el -> Graph.isConsistent $ Graph.insertEdge e el gr
\(GraphAndEdge gr e) el -> Graph.lookupEdge e (Graph.insertEdge e el gr) == Just el
insertEdgeSet :: (Edge e, Ord n) => Map (e n) el -> Graph e n el nl -> Graph e n el nl Source #
In the current implementation existing edges are replaced with new labels. However, I think we should better have an extra function for this purpose and you should not rely on this behavior. It is an unchecked error if edges between non-existing nodes are inserted.