algebraic-graphs-0.7: A library for algebraic graph construction and transformation
Copyright(c) Andrey Mokhov 2016-2022
LicenseMIT (see the file LICENSE)
Maintainerandrey.mokhov@gmail.com
Stabilityexperimental
Safe HaskellNone
LanguageHaskell2010

Algebra.Graph.Relation.Symmetric

Description

An abstract implementation of symmetric binary relations. To avoid name clashes with Algebra.Graph.Relation, this module can be imported qualified:

import qualified Algebra.Graph.Relation.Symmetric as Symmetric

Relation is an instance of the Graph type class, which can be used for polymorphic graph construction and manipulation.

Synopsis

Data structure

data Relation a Source #

This data type represents a symmetric binary relation over a set of elements of type a. Symmetric relations satisfy all laws of the Undirected type class, including the commutativity of connect:

connect x y == connect y x

The Show instance lists edge vertices in non-decreasing order:

show (empty     :: Relation Int) == "empty"
show (1         :: Relation Int) == "vertex 1"
show (1 + 2     :: Relation Int) == "vertices [1,2]"
show (1 * 2     :: Relation Int) == "edge 1 2"
show (2 * 1     :: Relation Int) == "edge 1 2"
show (1 * 2 * 1 :: Relation Int) == "edges [(1,1),(1,2)]"
show (3 * 2 * 1 :: Relation Int) == "edges [(1,2),(1,3),(2,3)]"
show (1 * 2 + 3 :: Relation Int) == "overlay (vertex 3) (edge 1 2)"

The total order on graphs is defined using size-lexicographic comparison:

  • Compare the number of vertices. In case of a tie, continue.
  • Compare the sets of vertices. In case of a tie, continue.
  • Compare the number of edges. In case of a tie, continue.
  • Compare the sets of edges.

Here are a few examples:

vertex 1 < vertex 2
vertex 3 < edge 1 2
vertex 1 < edge 1 1
edge 1 1 < edge 1 2
edge 1 2 < edge 1 1 + edge 2 2
edge 2 1 < edge 1 3
edge 1 2 == edge 2 1

Note that the resulting order refines the isSubgraphOf relation and is compatible with overlay and connect operations:

isSubgraphOf x y ==> x <= y
empty <= x
x     <= x + y
x + y <= x * y

Instances

Instances details
Eq a => Eq (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Relation.Symmetric

Methods

(==) :: Relation a -> Relation a -> Bool #

(/=) :: Relation a -> Relation a -> Bool #

(Ord a, Num a) => Num (Relation a) Source #

Note: this does not satisfy the usual ring laws; see Relation for more details.

Instance details

Defined in Algebra.Graph.Relation.Symmetric

Ord a => Ord (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Relation.Symmetric

Methods

compare :: Relation a -> Relation a -> Ordering #

(<) :: Relation a -> Relation a -> Bool #

(<=) :: Relation a -> Relation a -> Bool #

(>) :: Relation a -> Relation a -> Bool #

(>=) :: Relation a -> Relation a -> Bool #

max :: Relation a -> Relation a -> Relation a #

min :: Relation a -> Relation a -> Relation a #

(Ord a, Show a) => Show (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Relation.Symmetric

Methods

showsPrec :: Int -> Relation a -> ShowS #

show :: Relation a -> String #

showList :: [Relation a] -> ShowS #

IsString a => IsString (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Relation.Symmetric

Methods

fromString :: String -> Relation a #

Ord a => Semigroup (Relation a) Source #

Defined via overlay.

Instance details

Defined in Algebra.Graph.Relation.Symmetric

Methods

(<>) :: Relation a -> Relation a -> Relation a #

sconcat :: NonEmpty (Relation a) -> Relation a #

stimes :: Integral b => b -> Relation a -> Relation a #

Ord a => Monoid (Relation a) Source #

Defined via overlay and empty.

Instance details

Defined in Algebra.Graph.Relation.Symmetric

Methods

mempty :: Relation a #

mappend :: Relation a -> Relation a -> Relation a #

mconcat :: [Relation a] -> Relation a #

NFData a => NFData (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Relation.Symmetric

Methods

rnf :: Relation a -> () #

Ord a => ToGraph (Relation a) Source #

Defined via fromSymmetric and the ToGraph instance of Relation.

Instance details

Defined in Algebra.Graph.Relation.Symmetric

Associated Types

type ToVertex (Relation a) Source #

Methods

toGraph :: Relation a -> Graph (ToVertex (Relation a)) Source #

foldg :: r -> (ToVertex (Relation a) -> r) -> (r -> r -> r) -> (r -> r -> r) -> Relation a -> r Source #

isEmpty :: Relation a -> Bool Source #

hasVertex :: ToVertex (Relation a) -> Relation a -> Bool Source #

hasEdge :: ToVertex (Relation a) -> ToVertex (Relation a) -> Relation a -> Bool Source #

vertexCount :: Relation a -> Int Source #

edgeCount :: Relation a -> Int Source #

vertexList :: Relation a -> [ToVertex (Relation a)] Source #

edgeList :: Relation a -> [(ToVertex (Relation a), ToVertex (Relation a))] Source #

vertexSet :: Relation a -> Set (ToVertex (Relation a)) Source #

vertexIntSet :: Relation a -> IntSet Source #

edgeSet :: Relation a -> Set (ToVertex (Relation a), ToVertex (Relation a)) Source #

preSet :: ToVertex (Relation a) -> Relation a -> Set (ToVertex (Relation a)) Source #

preIntSet :: Int -> Relation a -> IntSet Source #

postSet :: ToVertex (Relation a) -> Relation a -> Set (ToVertex (Relation a)) Source #

postIntSet :: Int -> Relation a -> IntSet Source #

adjacencyList :: Relation a -> [(ToVertex (Relation a), [ToVertex (Relation a)])] Source #

dfsForest :: Relation a -> Forest (ToVertex (Relation a)) Source #

dfsForestFrom :: Relation a -> [ToVertex (Relation a)] -> Forest (ToVertex (Relation a)) Source #

dfs :: Relation a -> [ToVertex (Relation a)] -> [ToVertex (Relation a)] Source #

reachable :: Relation a -> ToVertex (Relation a) -> [ToVertex (Relation a)] Source #

topSort :: Relation a -> Either (Cycle (ToVertex (Relation a))) [ToVertex (Relation a)] Source #

isAcyclic :: Relation a -> Bool Source #

toAdjacencyMap :: Relation a -> AdjacencyMap (ToVertex (Relation a)) Source #

toAdjacencyMapTranspose :: Relation a -> AdjacencyMap (ToVertex (Relation a)) Source #

toAdjacencyIntMap :: Relation a -> AdjacencyIntMap Source #

toAdjacencyIntMapTranspose :: Relation a -> AdjacencyIntMap Source #

isDfsForestOf :: Forest (ToVertex (Relation a)) -> Relation a -> Bool Source #

isTopSortOf :: [ToVertex (Relation a)] -> Relation a -> Bool Source #

Ord a => Undirected (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Class

Ord a => Graph (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Class

Associated Types

type Vertex (Relation a) Source #

type ToVertex (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Relation.Symmetric

type ToVertex (Relation a) = a
type Vertex (Relation a) Source # 
Instance details

Defined in Algebra.Graph.Class

type Vertex (Relation a) = a

toSymmetric :: Ord a => Relation a -> Relation a Source #

Construct a symmetric relation from a given Algebra.Graph.Relation. Complexity: O(m * log(m)) time.

toSymmetric (edge 1 2)         == edge 1 2
toSymmetric . fromSymmetric    == id
fromSymmetric    . toSymmetric == symmetricClosure
vertexCount      . toSymmetric == vertexCount
(*2) . edgeCount . toSymmetric >= edgeCount

fromSymmetric :: Relation a -> Relation a Source #

Extract the underlying symmetric Algebra.Graph.Relation. Complexity: O(1) time and memory.

fromSymmetric (edge 1 2)    == edges [(1,2), (2,1)]
vertexCount . fromSymmetric == vertexCount
edgeCount   . fromSymmetric <= (*2) . edgeCount

Basic graph construction primitives

empty :: Relation a Source #

Construct the empty graph.

isEmpty     empty == True
hasVertex x empty == False
vertexCount empty == 0
edgeCount   empty == 0

vertex :: a -> Relation a Source #

Construct the graph comprising a single isolated vertex.

isEmpty     (vertex x) == False
hasVertex x (vertex y) == (x == y)
vertexCount (vertex x) == 1
edgeCount   (vertex x) == 0

edge :: Ord a => a -> a -> Relation a Source #

Construct the graph comprising a single edge.

edge x y               == connect (vertex x) (vertex y)
edge x y               == edge y x
edge x y               == edges [(x,y), (y,x)]
hasEdge x y (edge x y) == True
edgeCount   (edge x y) == 1
vertexCount (edge 1 1) == 1
vertexCount (edge 1 2) == 2

overlay :: Ord a => Relation a -> Relation a -> Relation a Source #

Overlay two graphs. This is a commutative, associative and idempotent operation with the identity empty. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

isEmpty     (overlay x y) == isEmpty   x   && isEmpty   y
hasVertex z (overlay x y) == hasVertex z x || hasVertex z y
vertexCount (overlay x y) >= vertexCount x
vertexCount (overlay x y) <= vertexCount x + vertexCount y
edgeCount   (overlay x y) >= edgeCount x
edgeCount   (overlay x y) <= edgeCount x   + edgeCount y
vertexCount (overlay 1 2) == 2
edgeCount   (overlay 1 2) == 0

connect :: Ord a => Relation a -> Relation a -> Relation a Source #

Connect two graphs. This is a commutative and associative operation with the identity empty, which distributes over overlay and obeys the decomposition axiom. Complexity: O((n + m) * log(n)) time and O(n + m) memory. Note that the number of edges in the resulting graph is quadratic with respect to the number of vertices of the arguments: m = O(m1 + m2 + n1 * n2).

connect x y               == connect y x
isEmpty     (connect x y) == isEmpty   x   && isEmpty   y
hasVertex z (connect x y) == hasVertex z x || hasVertex z y
vertexCount (connect x y) >= vertexCount x
vertexCount (connect x y) <= vertexCount x + vertexCount y
edgeCount   (connect x y) >= edgeCount x
edgeCount   (connect x y) >= edgeCount y
edgeCount   (connect x y) >= vertexCount x * vertexCount y `div` 2
vertexCount (connect 1 2) == 2
edgeCount   (connect 1 2) == 1

vertices :: Ord a => [a] -> Relation a Source #

Construct the graph comprising a given list of isolated vertices. Complexity: O(L * log(L)) time and O(L) memory, where L is the length of the given list.

vertices []            == empty
vertices [x]           == vertex x
vertices               == overlays . map vertex
hasVertex x . vertices == elem x
vertexCount . vertices == length . nub
vertexSet   . vertices == Set.fromList

edges :: Ord a => [(a, a)] -> Relation a Source #

Construct the graph from a list of edges. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

edges []             == empty
edges [(x,y)]        == edge x y
edges [(x,y), (y,x)] == edge x y

overlays :: Ord a => [Relation a] -> Relation a Source #

Overlay a given list of graphs. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

overlays []        == empty
overlays [x]       == x
overlays [x,y]     == overlay x y
overlays           == foldr overlay empty
isEmpty . overlays == all isEmpty

connects :: Ord a => [Relation a] -> Relation a Source #

Connect a given list of graphs. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

connects []        == empty
connects [x]       == x
connects [x,y]     == connect x y
connects           == foldr connect empty
isEmpty . connects == all isEmpty
connects           == connects . reverse

Relations on graphs

isSubgraphOf :: Ord a => Relation a -> Relation a -> Bool Source #

The isSubgraphOf function takes two graphs and returns True if the first graph is a subgraph of the second. Complexity: O((n + m) * log(n)) time.

isSubgraphOf empty         x             ==  True
isSubgraphOf (vertex x)    empty         ==  False
isSubgraphOf x             (overlay x y) ==  True
isSubgraphOf (overlay x y) (connect x y) ==  True
isSubgraphOf (path xs)     (circuit xs)  ==  True
isSubgraphOf (edge x y)    (edge y x)    ==  True
isSubgraphOf x y                         ==> x <= y

Graph properties

isEmpty :: Relation a -> Bool Source #

Check if a relation is empty. Complexity: O(1) time.

isEmpty empty                       == True
isEmpty (overlay empty empty)       == True
isEmpty (vertex x)                  == False
isEmpty (removeVertex x $ vertex x) == True
isEmpty (removeEdge x y $ edge x y) == False

hasVertex :: Ord a => a -> Relation a -> Bool Source #

Check if a graph contains a given vertex. Complexity: O(log(n)) time.

hasVertex x empty            == False
hasVertex x (vertex y)       == (x == y)
hasVertex x . removeVertex x == const False

hasEdge :: Ord a => a -> a -> Relation a -> Bool Source #

Check if a graph contains a given edge. Complexity: O(log(n)) time.

hasEdge x y empty            == False
hasEdge x y (vertex z)       == False
hasEdge x y (edge x y)       == True
hasEdge x y (edge y x)       == True
hasEdge x y . removeEdge x y == const False
hasEdge x y                  == elem (min x y, max x y) . edgeList

vertexCount :: Relation a -> Int Source #

The number of vertices in a graph. Complexity: O(1) time.

vertexCount empty             ==  0
vertexCount (vertex x)        ==  1
vertexCount                   ==  length . vertexList
vertexCount x < vertexCount y ==> x < y

edgeCount :: Ord a => Relation a -> Int Source #

The number of edges in a graph. Complexity: O(1) time.

edgeCount empty      == 0
edgeCount (vertex x) == 0
edgeCount (edge x y) == 1
edgeCount            == length . edgeList

vertexList :: Relation a -> [a] Source #

The sorted list of vertices of a given graph. Complexity: O(n) time and memory.

vertexList empty      == []
vertexList (vertex x) == [x]
vertexList . vertices == nub . sort

edgeList :: Ord a => Relation a -> [(a, a)] Source #

The sorted list of edges of a graph, where edge vertices appear in the non-decreasing order. Complexity: O(n + m) time and O(m) memory.

Note: If you need the sorted list of edges where an edge appears in both directions, use edgeList . fromSymmetric.

edgeList empty          == []
edgeList (vertex x)     == []
edgeList (edge x y)     == [(min x y, max y x)]
edgeList (star 2 [3,1]) == [(1,2), (2,3)]

adjacencyList :: Eq a => Relation a -> [(a, [a])] Source #

The sorted adjacency list of a graph. Complexity: O(n + m) time and memory.

adjacencyList empty          == []
adjacencyList (vertex x)     == [(x, [])]
adjacencyList (edge 1 2)     == [(1, [2]), (2, [1])]
adjacencyList (star 2 [3,1]) == [(1, [2]), (2, [1,3]), (3, [2])]
stars . adjacencyList        == id

vertexSet :: Relation a -> Set a Source #

The set of vertices of a given graph. Complexity: O(1) time.

vertexSet empty      == Set.empty
vertexSet . vertex   == Set.singleton
vertexSet . vertices == Set.fromList

edgeSet :: Ord a => Relation a -> Set (a, a) Source #

The set of edges of a given graph, where edge vertices appear in the non-decreasing order. Complexity: O(m) time.

Note: If you need the set of edges where an edge appears in both directions, use relation . fromSymmetric. The latter is much faster than this function, and takes only O(1) time and memory.

edgeSet empty      == Set.empty
edgeSet (vertex x) == Set.empty
edgeSet (edge x y) == Set.singleton (min x y, max x y)

neighbours :: Ord a => a -> Relation a -> Set a Source #

The set of neighbours of an element x is the set of elements that are related to it, i.e. neighbours x == { a | aRx }. In the context of undirected graphs, this corresponds to the set of adjacent vertices of vertex x.

neighbours x empty      == Set.empty
neighbours x (vertex x) == Set.empty
neighbours x (edge x y) == Set.fromList [y]
neighbours y (edge x y) == Set.fromList [x]

Standard families of graphs

path :: Ord a => [a] -> Relation a Source #

The path on a list of vertices. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

path []    == empty
path [x]   == vertex x
path [x,y] == edge x y
path       == path . reverse

circuit :: Ord a => [a] -> Relation a Source #

The circuit on a list of vertices. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

circuit []    == empty
circuit [x]   == edge x x
circuit [x,y] == edge x y
circuit       == circuit . reverse

clique :: Ord a => [a] -> Relation a Source #

The clique on a list of vertices. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

clique []         == empty
clique [x]        == vertex x
clique [x,y]      == edge x y
clique [x,y,z]    == edges [(x,y), (x,z), (y,z)]
clique (xs ++ ys) == connect (clique xs) (clique ys)
clique            == clique . reverse

biclique :: Ord a => [a] -> [a] -> Relation a Source #

The biclique on two lists of vertices. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

biclique []      []      == empty
biclique [x]     []      == vertex x
biclique []      [y]     == vertex y
biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,x2), (x2,y2)]
biclique xs      ys      == connect (vertices xs) (vertices ys)

star :: Ord a => a -> [a] -> Relation a Source #

The star formed by a centre vertex connected to a list of leaves. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

star x []    == vertex x
star x [y]   == edge x y
star x [y,z] == edges [(x,y), (x,z)]
star x ys    == connect (vertex x) (vertices ys)

stars :: Ord a => [(a, [a])] -> Relation a Source #

The stars formed by overlaying a list of stars. An inverse of adjacencyList. Complexity: O(L * log(n)) time, memory and size, where L is the total size of the input.

stars []                      == empty
stars [(x, [])]               == vertex x
stars [(x, [y])]              == edge x y
stars [(x, ys)]               == star x ys
stars                         == overlays . map (uncurry star)
stars . adjacencyList         == id
overlay (stars xs) (stars ys) == stars (xs ++ ys)

tree :: Ord a => Tree a -> Relation a Source #

The tree graph constructed from a given Tree data structure. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

tree (Node x [])                                         == vertex x
tree (Node x [Node y [Node z []]])                       == path [x,y,z]
tree (Node x [Node y [], Node z []])                     == star x [y,z]
tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5)]

forest :: Ord a => Forest a -> Relation a Source #

The forest graph constructed from a given Forest data structure. Complexity: O((n + m) * log(n)) time and O(n + m) memory.

forest []                                                  == empty
forest [x]                                                 == tree x
forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5)]
forest                                                     == overlays . map tree

Graph transformation

removeVertex :: Ord a => a -> Relation a -> Relation a Source #

Remove a vertex from a given graph. Complexity: O(n + m) time.

removeVertex x (vertex x)       == empty
removeVertex 1 (vertex 2)       == vertex 2
removeVertex x (edge x x)       == empty
removeVertex 1 (edge 1 2)       == vertex 2
removeVertex x . removeVertex x == removeVertex x

removeEdge :: Ord a => a -> a -> Relation a -> Relation a Source #

Remove an edge from a given graph. Complexity: O(log(m)) time.

removeEdge x y (edge x y)       == vertices [x,y]
removeEdge x y . removeEdge x y == removeEdge x y
removeEdge x y                  == removeEdge y x
removeEdge x y . removeVertex x == removeVertex x
removeEdge 1 1 (1 * 1 * 2 * 2)  == 1 * 2 * 2
removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2

replaceVertex :: Ord a => a -> a -> Relation a -> Relation a Source #

The function replaceVertex x y replaces vertex x with vertex y in a given Relation. If y already exists, x and y will be merged. Complexity: O((n + m) * log(n)) time.

replaceVertex x x            == id
replaceVertex x y (vertex x) == vertex y
replaceVertex x y            == mergeVertices (== x) y

mergeVertices :: Ord a => (a -> Bool) -> a -> Relation a -> Relation a Source #

Merge vertices satisfying a given predicate into a given vertex. Complexity: O((n + m) * log(n)) time, assuming that the predicate takes constant time.

mergeVertices (const False) x    == id
mergeVertices (== x) y           == replaceVertex x y
mergeVertices even 1 (0 * 2)     == 1 * 1
mergeVertices odd  1 (3 + 4 * 5) == 4 * 1

gmap :: Ord b => (a -> b) -> Relation a -> Relation b Source #

Transform a graph by applying a function to each of its vertices. This is similar to Functor's fmap but can be used with non-fully-parametric Relation. Complexity: O((n + m) * log(n)) time.

gmap f empty      == empty
gmap f (vertex x) == vertex (f x)
gmap f (edge x y) == edge (f x) (f y)
gmap id           == id
gmap f . gmap g   == gmap (f . g)

induce :: (a -> Bool) -> Relation a -> Relation a Source #

Construct the induced subgraph of a given graph by removing the vertices that do not satisfy a given predicate. Complexity: O(n + m) time, assuming that the predicate takes constant time.

induce (const True ) x      == x
induce (const False) x      == empty
induce (/= x)               == removeVertex x
induce p . induce q         == induce (\x -> p x && q x)
isSubgraphOf (induce p x) x == True

induceJust :: Ord a => Relation (Maybe a) -> Relation a Source #

Construct the induced subgraph of a given graph by removing the vertices that are Nothing. Complexity: O(n + m) time.

induceJust (vertex Nothing)                               == empty
induceJust (edge (Just x) Nothing)                        == vertex x
induceJust . gmap Just                                    == id
induceJust . gmap (\x -> if p x then Just x else Nothing) == induce p

Miscellaneous

consistent :: Ord a => Relation a -> Bool Source #

Check that the internal representation of a symmetric relation is consistent, i.e. that (i) that all edges refer to existing vertices, and (ii) all edges have their symmetric counterparts. It should be impossible to create an inconsistent Relation, and we use this function in testing.

consistent empty         == True
consistent (vertex x)    == True
consistent (overlay x y) == True
consistent (connect x y) == True
consistent (edge x y)    == True
consistent (edges xs)    == True
consistent (stars xs)    == True