From 38763fdd5384ad6f9bede4cfa41b88d0f08a5de5 Mon Sep 17 00:00:00 2001 From: Jonathan Dowland Date: Fri, 26 Oct 2018 16:34:48 +0100 Subject: [PATCH 1/8] Implement hasVertexP and hasEdgeP Predicate versions of hasVertex and hasEdge. Re-implement hasVertex and hasEdge in terms of the predicate versions. --- src/Algebra/Graph.hs | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Algebra/Graph.hs b/src/Algebra/Graph.hs index 3cd3dc167..04ba6615f 100644 --- a/src/Algebra/Graph.hs +++ b/src/Algebra/Graph.hs @@ -32,8 +32,8 @@ module Algebra.Graph ( isSubgraphOf, (===), -- * Graph properties - isEmpty, size, hasVertex, hasEdge, vertexCount, edgeCount, vertexList, - edgeList, vertexSet, edgeSet, adjacencyList, + isEmpty, size, hasVertexP, hasVertex, hasEdgeP, hasEdge, vertexCount, + edgeCount, vertexList, edgeList, vertexSet, edgeSet, adjacencyList, -- * Standard families of graphs path, circuit, clique, biclique, star, stars, tree, forest, mesh, torus, @@ -472,6 +472,12 @@ isEmpty = foldg True (const False) (&&) (&&) size :: Graph a -> Int size = foldg 1 (const 1) (+) (+) +-- | Check if a graph contains a vertex which satisfied the supplied predicate. +-- Complexity: /O(s)/ time. +-- +hasVertexP :: (a -> Bool) -> Graph a -> Bool +hasVertexP pred = foldg False pred (||) (||) + -- | Check if a graph contains a given vertex. -- Complexity: /O(s)/ time. -- @@ -483,7 +489,25 @@ size = foldg 1 (const 1) (+) (+) -- @ {-# SPECIALISE hasVertex :: Int -> Graph Int -> Bool #-} hasVertex :: Eq a => a -> Graph a -> Bool -hasVertex x = foldg False (==x) (||) (||) +hasVertex x = hasVertexP (==x) + +-- | Check if a graph contains an edge whose vertices match the supplied +-- predicates. +-- Complexity: /O(s)/ time. +-- +hasEdgeP :: (a -> Bool) -> (a -> Bool) -> Graph a -> Bool +hasEdgeP predFrom predTo g = hit g == Edge + where + hit Empty = Miss + hit (Vertex x ) = if predFrom x then Tail else Miss + hit (Overlay x y) = case hit x of + Miss -> hit y + Tail -> max Tail (hit y) + Edge -> Edge + hit (Connect x y) = case hit x of + Miss -> hit y + Tail -> if hasVertexP predTo y then Edge else Tail + Edge -> Edge -- | Check if a graph contains a given edge. -- Complexity: /O(s)/ time. @@ -497,18 +521,7 @@ hasVertex x = foldg False (==x) (||) (||) -- @ {-# SPECIALISE hasEdge :: Int -> Int -> Graph Int -> Bool #-} hasEdge :: Eq a => a -> a -> Graph a -> Bool -hasEdge s t g = hit g == Edge - where - hit Empty = Miss - hit (Vertex x ) = if x == s then Tail else Miss - hit (Overlay x y) = case hit x of - Miss -> hit y - Tail -> max Tail (hit y) - Edge -> Edge - hit (Connect x y) = case hit x of - Miss -> hit y - Tail -> if hasVertex t y then Edge else Tail - Edge -> Edge +hasEdge s t g = hasEdgeP (==s) (==t) g -- | The number of vertices in a graph. -- Complexity: /O(s * log(n))/ time. From 820798fd1bca2fdc01c9dbaaf4ecd8d6911cc94b Mon Sep 17 00:00:00 2001 From: Jonathan Dowland Date: Tue, 30 Oct 2018 21:52:34 +0000 Subject: [PATCH 2/8] Add INLINE pragmas for hasEdgeP and hasVertexP Thanks Alexandre Moine! --- src/Algebra/Graph.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Algebra/Graph.hs b/src/Algebra/Graph.hs index 04ba6615f..cb8804b50 100644 --- a/src/Algebra/Graph.hs +++ b/src/Algebra/Graph.hs @@ -475,6 +475,7 @@ size = foldg 1 (const 1) (+) (+) -- | Check if a graph contains a vertex which satisfied the supplied predicate. -- Complexity: /O(s)/ time. -- +{-# INLINE [1] hasVertexP #-} hasVertexP :: (a -> Bool) -> Graph a -> Bool hasVertexP pred = foldg False pred (||) (||) @@ -495,6 +496,7 @@ hasVertex x = hasVertexP (==x) -- predicates. -- Complexity: /O(s)/ time. -- +{-# INLINE [1] hasEdgeP #-} hasEdgeP :: (a -> Bool) -> (a -> Bool) -> Graph a -> Bool hasEdgeP predFrom predTo g = hit g == Edge where From ab78e05901e56ea21d6047ff0ce543bb89c3c390 Mon Sep 17 00:00:00 2001 From: Jonathan Dowland Date: Fri, 2 Nov 2018 10:56:12 +0000 Subject: [PATCH 3/8] implement findVertices and re-implement hasVertex re-implement hasVertex in terms of findVertices --- src/Algebra/Graph.hs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Algebra/Graph.hs b/src/Algebra/Graph.hs index cb8804b50..13417e57f 100644 --- a/src/Algebra/Graph.hs +++ b/src/Algebra/Graph.hs @@ -35,6 +35,8 @@ module Algebra.Graph ( isEmpty, size, hasVertexP, hasVertex, hasEdgeP, hasEdge, vertexCount, edgeCount, vertexList, edgeList, vertexSet, edgeSet, adjacencyList, + findVertices, + -- * Standard families of graphs path, circuit, clique, biclique, star, stars, tree, forest, mesh, torus, deBruijn, @@ -472,6 +474,10 @@ isEmpty = foldg True (const False) (&&) (&&) size :: Graph a -> Int size = foldg 1 (const 1) (+) (+) +{-# INLINE [1] findVertices #-} +findVertices :: (a -> Bool) -> Graph a -> [a] +findVertices p = foldg [] (\x -> [ x | p x ]) (++) (++) + -- | Check if a graph contains a vertex which satisfied the supplied predicate. -- Complexity: /O(s)/ time. -- @@ -490,7 +496,8 @@ hasVertexP pred = foldg False pred (||) (||) -- @ {-# SPECIALISE hasVertex :: Int -> Graph Int -> Bool #-} hasVertex :: Eq a => a -> Graph a -> Bool -hasVertex x = hasVertexP (==x) +--hasVertex x = hasVertexP (==x) +hasVertex x g = not . null $ findVertices (== x) g -- | Check if a graph contains an edge whose vertices match the supplied -- predicates. From 511633a1ecb6fe85ee2a85b2f85b8131d31890a9 Mon Sep 17 00:00:00 2001 From: Jonathan Dowland Date: Fri, 2 Nov 2018 10:58:59 +0000 Subject: [PATCH 4/8] fixup --- src/Algebra/Graph.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Algebra/Graph.hs b/src/Algebra/Graph.hs index 13417e57f..61075090f 100644 --- a/src/Algebra/Graph.hs +++ b/src/Algebra/Graph.hs @@ -496,7 +496,6 @@ hasVertexP pred = foldg False pred (||) (||) -- @ {-# SPECIALISE hasVertex :: Int -> Graph Int -> Bool #-} hasVertex :: Eq a => a -> Graph a -> Bool ---hasVertex x = hasVertexP (==x) hasVertex x g = not . null $ findVertices (== x) g -- | Check if a graph contains an edge whose vertices match the supplied From 8d273d865283c7d9a94ed1ab1681632414a1832e Mon Sep 17 00:00:00 2001 From: Jonathan Dowland Date: Fri, 2 Nov 2018 13:49:47 +0000 Subject: [PATCH 5/8] Add TupleSections LANGUAGE pragma Required by the implementation of `box` --- src/Algebra/Graph.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Algebra/Graph.hs b/src/Algebra/Graph.hs index 61075090f..053c7d533 100644 --- a/src/Algebra/Graph.hs +++ b/src/Algebra/Graph.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE DeriveFunctor #-} +{-# LANGUAGE DeriveFunctor, TupleSections #-} ----------------------------------------------------------------------------- -- | -- Module : Algebra.Graph From 90420fc549e45397ab585e904c050fdc709be285 Mon Sep 17 00:00:00 2001 From: Jonathan Dowland Date: Fri, 2 Nov 2018 13:50:42 +0000 Subject: [PATCH 6/8] implement findEdges --- src/Algebra/Graph.hs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Algebra/Graph.hs b/src/Algebra/Graph.hs index 053c7d533..a991308ef 100644 --- a/src/Algebra/Graph.hs +++ b/src/Algebra/Graph.hs @@ -35,7 +35,7 @@ module Algebra.Graph ( isEmpty, size, hasVertexP, hasVertex, hasEdgeP, hasEdge, vertexCount, edgeCount, vertexList, edgeList, vertexSet, edgeSet, adjacencyList, - findVertices, + findVertices, findEdges, -- * Standard families of graphs path, circuit, clique, biclique, star, stars, tree, forest, mesh, torus, @@ -60,6 +60,7 @@ import Control.DeepSeq (NFData (..)) import Control.Monad.Compat import Control.Monad.State (runState, get, put) import Data.Foldable (toList) +import Data.List (intersect) import Data.Monoid ((<>)) import Data.Maybe (fromMaybe) import Data.Tree @@ -498,6 +499,15 @@ hasVertexP pred = foldg False pred (||) (||) hasVertex :: Eq a => a -> Graph a -> Bool hasVertex x g = not . null $ findVertices (== x) g +-- | Find all edges in a graph whose vertices match the supplied predicates. +-- | Complexity: XXX +{-# INLINE [1] findEdges #-} +findEdges :: (a -> Bool) -> (a -> Bool) -> Graph a -> [(a, a)] +findEdges f t (Overlay a b) = findEdges f t a ++ findEdges f t b +findEdges f t (Connect a b) = + [(x,y) | [x,y] <- sequence [findVertices f a, findVertices t b]] ++ findEdges f t (Overlay a b) +findEdges _ _ _ = [] + -- | Check if a graph contains an edge whose vertices match the supplied -- predicates. -- Complexity: /O(s)/ time. From 655c72c952995d64ea61fc61e08c3a12dc56c9c2 Mon Sep 17 00:00:00 2001 From: Jonathan Dowland Date: Fri, 2 Nov 2018 13:51:15 +0000 Subject: [PATCH 7/8] re-implement hasEdgeP in terms of findEdges --- src/Algebra/Graph.hs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/Algebra/Graph.hs b/src/Algebra/Graph.hs index a991308ef..aed76f280 100644 --- a/src/Algebra/Graph.hs +++ b/src/Algebra/Graph.hs @@ -514,18 +514,7 @@ findEdges _ _ _ = [] -- {-# INLINE [1] hasEdgeP #-} hasEdgeP :: (a -> Bool) -> (a -> Bool) -> Graph a -> Bool -hasEdgeP predFrom predTo g = hit g == Edge - where - hit Empty = Miss - hit (Vertex x ) = if predFrom x then Tail else Miss - hit (Overlay x y) = case hit x of - Miss -> hit y - Tail -> max Tail (hit y) - Edge -> Edge - hit (Connect x y) = case hit x of - Miss -> hit y - Tail -> if hasVertexP predTo y then Edge else Tail - Edge -> Edge +hasEdgeP f t g = not . null $ findEdges f t g -- | Check if a graph contains a given edge. -- Complexity: /O(s)/ time. From 5ed33b63284afb275d7584d0203d0b4327ecc02e Mon Sep 17 00:00:00 2001 From: Jonathan Dowland Date: Fri, 2 Nov 2018 13:51:35 +0000 Subject: [PATCH 8/8] Doc strings and some TODOs for complexity analysis --- src/Algebra/Graph.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Algebra/Graph.hs b/src/Algebra/Graph.hs index aed76f280..5e6c5d507 100644 --- a/src/Algebra/Graph.hs +++ b/src/Algebra/Graph.hs @@ -475,6 +475,8 @@ isEmpty = foldg True (const False) (&&) (&&) size :: Graph a -> Int size = foldg 1 (const 1) (+) (+) +-- | Find all vertices in a graph matching the supplied predicate. +-- | Complexity: XXX {-# INLINE [1] findVertices #-} findVertices :: (a -> Bool) -> Graph a -> [a] findVertices p = foldg [] (\x -> [ x | p x ]) (++) (++) @@ -510,7 +512,7 @@ findEdges _ _ _ = [] -- | Check if a graph contains an edge whose vertices match the supplied -- predicates. --- Complexity: /O(s)/ time. +-- Complexity: XXX -- {-# INLINE [1] hasEdgeP #-} hasEdgeP :: (a -> Bool) -> (a -> Bool) -> Graph a -> Bool