HORIZON HASKELLDocslts/ghc-10.0.x77a86622026-10-31Search packagesCtrl K
Theme: |

GHC 10.0.0.20260917 · lts/ghc-10.0.x · 77a8662 · 2026-10-31

Modulealgebraic-graphs-0.8Haskell2010

Algebra.Graph.Labelled.AdjacencyMap

Alga is a library for algebraic construction and manipulation of graphs in Haskell. See this paper for the motivation behind the library, the underlying theory, and implementation details.

This module defines the AdjacencyMap data type for edge-labelled graphs, as well as associated operations and algorithms. AdjacencyMap is an instance of the C.Graph type class, which can be used for polymorphic graph construction and manipulation.

Contents
  1. Data structure
  2. Basic graph construction primitives
  3. Relations on graphs
  4. Graph properties
  5. Graph transformation
  6. Relational operations
  7. Miscellaneous
Synopsis

Data structure

newtypenewtype AdjacencyMap e a

Edge-labelled graphs, where the type variable e stands for edge labels. For example, AdjacencyMap Bool a is isomorphic to unlabelled graphs defined in the top-level module Algebra.Graph.AdjacencyMap, where False and True denote the lack of and the existence of an unlabelled edge, respectively.

Instances14Eq, Num, Ord, Show, IsString, Generic, …
valueadjacencyMap :: AdjacencyMap e a -> Map a (Map a e)

The adjacency map of an edge-labelled graph: each vertex is associated with a map from its direct successors to the corresponding edge labels.

Basic graph construction primitives

value(-<) :: a -> e -> (a, e)

The left-hand part of a convenient ternary-ish operator x-<e>-y for creating labelled edges.

x -<e>- y == edge e x y
value(>-) :: (Eq e, Monoid e, Ord a) => (a, e) -> a -> AdjacencyMap e a

The right-hand part of a convenient ternary-ish operator x-<e>-y for creating labelled edges.

x -<e>- y == edge e x y
valueoverlay
  1. :: (Eq e, Monoid e, Ord a)
  2. => AdjacencyMap e a
  3. -> AdjacencyMap e a
  4. -> AdjacencyMap e a

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

Note: overlay composes edges in parallel using the operator <+> with zero acting as the identity:

edgeLabel x y $ overlay (edge e x y) (edge zero x y) == e
edgeLabel x y $ overlay (edge e x y) (edge f    x y) == e <+> f

Furthermore, when applied to transitive graphs, overlay composes edges in sequence using the operator <.> with one acting as the identity:

edgeLabel x z $ transitiveClosure (overlay (edge e x y) (edge one y z)) == e
edgeLabel x z $ transitiveClosure (overlay (edge e x y) (edge f   y z)) == e <.> f
valueconnect
  1. :: (Eq e, Monoid e, Ord a)
  2. => e
  3. -> AdjacencyMap e a
  4. -> AdjacencyMap e a
  5. -> AdjacencyMap e a

Connect two graphs with edges labelled by a given label. When applied to the same labels, this is an 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).

isEmpty     (connect e x y) == isEmpty   x   && isEmpty   y
hasVertex z (connect e x y) == hasVertex z x || hasVertex z y
vertexCount (connect e x y) >= vertexCount x
vertexCount (connect e x y) <= vertexCount x + vertexCount y
edgeCount   (connect e x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y
vertexCount (connect e 1 2) == 2
edgeCount   (connect e 1 2) == if e == zero then 0 else 1

Relations on graphs

Graph properties

valuevertexList :: AdjacencyMap e a -> [a]

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

vertexList empty      == []
vertexList (vertex x) == [x]
vertexList . vertices == Data.List.nub . Data.List.sort
valueedgeList :: AdjacencyMap e a -> [(e, a, a)]

The list of edges of a graph, sorted lexicographically with respect to pairs of connected vertices (i.e. edge-labels are ignored when sorting). Complexity: O(n + m) time and O(m) memory.

edgeList empty        == []
edgeList (vertex x)   == []
edgeList (edge e x y) == if e == zero then [] else [(e,x,y)]

Graph transformation

valueemap :: (Eq f, Monoid f) => (e -> f) -> AdjacencyMap e a -> AdjacencyMap f a

Transform a graph by applying a function h to each of its edge labels. Complexity: O((n + m) * log(n)) time.

The function h is required to be a homomorphism on the underlying type of labels e. At the very least it must preserve zero and <+>:

h zero      == zero
h x <+> h y == h (x <+> y)

If e is also a semiring, then h must also preserve the multiplicative structure:

h one       == one
h x <.> h y == h (x <.> y)

If the above requirements hold, then the implementation provides the following guarantees.

emap h empty           == empty
emap h (vertex x)      == vertex x
emap h (edge e x y)    == edge (h e) x y
emap h (overlay x y)   == overlay (emap h x) (emap h y)
emap h (connect e x y) == connect (h e) (emap h x) (emap h y)
emap id                == id
emap g . emap h        == emap (g . h)
valueinduce :: (a -> Bool) -> AdjacencyMap e a -> AdjacencyMap e a

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

Relational operations

valueclosure
  1. :: (Eq e, Ord a, StarSemiring e)
  2. => AdjacencyMap e a
  3. -> AdjacencyMap e a

Compute the reflexive and transitive closure of a graph over the underlying star semiring using the Warshall-Floyd-Kleene algorithm.

closure empty         == empty
closure (vertex x)    == edge one x x
closure (edge e x x)  == edge one x x
closure (edge e x y)  == edges [(one,x,x), (e,x,y), (one,y,y)]
closure               == reflexiveClosure . transitiveClosure
closure               == transitiveClosure . reflexiveClosure
closure . closure     == closure
postSet x (closure y) == Set.fromList (reachable y x)

Miscellaneous

valueconsistent :: (Ord a, Eq e, Monoid e) => AdjacencyMap e a -> Bool

Check that the internal graph representation is consistent, i.e. that all edges refer to existing vertices, and there are no zero-labelled edges. It should be impossible to create an inconsistent adjacency map, and we use this function in testing.