Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better hasEdge for Algrebra.Graph #88

Merged
merged 10 commits into from
Jul 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions src/Algebra/Graph.hs
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,6 @@ size = foldg 1 (const 1) (+) (+)
hasVertex :: Eq a => a -> Graph a -> Bool
hasVertex x = foldg False (==x) (||) (||)

-- TODO: Benchmark to see if this implementation is faster than the default
-- implementation provided by the ToGraph type class.
-- | Check if a graph contains a given edge.
-- Complexity: /O(s)/ time.
--
Expand All @@ -459,8 +457,28 @@ hasVertex x = foldg False (==x) (||) (||)
-- hasEdge x y == 'elem' (x,y) . 'edgeList'
-- @
{-# SPECIALISE hasEdge :: Int -> Int -> Graph Int -> Bool #-}
hasEdge :: Ord a => a -> a -> Graph a -> Bool
hasEdge u v = (edge u v `isSubgraphOf`) . induce (`elem` [u, v])
hasEdge :: Eq a => a -> a -> Graph a -> Bool
hasEdge s t = if s == t -- We test if we search for a loop
then hasSelfLoop s
else hasEdge' . induce' -- if not, we convert the supplied @Graph a@ to a @Graph Bool@
-- where @s@ is @Vertex True@, @v@ is @Vertex False@ and other
-- vertices are removed.
-- Then we check if there is an edge from @True@ to @False@
where
hasEdge' g = case foldg e v o c g of (_, _, r) -> r
where
e = (False , False , False )
v x = (x , not x , False )
o (xs, xt, xst) (ys, yt, yst) = (xs || ys, xt || yt, xst || yst)
c (xs, xt, xst) (ys, yt, yst) = (xs || ys, xt || yt, xs && yt || xst || yst)
induce' = foldg Empty
(\x -> if x == s then Vertex True else if x == t then Vertex False else Empty)
(k Overlay)
(k Connect)
where
k _ x Empty = x -- Constant folding to get rid of Empty leaves
k _ Empty y = y
k f x y = f x y

-- | Check if a graph contains a given loop.
-- Complexity: /O(s)/ time.
Expand Down
41 changes: 39 additions & 2 deletions src/Algebra/Graph/Fold.hs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ instance Traversable Fold where
instance ToGraph (Fold a) where
type ToVertex (Fold a) = a
foldg = foldg
hasEdge = hasEdge
hasSelfLoop = hasSelfLoop

-- | Construct the /empty graph/.
-- Complexity: /O(1)/ time, memory and size.
Expand Down Expand Up @@ -408,7 +410,27 @@ hasVertex = T.hasVertex
-- hasEdge x y == 'elem' (x,y) . 'edgeList'
-- @
hasEdge :: Eq a => a -> a -> Fold a -> Bool
hasEdge = T.hasEdge
hasEdge s t = if s == t -- We test if we search for a loop
then hasSelfLoop s
else maybe False hasEdge' . induce' -- if not, we convert the supplied @Graph a@ to a @Graph Bool@
-- where @s@ is @Vertex True@, @v@ is @Vertex False@ and other
-- vertices are removed.
-- Then we check if there is an edge from @True@ to @False@
where
hasEdge' g = case foldg e v o c g of (_, _, r) -> r
where
e = (False , False , False )
v x = (x , not x , False )
o (xs, xt, xst) (ys, yt, yst) = (xs || ys, xt || yt, xst || yst)
c (xs, xt, xst) (ys, yt, yst) = (xs || ys, xt || yt, xs && yt || xst || yst)
induce' = foldg Nothing
(\x -> if x == s then Just (vertex True) else if x == t then Just (vertex False) else Nothing)
(k overlay)
(k connect)
where
k _ x Nothing = x -- Constant folding to get rid of Empty leaves
k _ Nothing y = y
k f (Just x) (Just y) = Just $ f x y

-- | Check if a graph contains a given loop.
-- Complexity: /O(s)/ time.
Expand All @@ -422,7 +444,22 @@ hasEdge = T.hasEdge
-- hasSelfLoop x == 'elem' (x,x) . 'edgeList'
-- @
hasSelfLoop :: Eq a => a -> Fold a -> Bool
hasSelfLoop = T.hasSelfLoop
hasSelfLoop t = maybe False hasEdge' . induce'
where
hasEdge' g = case foldg e v o c g of (_, _, r) -> r
where
e = (False , False , False )
v x = (x , x , False )
o (xs, xt, xst) (ys, yt, yst) = (xs || ys, xt || yt, xst || yst)
c (xs, xt, xst) (ys, yt, yst) = (xs || ys, xt || yt, xs && yt || xst || yst)
induce' = foldg Nothing
(\x -> if x==t then Just (vertex True) else Nothing)
(k overlay)
(k connect)
where
k _ x Nothing = x -- Constant folding to get rid of Empty leaves
k _ Nothing y = y
k f (Just x) (Just y) = Just $ f x y

-- | The number of vertices in a graph.
-- Complexity: /O(s * log(n))/ time.
Expand Down