packages feed

graphite 0.2.1.0 → 0.3.0.0

raw patch · 9 files changed

+177/−105 lines, 9 filesdep +containersPVP ok

version bump matches the API change (PVP)

Dependencies added: containers

API changes (from Hackage documentation)

- Data.Graph.Connectivity: isDisconnected :: UGraph v e -> Bool
- Data.Graph.Connectivity: unreachableVertices :: UGraph v e -> [v]
- Data.Graph.DGraph: isIsolated :: DGraph v e -> Bool
- Data.Graph.Visualize: plotIO :: (Show e) => UGraph Int e -> FilePath -> IO FilePath
- Data.Graph.Visualize: plotXdgIO :: (Show e) => UGraph Int e -> FilePath -> IO ()
+ Data.Graph.Connectivity: isIsolated :: (Graph g, Hashable v, Eq v) => g v e -> v -> Bool
+ Data.Graph.Connectivity: isStronglyConnected :: (Hashable v, Eq v, Ord v) => DGraph v e -> Bool
+ Data.Graph.DGraph: toUndirected :: (Hashable v, Eq v) => DGraph v e -> UGraph v e
+ Data.Graph.Types: areAdjacent :: (Graph g, Hashable v, Eq v) => g v e -> v -> v -> Bool
+ Data.Graph.Types: directlyReachableVertices :: (Graph g, Hashable v, Eq v) => g v e -> v -> [v]
+ Data.Graph.Visualize: plotDirectedIO :: (Show e) => DGraph Int e -> FilePath -> IO FilePath
+ Data.Graph.Visualize: plotDirectedXdgIO :: (Show e) => DGraph Int e -> FilePath -> IO ()
+ Data.Graph.Visualize: plotUndirectedIO :: (Show e) => UGraph Int e -> FilePath -> IO FilePath
+ Data.Graph.Visualize: plotUndirectedXdgIO :: (Show e) => UGraph Int e -> FilePath -> IO ()
- Data.Graph.Connectivity: areConnected :: UGraph v e -> v -> v -> Bool
+ Data.Graph.Connectivity: areConnected :: forall g v e. (Graph g, Hashable v, Eq v, Ord v) => g v e -> v -> v -> Bool
- Data.Graph.Connectivity: areDisconnected :: UGraph v e -> v -> v -> Bool
+ Data.Graph.Connectivity: areDisconnected :: (Graph g, Hashable v, Eq v, Ord v) => g v e -> v -> v -> Bool
- Data.Graph.Connectivity: isConnected :: UGraph v e -> Bool
+ Data.Graph.Connectivity: isConnected :: (Hashable v, Eq v) => UGraph v e -> Bool
- Data.Graph.Connectivity: isWeaklyConnected :: DGraph v e -> Bool
+ Data.Graph.Connectivity: isWeaklyConnected :: (Hashable v, Eq v) => DGraph v e -> Bool
- Data.Graph.DGraph: removeArc :: (Hashable v, Eq v) => Arc v e -> DGraph v e -> DGraph v e
+ Data.Graph.DGraph: removeArc :: (Hashable v, Eq v) => DGraph v e -> Arc v e -> DGraph v e
- Data.Graph.DGraph: removeArc' :: (Hashable v, Eq v) => (v, v) -> DGraph v e -> DGraph v e
+ Data.Graph.DGraph: removeArc' :: (Hashable v, Eq v) => DGraph v e -> (v, v) -> DGraph v e
- Data.Graph.DGraph: removeArcAndVertices :: (Hashable v, Eq v) => Arc v e -> DGraph v e -> DGraph v e
+ Data.Graph.DGraph: removeArcAndVertices :: (Hashable v, Eq v) => DGraph v e -> Arc v e -> DGraph v e
- Data.Graph.DGraph: removeArcAndVertices' :: (Hashable v, Eq v) => (v, v) -> DGraph v e -> DGraph v e
+ Data.Graph.DGraph: removeArcAndVertices' :: (Hashable v, Eq v) => DGraph v e -> (v, v) -> DGraph v e
- Data.Graph.Types: insertEdgePair :: (Graph g, Hashable v, Eq v) => (v, v) -> g v () -> g v ()
+ Data.Graph.Types: insertEdgePair :: (Graph g, Hashable v, Eq v) => g v () -> (v, v) -> g v ()
- Data.Graph.Types: insertVertex :: (Graph g, Hashable v, Eq v) => v -> g v e -> g v e
+ Data.Graph.Types: insertVertex :: (Graph g, Hashable v, Eq v) => g v e -> v -> g v e
- Data.Graph.Types: insertVertices :: (Graph g, Hashable v, Eq v) => [v] -> g v e -> g v e
+ Data.Graph.Types: insertVertices :: (Graph g, Hashable v, Eq v) => g v e -> [v] -> g v e
- Data.Graph.Types: removeEdgePair :: (Graph g, Hashable v, Eq v) => (v, v) -> g v e -> g v e
+ Data.Graph.Types: removeEdgePair :: (Graph g, Hashable v, Eq v) => g v e -> (v, v) -> g v e
- Data.Graph.Types: removeEdgePairAndVertices :: (Graph g, Hashable v, Eq v) => (v, v) -> g v e -> g v e
+ Data.Graph.Types: removeEdgePairAndVertices :: (Graph g, Hashable v, Eq v) => g v e -> (v, v) -> g v e
- Data.Graph.UGraph: removeEdge :: (Hashable v, Eq v) => Edge v e -> UGraph v e -> UGraph v e
+ Data.Graph.UGraph: removeEdge :: (Hashable v, Eq v) => UGraph v e -> Edge v e -> UGraph v e
- Data.Graph.UGraph: removeEdge' :: (Hashable v, Eq v) => (v, v) -> UGraph v e -> UGraph v e
+ Data.Graph.UGraph: removeEdge' :: (Hashable v, Eq v) => UGraph v e -> (v, v) -> UGraph v e
- Data.Graph.UGraph: removeEdgeAndVertices :: (Hashable v, Eq v) => Edge v e -> UGraph v e -> UGraph v e
+ Data.Graph.UGraph: removeEdgeAndVertices :: (Hashable v, Eq v) => UGraph v e -> Edge v e -> UGraph v e
- Data.Graph.UGraph: removeEdgeAndVertices' :: (Hashable v, Eq v) => (v, v) -> UGraph v e -> UGraph v e
+ Data.Graph.UGraph: removeEdgeAndVertices' :: (Hashable v, Eq v) => UGraph v e -> (v, v) -> UGraph v e

Files

graphite.cabal view
@@ -1,5 +1,5 @@ name:                graphite-version:             0.2.1.0+version:             0.3.0.0 synopsis:            Graphs and networks library description:         Represent, analyze and visualize graphs homepage:            https://github.com/alx741/graphite#readme@@ -23,10 +23,11 @@                      , Data.Graph.Connectivity   build-depends:       base >= 4.7 && < 5                      , hashable+                     , containers+                     , unordered-containers                      , random                      , process                      , graphviz-                     , unordered-containers                      , QuickCheck   ghc-options:         -Wall   default-language:    Haskell2010
src/Data/Graph/Connectivity.hs view
@@ -1,45 +1,76 @@ -- | For Connectivity analisis purposes a 'DGraph' can be converted into a -- | 'UGraph' using 'toUndirected' +{-# LANGUAGE ScopedTypeVariables #-}+ module Data.Graph.Connectivity where -import Data.Graph.UGraph-import Data.Graph.DGraph+import Data.List (foldl') --- | Tell if a 'UGraph' is connected--- | An Undirected Graph is @connected@ when there is a path between every pair--- | of vertices-isConnected :: UGraph v e -> Bool-isConnected = undefined+import           Data.Hashable+import qualified Data.Set      as S --- | Tell if a 'UGraph' is disconnected--- | An Undirected Graph is @disconnected@ when its not @connected@. See--- | 'isConnected'--- TODO: An edgeles graph with two or more vertices is disconnected-isDisconnected :: UGraph v e -> Bool-isDisconnected = not . isConnected+import Data.Graph.DGraph+import Data.Graph.Types+import Data.Graph.UGraph --- | Tell if two vertices of a 'UGraph' are connected+-- | Tell if two vertices of a graph are connected -- | Two vertices are @connected@ if it exists a path between them-areConnected :: UGraph v e -> v -> v -> Bool-areConnected = undefined+-- | The order of the vertices is relevant when the graph is directed+areConnected :: forall g v e . (Graph g, Hashable v, Eq v, Ord v)+ => g v e+ -> v+ -> v+ -> Bool+areConnected g fromV toV+    | fromV == toV = True+    | otherwise = search (directlyReachableVertices g fromV) S.empty toV+    where+        search :: [v] -> S.Set v -> v -> Bool+        search [] _ _ = False+        search (v:vs) banned v'+            | v `S.member` banned = search vs banned v'+            | v == v' = True+            | otherwise =+                search (directlyReachableVertices g v) banned' v'+                || search vs banned' v'+            where banned' = v `S.insert` banned  -- | Tell if two vertices of a 'UGraph' are disconnected -- | Two vertices are @disconnected@ if it doesn't exist a path between them-areDisconnected :: UGraph v e -> v -> v -> Bool-areDisconnected = undefined+areDisconnected :: (Graph g, Hashable v, Eq v, Ord v) => g v e -> v -> v -> Bool+areDisconnected g fromV toV = not $ areConnected g fromV toV --- | Retrieve all the unreachable vertices of a 'UGraph'--- | The @unreachable vertices@ are those with no adjacent 'Edge's-unreachableVertices :: UGraph v e -> [v]-unreachableVertices = undefined+-- | Tell if a vertex is isolated+-- | A vertex is @isolated@ if it has no incidet edges, that is, it has a degree+-- | of zero+isIsolated :: (Graph g, Hashable v, Eq v) => g v e -> v -> Bool+isIsolated g v = vertexDegree g v == 0 +-- | Tell if a graph is connected+-- | An Undirected Graph is @connected@ when there is a path between every pair+-- | of vertices+isConnected :: (Hashable v, Eq v) => UGraph v e -> Bool+isConnected g = foldl' (\b v -> b && (not $ isIsolated g v)) True $ vertices g+ -- | Tell if a 'DGraph' is weakly connected--- | A Directed Graph is @weakly connected@ if the equivalent undirected graph+-- | A Directed Graph is @weakly connected@ if the underlying undirected graph -- | is @connected@-isWeaklyConnected :: DGraph v e -> Bool-isWeaklyConnected = undefined -- isConnected . toUndirected+isWeaklyConnected :: (Hashable v, Eq v) => DGraph v e -> Bool+isWeaklyConnected = isConnected . toUndirected +-- | Tell if a 'DGraph' is strongly connected+-- | A Directed Graph is @strongly connected@ if it contains a directed path+-- | on every pair of vertices+isStronglyConnected :: (Hashable v, Eq v, Ord v) => DGraph v e -> Bool+isStronglyConnected g = go vs True+    where+        vs = vertices g+        go _ False = False+        go [] bool = bool+        go (v':vs') bool =+            go vs' $ foldl' (\b v -> b && (areConnected g v v')) bool vs+ -- TODO -- * connected component -- * strong components@@ -55,3 +86,5 @@ -- * super-connectivity -- * hyper-connectivity -- * Menger's theorem++-- Robin's Theorem: a graph is orientable if it is connected and has no bridges
src/Data/Graph/DGraph.hs view
@@ -9,7 +9,8 @@ import qualified Data.HashMap.Lazy as HM import           Test.QuickCheck -import Data.Graph.Types+import           Data.Graph.Types+import qualified Data.Graph.UGraph as UG  -- | Directed Graph of Vertices in /v/ and Arcs with attributes in /e/ newtype DGraph v e = DGraph { unDGraph :: HM.HashMap v (Links v e) }@@ -22,17 +23,22 @@     edgePairs = arcs'      containsVertex (DGraph g) = flip HM.member g-    adjacentVertices = undefined+    areAdjacent (DGraph g) v1 v2 =+        HM.member v2 (getLinks v1 g) || HM.member v1 (getLinks v2 g)+    adjacentVertices g v = filter+        (\v' -> containsArc' g (v, v') || containsArc' g (v', v))+        (vertices g)+    directlyReachableVertices (DGraph g) v = v : (HM.keys $ getLinks v g)      -- | The total number of inbounding and outbounding 'Arc's of a vertex     vertexDegree g v = vertexIndegree g v + vertexOutdegree g v -    insertVertex v (DGraph g) = DGraph $ hashMapInsert v HM.empty g-    insertVertices vs g = foldl' (flip insertVertex) g vs+    insertVertex (DGraph g) v = DGraph $ hashMapInsert v HM.empty g+    insertVertices = foldl' insertVertex      containsEdgePair = containsArc'     incidentEdgePairs g v = fmap toPair $ incidentArcs g v-    insertEdgePair (v1, v2) g = insertArc (Arc v1 v2 ()) g+    insertEdgePair g (v1, v2) = insertArc (Arc v1 v2 ()) g     removeEdgePair = removeArc'     removeEdgePairAndVertices = removeArcAndVertices' @@ -54,7 +60,7 @@ removeVertex :: (Hashable v, Eq v) => v -> DGraph v e -> DGraph v e removeVertex v g = DGraph     $ (\(DGraph g') -> HM.delete v g')-    $ foldl' (flip removeArc) g $ incidentArcs g v+    $ foldl' removeArc g $ incidentArcs g v  -- | @O(log n)@ Insert a directed 'Arc' into a 'DGraph' -- | The involved vertices are inserted if don't exist. If the graph already@@ -62,7 +68,7 @@ insertArc :: (Hashable v, Eq v) => Arc v e -> DGraph v e -> DGraph v e insertArc (Arc fromV toV edgeAttr) g = DGraph     $ HM.adjust (insertLink toV edgeAttr) fromV g'-    where g' = unDGraph $ insertVertices [fromV, toV] g+    where g' = unDGraph $ insertVertices g [fromV, toV]  -- | @O(m*log n)@ Insert many directed 'Arc's into a 'DGraph' -- | Same rules as 'insertArc' are applied@@ -71,25 +77,25 @@  -- | @O(log n)@ Remove the directed 'Arc' from a 'DGraph' if present -- | The involved vertices are left untouched-removeArc :: (Hashable v, Eq v) => Arc v e -> DGraph v e -> DGraph v e-removeArc = removeArc' . toPair+removeArc :: (Hashable v, Eq v) => DGraph v e -> Arc v e -> DGraph v e+removeArc g = removeEdgePair g . toPair  -- | Same as 'removeArc' but the arc is an ordered pair-removeArc' :: (Hashable v, Eq v) => (v, v) -> DGraph v e -> DGraph v e-removeArc' (v1, v2) (DGraph g) = case HM.lookup v1 g of+removeArc' :: (Hashable v, Eq v) => DGraph v e -> (v, v) -> DGraph v e+removeArc' (DGraph g) (v1, v2) = case HM.lookup v1 g of     Nothing -> DGraph g     Just v1Links -> DGraph $ HM.adjust (const v1Links') v1 g         where v1Links' = HM.delete v2 v1Links  -- | @O(log n)@ Remove the directed 'Arc' from a 'DGraph' if present -- | The involved vertices are also removed-removeArcAndVertices :: (Hashable v, Eq v) => Arc v e -> DGraph v e -> DGraph v e-removeArcAndVertices = removeArcAndVertices' . toPair+removeArcAndVertices :: (Hashable v, Eq v) => DGraph v e -> Arc v e -> DGraph v e+removeArcAndVertices g = removeEdgePairAndVertices g . toPair  -- | Same as 'removeArcAndVertices' but the arc is an ordered pair-removeArcAndVertices' :: (Hashable v, Eq v) => (v, v) -> DGraph v e -> DGraph v e-removeArcAndVertices' (v1, v2) g =-    removeVertex v2 $ removeVertex v1 $ removeArc' (v1, v2) g+removeArcAndVertices' :: (Hashable v, Eq v) => DGraph v e -> (v, v) -> DGraph v e+removeArcAndVertices' g (v1, v2) =+    removeVertex v2 $ removeVertex v1 $ removeEdgePair g (v1, v2)  -- | @O(n*m)@ Retrieve the 'Arc's of a 'DGraph' arcs :: forall v e . (Hashable v, Eq v) => DGraph v e -> [Arc v e]@@ -139,12 +145,6 @@ isOriented :: DGraph v e -> Bool isOriented = undefined --- | Tell if a 'DGraph' is isolated--- | A graph is @isolated@ if it has no edges, that is, it has a degree of 0--- | TODO: What if it has a loop?-isIsolated :: DGraph v e -> Bool-isIsolated = undefined- -- | Indegree of a vertex -- | The number of inbounding 'Arc's to a vertex vertexIndegree :: DGraph v e -> v -> Int@@ -189,6 +189,12 @@ -- | A vertex is a @internal@ when its neither a @source@ nor a @sink@ isInternal :: DGraph v e -> v -> Bool isInternal g v = not $ isSource g v || isSink g v++-- | Convert a directed 'DGraph' to an undirected 'UGraph' by converting all of+-- | its 'Arc's into 'Edge's+toUndirected :: (Hashable v, Eq v) => DGraph v e -> UG.UGraph v e+toUndirected g = UG.insertEdges (fmap arcToEdge $ arcs g) empty+    where arcToEdge (Arc fromV toV attr) = Edge fromV toV attr  -- | Tell if a 'DegreeSequence' is a Directed Graphic -- | A @Directed Graphic@ is a Degree Sequence for wich a 'DGraph' exists
src/Data/Graph/Generation.hs view
@@ -22,12 +22,17 @@         go :: Graph g => [Int] -> Float -> g Int () -> IO (g Int ())         go [] _ g = return g         go (v:vs) pv g = do-            rnds <- randomRs (0.0, 1.0) <$> newStdGen+            rnds <- replicateM (length vs + 1) $ randomRIO (0.0, 1.0)+            flipDir <- randomRIO (True, False)             let vs' = zip rnds vs-            go vs pv $! (foldl' (putV pv v) g vs')+            let g' = insertVertex g v+            go vs pv $! (foldl' (putV pv v flipDir) g' vs') -        putV :: Graph g => Float -> Int -> g Int () -> (Float, Int) -> g Int ()-        putV pv v g (p', v') | p' < pv = insertEdgePair (v, v') g | otherwise = g+        putV :: Graph g => Float -> Int -> Bool -> g Int () -> (Float, Int) -> g Int ()+        putV pv v flipDir g (p', v')+            | p' < pv = insertEdgePair g pair+            | otherwise = g+                where pair = if flipDir then (v', v) else (v, v')  -- | Generate a random square binary matrix -- | Useful for use with 'fromAdjacencyMatrix'
src/Data/Graph/Types.hs view
@@ -32,9 +32,19 @@     -- | Tell if a vertex exists in the graph     containsVertex :: (Hashable v, Eq v) => g v e -> v -> Bool +    -- | Tell if two vertices are adjacent+    areAdjacent :: (Hashable v, Eq v) => g v e -> v -> v -> Bool+     -- | Retrieve the adjacent vertices of a vertex     adjacentVertices :: (Hashable v, Eq v) => g v e -> v -> [v] +    -- | Retrieve the vertices that are directly reachable from a particular+    -- | vertex.+    -- | A vertex is @directly reachable@ to other if there is an edge that+    -- | connects @from@ one vertex @to@ the other+    -- | Every vertex is directly reachable from itself+    directlyReachableVertices :: (Hashable v, Eq v) => g v e -> v -> [v]+     -- | Total number of incident edges of a vertex     vertexDegree :: (Hashable v, Eq v) => g v e -> v -> Int @@ -65,12 +75,12 @@      -- | Insert a vertex into a graph     -- | If the graph already contains the vertex leave the graph untouched-    insertVertex :: (Hashable v, Eq v) => v -> g v e -> g v e+    insertVertex :: (Hashable v, Eq v) => g v e -> v -> g v e      -- | Insert a many vertices into a graph     -- | New vertices are inserted and already contained vertices are left     -- | untouched-    insertVertices :: (Hashable v, Eq v) => [v] -> g v e -> g v e+    insertVertices :: (Hashable v, Eq v) => g v e -> [v] -> g v e      -- | Tell if an edge exists in the graph     containsEdgePair :: (Hashable v, Eq v) => g v e -> (v, v) -> Bool@@ -81,15 +91,15 @@     -- | Insert an edge into a graph     -- | The involved vertices are inserted if don't exist. If the graph already     -- | contains the edge, its attribute is updated-    insertEdgePair :: (Hashable v, Eq v) => (v, v) -> g v () -> g v ()+    insertEdgePair :: (Hashable v, Eq v) => g v () -> (v, v) -> g v ()      -- | Remove the edge from a graph present     -- | The involved vertices are left untouched-    removeEdgePair :: (Hashable v, Eq v) => (v, v) -> g v e -> g v e+    removeEdgePair :: (Hashable v, Eq v) => g v e -> (v, v) -> g v e      -- | Remove the edge from a graph if present     -- | The involved vertices are also removed-    removeEdgePairAndVertices :: (Hashable v, Eq v) => (v, v) -> g v e -> g v e+    removeEdgePairAndVertices :: (Hashable v, Eq v) => g v e -> (v, v) -> g v e      -- | Tell if a graph is simple     -- | A graph is @simple@ if it has no multiple edges nor loops
src/Data/Graph/UGraph.hs view
@@ -4,7 +4,7 @@  module Data.Graph.UGraph where -import Data.List     (foldl', reverse, sort)+import Data.List (foldl', reverse, sort)  import           Data.Hashable import qualified Data.HashMap.Lazy as HM@@ -27,14 +27,16 @@     edgePairs g = toPair <$> edges g      containsVertex (UGraph g) = flip HM.member g+    areAdjacent (UGraph g) v1 v2 = HM.member v2 $ getLinks v1 g     adjacentVertices (UGraph g) v = HM.keys $ getLinks v g+    directlyReachableVertices g v = v : (adjacentVertices g v)     vertexDegree (UGraph g) v = length $ HM.keys $ getLinks v g-    insertVertex v (UGraph g) = UGraph $ hashMapInsert v HM.empty g-    insertVertices vs g = foldl' (flip insertVertex) g vs+    insertVertex (UGraph g) v = UGraph $ hashMapInsert v HM.empty g+    insertVertices = foldl' insertVertex      containsEdgePair = containsEdge'     incidentEdgePairs g v = fmap toPair $ incidentEdges g v-    insertEdgePair (v1, v2) g = insertEdge (Edge v1 v2 ()) g+    insertEdgePair g (v1, v2) = insertEdge (Edge v1 v2 ()) g     removeEdgePair = removeEdge'     removeEdgePairAndVertices = removeEdgeAndVertices' @@ -63,7 +65,7 @@ removeVertex :: (Hashable v, Eq v) => v -> UGraph v e -> UGraph v e removeVertex v g = UGraph     $ (\(UGraph g') -> HM.delete v g')-    $ foldl' (flip removeEdge) g $ incidentEdges g v+    $ foldl' removeEdge g $ incidentEdges g v  -- | @O(log n)@ Insert an undirected 'Edge' into a 'UGraph' -- | The involved vertices are inserted if don't exist. If the graph already@@ -71,7 +73,7 @@ insertEdge :: (Hashable v, Eq v) => Edge v e -> UGraph v e -> UGraph v e insertEdge (Edge v1 v2 edgeAttr) g = UGraph $ link v2 v1 $ link v1 v2 g'     where-        g' = unUGraph $ insertVertices [v1, v2] g+        g' = unUGraph $ insertVertices g [v1, v2]         link fromV toV = HM.adjust (insertLink toV edgeAttr) fromV  -- | @O(m*log n)@ Insert many directed 'Edge's into a 'UGraph'@@ -81,12 +83,12 @@  -- | @O(log n)@ Remove the undirected 'Edge' from a 'UGraph' if present -- | The involved vertices are left untouched-removeEdge :: (Hashable v, Eq v) => Edge v e -> UGraph v e -> UGraph v e-removeEdge = removeEdgePair . toPair+removeEdge :: (Hashable v, Eq v) => UGraph v e -> Edge v e -> UGraph v e+removeEdge g = removeEdgePair g . toPair  -- | Same as 'removeEdge' but the edge is an unordered pair-removeEdge' :: (Hashable v, Eq v) => (v, v) -> UGraph v e -> UGraph v e-removeEdge' (v1, v2) graph@(UGraph g)+removeEdge' :: (Hashable v, Eq v) => UGraph v e -> (v, v) -> UGraph v e+removeEdge' graph@(UGraph g) (v1, v2)     | containsVertex graph v1 && containsVertex graph v2 =         UGraph $ update v2Links v2 $ update v1Links v1 g     | otherwise = UGraph g@@ -97,13 +99,13 @@  -- | @O(log n)@ Remove the undirected 'Edge' from a 'UGraph' if present -- | The involved vertices are also removed-removeEdgeAndVertices :: (Hashable v, Eq v) => Edge v e -> UGraph v e -> UGraph v e-removeEdgeAndVertices = removeEdgePairAndVertices . toPair+removeEdgeAndVertices :: (Hashable v, Eq v) => UGraph v e -> Edge v e -> UGraph v e+removeEdgeAndVertices g = removeEdgePairAndVertices g . toPair  -- | Same as 'removeEdgeAndVertices' but the edge is an unordered pair-removeEdgeAndVertices' :: (Hashable v, Eq v) => (v, v) -> UGraph v e -> UGraph v e-removeEdgeAndVertices' (v1, v2) g =-    removeVertex v2 $ removeVertex v1 $ removeEdgePair (v1, v2) g+removeEdgeAndVertices' :: (Hashable v, Eq v) => UGraph v e -> (v, v) -> UGraph v e+removeEdgeAndVertices' g (v1, v2) =+    removeVertex v2 $ removeVertex v1 $ removeEdgePair g (v1, v2)  -- | @O(n*m)@ Retrieve the 'Edge's of a 'UGraph' edges :: forall v e . (Hashable v, Eq v) => UGraph v e -> [Edge v e]
src/Data/Graph/Visualize.hs view
@@ -1,40 +1,55 @@ module Data.Graph.Visualize-    ( plotIO-    , plotXdgIO+    ( plotUndirectedIO+    , plotUndirectedXdgIO++    , plotDirectedIO+    , plotDirectedXdgIO     ) where  import Data.GraphViz-import Data.GraphViz.Attributes.Complete import Data.Hashable-import Data.Monoid                       ((<>))+import Data.Monoid    ((<>)) import System.Process -import qualified Data.Graph.UGraph as G-import           Data.Graph.Types+import Data.Graph.DGraph+import Data.Graph.Types+import Data.Graph.UGraph  -- | Plot an undirected 'UGraph' to a PNG image file-plotIO :: (Show e) => G.UGraph Int e -> FilePath -> IO FilePath-plotIO g fp = addExtension (runGraphvizCommand Sfdp $ toDot' g) Png fp+plotUndirectedIO :: (Show e) => UGraph Int e -> FilePath -> IO FilePath+plotUndirectedIO g fp = addExtension (runGraphvizCommand Sfdp $ toUndirectedDot g) Png fp --- | Same as 'plotIO' but open the resulting image with /xdg-open/-plotXdgIO :: (Show e) => G.UGraph Int e -> FilePath -> IO ()-plotXdgIO g fp = do-    fp' <- plotIO g fp+-- | Same as 'plotUndirectedIO' but open the resulting image with /xdg-open/+plotUndirectedXdgIO :: (Show e) => UGraph Int e -> FilePath -> IO ()+plotUndirectedXdgIO g fp = do+    fp' <- plotUndirectedIO g fp     _ <- system $ "xdg-open " <> fp'     return () -labeledNodes :: (Show v) => G.UGraph v e -> [(v, String)]+-- | Plot a directed 'DGraph' to a PNG image file+plotDirectedIO :: (Show e) => DGraph Int e -> FilePath -> IO FilePath+plotDirectedIO g fp = addExtension (runGraphvizCommand Sfdp $ toDirectedDot g) Png fp++-- | Same as 'plotDirectedIO' but open the resulting image with /xdg-open/+plotDirectedXdgIO :: (Show e) => DGraph Int e -> FilePath -> IO ()+plotDirectedXdgIO g fp = do+    fp' <- plotDirectedIO g fp+    _ <- system $ "xdg-open " <> fp'+    return ()++labeledNodes :: (Graph g, Show v) => g v e -> [(v, String)] labeledNodes g = fmap (\v -> (v, show v)) $ vertices g -labeledEdges :: (Hashable v, Eq v, Show e) => G.UGraph v e -> [(v, v, String)]-labeledEdges g = fmap (\(Edge v1 v2 attr) -> (v1, v2, show attr)) $ G.edges g+labeledEdges :: (Hashable v, Eq v, Show e) => UGraph v e -> [(v, v, String)]+labeledEdges g = fmap (\(Edge v1 v2 attr) -> (v1, v2, show attr)) $ edges g -toDot' :: (Show e) => G.UGraph Int e -> DotGraph Int-toDot' g = graphElemsToDot params (labeledNodes g) (labeledEdges g)-    where params = nonClusteredParams-            { isDirected = False-            , globalAttributes = [GraphAttrs-                [ NodeSep 1, Overlap ScaleOverlaps-                , Shape Circle-                ]]-            }+labeledArcs :: (Hashable v, Eq v, Show e) => DGraph v e -> [(v, v, String)]+labeledArcs g = fmap (\(Arc v1 v2 attr) -> (v1, v2, show attr)) $ arcs g++toUndirectedDot :: (Show e) => UGraph Int e -> DotGraph Int+toUndirectedDot g = graphElemsToDot params (labeledNodes g) (labeledEdges g)+    where params = nonClusteredParams { isDirected = False }++toDirectedDot :: (Show e) => DGraph Int e -> DotGraph Int+toDirectedDot g = graphElemsToDot params (labeledNodes g) (labeledArcs g)+    where params = nonClusteredParams { isDirected = True }
test/Data/Graph/DGraphSpec.hs view
@@ -10,8 +10,8 @@ spec = do     describe "Directed Graph (DGraph)" $ do         it "Can tell if a vertex exists" $ property $ do-            let g = insertVertex 1 empty :: DGraph Int ()-            let g' = insertVertex 2 empty :: DGraph Int ()+            let g = insertVertex empty 1 :: DGraph Int ()+            let g' = insertVertex empty 2 :: DGraph Int ()             containsVertex g 1 `shouldBe` True             containsVertex g' 1 `shouldBe` False @@ -23,12 +23,12 @@          it "Increments its order when a new vertex is inserted" $ property $             \g v -> (not $ g `containsVertex` v)-                ==> order g + 1 == order (insertVertex v (g :: DGraph Int ()))+                ==> order g + 1 == order (insertVertex (g :: DGraph Int ()) v)         it "Increments its size when a new arc is inserted" $ property $             \g arc -> (not $ g `containsArc` arc)                 ==> size g + 1 == size (insertArc arc (g :: DGraph Int ()))          it "Is id when inserting and removing a new vertex" $ property $             \g v -> (not $ g `containsVertex` v)-                ==> ((removeVertex v . insertVertex v) g)+                ==> (removeVertex v $ insertVertex g v)                     == (g :: DGraph Int ())
test/Data/Graph/UGraphSpec.hs view
@@ -10,8 +10,8 @@ spec = do     describe "Undirected Graph (UGraph)" $ do         it "Can tell if a vertex exists" $ property $ do-            let g = insertVertex 1 empty :: UGraph Int ()-            let g' = insertVertex 2 empty :: UGraph Int ()+            let g = insertVertex empty 1 :: UGraph Int ()+            let g' = insertVertex empty 2 :: UGraph Int ()             containsVertex g 1 `shouldBe` True             containsVertex g' 1 `shouldBe` False @@ -27,12 +27,12 @@          it "Increments its order when a new vertex is inserted" $ property $             \g v -> (not $ g `containsVertex` v)-                ==> order g + 1 == order (insertVertex v (g :: UGraph Int ()))+                ==> order g + 1 == order (insertVertex (g :: UGraph Int ()) v)         it "Increments its size when a new edge is inserted" $ property $             \g edge -> (not $ g `containsEdge` edge)                 ==> size g + 1 == size (insertEdge edge (g :: UGraph Int ()))          it "Is id when inserting and removing a new vertex" $ property $             \g v -> (not $ g `containsVertex` v)-                ==> ((removeVertex v . insertVertex v) g)+                ==> (removeVertex v $ insertVertex g v)                     == (g :: UGraph Int ())