A cycle of odd length. For example, [1,2,3] represents the cycle
1 -> 2 -> 3 -> 1.
Modulealgebraic-graphs-0.8Haskell2010
Algebra.Graph.Bipartite.AdjacencyMap.Algorithm
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 provides several basic algorithms on undirected bipartite graphs.
- 4 types
- 15 values
- Packagealgebraic-graphs-0.8
- Exports19
- LanguageHaskell2010
- LicenceMIT
- SourceAlgorithm.hs
Bipartiteness test
2 declarationsTest the bipartiteness of a given Algebra.Graph.AdjacencyMap. In case of success, return an AdjacencyMap with the same set of edges and each vertex marked with the part it belongs to. In case of failure, return any cycle of odd length in the graph.
The returned partition is lexicographically smallest, assuming that vertices of the left part precede all the vertices of the right part.
The returned cycle is optimal in the following sense: there exists a path
that is either empty or ends in a vertex adjacent to the first vertex in the
cycle, such that all vertices in path ++ cycle are distinct and
path ++ cycle is lexicographically smallest among all such pairs of
paths and cycles.
Note: since AdjacencyMap represents undirected bipartite graphs, all edges in the input graph are treated as undirected. See the examples and the correctness property for a clarification.
Complexity: O((n + m) * log(n)) time and O(n + m) memory.
detectParts empty == Right empty
detectParts (vertex x) == Right (leftVertex x)
detectParts (edge x x) == Left [x]
detectParts (edge 1 2) == Right (edge 1 2)
detectParts (1 * (2 + 3)) == Right (edges [(1,2), (1,3)])
detectParts (1 * 2 * 3) == Left [1, 2, 3]
detectParts ((1 + 3) * (2 + 4) + 6 * 5) == Right (swap (1 + 3) * (2 + 4) + swap 5 * 6)
detectParts ((1 * 3 * 4) + 2 * (1 + 2)) == Left [2]
detectParts (clique [1..10]) == Left [1, 2, 3]
detectParts (circuit [1..10]) == Right (circuit [(x, x + 1) | x <- [1,3,5,7,9]])
detectParts (circuit [1..11]) == Left [1..11]
detectParts (biclique [] xs) == Right (vertices xs [])
detectParts (biclique (map Left (x:xs)) (map Right ys)) == Right (biclique (map Left (x:xs)) (map Right ys))
isRight (detectParts (star x ys)) == notElem x ys
isRight (detectParts (fromBipartite (toBipartite x))) == True
The correctness of detectParts can be expressed by the following property:
let undirected = symmetricClosure input in
case detectParts input of
Left cycle -> mod (length cycle) 2 == 1 && isSubgraphOf (circuit cycle) undirected
Right result -> gmap fromEither (fromBipartite result) == undirected
Matchings
7 declarationsA matching is a set of pairwise non-adjacent edges between the two parts of a bipartite graph.
The Show instance is defined using the matching function, with the edges listed in the ascending order of left vertices.
show (matching []) == "matching []"
show (matching [(2,'a'), (1,'b')]) == "matching [(1,'b'),(2,'a')]"
Instances5Eq, Ord, Show, Generic, Rep
(Eq a, Eq b) => Eq (Matching a b)Defined in algebraic-graphs-0.8 · Algebra.Graph.Bipartite.AdjacencyMap.Algorithm(Ord a, Ord b) => Ord (Matching a b)Defined in algebraic-graphs-0.8 · Algebra.Graph.Bipartite.AdjacencyMap.Algorithm(Show a, Show b) => Show (Matching a b)Defined in algebraic-graphs-0.8 · Algebra.Graph.Bipartite.AdjacencyMap.AlgorithmGeneric (Matching a b)Defined in algebraic-graphs-0.8 · Algebra.Graph.Bipartite.AdjacencyMap.Algorithmtype Rep (Matching a b) = D1 ('MetaDataDefined in algebraic-graphs-0.8 · Algebra.Graph.Bipartite.AdjacencyMap.Algorithm"Matching"
"Algebra.Graph.Bipartite.AdjacencyMap.Algorithm"
"algebraic-graphs-0.8-8JX2W3BiNP382gnPBc0Np8"
'False) (C1 ('MetaCons"Matching"
'PrefixI 'True) (S1 ('MetaSel ('Just"pairOfLeft"
) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Map a b)) :*: S1 ('MetaSel ('Just"pairOfRight"
) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Map b a))))
Construct a Matching from a list of edges. Complexity: O(L * log(L)) time, where L is the length of the given list.
Edges that appear closer to the end of the list supersede all previous edges. That is, if two edges from the list share a vertex, the one that appears closer to the beginning is ignored.
pairOfLeft (matching []) == Map.empty
pairOfRight (matching []) == Map.empty
pairOfLeft (matching [(2,'a'), (1,'b')]) == Map.fromList [(2,'a'), (1,'b')]
pairOfLeft (matching [(1,'a'), (1,'b')]) == Map.singleton 1 'b'
matching [(1,'a'), (1,'b'), (2,'b'), (2,'a')] == matching [(2,'a')]
Check if a given Matching is a valid matching of a bipartite graph. Complexity: O(S * log(n)), where S is the size of the matching.
isMatchingOf (matching []) x == True
isMatchingOf (matching xs) empty == null xs
isMatchingOf (matching [(x,y)]) (edge x y) == True
isMatchingOf (matching [(1,2)]) (edge 2 1) == False
Find a maximum matching in a bipartite graph. A matching is maximum if it has the largest possible size. Complexity: O(m * sqrt(n) * log(n)) time.
maxMatching empty == matching []
maxMatching (vertices xs ys) == matching []
maxMatching (path [1,2,3,4]) == matching [(1,2), (3,4)]
matchingSize (maxMatching (circuit [(1,2), (3,4), (5,6)])) == 3
matchingSize (maxMatching (star x (y:ys))) == 1
matchingSize (maxMatching (biclique xs ys)) == min (length (nub xs)) (length (nub ys))
isMatchingOf (maxMatching x) x == True
Vertex covers
4 declarationsA vertex cover of a bipartite graph.
A vertex cover is a subset of vertices such that every edge is incident to
some vertex in the subset. We represent vertex covers by storing two sets of
vertices, one for each part. An equivalent representation, which is slightly
less memory efficient, is Set (Either a b).
Check if a given pair of sets is a vertex cover of a bipartite graph. Complexity: O(m * log(n)).
isVertexCoverOf (xs , ys ) empty == Set.null xs && Set.null ys
isVertexCoverOf (xs , ys ) (leftVertex x) == Set.isSubsetOf xs (Set.singleton x) && Set.null ys
isVertexCoverOf (Set.empty , Set.empty ) (edge x y) == False
isVertexCoverOf (Set.singleton x, ys ) (edge x y) == Set.isSubsetOf ys (Set.singleton y)
isVertexCoverOf (xs , Set.singleton y) (edge x y) == Set.isSubsetOf xs (Set.singleton x)
The number of vertices in a vertex cover. Complexity: O(1) time.
Find a minimum vertex cover in a bipartite graph. A vertex cover is minimum if it has the smallest possible size. Complexity: O(m * sqrt(n) * log(n)).
minVertexCover empty == (Set.empty, Set.empty)
minVertexCover (vertices xs ys) == (Set.empty, Set.empty)
minVertexCover (path [1,2,3]) == (Set.empty, Set.singleton 2)
minVertexCover (star x (1:2:ys)) == (Set.singleton x, Set.empty)
vertexCoverSize (minVertexCover (biclique xs ys)) == min (length (nub xs)) (length (nub ys))
vertexCoverSize . minVertexCover == matchingSize . maxMatching
isVertexCoverOf (minVertexCover x) x == True
Independent sets
4 declarationsAn independent set of a bipartite graph.
An independent set is a subset of vertices such that no two of them are
adjacent. We represent independent sets by storing two sets of vertices, one
for each part. An equivalent representation, which is slightly less memory
efficient, is Set (Either a b).
Check if a given pair of sets is an independent set of a bipartite graph. Complexity: O(m * log(n)).
isIndependentSetOf (xs , ys ) empty == Set.null xs && Set.null ys
isIndependentSetOf (xs , ys ) (leftVertex x) == Set.isSubsetOf xs (Set.singleton x) && Set.null ys
isIndependentSetOf (Set.empty , Set.empty ) (edge x y) == True
isIndependentSetOf (Set.singleton x, ys ) (edge x y) == Set.null ys
isIndependentSetOf (xs , Set.singleton y) (edge x y) == Set.null xs
The number of vertices in an independent set. Complexity: O(1) time.
Find a maximum independent set in a bipartite graph. An independent set is maximum if it has the largest possible size. Complexity: O(m * sqrt(n) * log(n)).
maxIndependentSet empty == (Set.empty, Set.empty)
maxIndependentSet (vertices xs ys) == (Set.fromList xs, Set.fromList ys)
maxIndependentSet (path [1,2,3]) == (Set.fromList [1,3], Set.empty)
maxIndependentSet (star x (1:2:ys)) == (Set.empty, Set.fromList (1:2:ys))
independentSetSize (maxIndependentSet (biclique xs ys)) == max (length (nub xs)) (length (nub ys))
independentSetSize (maxIndependentSet x) == vertexCount x - vertexCoverSize (minVertexCover x)
isIndependentSetOf (maxIndependentSet x) x == True
Miscellaneous
2 declarationsGiven a matching in a bipartite graph, find either a vertex cover of the same size or an augmenting path with respect to the matching, thereby demonstrating that the matching is not maximum. Complexity: O((m + n) * log(n)).
An alternating path is a path whose edges belong alternately to the matching and not to the matching. An augmenting path is an alternating path that starts from and ends on the vertices that are not covered by the matching. A matching is maximum if and only if there is no augmenting path with respect to it.
augmentingPath (matching []) empty == Left (Set.empty, Set.empty)
augmentingPath (matching []) (edge 1 2) == Right [1,2]
augmentingPath (matching [(1,2)]) (path [1,2,3]) == Left (Set.empty, Set.singleton 2)
augmentingPath (matching [(3,2)]) (path [1,2,3,4]) == Right [1,2,3,4]
isLeft (augmentingPath (maxMatching x) x) == True
Check if the internal representation of a matching is consistent, i.e. that every edge that is present in pairOfLeft is also present in pairOfRight. Complexity: O(S * log(S)), where S is the size of the matching.
consistentMatching (matching xs) == True
consistentMatching (maxMatching x) == True