packages feed

algebraic-graphs 0.0.4 → 0.0.5

raw patch · 26 files changed

+2406/−3215 lines, 26 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Algebra.Graph.AdjacencyMap: data GraphKL a
- Algebra.Graph.AdjacencyMap: fromGraphKL :: Ord a => GraphKL a -> AdjacencyMap a
- Algebra.Graph.AdjacencyMap: getGraph :: GraphKL a -> Graph
- Algebra.Graph.AdjacencyMap: getVertex :: GraphKL a -> Vertex -> a
- Algebra.Graph.AdjacencyMap: graphKL :: Ord a => AdjacencyMap a -> GraphKL a
- Algebra.Graph.AdjacencyMap: postset :: Ord a => a -> AdjacencyMap a -> Set a
- Algebra.Graph.AdjacencyMap.Internal: AdjacencyMap :: Map a (Set a) -> AdjacencyMap a
- Algebra.Graph.AdjacencyMap.Internal: newtype AdjacencyMap a
- Algebra.Graph.IntAdjacencyMap: data GraphKL
- Algebra.Graph.IntAdjacencyMap: fromGraphKL :: GraphKL -> IntAdjacencyMap
- Algebra.Graph.IntAdjacencyMap: getGraph :: GraphKL -> Graph
- Algebra.Graph.IntAdjacencyMap: getVertex :: GraphKL -> Vertex -> Int
- Algebra.Graph.IntAdjacencyMap: graphKL :: IntAdjacencyMap -> GraphKL
- Algebra.Graph.IntAdjacencyMap: postset :: Int -> IntAdjacencyMap -> IntSet
- Algebra.Graph.IntAdjacencyMap: vertexSet :: IntAdjacencyMap -> IntSet
- Algebra.Graph.IntAdjacencyMap.Internal: IntAdjacencyMap :: IntMap IntSet -> IntAdjacencyMap
- Algebra.Graph.IntAdjacencyMap.Internal: newtype IntAdjacencyMap
- Algebra.Graph.Relation: postset :: Ord a => a -> Relation a -> Set a
- Algebra.Graph.Relation: preset :: Ord a => a -> Relation a -> Set a
+ Algebra.Graph.AdjacencyMap: dfs :: [a] -> AdjacencyMap a -> [a]
+ Algebra.Graph.AdjacencyMap: dfsForestFrom :: [a] -> AdjacencyMap a -> Forest a
+ Algebra.Graph.AdjacencyMap: postSet :: Ord a => a -> AdjacencyMap a -> Set a
+ Algebra.Graph.AdjacencyMap: transpose :: Ord a => AdjacencyMap a -> AdjacencyMap a
+ Algebra.Graph.AdjacencyMap.Internal: AM :: !(Map a (Set a)) -> GraphKL a -> AdjacencyMap a
+ Algebra.Graph.AdjacencyMap.Internal: GraphKL :: Graph -> (Vertex -> a) -> (a -> Maybe Vertex) -> GraphKL a
+ Algebra.Graph.AdjacencyMap.Internal: [fromVertexKL] :: GraphKL a -> Vertex -> a
+ Algebra.Graph.AdjacencyMap.Internal: [graphKL] :: AdjacencyMap a -> GraphKL a
+ Algebra.Graph.AdjacencyMap.Internal: [toGraphKL] :: GraphKL a -> Graph
+ Algebra.Graph.AdjacencyMap.Internal: [toVertexKL] :: GraphKL a -> a -> Maybe Vertex
+ Algebra.Graph.AdjacencyMap.Internal: data AdjacencyMap a
+ Algebra.Graph.AdjacencyMap.Internal: data GraphKL a
+ Algebra.Graph.AdjacencyMap.Internal: instance Algebra.Graph.Class.ToGraph (Algebra.Graph.AdjacencyMap.Internal.AdjacencyMap a)
+ Algebra.Graph.AdjacencyMap.Internal: mkAM :: Ord a => Map a (Set a) -> AdjacencyMap a
+ Algebra.Graph.AdjacencyMap.Internal: mkGraphKL :: Ord a => Map a (Set a) -> GraphKL a
+ Algebra.Graph.Export: (<+>) :: (Eq s, IsString s, Monoid s) => Doc s -> Doc s -> Doc s
+ Algebra.Graph.Export: brackets :: IsString s => Doc s -> Doc s
+ Algebra.Graph.Export: data Doc s
+ Algebra.Graph.Export: doubleQuotes :: IsString s => Doc s -> Doc s
+ Algebra.Graph.Export: export :: (Ord a, ToGraph g, ToVertex g ~ a) => (a -> Doc s) -> (a -> a -> Doc s) -> g -> Doc s
+ Algebra.Graph.Export: indent :: IsString s => Int -> Doc s -> Doc s
+ Algebra.Graph.Export: infixl 7 <+>
+ Algebra.Graph.Export: instance (GHC.Base.Monoid s, GHC.Classes.Eq s) => GHC.Classes.Eq (Algebra.Graph.Export.Doc s)
+ Algebra.Graph.Export: instance (GHC.Base.Monoid s, GHC.Classes.Ord s) => GHC.Classes.Ord (Algebra.Graph.Export.Doc s)
+ Algebra.Graph.Export: instance (GHC.Base.Monoid s, GHC.Show.Show s) => GHC.Show.Show (Algebra.Graph.Export.Doc s)
+ Algebra.Graph.Export: instance Data.Semigroup.Semigroup (Algebra.Graph.Export.Doc s)
+ Algebra.Graph.Export: instance Data.String.IsString s => Data.String.IsString (Algebra.Graph.Export.Doc s)
+ Algebra.Graph.Export: instance GHC.Base.Monoid (Algebra.Graph.Export.Doc s)
+ Algebra.Graph.Export: literal :: s -> Doc s
+ Algebra.Graph.Export: render :: Monoid s => Doc s -> s
+ Algebra.Graph.Export: unlines :: IsString s => [Doc s] -> Doc s
+ Algebra.Graph.Export.Dot: (:=) :: s -> s -> Attribute s
+ Algebra.Graph.Export.Dot: Style :: s -> s -> [Attribute s] -> [Attribute s] -> [Attribute s] -> (a -> s) -> (a -> [Attribute s]) -> (a -> a -> [Attribute s]) -> Style a s
+ Algebra.Graph.Export.Dot: [defaultEdgeAttributes] :: Style a s -> [Attribute s]
+ Algebra.Graph.Export.Dot: [defaultVertexAttributes] :: Style a s -> [Attribute s]
+ Algebra.Graph.Export.Dot: [edgeAttributes] :: Style a s -> a -> a -> [Attribute s]
+ Algebra.Graph.Export.Dot: [graphAttributes] :: Style a s -> [Attribute s]
+ Algebra.Graph.Export.Dot: [graphName] :: Style a s -> s
+ Algebra.Graph.Export.Dot: [preamble] :: Style a s -> s
+ Algebra.Graph.Export.Dot: [vertexAttributes] :: Style a s -> a -> [Attribute s]
+ Algebra.Graph.Export.Dot: [vertexName] :: Style a s -> a -> s
+ Algebra.Graph.Export.Dot: data Attribute s
+ Algebra.Graph.Export.Dot: data Style a s
+ Algebra.Graph.Export.Dot: defaultStyle :: Monoid s => (a -> s) -> Style a s
+ Algebra.Graph.Export.Dot: defaultStyleViaShow :: (Show a, IsString s, Monoid s) => Style a s
+ Algebra.Graph.Export.Dot: export :: (IsString s, Monoid s, Eq s, Ord a, ToGraph g, ToVertex g ~ a) => Style a s -> g -> s
+ Algebra.Graph.Export.Dot: exportAsIs :: (IsString s, Monoid s, Ord s, ToGraph g, ToVertex g ~ s) => g -> s
+ Algebra.Graph.Export.Dot: exportViaShow :: (IsString s, Monoid s, Eq s, ToGraph g, Ord (ToVertex g), Show (ToVertex g)) => g -> s
+ Algebra.Graph.HigherKinded.Class: hasEdge :: (Eq (g a), Graph g, Ord a) => a -> a -> g a -> Bool
+ Algebra.Graph.IntAdjacencyMap: dfs :: [Int] -> IntAdjacencyMap -> [Int]
+ Algebra.Graph.IntAdjacencyMap: dfsForestFrom :: [Int] -> IntAdjacencyMap -> Forest Int
+ Algebra.Graph.IntAdjacencyMap: postIntSet :: Int -> IntAdjacencyMap -> IntSet
+ Algebra.Graph.IntAdjacencyMap: transpose :: IntAdjacencyMap -> IntAdjacencyMap
+ Algebra.Graph.IntAdjacencyMap: vertexIntSet :: IntAdjacencyMap -> IntSet
+ Algebra.Graph.IntAdjacencyMap.Internal: AM :: !(IntMap IntSet) -> GraphKL -> IntAdjacencyMap
+ Algebra.Graph.IntAdjacencyMap.Internal: GraphKL :: Graph -> (Vertex -> Int) -> (Int -> Maybe Vertex) -> GraphKL
+ Algebra.Graph.IntAdjacencyMap.Internal: [fromVertexKL] :: GraphKL -> Vertex -> Int
+ Algebra.Graph.IntAdjacencyMap.Internal: [graphKL] :: IntAdjacencyMap -> GraphKL
+ Algebra.Graph.IntAdjacencyMap.Internal: [toGraphKL] :: GraphKL -> Graph
+ Algebra.Graph.IntAdjacencyMap.Internal: [toVertexKL] :: GraphKL -> Int -> Maybe Vertex
+ Algebra.Graph.IntAdjacencyMap.Internal: data GraphKL
+ Algebra.Graph.IntAdjacencyMap.Internal: data IntAdjacencyMap
+ Algebra.Graph.IntAdjacencyMap.Internal: instance Algebra.Graph.Class.ToGraph Algebra.Graph.IntAdjacencyMap.Internal.IntAdjacencyMap
+ Algebra.Graph.IntAdjacencyMap.Internal: mkAM :: IntMap IntSet -> IntAdjacencyMap
+ Algebra.Graph.IntAdjacencyMap.Internal: mkGraphKL :: IntMap IntSet -> GraphKL
+ Algebra.Graph.Relation: postSet :: Ord a => a -> Relation a -> Set a
+ Algebra.Graph.Relation: preSet :: Ord a => a -> Relation a -> Set a
+ Algebra.Graph.Relation.Internal: instance Algebra.Graph.Class.ToGraph (Algebra.Graph.Relation.Internal.Relation a)
- Algebra.Graph: hasEdge :: Eq a => a -> a -> Graph a -> Bool
+ Algebra.Graph: hasEdge :: Ord a => a -> a -> Graph a -> Bool
- Algebra.Graph: mergeVertices :: Eq a => (a -> Bool) -> a -> Graph a -> Graph a
+ Algebra.Graph: mergeVertices :: (a -> Bool) -> a -> Graph a -> Graph a
- Algebra.Graph.AdjacencyMap: adjacencyMap :: AdjacencyMap a -> Map a (Set a)
+ Algebra.Graph.AdjacencyMap: adjacencyMap :: AdjacencyMap a -> (Map a (Set a))
- Algebra.Graph.AdjacencyMap: dfsForest :: Ord a => AdjacencyMap a -> Forest a
+ Algebra.Graph.AdjacencyMap: dfsForest :: AdjacencyMap a -> Forest a
- Algebra.Graph.AdjacencyMap: edgeCount :: Ord a => AdjacencyMap a -> Int
+ Algebra.Graph.AdjacencyMap: edgeCount :: AdjacencyMap a -> Int
- Algebra.Graph.AdjacencyMap: vertexCount :: Ord a => AdjacencyMap a -> Int
+ Algebra.Graph.AdjacencyMap: vertexCount :: AdjacencyMap a -> Int
- Algebra.Graph.AdjacencyMap: vertexList :: Ord a => AdjacencyMap a -> [a]
+ Algebra.Graph.AdjacencyMap: vertexList :: AdjacencyMap a -> [a]
- Algebra.Graph.AdjacencyMap: vertexSet :: Ord a => AdjacencyMap a -> Set a
+ Algebra.Graph.AdjacencyMap: vertexSet :: AdjacencyMap a -> Set a
- Algebra.Graph.AdjacencyMap.Internal: [adjacencyMap] :: AdjacencyMap a -> Map a (Set a)
+ Algebra.Graph.AdjacencyMap.Internal: [adjacencyMap] :: AdjacencyMap a -> !(Map a (Set a))
- Algebra.Graph.Fold: hasEdge :: Eq a => a -> a -> Fold a -> Bool
+ Algebra.Graph.Fold: hasEdge :: Ord a => a -> a -> Fold a -> Bool
- Algebra.Graph.HigherKinded.Class: mergeVertices :: (Eq a, Graph g) => (a -> Bool) -> a -> g a -> g a
+ Algebra.Graph.HigherKinded.Class: mergeVertices :: Graph g => (a -> Bool) -> a -> g a -> g a
- Algebra.Graph.IntAdjacencyMap: adjacencyMap :: IntAdjacencyMap -> IntMap IntSet
+ Algebra.Graph.IntAdjacencyMap: adjacencyMap :: IntAdjacencyMap -> (IntMap IntSet)
- Algebra.Graph.IntAdjacencyMap.Internal: [adjacencyMap] :: IntAdjacencyMap -> IntMap IntSet
+ Algebra.Graph.IntAdjacencyMap.Internal: [adjacencyMap] :: IntAdjacencyMap -> !(IntMap IntSet)
- Algebra.Graph.Relation: edgeCount :: Ord a => Relation a -> Int
+ Algebra.Graph.Relation: edgeCount :: Relation a -> Int
- Algebra.Graph.Relation: edgeList :: Ord a => Relation a -> [(a, a)]
+ Algebra.Graph.Relation: edgeList :: Relation a -> [(a, a)]
- Algebra.Graph.Relation: edgeSet :: Ord a => Relation a -> Set (a, a)
+ Algebra.Graph.Relation: edgeSet :: Relation a -> Set (a, a)
- Algebra.Graph.Relation: gmap :: (Ord a, Ord b) => (a -> b) -> Relation a -> Relation b
+ Algebra.Graph.Relation: gmap :: Ord b => (a -> b) -> Relation a -> Relation b
- Algebra.Graph.Relation: induce :: Ord a => (a -> Bool) -> Relation a -> Relation a
+ Algebra.Graph.Relation: induce :: (a -> Bool) -> Relation a -> Relation a
- Algebra.Graph.Relation: vertexCount :: Ord a => Relation a -> Int
+ Algebra.Graph.Relation: vertexCount :: Relation a -> Int
- Algebra.Graph.Relation: vertexList :: Ord a => Relation a -> [a]
+ Algebra.Graph.Relation: vertexList :: Relation a -> [a]
- Algebra.Graph.Relation: vertexSet :: Ord a => Relation a -> Set a
+ Algebra.Graph.Relation: vertexSet :: Relation a -> Set a

Files

+ CHANGES.md view
@@ -0,0 +1,10 @@+# Change log
+
+## 0.0.5
+
+* Add `dfs`.
+* #19: Move `GraphKL` to an internal module.
+* #18: Add `dfsForestFrom`.
+* #16: Add support for graph export, in particular in DOT format.
+* Make API more consistent, e.g. rename `postset` to `postSet`.
+* Improve documentation and tests.
algebraic-graphs.cabal view
@@ -1,5 +1,5 @@ name:          algebraic-graphs-version:       0.0.4+version:       0.0.5 synopsis:      A library for algebraic graph construction and transformation license:       MIT license-file:  LICENSE@@ -9,7 +9,7 @@ homepage:      https://github.com/snowleopard/alga category:      Algebra, Algorithms, Data Structures, Graphs build-type:    Simple-cabal-version: >=1.10+cabal-version: >=1.18 tested-with:   GHC==8.0.2 stability:     experimental description:@@ -41,6 +41,7 @@     <https://github.com/snowleopard/alga/issues discussions on the library API>.  extra-doc-files:+    CHANGES.md     README.md  source-repository head@@ -53,6 +54,8 @@                         Algebra.Graph.AdjacencyMap,                         Algebra.Graph.AdjacencyMap.Internal,                         Algebra.Graph.Class,+                        Algebra.Graph.Export,+                        Algebra.Graph.Export.Dot,                         Algebra.Graph.Fold,                         Algebra.Graph.HigherKinded.Class,                         Algebra.Graph.IntAdjacencyMap,@@ -77,16 +80,24 @@                         DeriveFunctor                         DeriveTraversable                         OverloadedStrings-    GHC-options:        -Wall -fwarn-tabs+                        RecordWildCards+    GHC-options:        -Wall+                        -Wcompat+                        -Wincomplete-record-updates+                        -Wincomplete-uni-patterns+                        -Wredundant-constraints  test-suite test-alga     hs-source-dirs:     test     type:               exitcode-stdio-1.0     main-is:            Main.hs     other-modules:      Algebra.Graph.Test,+                        Algebra.Graph.Test.API,                         Algebra.Graph.Test.AdjacencyMap,                         Algebra.Graph.Test.Arbitrary,+                        Algebra.Graph.Test.Export,                         Algebra.Graph.Test.Fold,+                        Algebra.Graph.Test.Generic,                         Algebra.Graph.Test.Graph,                         Algebra.Graph.Test.IntAdjacencyMap,                         Algebra.Graph.Test.Relation@@ -96,12 +107,19 @@                         extra      >= 1.5,                         QuickCheck >= 2.9     default-language:   Haskell2010-    GHC-options:        -O2 -Wall -fwarn-tabs+    GHC-options:        -O2+                        -Wall+                        -Wcompat+                        -Wincomplete-record-updates+                        -Wincomplete-uni-patterns+                        -Wredundant-constraints     default-extensions: FlexibleContexts                         GeneralizedNewtypeDeriving                         TypeFamilies                         ScopedTypeVariables-    other-extensions:   RankNTypes+    other-extensions:   ConstrainedClassMethods+                        ConstraintKinds+                        RankNTypes                         ViewPatterns  benchmark benchmark-alga@@ -113,7 +131,12 @@                         containers >= 0.5,                         criterion  >= 1.1     default-language:   Haskell2010-    GHC-options:        -O2 -Wall -fwarn-tabs+    GHC-options:        -O2+                        -Wall+                        -Wcompat+                        -Wincomplete-record-updates+                        -Wincomplete-uni-patterns+                        -Wredundant-constraints     default-extensions: FlexibleContexts                         TypeFamilies                         ScopedTypeVariables
src/Algebra/Graph.hs view
@@ -433,9 +433,10 @@ -- hasEdge x y ('vertex' z)       == False -- hasEdge x y ('edge' x y)       == True -- hasEdge x y . 'removeEdge' x y == const False+-- hasEdge x y                  == 'elem' (x,y) . 'edgeList' -- @-hasEdge :: Eq a => a -> a -> Graph a -> Bool-hasEdge s t g = not $ intact st where (_, _, st) = smash s t g+hasEdge :: Ord a => a -> a -> Graph a -> Bool+hasEdge = H.hasEdge  -- | The number of vertices in a graph. -- Complexity: /O(s * log(n))/ time.@@ -555,11 +556,12 @@ -- given list. -- -- @--- clique []        == 'empty'--- clique [x]       == 'vertex' x--- clique [x,y]     == 'edge' x y--- clique [x,y,z]   == 'edges' [(x,y), (x,z), (y,z)]--- clique . 'reverse' == 'transpose' . clique+-- 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 . 'reverse'  == 'transpose' . clique -- @ clique :: [a] -> Graph a clique = H.clique@@ -653,13 +655,14 @@ -- -- @ --           deBruijn 0 xs               == 'edge' [] []--- n > 0 'Test.QuickCheck.==>' deBruijn n []               == 'empty'+-- n > 0 ==> deBruijn n []               == 'empty' --           deBruijn 1 [0,1]            == 'edges' [ ([0],[0]), ([0],[1]), ([1],[0]), ([1],[1]) ] --           deBruijn 2 "0"              == 'edge' "00" "00" --           deBruijn 2 "01"             == 'edges' [ ("00","00"), ("00","01"), ("01","10"), ("01","11") --                                                , ("10","00"), ("10","01"), ("11","10"), ("11","11") ]+--           'transpose'   (deBruijn n xs) == 'fmap' 'reverse' $ deBruijn n xs --           'vertexCount' (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^n--- n > 0 'Test.QuickCheck.==>' 'edgeCount'   (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^(n + 1)+-- n > 0 ==> 'edgeCount'   (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^(n + 1) -- @ deBruijn :: Int -> [a] -> Graph [a] deBruijn = H.deBruijn@@ -675,7 +678,8 @@ removeVertex = H.removeVertex  -- | Remove an edge from a given graph.--- Complexity: /O(s)/ time and memory.+-- Complexity: /O(s)/ time and memory. The worst case size complexity is /O(s^2)/,+-- although in practice it is usually also linear /O(s)/. -- -- @ -- removeEdge x y ('edge' x y)       == 'vertices' [x, y]@@ -737,7 +741,7 @@ -- mergeVertices even 1 (0 * 2)     == 1 * 1 -- mergeVertices odd  1 (3 + 4 * 5) == 4 * 1 -- @-mergeVertices :: Eq a => (a -> Bool) -> a -> Graph a -> Graph a+mergeVertices :: (a -> Bool) -> a -> Graph a -> Graph a mergeVertices = H.mergeVertices  -- | Split a vertex into a list of vertices with the same connectivity.
src/Algebra/Graph/AdjacencyMap.hs view
@@ -29,23 +29,20 @@      -- * Graph properties     isEmpty, hasVertex, hasEdge, vertexCount, edgeCount, vertexList, edgeList,-    adjacencyList, vertexSet, edgeSet, postset,+    adjacencyList, vertexSet, edgeSet, postSet,      -- * Standard families of graphs     path, circuit, clique, biclique, star, tree, forest,      -- * Graph transformation-    removeVertex, removeEdge, replaceVertex, mergeVertices, gmap, induce,+    removeVertex, removeEdge, replaceVertex, mergeVertices, transpose, gmap, induce,      -- * Algorithms-    dfsForest, topSort, isTopSort, scc,--    -- * Interoperability with King-Launchbury graphs-    GraphKL, getGraph, getVertex, graphKL, fromGraphKL+    dfsForest, dfsForestFrom, dfs, topSort, isTopSort, scc   ) where -import Data.Array import Data.Foldable (toList)+import Data.Maybe import Data.Set (Set) import Data.Tree @@ -144,7 +141,7 @@ -- 'vertexSet'   . vertices == Set.'Set.fromList' -- @ vertices :: Ord a => [a] -> AdjacencyMap a-vertices = AdjacencyMap . Map.fromList . map (\x -> (x, Set.empty))+vertices = mkAM . Map.fromList . map (\x -> (x, Set.empty))  -- | Construct the graph from a list of edges. -- Complexity: /O((n + m) * log(n))/ time and /O(n + m)/ memory.@@ -207,7 +204,7 @@ -- 'overlay' (fromAdjacencyList xs) (fromAdjacencyList ys) == fromAdjacencyList (xs ++ ys) -- @ fromAdjacencyList :: Ord a => [(a, [a])] -> AdjacencyMap a-fromAdjacencyList as = AdjacencyMap $ Map.unionWith Set.union vs es+fromAdjacencyList as = mkAM $ Map.unionWith Set.union vs es   where     ss = map (fmap Set.fromList) as     vs = Map.fromSet (const Set.empty) . Set.unions $ map snd ss@@ -259,6 +256,7 @@ -- hasEdge x y ('vertex' z)       == False -- hasEdge x y ('edge' x y)       == True -- hasEdge x y . 'removeEdge' x y == const False+-- hasEdge x y                  == 'elem' (x,y) . 'edgeList' -- @ hasEdge :: Ord a => a -> a -> AdjacencyMap a -> Bool hasEdge u v a = case Map.lookup u (adjacencyMap a) of@@ -273,7 +271,7 @@ -- vertexCount ('vertex' x) == 1 -- vertexCount            == 'length' . 'vertexList' -- @-vertexCount :: Ord a => AdjacencyMap a -> Int+vertexCount :: AdjacencyMap a -> Int vertexCount = Map.size . adjacencyMap  -- | The number of edges in a graph.@@ -285,7 +283,7 @@ -- edgeCount ('edge' x y) == 1 -- edgeCount            == 'length' . 'edgeList' -- @-edgeCount :: Ord a => AdjacencyMap a -> Int+edgeCount :: AdjacencyMap a -> Int edgeCount = Map.foldr (\es r -> (Set.size es + r)) 0 . adjacencyMap  -- | The sorted list of vertices of a given graph.@@ -296,7 +294,7 @@ -- vertexList ('vertex' x) == [x] -- vertexList . 'vertices' == 'Data.List.nub' . 'Data.List.sort' -- @-vertexList :: Ord a => AdjacencyMap a -> [a]+vertexList :: AdjacencyMap a -> [a] vertexList = Map.keys . adjacencyMap  -- | The sorted list of edges of a graph.@@ -308,9 +306,10 @@ -- edgeList ('edge' x y)     == [(x,y)] -- edgeList ('star' 2 [3,1]) == [(2,1), (2,3)] -- edgeList . 'edges'        == 'Data.List.nub' . 'Data.List.sort'+-- edgeList . 'transpose'    == 'Data.List.sort' . map 'Data.Tuple.swap' . edgeList -- @ edgeList :: AdjacencyMap a -> [(a, a)]-edgeList (AdjacencyMap m) = [ (x, y) | (x, ys) <- Map.toAscList m, y <- Set.toAscList ys ]+edgeList (AM m _) = [ (x, y) | (x, ys) <- Map.toAscList m, y <- Set.toAscList ys ]  -- | The sorted /adjacency list/ of a graph. -- Complexity: /O(n + m)/ time and /O(m)/ memory.@@ -334,7 +333,7 @@ -- vertexSet . 'vertices' == Set.'Set.fromList' -- vertexSet . 'clique'   == Set.'Set.fromList' -- @-vertexSet :: Ord a => AdjacencyMap a -> Set a+vertexSet :: AdjacencyMap a -> Set a vertexSet = Map.keysSet . adjacencyMap  -- | The set of edges of a given graph.@@ -352,21 +351,22 @@ -- | The /postset/ of a vertex is the set of its /direct successors/. -- -- @--- postset x 'empty'      == Set.'Set.empty'--- postset x ('vertex' x) == Set.'Set.empty'--- postset x ('edge' x y) == Set.'Set.fromList' [y]--- postset 2 ('edge' 1 2) == Set.'Set.empty'+-- postSet x 'empty'      == Set.'Set.empty'+-- postSet x ('vertex' x) == Set.'Set.empty'+-- postSet x ('edge' x y) == Set.'Set.fromList' [y]+-- postSet 2 ('edge' 1 2) == Set.'Set.empty' -- @-postset :: Ord a => a -> AdjacencyMap a -> Set a-postset x = Map.findWithDefault Set.empty x . adjacencyMap+postSet :: Ord a => a -> AdjacencyMap a -> Set a+postSet x = Map.findWithDefault Set.empty x . adjacencyMap  -- | 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 []        == 'empty'+-- path [x]       == 'vertex' x+-- path [x,y]     == 'edge' x y+-- path . 'reverse' == 'transpose' . path -- @ path :: Ord a => [a] -> AdjacencyMap a path = C.path@@ -375,9 +375,10 @@ -- Complexity: /O((n + m) * log(n))/ time and /O(n + m)/ memory. -- -- @--- circuit []    == 'empty'--- circuit [x]   == 'edge' x x--- circuit [x,y] == 'edges' [(x,y), (y,x)]+-- circuit []        == 'empty'+-- circuit [x]       == 'edge' x x+-- circuit [x,y]     == 'edges' [(x,y), (y,x)]+-- circuit . 'reverse' == 'transpose' . circuit -- @ circuit :: Ord a => [a] -> AdjacencyMap a circuit = C.circuit@@ -386,10 +387,12 @@ -- 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 []         == '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 . 'reverse'  == 'transpose' . clique -- @ clique :: Ord a => [a] -> AdjacencyMap a clique = C.clique@@ -405,7 +408,7 @@ -- biclique xs      ys      == 'connect' ('vertices' xs) ('vertices' ys) -- @ biclique :: Ord a => [a] -> [a] -> AdjacencyMap a-biclique xs ys = AdjacencyMap $ Map.fromSet adjacent (x `Set.union` y)+biclique xs ys = mkAM $ Map.fromSet adjacent (x `Set.union` y)   where     x = Set.fromList xs     y = Set.fromList ys@@ -456,7 +459,7 @@ -- removeVertex x . removeVertex x == removeVertex x -- @ removeVertex :: Ord a => a -> AdjacencyMap a -> AdjacencyMap a-removeVertex x = AdjacencyMap . Map.map (Set.delete x) . Map.delete x . adjacencyMap+removeVertex x = mkAM . Map.map (Set.delete x) . Map.delete x . adjacencyMap  -- | Remove an edge from a given graph. -- Complexity: /O(log(n))/ time.@@ -469,7 +472,7 @@ -- removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2 -- @ removeEdge :: Ord a => a -> a -> AdjacencyMap a -> AdjacencyMap a-removeEdge x y = AdjacencyMap . Map.adjust (Set.delete y) x . adjacencyMap+removeEdge x y = mkAM . Map.adjust (Set.delete y) x . adjacencyMap  -- | The function @'replaceVertex' x y@ replaces vertex @x@ with vertex @y@ in a -- given 'AdjacencyMap'. If @y@ already exists, @x@ and @y@ will be merged.@@ -496,6 +499,25 @@ mergeVertices :: Ord a => (a -> Bool) -> a -> AdjacencyMap a -> AdjacencyMap a mergeVertices p v = gmap $ \u -> if p u then v else u +-- | Transpose a given graph.+-- Complexity: /O(m * log(n))/ time, /O(n + m)/ memory.+--+-- @+-- transpose 'empty'       == 'empty'+-- transpose ('vertex' x)  == 'vertex' x+-- transpose ('edge' x y)  == 'edge' y x+-- transpose . transpose == id+-- transpose . 'path'      == 'path'    . 'reverse'+-- transpose . 'circuit'   == 'circuit' . 'reverse'+-- transpose . 'clique'    == 'clique'  . 'reverse'+-- 'edgeList' . transpose  == 'Data.List.sort' . map 'Data.Tuple.swap' . 'edgeList'+-- @+transpose :: Ord a => AdjacencyMap a -> AdjacencyMap a+transpose (AM m _) = mkAM $ Map.foldrWithKey combine vs m+  where+    combine v es = Map.unionWith Set.union (Map.fromSet (const $ Set.singleton v) es)+    vs           = Map.fromSet (const Set.empty) (Map.keysSet m)+ -- | 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 -- 'AdjacencyMap'.@@ -509,7 +531,7 @@ -- gmap f . gmap g   == gmap (f . g) -- @ gmap :: (Ord a, Ord b) => (a -> b) -> AdjacencyMap a -> AdjacencyMap b-gmap f = AdjacencyMap . Map.map (Set.map f) . Map.mapKeysWith Set.union f . adjacencyMap+gmap f = mkAM . Map.map (Set.map f) . Map.mapKeysWith Set.union f . adjacencyMap  -- | Construct the /induced subgraph/ of a given graph by removing the -- vertices that do not satisfy a given predicate.@@ -524,7 +546,7 @@ -- 'isSubgraphOf' (induce p x) x == True -- @ induce :: Ord a => (a -> Bool) -> AdjacencyMap a -> AdjacencyMap a-induce p = AdjacencyMap . Map.map (Set.filter p) . Map.filterWithKey (\k _ -> p k) . adjacencyMap+induce p = mkAM . Map.map (Set.filter p) . Map.filterWithKey (\k _ -> p k) . adjacencyMap  -- | Compute the /depth-first search/ forest of a graph. --@@ -534,6 +556,8 @@ -- 'forest' (dfsForest $ 'edge' 2 1)         == 'vertices' [1, 2] -- 'isSubgraphOf' ('forest' $ dfsForest x) x == True -- dfsForest . 'forest' . dfsForest        == dfsForest+-- dfsForest ('vertices' vs)               == map (\\v -> Node v []) ('Data.List.nub' $ 'Data.List.sort' vs)+-- 'dfsForestFrom' ('vertexList' x) x        == dfsForest x -- dfsForest $ 3 * (1 + 4) * (1 + 5)     == [ Node { rootLabel = 1 --                                                 , subForest = [ Node { rootLabel = 5 --                                                                      , subForest = [] }]}@@ -541,9 +565,49 @@ --                                                 , subForest = [ Node { rootLabel = 4 --                                                                      , subForest = [] }]}] -- @-dfsForest :: Ord a => AdjacencyMap a -> Forest a-dfsForest m = let GraphKL g r = graphKL m in fmap (fmap r) (KL.dff g)+dfsForest :: AdjacencyMap a -> Forest a+dfsForest (AM _ (GraphKL g r _)) = fmap (fmap r) (KL.dff g) +-- | Compute the /depth-first search/ forest of a graph, searching from each of+-- the given vertices in order. Note that the resulting forest does not+-- necessarily span the whole graph, as some vertices may be unreachable.+--+-- @+-- 'forest' (dfsForestFrom [1]    $ 'edge' 1 1)     == 'vertex' 1+-- 'forest' (dfsForestFrom [1]    $ 'edge' 1 2)     == 'edge' 1 2+-- 'forest' (dfsForestFrom [2]    $ 'edge' 1 2)     == 'vertex' 2+-- 'forest' (dfsForestFrom [3]    $ 'edge' 1 2)     == 'empty'+-- 'forest' (dfsForestFrom [2, 1] $ 'edge' 1 2)     == 'vertices' [1, 2]+-- 'isSubgraphOf' ('forest' $ dfsForestFrom vs x) x == True+-- dfsForestFrom ('vertexList' x) x               == 'dfsForest' x+-- dfsForestFrom vs             ('vertices' vs)   == map (\\v -> Node v []) ('Data.List.nub' vs)+-- dfsForestFrom []             x               == []+-- dfsForestFrom [1, 4] $ 3 * (1 + 4) * (1 + 5) == [ Node { rootLabel = 1+--                                                        , subForest = [ Node { rootLabel = 5+--                                                                             , subForest = [] }+--                                                 , Node { rootLabel = 4+--                                                        , subForest = [] }]+-- @+dfsForestFrom :: [a] -> AdjacencyMap a -> Forest a+dfsForestFrom vs (AM _ (GraphKL g r t)) = fmap (fmap r) (KL.dfs g (mapMaybe t vs))++-- | Compute the list of vertices visited by the /depth-first search/ in a graph,+-- when searching from each of the given vertices in order.+--+-- @+-- dfs [1]    $ 'edge' 1 1                == [1]+-- dfs [1]    $ 'edge' 1 2                == [1, 2]+-- dfs [2]    $ 'edge' 1 2                == [2]+-- dfs [3]    $ 'edge' 1 2                == []+-- dfs [1, 2] $ 'edge' 1 2                == [1, 2]+-- dfs [2, 1] $ 'edge' 1 2                == [2, 1]+-- dfs []     $ x                       == []+-- dfs [1, 4] $ 3 * (1 + 4) * (1 + 5)   == [1, 5, 4]+-- 'isSubgraphOf' ('vertices' $ dfs vs x) x == True+-- @+dfs :: [a] -> AdjacencyMap a -> [a]+dfs vs = concatMap flatten . dfsForestFrom vs+ -- | Compute the /topological sort/ of a graph or return @Nothing@ if the graph -- is cyclic. --@@ -553,10 +617,10 @@ -- fmap (flip 'isTopSort' x) (topSort x) /= Just False -- @ topSort :: Ord a => AdjacencyMap a -> Maybe [a]-topSort m = if isTopSort result m then Just result else Nothing+topSort m@(AM _ (GraphKL g r _)) =+    if isTopSort result m then Just result else Nothing   where-    GraphKL g r = graphKL m-    result      = map r (KL.topSort g)+    result = map r (KL.topSort g)  -- | Check if a given list of vertices is a valid /topological sort/ of a graph. --@@ -573,7 +637,7 @@   where     go seen []     = seen == Map.keysSet (adjacencyMap m)     go seen (v:vs) = let newSeen = seen `seq` Set.insert v seen-        in postset v m `Set.intersection` newSeen == Set.empty && go newSeen vs+        in postSet v m `Set.intersection` newSeen == Set.empty && go newSeen vs  -- | Compute the /condensation/ of a graph, where each vertex corresponds to a -- /strongly-connected component/ of the original graph.@@ -589,40 +653,8 @@ --                                  , (Set.'Set.fromList' [3]  , Set.'Set.fromList' [5]  )] -- @ scc :: Ord a => AdjacencyMap a -> AdjacencyMap (Set a)-scc m = gmap (\v -> Map.findWithDefault Set.empty v components) m-  where-    GraphKL g r = graphKL m-    components  = Map.fromList $ concatMap (expand . fmap r . toList) (KL.scc g)-    expand xs   = let s = Set.fromList xs in map (\x -> (x, s)) xs---- | 'GraphKL' encapsulates King-Launchbury graphs, which are implemented in--- the "Data.Graph" module of the @containers@ library. If @graphKL g == h@ then--- the following holds:------ @--- map ('getVertex' h) ('Data.Graph.vertices' $ 'getGraph' h)                            == Set.'Set.toAscList' ('vertexSet' g)--- map (\\(x, y) -> ('getVertex' h x, 'getVertex' h y)) ('Data.Graph.edges' $ 'getGraph' h) == 'edgeList' g--- @-data GraphKL a = GraphKL {-    -- | Array-based graph representation (King and Launchbury, 1995).-    getGraph :: KL.Graph,-    -- | A mapping of "Data.Graph.Vertex" to vertices of type @a@.-    getVertex :: KL.Vertex -> a }---- | Build 'GraphKL' from the adjacency map of a graph.------ @--- 'fromGraphKL' . graphKL == id--- @-graphKL :: Ord a => AdjacencyMap a -> GraphKL a-graphKL m = GraphKL g $ \u -> case r u of (_, v, _) -> v+scc m@(AM _ (GraphKL g r _)) =+    gmap (\v -> Map.findWithDefault Set.empty v components) m   where-    (g, r) = KL.graphFromEdges' [ ((), v, us) | (v, us) <- adjacencyList m ]---- | Extract the adjacency map of a King-Launchbury graph.------ @--- fromGraphKL . 'graphKL' == id--- @-fromGraphKL :: Ord a => GraphKL a -> AdjacencyMap a-fromGraphKL (GraphKL g r) = fromAdjacencyList $ map (\(x, ys) -> (r x, map r ys)) (assocs g)+    components = Map.fromList $ concatMap (expand . fmap r . toList) (KL.scc g)+    expand xs  = let s = Set.fromList xs in map (\x -> (x, s)) xs
src/Algebra/Graph/AdjacencyMap/Internal.hs view
@@ -12,7 +12,10 @@ ----------------------------------------------------------------------------- module Algebra.Graph.AdjacencyMap.Internal (     -- * Adjacency map implementation-    AdjacencyMap (..), consistent+    AdjacencyMap (..), mkAM, consistent,++    -- * Interoperability with King-Launchbury graphs+    GraphKL (..), mkGraphKL   ) where  import Data.Map.Strict (Map, keysSet, fromSet)@@ -20,6 +23,7 @@  import Algebra.Graph.Class +import qualified Data.Graph      as KL import qualified Data.Map.Strict as Map import qualified Data.Set        as Set @@ -83,14 +87,25 @@ When specifying the time and memory complexity of graph algorithms, /n/ and /m/ will denote the number of vertices and edges in the graph, respectively. -}-newtype AdjacencyMap a = AdjacencyMap {+data AdjacencyMap a = AM {     -- | The /adjacency map/ of the graph: each vertex is associated with a set     -- of its direct successors.-    adjacencyMap :: Map a (Set a)-  } deriving Eq+    adjacencyMap :: !(Map a (Set a)),+    -- | Cached King-Launchbury representation.+    -- /Note: this field is for internal use only/.+    graphKL :: GraphKL a } +-- | Construct an 'AdjacencyMap' from a map of successor sets and (lazily)+-- compute the corresponding King-Launchbury representation.+-- /Note: this function is for internal use only/.+mkAM :: Ord a => Map a (Set a) -> AdjacencyMap a+mkAM m = AM m (mkGraphKL m)++instance Eq a => Eq (AdjacencyMap a) where+    x == y = adjacencyMap x == adjacencyMap y+ instance (Ord a, Show a) => Show (AdjacencyMap a) where-    show (AdjacencyMap m)+    show (AM m _)         | m == Map.empty = "empty"         | es == []       = if Set.size vs > 1 then "vertices " ++ show (Set.toAscList vs)                                               else "vertex "   ++ show v@@ -106,10 +121,10 @@  instance Ord a => Graph (AdjacencyMap a) where     type Vertex (AdjacencyMap a) = a-    empty       = AdjacencyMap $ Map.empty-    vertex x    = AdjacencyMap $ Map.singleton x Set.empty-    overlay x y = AdjacencyMap $ Map.unionWith Set.union (adjacencyMap x) (adjacencyMap y)-    connect x y = AdjacencyMap $ Map.unionsWith Set.union [ adjacencyMap x, adjacencyMap y,+    empty       = mkAM $ Map.empty+    vertex x    = mkAM $ Map.singleton x Set.empty+    overlay x y = mkAM $ Map.unionWith Set.union (adjacencyMap x) (adjacencyMap y)+    connect x y = mkAM $ Map.unionsWith Set.union [ adjacencyMap x, adjacencyMap y,         fromSet (const . keysSet $ adjacencyMap y) (keysSet $ adjacencyMap x) ]  instance (Ord a, Num a) => Num (AdjacencyMap a) where@@ -120,6 +135,10 @@     abs         = id     negate      = id +instance ToGraph (AdjacencyMap a) where+    type ToVertex (AdjacencyMap a) = a+    toGraph = overlays . map (uncurry star . fmap Set.toList) . Map.toList . adjacencyMap+ -- | Check if the internal graph representation is consistent, i.e. that all -- edges refer to existing vertices. It should be impossible to create an -- inconsistent adjacency map, and we use this function in testing.@@ -136,7 +155,7 @@ -- consistent ('Algebra.Graph.AdjacencyMap.fromAdjacencyList' xs) == True -- @ consistent :: Ord a => AdjacencyMap a -> Bool-consistent (AdjacencyMap m) = referredToVertexSet m `Set.isSubsetOf` keysSet m+consistent (AM m _) = referredToVertexSet m `Set.isSubsetOf` keysSet m  -- The set of vertices that are referred to by the edges referredToVertexSet :: Ord a => Map a (Set a) -> Set a@@ -145,3 +164,32 @@ -- The list of edges in adjacency map internalEdgeList :: Map a (Set a) -> [(a, a)] internalEdgeList m = [ (x, y) | (x, ys) <- Map.toAscList m, y <- Set.toAscList ys ]++-- | 'GraphKL' encapsulates King-Launchbury graphs, which are implemented in+-- the "Data.Graph" module of the @containers@ library.+-- /Note: this data structure is for internal use only/.+--+-- If @mkGraphKL (adjacencyMap g) == h@ then the following holds:+--+-- @+-- map ('fromVertexKL' h) ('Data.Graph.vertices' $ 'toGraphKL' h)                               == 'Algebra.Graph.AdjacencyMap.vertexList' g+-- map (\\(x, y) -> ('fromVertexKL' h x, 'fromVertexKL' h y)) ('Data.Graph.edges' $ 'toGraphKL' h) == 'Algebra.Graph.AdjacencyMap.edgeList' g+-- @+data GraphKL a = GraphKL {+    -- | Array-based graph representation (King and Launchbury, 1995).+    toGraphKL :: KL.Graph,+    -- | A mapping of "Data.Graph.Vertex" to vertices of type @a@.+    fromVertexKL :: KL.Vertex -> a,+    -- | A mapping from vertices of type @a@ to "Data.Graph.Vertex".+    -- Returns 'Nothing' if the argument is not in the graph.+    toVertexKL :: a -> Maybe KL.Vertex }++-- | Build 'GraphKL' from a map of successor sets.+-- /Note: this function is for internal use only/.+mkGraphKL :: Ord a => Map a (Set a) -> GraphKL a+mkGraphKL m = GraphKL+    { toGraphKL    = g+    , fromVertexKL = \u -> case r u of (_, v, _) -> v+    , toVertexKL   = t }+  where+    (g, r, t) = KL.graphFromEdges [ ((), v, Set.toAscList us) | (v, us) <- Map.toAscList m ]
src/Algebra/Graph/Class.hs view
@@ -333,10 +333,11 @@ -- given list. -- -- @--- clique []      == 'empty'--- clique [x]     == 'vertex' x--- clique [x,y]   == 'edge' x y--- clique [x,y,z] == 'edges' [(x,y), (x,z), (y,z)]+-- 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 :: Graph g => [Vertex g] -> g clique = connects . map vertex
+ src/Algebra/Graph/Export.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module     : Algebra.Graph.Export+-- Copyright  : (c) Andrey Mokhov 2016-2017+-- License    : MIT (see the file LICENSE)+-- Maintainer : andrey.mokhov@gmail.com+-- Stability  : experimental+--+-- __Alga__ is a library for algebraic construction and manipulation of graphs+-- in Haskell. See <https://github.com/snowleopard/alga-paper this paper> for the+-- motivation behind the library, the underlying theory, and implementation details.+--+-- This module defines basic data types and functions for exporting graphs in+-- textual and binary formats. "Algebra.Graph.Export.Dot" provides DOT-specific+-- functionality.+-----------------------------------------------------------------------------+module Algebra.Graph.Export (+    -- * Constructing and exporting documents+    Doc, literal, render,++    -- * Common combinators for text documents+    (<+>), brackets, doubleQuotes, indent, unlines,++    -- * Generic graph export+    export+  ) where++import Data.Semigroup+import Data.String hiding (unlines)+import Prelude hiding (unlines)++import Algebra.Graph.AdjacencyMap+import Algebra.Graph.Class (ToGraph (..))++-- | An abstract document type, where @s@ is the type of strings or words (text+-- or binary). 'Doc' @s@ is a 'Monoid', therefore 'mempty' corresponds to the+-- empty document and two documents can be concatenated with 'mappend' (or+-- operator 'Data.Monoid.<>'). Note that most functions on 'Doc' @s@ require+-- that the underlying type @s@ is also a 'Monoid'.+newtype Doc s = Doc (Endo [s]) deriving (Monoid, Semigroup)++instance (Monoid s, Show s) => Show (Doc s) where+    show = show . render++instance (Monoid s, Eq s) => Eq (Doc s) where+    x == y = render x == render y++instance (Monoid s, Ord s) => Ord (Doc s) where+    compare x y = compare (render x) (render y)++instance IsString s => IsString (Doc s) where+    fromString = literal . fromString++-- | Construct a document comprising a single string or word. If @s@ is an+-- instance of class 'IsString', then documents of type 'Doc' @s@ can be+-- constructed directly from string literals (see the second example below).+--+-- @+-- literal "Hello, " <> literal "World!" == literal "Hello, World!"+-- literal "I am just a string literal"  == "I am just a string literal"+-- literal 'mempty'                        == 'mempty'+-- 'render' . literal                      == 'id'+-- literal . 'render'                      == 'id'+-- @+literal :: s -> Doc s+literal = Doc . Endo . (:)++-- | Render a document as a single string or word. An inverse of the function+-- 'literal'.+--+-- @+-- render ('literal' "al" <> 'literal' "ga") :: ('IsString' s, 'Monoid' s) => s+-- render ('literal' "al" <> 'literal' "ga") == "alga"+-- render 'mempty'                         == 'mempty'+-- render . 'literal'                      == 'id'+-- 'literal' . render                      == 'id'+-- @+render :: Monoid s => Doc s -> s+render (Doc x) = mconcat $ appEndo x []++-- | Concatenate two documents, separated by a single space, unless one of the+-- documents is empty. The operator \<+\> is associative with identity 'mempty'.+--+-- @+-- x \<+\> 'mempty'         == x+-- 'mempty' \<+\> x         == x+-- x \<+\> (y \<+\> z)      == (x \<+\> y) \<+\> z+-- "name" \<+\> "surname" == "name surname"+-- @+(<+>) :: (Eq s, IsString s, Monoid s) => Doc s -> Doc s -> Doc s+x <+> y | x == mempty = y+        | y == mempty = x+        | otherwise   = x <> " " <> y++infixl 7 <+>++-- | Wrap a document in square brackets.+--+-- @+-- brackets "i"    == "[i]"+-- brackets 'mempty' == "[]"+-- @+brackets :: IsString s => Doc s -> Doc s+brackets x = "[" <> x <> "]"++-- | Wrap a document into double quotes.+--+-- @+-- doubleQuotes "\/path\/with spaces"   == "\\"\/path\/with spaces\\""+-- doubleQuotes (doubleQuotes 'mempty') == "\\"\\"\\"\\""+-- @+doubleQuotes :: IsString s => Doc s -> Doc s+doubleQuotes x = "\"" <> x <> "\""++-- | Prepend a given number of spaces to a document.+--+-- @+-- indent 0        == 'id'+-- indent 1 'mempty' == " "+-- @+indent :: IsString s => Int -> Doc s -> Doc s+indent spaces x = fromString (replicate spaces ' ') <> x++-- | Concatenate documents after appending a terminating newline symbol to each.+--+-- @+-- unlines []                    == 'mempty'+-- unlines ['mempty']              == "\\n"+-- unlines ["title", "subtitle"] == "title\\nsubtitle\\n"+-- @+unlines :: IsString s => [Doc s] -> Doc s+unlines []     = mempty+unlines (x:xs) = x <> "\n" <> unlines xs++-- TODO: Avoid round-trip graph conversion if g :: AdjacencyMap a.+-- | Export a graph into a document given two functions that construct documents+-- for individual vertices and edges. The order of export is: vertices, sorted+-- by 'Ord' @a@, and then edges, sorted by 'Ord' @(a, a)@.+--+-- For example:+--+-- @+-- vDoc x   = 'literal' ('show' x) <> "\\n"+-- eDoc x y = 'literal' ('show' x) <> " -> " <> 'literal' ('show' y) <> "\\n"+-- > putStrLn $ 'render' $ export vDoc eDoc (1 + 2 * (3 + 4) :: 'Algebra.Graph.Graph' Int)+--+-- 1+-- 2+-- 3+-- 4+-- 2 -> 3+-- 2 -> 4+-- @+export :: (Ord a, ToGraph g, ToVertex g ~ a) => (a -> Doc s) -> (a -> a -> Doc s) -> g -> Doc s+export vs es g = vDoc <> eDoc+  where+    vDoc   = mconcat $ map (vs        ) (vertexList adjMap)+    eDoc   = mconcat $ map (uncurry es) (edgeList   adjMap)+    adjMap = toGraph g
+ src/Algebra/Graph/Export/Dot.hs view
@@ -0,0 +1,174 @@+{-# LANGUAGE OverloadedStrings, RecordWildCards #-}+-----------------------------------------------------------------------------+-- |+-- Module     : Algebra.Graph.Export.Dot+-- Copyright  : (c) Andrey Mokhov 2016-2017+-- License    : MIT (see the file LICENSE)+-- Maintainer : andrey.mokhov@gmail.com+-- Stability  : experimental+--+-- __Alga__ is a library for algebraic construction and manipulation of graphs+-- in Haskell. See <https://github.com/snowleopard/alga-paper this paper> for the+-- motivation behind the library, the underlying theory, and implementation details.+--+-- This module defines functions for exporting graphs in the DOT file format.+-----------------------------------------------------------------------------+module Algebra.Graph.Export.Dot (+    -- * Graph attributes and style+    Attribute (..), Style (..), defaultStyle, defaultStyleViaShow,++    -- * Export functions+    export, exportAsIs, exportViaShow+  ) where++import Data.List hiding (unlines)+import Data.Monoid+import Data.String hiding (unlines)+import Prelude hiding (unlines)++import Algebra.Graph.Class (ToGraph (..))+import Algebra.Graph.Export hiding (export)+import qualified Algebra.Graph.Export as E++-- | An attribute is just a key-value pair, for example @"shape" := "box"@.+-- Attributes are used to specify the style of graph elements during export.+data Attribute s = (:=) s s++-- | The record 'Style' @a@ @s@ specifies the style to use when exporting a+-- graph in the DOT format. Here @a@ is the type of the graph vertices, and @s@+-- is the type of string to represent the resulting DOT document (e.g. String,+-- Text, etc.). Most fields can be empty. The only field that has no obvious+-- default value is 'vertexName', which holds a function of type @a -> s@ to+-- compute vertex names. See the example for the function 'export'.+data Style a s = Style+    { graphName :: s+    -- ^ Name of the graph.+    , preamble :: s+    -- ^ Preamble is added at the beginning of the DOT file body.+    , graphAttributes :: [Attribute s]+    -- ^ Graph style, e.g. @["bgcolor" := "azure"]@.+    , defaultVertexAttributes :: [Attribute s]+    -- ^ Default vertex style, e.g. @["shape" := "diamond"]@.+    , defaultEdgeAttributes :: [Attribute s]+    -- ^ Default edge style, e.g. @["style" := "dashed"]@.+    , vertexName :: a -> s+    -- ^ Compute a vertex name.+    , vertexAttributes :: a -> [Attribute s]+    -- ^ Attributes of a specific vertex.+    , edgeAttributes   :: a -> a -> [Attribute s]+    -- ^ Attributes of a specific edge.+    }++-- | Default style for exporting graphs. All style settings are empty except for+-- 'vertexName', which is provided as the only argument.+defaultStyle :: Monoid s => (a -> s) -> Style a s+defaultStyle v = Style mempty mempty [] [] [] v (\_ -> []) (\_ _ -> [])++-- | Default style for exporting graphs whose vertices are 'Show'-able. All+-- style settings are empty except for 'vertexName', which is computed from+-- 'show'.+--+-- @+-- defaultStyleViaShow = 'defaultStyle' ('fromString' . 'show')+-- @+defaultStyleViaShow :: (Show a, IsString s, Monoid s) => Style a s+defaultStyleViaShow = defaultStyle (fromString . show)++-- | Export a graph with a given style.+--+-- For example:+--+-- @+-- style :: 'Style' Int String+-- style = 'Style'+--     { 'graphName'               = \"Example\"+--     , 'preamble'                = "  // This is an example\\n"+--     , 'graphAttributes'         = ["label" := \"Example\", "labelloc" := "top"]+--     , 'defaultVertexAttributes' = ["shape" := "circle"]+--     , 'defaultEdgeAttributes'   = 'mempty'+--     , 'vertexName'              = \\x   -> "v" ++ 'show' x+--     , 'vertexAttributes'        = \\x   -> ["color" := "blue"   | 'odd' x      ]+--     , 'edgeAttributes'          = \\x y -> ["style" := "dashed" | 'odd' (x * y)] }+--+-- > putStrLn $ export style (1 * 2 + 3 * 4 * 5 :: 'Graph' Int)+--+-- digraph Example+-- {+--   // This is an example+--+--   graph [label=\"Example\" labelloc="top"]+--   node [shape="circle"]+--   "v1" [color="blue"]+--   "v2"+--   "v3" [color="blue"]+--   "v4"+--   "v5" [color="blue"]+--   "v1" -> "v2"+--   "v3" -> "v4"+--   "v3" -> "v5" [style="dashed"]+--   "v4" -> "v5"+-- }+-- @+export :: (IsString s, Monoid s, Eq s, Ord a, ToGraph g, ToVertex g ~ a) => Style a s -> g -> s+export Style {..} g = render $ header <> body <> "}\n"+  where+    header    = "digraph" <+> literal graphName <> "\n{\n"+             <> if preamble == mempty then mempty else (literal preamble <> "\n")+    with x as = if null as            then mempty else line (x <+> attributes as)+    line s    = indent 2 s <> "\n"+    body      = ("graph" `with` graphAttributes)+             <> ("node"  `with` defaultVertexAttributes)+             <> ("edge"  `with` defaultEdgeAttributes)+             <> E.export vDoc eDoc g+    label     = doubleQuotes . literal . vertexName+    vDoc x    = line $ label x <+>                      attributes (vertexAttributes x)+    eDoc x y  = line $ label x <> " -> " <> label y <+> attributes (edgeAttributes x y)++-- A list of attributes formatted as a DOT document.+-- Example: @attributes ["label" := "A label", "shape" := "box"]@+-- corresponds to document: @ [label="A label" shape="box"]@.+attributes :: IsString s => [Attribute s] -> Doc s+attributes [] = mempty+attributes as = brackets . mconcat . intersperse " " $ map dot as+  where+    dot (k := v) = literal k <> "=" <> doubleQuotes (literal v)++-- | Export a graph whose vertices are represented simply by their names.+--+-- For example:+--+-- @+-- > Text.putStrLn $ exportAsIs ('Algebra.Graph.AdjacencyMap.circuit' ["a", "b", "c"] :: 'Algebra.Graph.AdjacencyMap.AdjacencyMap' Text)+--+-- digraph+-- {+--   "a"+--   "b"+--   "c"+--   "a" -> "b"+--   "b" -> "c"+--   "c" -> "a"+-- }+-- @+exportAsIs :: (IsString s, Monoid s, Ord s, ToGraph g, ToVertex g ~ s) => g -> s+exportAsIs = export (defaultStyle id)++-- | Export a graph using the 'defaultStyleViaShow'.+--+-- For example:+--+-- @+-- > putStrLn $ exportViaShow (1 + 2 * (3 + 4) :: 'Algebra.Graph.Graph' Int)+--+-- digraph+-- {+--   "1"+--   "2"+--   "3"+--   "4"+--   "2" -> "3"+--   "2" -> "4"+-- }+-- @+exportViaShow :: (IsString s, Monoid s, Eq s, ToGraph g, Ord (ToVertex g), Show (ToVertex g)) => g -> s+exportViaShow = export defaultStyleViaShow
src/Algebra/Graph/Fold.hs view
@@ -397,12 +397,10 @@ -- hasEdge x y ('vertex' z)       == False -- hasEdge x y ('edge' x y)       == True -- hasEdge x y . 'removeEdge' x y == const False+-- hasEdge x y                  == 'elem' (x,y) . 'edgeList' -- @-hasEdge :: Eq a => a -> a -> Fold a -> Bool-hasEdge s t = not . intact . edgelessPiece s t--edgelessPiece :: forall a. Eq a => a -> a -> Fold a -> Piece (Fold a)-edgelessPiece s t g = st where (_, _, st :: Piece (Fold a)) = smash s t g+hasEdge :: Ord a => a -> a -> Fold a -> Bool+hasEdge = H.hasEdge  data Piece g = Piece { piece :: g, intact :: Bool, trivial :: Bool } @@ -557,13 +555,14 @@ -- -- @ --           deBruijn 0 xs               == 'edge' [] []--- n > 0 'Test.QuickCheck.==>' deBruijn n []               == 'empty'+-- n > 0 ==> deBruijn n []               == 'empty' --           deBruijn 1 [0,1]            == 'edges' [ ([0],[0]), ([0],[1]), ([1],[0]), ([1],[1]) ] --           deBruijn 2 "0"              == 'edge' "00" "00" --           deBruijn 2 "01"             == 'edges' [ ("00","00"), ("00","01"), ("01","10"), ("01","11") --                                                , ("10","00"), ("10","01"), ("11","10"), ("11","11") ]+--           'transpose'   (deBruijn n xs) == 'gmap' 'reverse' $ deBruijn n xs --           'vertexCount' (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^n--- n > 0 'Test.QuickCheck.==>' 'edgeCount'   (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^(n + 1)+-- n > 0 ==> 'edgeCount'   (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^(n + 1) -- @ deBruijn :: (C.Graph g, C.Vertex g ~ [a]) => Int -> [a] -> g deBruijn 0   _        = edge [] []@@ -584,7 +583,8 @@ removeVertex v = induce (/= v)  -- | Remove an edge from a given graph.--- Complexity: /O(s)/ time and memory.+-- Complexity: /O(s)/ time and memory. The worst case size complexity is /O(s^2)/,+-- although in practice it is usually also linear /O(s)/. -- -- @ -- removeEdge x y ('edge' x y)       == 'vertices' [x, y]
src/Algebra/Graph/HigherKinded/Class.hs view
@@ -42,7 +42,7 @@     isSubgraphOf,      -- * Graph properties-    isEmpty, hasVertex, vertexCount, vertexList, vertexSet, vertexIntSet,+    isEmpty, hasVertex, hasEdge, vertexCount, vertexList, vertexSet, vertexIntSet,      -- * Standard families of graphs     path, circuit, clique, biclique, star, tree, forest, mesh, torus, deBruijn,@@ -298,6 +298,18 @@ hasVertex :: (Eq a, Graph g) => a -> g a -> Bool hasVertex = elem +-- | Check if a graph contains a given edge.+-- Complexity: /O(s)/ time.+--+-- @+-- hasEdge x y 'empty'            == False+-- hasEdge x y ('vertex' z)       == False+-- hasEdge x y ('edge' x y)       == True+-- hasEdge x y                  == 'elem' (x,y) . 'edgeList'+-- @+hasEdge :: (Eq (g a), Graph g, Ord a) => a -> a -> g a -> Bool+hasEdge u v = (edge u v `isSubgraphOf`) . induce (`elem` [u, v])+ -- | The number of vertices in a graph. -- Complexity: /O(s * log(n))/ time. --@@ -377,10 +389,11 @@ -- given list. -- -- @--- clique []      == 'empty'--- clique [x]     == 'vertex' x--- clique [x,y]   == 'edge' x y--- clique [x,y,z] == 'edges' [(x,y), (x,z), (y,z)]+-- 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 :: Graph g => [a] -> g a clique = connects . map vertex@@ -474,13 +487,14 @@ -- -- @ --           deBruijn 0 xs               == 'edge' [] []--- n > 0 'Test.QuickCheck.==>' deBruijn n []               == 'empty'+-- n > 0 ==> deBruijn n []               == 'empty' --           deBruijn 1 [0,1]            == 'edges' [ ([0],[0]), ([0],[1]), ([1],[0]), ([1],[1]) ] --           deBruijn 2 "0"              == 'edge' "00" "00" --           deBruijn 2 "01"             == 'edges' [ ("00","00"), ("00","01"), ("01","10"), ("01","11") --                                                , ("10","00"), ("10","01"), ("11","10"), ("11","11") ]+--           'transpose'   (deBruijn n xs) == 'fmap' 'reverse' $ deBruijn n xs --           'vertexCount' (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^n--- n > 0 'Test.QuickCheck.==>' 'edgeCount'   (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^(n + 1)+-- n > 0 ==> 'edgeCount'   (deBruijn n xs) == ('length' $ 'Data.List.nub' xs)^(n + 1) -- @ deBruijn :: Graph g => Int -> [a] -> g [a] deBruijn 0   _        = edge [] []@@ -537,7 +551,7 @@ -- mergeVertices even 1 (0 * 2)     == 1 * 1 -- mergeVertices odd  1 (3 + 4 * 5) == 4 * 1 -- @-mergeVertices :: (Eq a, Graph g) => (a -> Bool) -> a -> g a -> g a+mergeVertices :: Graph g => (a -> Bool) -> a -> g a -> g a mergeVertices p v = fmap $ \w -> if p w then v else w  -- | Split a vertex into a list of vertices with the same connectivity.
src/Algebra/Graph/IntAdjacencyMap.hs view
@@ -29,23 +29,20 @@      -- * Graph properties     isEmpty, hasVertex, hasEdge, vertexCount, edgeCount, vertexList, edgeList,-    adjacencyList, vertexSet, edgeSet, postset,+    adjacencyList, vertexIntSet, edgeSet, postIntSet,      -- * Standard families of graphs     path, circuit, clique, biclique, star, tree, forest,      -- * Graph transformation-    removeVertex, removeEdge, replaceVertex, mergeVertices, gmap, induce,+    removeVertex, removeEdge, replaceVertex, mergeVertices, transpose, gmap, induce,      -- * Algorithms-    dfsForest, topSort, isTopSort,--    -- * Interoperability with King-Launchbury graphs-    GraphKL, getGraph, getVertex, graphKL, fromGraphKL+    dfsForest, dfsForestFrom, dfs, topSort, isTopSort   ) where -import Data.Array import Data.IntSet (IntSet)+import Data.Maybe import Data.Set (Set) import Data.Tree @@ -138,14 +135,14 @@ -- of the given list. -- -- @--- vertices []            == 'empty'--- vertices [x]           == 'vertex' x--- 'hasVertex' x . vertices == 'elem' x--- 'vertexCount' . vertices == 'length' . 'Data.List.nub'--- 'vertexSet'   . vertices == IntSet.'IntSet.fromList'+-- vertices []             == 'empty'+-- vertices [x]            == 'vertex' x+-- 'hasVertex' x  . vertices == 'elem' x+-- 'vertexCount'  . vertices == 'length' . 'Data.List.nub'+-- 'vertexIntSet' . vertices == IntSet.'IntSet.fromList' -- @ vertices :: [Int] -> IntAdjacencyMap-vertices = IntAdjacencyMap . IntMap.fromList . map (\x -> (x, IntSet.empty))+vertices = mkAM . IntMap.fromList . map (\x -> (x, IntSet.empty))  -- | Construct the graph from a list of edges. -- Complexity: /O((n + m) * log(n))/ time and /O(n + m)/ memory.@@ -208,7 +205,7 @@ -- 'overlay' (fromAdjacencyList xs) (fromAdjacencyList ys) == fromAdjacencyList (xs ++ ys) -- @ fromAdjacencyList :: [(Int, [Int])] -> IntAdjacencyMap-fromAdjacencyList as = IntAdjacencyMap $ IntMap.unionWith IntSet.union vs es+fromAdjacencyList as = mkAM $ IntMap.unionWith IntSet.union vs es   where     ss = map (fmap IntSet.fromList) as     vs = IntMap.fromSet (const IntSet.empty) . IntSet.unions $ map snd ss@@ -260,6 +257,7 @@ -- hasEdge x y ('vertex' z)       == False -- hasEdge x y ('edge' x y)       == True -- hasEdge x y . 'removeEdge' x y == const False+-- hasEdge x y                  == 'elem' (x,y) . 'edgeList' -- @ hasEdge :: Int -> Int -> IntAdjacencyMap -> Bool hasEdge u v a = case IntMap.lookup u (adjacencyMap a) of@@ -309,9 +307,10 @@ -- edgeList ('edge' x y)     == [(x,y)] -- edgeList ('star' 2 [3,1]) == [(2,1), (2,3)] -- edgeList . 'edges'        == 'Data.List.nub' . 'Data.List.sort'+-- edgeList . 'transpose'    == 'Data.List.sort' . map 'Data.Tuple.swap' . edgeList -- @ edgeList :: IntAdjacencyMap -> [(Int, Int)]-edgeList (IntAdjacencyMap m) = [ (x, y) | (x, ys) <- IntMap.toAscList m, y <- IntSet.toAscList ys ]+edgeList (AM m _) = [ (x, y) | (x, ys) <- IntMap.toAscList m, y <- IntSet.toAscList ys ]  -- | The sorted /adjacency list/ of a graph. -- Complexity: /O(n + m)/ time and /O(m)/ memory.@@ -330,13 +329,13 @@ -- Complexity: /O(n)/ time and memory. -- -- @--- vertexSet 'empty'      == IntSet.'IntSet.empty'--- vertexSet . 'vertex'   == IntSet.'IntSet.singleton'--- vertexSet . 'vertices' == IntSet.'IntSet.fromList'--- vertexSet . 'clique'   == IntSet.'IntSet.fromList'+-- vertexIntSet 'empty'      == IntSet.'IntSet.empty'+-- vertexIntSet . 'vertex'   == IntSet.'IntSet.singleton'+-- vertexIntSet . 'vertices' == IntSet.'IntSet.fromList'+-- vertexIntSet . 'clique'   == IntSet.'IntSet.fromList' -- @-vertexSet :: IntAdjacencyMap -> IntSet-vertexSet = IntMap.keysSet . adjacencyMap+vertexIntSet :: IntAdjacencyMap -> IntSet+vertexIntSet = IntMap.keysSet . adjacencyMap  -- | The set of edges of a given graph. -- Complexity: /O((n + m) * log(m))/ time and /O(m)/ memory.@@ -355,21 +354,22 @@ -- | The /postset/ of a vertex is the set of its /direct successors/. -- -- @--- postset x 'empty'      == IntSet.'IntSet.empty'--- postset x ('vertex' x) == IntSet.'IntSet.empty'--- postset x ('edge' x y) == IntSet.'IntSet.fromList' [y]--- postset 2 ('edge' 1 2) == IntSet.'IntSet.empty'+-- postIntSet x 'empty'      == IntSet.'IntSet.empty'+-- postIntSet x ('vertex' x) == IntSet.'IntSet.empty'+-- postIntSet x ('edge' x y) == IntSet.'IntSet.fromList' [y]+-- postIntSet 2 ('edge' 1 2) == IntSet.'IntSet.empty' -- @-postset :: Int -> IntAdjacencyMap -> IntSet-postset x = IntMap.findWithDefault IntSet.empty x . adjacencyMap+postIntSet :: Int -> IntAdjacencyMap -> IntSet+postIntSet x = IntMap.findWithDefault IntSet.empty x . adjacencyMap  -- | 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 []        == 'empty'+-- path [x]       == 'vertex' x+-- path [x,y]     == 'edge' x y+-- path . 'reverse' == 'transpose' . path -- @ path :: [Int] -> IntAdjacencyMap path = C.path@@ -378,9 +378,10 @@ -- Complexity: /O((n + m) * log(n))/ time and /O(n + m)/ memory. -- -- @--- circuit []    == 'empty'--- circuit [x]   == 'edge' x x--- circuit [x,y] == 'edges' [(x,y), (y,x)]+-- circuit []        == 'empty'+-- circuit [x]       == 'edge' x x+-- circuit [x,y]     == 'edges' [(x,y), (y,x)]+-- circuit . 'reverse' == 'transpose' . circuit -- @ circuit :: [Int] -> IntAdjacencyMap circuit = C.circuit@@ -389,10 +390,12 @@ -- 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 []         == '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 . 'reverse'  == 'transpose' . clique -- @ clique :: [Int] -> IntAdjacencyMap clique = C.clique@@ -408,7 +411,7 @@ -- biclique xs      ys      == 'connect' ('vertices' xs) ('vertices' ys) -- @ biclique :: [Int] -> [Int] -> IntAdjacencyMap-biclique xs ys = IntAdjacencyMap $ IntMap.fromSet adjacent (x `IntSet.union` y)+biclique xs ys = mkAM $ IntMap.fromSet adjacent (x `IntSet.union` y)   where     x = IntSet.fromList xs     y = IntSet.fromList ys@@ -459,7 +462,7 @@ -- removeVertex x . removeVertex x == removeVertex x -- @ removeVertex :: Int -> IntAdjacencyMap -> IntAdjacencyMap-removeVertex x = IntAdjacencyMap . IntMap.map (IntSet.delete x) . IntMap.delete x . adjacencyMap+removeVertex x = mkAM . IntMap.map (IntSet.delete x) . IntMap.delete x . adjacencyMap  -- | Remove an edge from a given graph. -- Complexity: /O(log(n))/ time.@@ -472,7 +475,7 @@ -- removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2 -- @ removeEdge :: Int -> Int -> IntAdjacencyMap -> IntAdjacencyMap-removeEdge x y = IntAdjacencyMap . IntMap.adjust (IntSet.delete y) x . adjacencyMap+removeEdge x y = mkAM . IntMap.adjust (IntSet.delete y) x . adjacencyMap  -- | The function @'replaceVertex' x y@ replaces vertex @x@ with vertex @y@ in a -- given 'IntAdjacencyMap'. If @y@ already exists, @x@ and @y@ will be merged.@@ -499,6 +502,25 @@ mergeVertices :: (Int -> Bool) -> Int -> IntAdjacencyMap -> IntAdjacencyMap mergeVertices p v = gmap $ \u -> if p u then v else u +-- | Transpose a given graph.+-- Complexity: /O(m * log(n))/ time, /O(n + m)/ memory.+--+-- @+-- transpose 'empty'       == 'empty'+-- transpose ('vertex' x)  == 'vertex' x+-- transpose ('edge' x y)  == 'edge' y x+-- transpose . transpose == id+-- transpose . 'path'      == 'path'    . 'reverse'+-- transpose . 'circuit'   == 'circuit' . 'reverse'+-- transpose . 'clique'    == 'clique'  . 'reverse'+-- 'edgeList' . transpose  == 'Data.List.sort' . map 'Data.Tuple.swap' . 'edgeList'+-- @+transpose :: IntAdjacencyMap -> IntAdjacencyMap+transpose (AM m _) = mkAM $ IntMap.foldrWithKey combine vs m+  where+    combine v es = IntMap.unionWith IntSet.union (IntMap.fromSet (const $ IntSet.singleton v) es)+    vs           = IntMap.fromSet (const IntSet.empty) (IntMap.keysSet m)+ -- | 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 -- 'IntAdjacencyMap'.@@ -512,7 +534,7 @@ -- gmap f . gmap g   == gmap (f . g) -- @ gmap :: (Int -> Int) -> IntAdjacencyMap -> IntAdjacencyMap-gmap f = IntAdjacencyMap . IntMap.map (IntSet.map f) . IntMap.mapKeysWith IntSet.union f . adjacencyMap+gmap f = mkAM . IntMap.map (IntSet.map f) . IntMap.mapKeysWith IntSet.union f . adjacencyMap  -- | Construct the /induced subgraph/ of a given graph by removing the -- vertices that do not satisfy a given predicate.@@ -527,7 +549,7 @@ -- 'isSubgraphOf' (induce p x) x == True -- @ induce :: (Int -> Bool) -> IntAdjacencyMap -> IntAdjacencyMap-induce p = IntAdjacencyMap . IntMap.map (IntSet.filter p) . IntMap.filterWithKey (\k _ -> p k) . adjacencyMap+induce p = mkAM . IntMap.map (IntSet.filter p) . IntMap.filterWithKey (\k _ -> p k) . adjacencyMap  -- | Compute the /depth-first search/ forest of a graph. --@@ -537,6 +559,8 @@ -- 'forest' (dfsForest $ 'edge' 2 1)         == 'vertices' [1, 2] -- 'isSubgraphOf' ('forest' $ dfsForest x) x == True -- dfsForest . 'forest' . dfsForest        == dfsForest+-- dfsForest ('vertices' vs)               == map (\\v -> Node v []) ('Data.List.nub' $ 'Data.List.sort' vs)+-- 'dfsForestFrom' ('vertexList' x) x        == dfsForest x -- dfsForest $ 3 * (1 + 4) * (1 + 5)     == [ Node { rootLabel = 1 --                                                 , subForest = [ Node { rootLabel = 5 --                                                                      , subForest = [] }]}@@ -545,8 +569,48 @@ --                                                                      , subForest = [] }]}] -- @ dfsForest :: IntAdjacencyMap -> Forest Int-dfsForest m = let GraphKL g r = graphKL m in fmap (fmap r) (KL.dff g)+dfsForest (AM _ (GraphKL g r _)) = fmap (fmap r) (KL.dff g) +-- | Compute the /depth-first search/ forest of a graph, searching from each of+-- the given vertices in order. Note that the resulting forest does not+-- necessarily span the whole graph, as some vertices may be unreachable.+--+-- @+-- 'forest' (dfsForestFrom [1]    $ 'edge' 1 1)     == 'vertex' 1+-- 'forest' (dfsForestFrom [1]    $ 'edge' 1 2)     == 'edge' 1 2+-- 'forest' (dfsForestFrom [2]    $ 'edge' 1 2)     == 'vertex' 2+-- 'forest' (dfsForestFrom [3]    $ 'edge' 1 2)     == 'empty'+-- 'forest' (dfsForestFrom [2, 1] $ 'edge' 1 2)     == 'vertices' [1, 2]+-- 'isSubgraphOf' ('forest' $ dfsForestFrom vs x) x == True+-- dfsForestFrom ('vertexList' x) x               == 'dfsForest' x+-- dfsForestFrom vs             ('vertices' vs)   == map (\\v -> Node v []) ('Data.List.nub' vs)+-- dfsForestFrom []             x               == []+-- dfsForestFrom [1, 4] $ 3 * (1 + 4) * (1 + 5) == [ Node { rootLabel = 1+--                                                        , subForest = [ Node { rootLabel = 5+--                                                                             , subForest = [] }+--                                                 , Node { rootLabel = 4+--                                                        , subForest = [] }]+-- @+dfsForestFrom :: [Int] -> IntAdjacencyMap -> Forest Int+dfsForestFrom vs (AM _ (GraphKL g r t)) = fmap (fmap r) (KL.dfs g (mapMaybe t vs))++-- | Compute the list of vertices visited by the /depth-first search/ in a graph,+-- when searching from each of the given vertices in order.+--+-- @+-- dfs [1]    $ 'edge' 1 1                == [1]+-- dfs [1]    $ 'edge' 1 2                == [1, 2]+-- dfs [2]    $ 'edge' 1 2                == [2]+-- dfs [3]    $ 'edge' 1 2                == []+-- dfs [1, 2] $ 'edge' 1 2                == [1, 2]+-- dfs [2, 1] $ 'edge' 1 2                == [2, 1]+-- dfs []     $ x                       == []+-- dfs [1, 4] $ 3 * (1 + 4) * (1 + 5)   == [1, 5, 4]+-- 'isSubgraphOf' ('vertices' $ dfs vs x) x == True+-- @+dfs :: [Int] -> IntAdjacencyMap -> [Int]+dfs vs = concatMap flatten . dfsForestFrom vs+ -- | Compute the /topological sort/ of a graph or return @Nothing@ if the graph -- is cyclic. --@@ -556,10 +620,10 @@ -- fmap (flip 'isTopSort' x) (topSort x) /= Just False -- @ topSort :: IntAdjacencyMap -> Maybe [Int]-topSort m = if isTopSort result m then Just result else Nothing+topSort m@(AM _ (GraphKL g r _)) =+    if isTopSort result m then Just result else Nothing   where-    GraphKL g r = graphKL m-    result      = map r (KL.topSort g)+    result = map r (KL.topSort g)  -- | Check if a given list of vertices is a valid /topological sort/ of a graph. --@@ -576,36 +640,4 @@   where     go seen []     = seen == IntMap.keysSet (adjacencyMap m)     go seen (v:vs) = let newSeen = seen `seq` IntSet.insert v seen-        in postset v m `IntSet.intersection` newSeen == IntSet.empty && go newSeen vs---- | 'GraphKL' encapsulates King-Launchbury graphs, which are implemented in--- the "Data.Graph" module of the @containers@ library. If @graphKL g == h@ then--- the following holds:------ @--- map ('getVertex' h) ('Data.Graph.vertices' $ 'getGraph' h)                            == IntSet.'IntSet.toAscList' ('vertexSet' g)--- map (\\(x, y) -> ('getVertex' h x, 'getVertex' h y)) ('Data.Graph.edges' $ 'getGraph' h) == 'edgeList' g--- @-data GraphKL = GraphKL {-    -- | Array-based graph representation (King and Launchbury, 1995).-    getGraph :: KL.Graph,-    -- | A mapping of "Data.Graph.Vertex" to vertices of type @a@.-    getVertex :: KL.Vertex -> Int }---- | Build 'GraphKL' from the adjacency map of a graph.------ @--- 'fromGraphKL' . graphKL == id--- @-graphKL :: IntAdjacencyMap -> GraphKL-graphKL m = GraphKL g $ \u -> case r u of (_, v, _) -> v-  where-    (g, r) = KL.graphFromEdges' [ ((), v, us) | (v, us) <- adjacencyList m ]---- | Extract the adjacency map of a King-Launchbury graph.------ @--- fromGraphKL . 'graphKL' == id--- @-fromGraphKL :: GraphKL -> IntAdjacencyMap-fromGraphKL (GraphKL g r) = fromAdjacencyList $ map (\(x, ys) -> (r x, map r ys)) (assocs g)+        in postIntSet v m `IntSet.intersection` newSeen == IntSet.empty && go newSeen vs
src/Algebra/Graph/IntAdjacencyMap/Internal.hs view
@@ -12,7 +12,10 @@ ----------------------------------------------------------------------------- module Algebra.Graph.IntAdjacencyMap.Internal (     -- * Adjacency map implementation-    IntAdjacencyMap (..), consistent+    IntAdjacencyMap (..), mkAM, consistent,++    -- * Interoperability with King-Launchbury graphs+    GraphKL (..), mkGraphKL   ) where  import Data.IntMap.Strict (IntMap, keysSet, fromSet)@@ -20,6 +23,7 @@  import Algebra.Graph.Class +import qualified Data.Graph         as KL import qualified Data.IntMap.Strict as IntMap import qualified Data.IntSet        as IntSet @@ -83,14 +87,25 @@ When specifying the time and memory complexity of graph algorithms, /n/ and /m/ will denote the number of vertices and edges in the graph, respectively. -}-newtype IntAdjacencyMap = IntAdjacencyMap {+data IntAdjacencyMap = AM {     -- | The /adjacency map/ of the graph: each vertex is associated with a set     -- of its direct successors.-    adjacencyMap :: IntMap IntSet-  } deriving Eq+    adjacencyMap :: !(IntMap IntSet),+    -- | Cached King-Launchbury representation.+    -- /Note: this field is for internal use only/.+    graphKL :: GraphKL } +-- | Construct an 'AdjacencyMap' from a map of successor sets and (lazily)+-- compute the corresponding King-Launchbury representation.+-- /Note: this function is for internal use only/.+mkAM :: IntMap IntSet -> IntAdjacencyMap+mkAM m = AM m (mkGraphKL m)++instance Eq IntAdjacencyMap where+    x == y = adjacencyMap x == adjacencyMap y+ instance Show IntAdjacencyMap where-    show (IntAdjacencyMap m)+    show (AM m _)         | m == IntMap.empty = "empty"         | es == []          = if IntSet.size vs > 1 then "vertices " ++ show (IntSet.toAscList vs)                                                     else "vertex "   ++ show v@@ -106,10 +121,10 @@  instance Graph IntAdjacencyMap where     type Vertex IntAdjacencyMap = Int-    empty       = IntAdjacencyMap $ IntMap.empty-    vertex x    = IntAdjacencyMap $ IntMap.singleton x IntSet.empty-    overlay x y = IntAdjacencyMap $ IntMap.unionWith IntSet.union (adjacencyMap x) (adjacencyMap y)-    connect x y = IntAdjacencyMap $ IntMap.unionsWith IntSet.union [ adjacencyMap x, adjacencyMap y,+    empty       = mkAM $ IntMap.empty+    vertex x    = mkAM $ IntMap.singleton x IntSet.empty+    overlay x y = mkAM $ IntMap.unionWith IntSet.union (adjacencyMap x) (adjacencyMap y)+    connect x y = mkAM $ IntMap.unionsWith IntSet.union [ adjacencyMap x, adjacencyMap y,         fromSet (const . keysSet $ adjacencyMap y) (keysSet $ adjacencyMap x) ]  instance Num IntAdjacencyMap where@@ -120,6 +135,10 @@     abs         = id     negate      = id +instance ToGraph IntAdjacencyMap where+    type ToVertex IntAdjacencyMap = Int+    toGraph = overlays . map (uncurry star . fmap IntSet.toList) . IntMap.toList . adjacencyMap+ -- | Check if the internal graph representation is consistent, i.e. that all -- edges refer to existing vertices. It should be impossible to create an -- inconsistent adjacency map, and we use this function in testing.@@ -136,7 +155,7 @@ -- consistent ('Algebra.Graph.IntAdjacencyMap.fromAdjacencyList' xs) == True -- @ consistent :: IntAdjacencyMap -> Bool-consistent (IntAdjacencyMap m) = referredToVertexSet m `IntSet.isSubsetOf` keysSet m+consistent (AM m _) = referredToVertexSet m `IntSet.isSubsetOf` keysSet m  -- The set of vertices that are referred to by the edges referredToVertexSet :: IntMap IntSet -> IntSet@@ -145,3 +164,32 @@ -- The list of edges in adjacency map internalEdgeList :: IntMap IntSet -> [(Int, Int)] internalEdgeList m = [ (x, y) | (x, ys) <- IntMap.toAscList m, y <- IntSet.toAscList ys ]++-- | 'GraphKL' encapsulates King-Launchbury graphs, which are implemented in+-- the "Data.Graph" module of the @containers@ library.+-- /Note: this data structure is for internal use only/.+--+-- If @mkGraphKL (adjacencyMap g) == h@ then the following holds:+--+-- @+-- map ('fromVertexKL' h) ('Data.Graph.vertices' $ 'toGraphKL' h)                               == 'Algebra.Graph.AdjacencyMap.vertexList' g+-- map (\\(x, y) -> ('fromVertexKL' h x, 'fromVertexKL' h y)) ('Data.Graph.edges' $ 'toGraphKL' h) == 'Algebra.Graph.AdjacencyMap.edgeList' g+-- @+data GraphKL = GraphKL {+    -- | Array-based graph representation (King and Launchbury, 1995).+    toGraphKL :: KL.Graph,+    -- | A mapping of "Data.Graph.Vertex" to vertices of type @Int@.+    fromVertexKL :: KL.Vertex -> Int,+    -- | A mapping from vertices of type @Int@ to "Data.Graph.Vertex".+    -- Returns 'Nothing' if the argument is not in the graph.+    toVertexKL :: Int -> Maybe KL.Vertex }++-- | Build 'GraphKL' from a map of successor sets.+-- /Note: this function is for internal use only/.+mkGraphKL :: IntMap IntSet -> GraphKL+mkGraphKL m = GraphKL+    { toGraphKL    = g+    , fromVertexKL = \u -> case r u of (_, v, _) -> v+    , toVertexKL   = t }+  where+    (g, r, t) = KL.graphFromEdges [ ((), v, IntSet.toAscList us) | (v, us) <- IntMap.toAscList m ]
src/Algebra/Graph/Relation.hs view
@@ -27,7 +27,7 @@      -- * Graph properties     isEmpty, hasVertex, hasEdge, vertexCount, edgeCount, vertexList, edgeList,-    vertexSet, vertexIntSet, edgeSet, preset, postset,+    vertexSet, vertexIntSet, edgeSet, preSet, postSet,      -- * Standard families of graphs     path, circuit, clique, biclique, star, tree, forest,@@ -248,6 +248,7 @@ -- hasEdge x y ('vertex' z)       == False -- hasEdge x y ('edge' x y)       == True -- hasEdge x y . 'removeEdge' x y == const False+-- hasEdge x y                  == 'elem' (x,y) . 'edgeList' -- @ hasEdge :: Ord a => a -> a -> Relation a -> Bool hasEdge x y = Set.member (x, y) . relation@@ -260,7 +261,7 @@ -- vertexCount ('vertex' x) == 1 -- vertexCount            == 'length' . 'vertexList' -- @-vertexCount :: Ord a => Relation a -> Int+vertexCount :: Relation a -> Int vertexCount = Set.size . domain  -- | The number of edges in a graph.@@ -272,7 +273,7 @@ -- edgeCount ('edge' x y) == 1 -- edgeCount            == 'length' . 'edgeList' -- @-edgeCount :: Ord a => Relation a -> Int+edgeCount :: Relation a -> Int edgeCount = Set.size . relation  -- | The sorted list of vertices of a given graph.@@ -283,7 +284,7 @@ -- vertexList ('vertex' x) == [x] -- vertexList . 'vertices' == 'Data.List.nub' . 'Data.List.sort' -- @-vertexList :: Ord a => Relation a -> [a]+vertexList :: Relation a -> [a] vertexList = Set.toAscList . domain  -- | The sorted list of edges of a graph.@@ -297,7 +298,7 @@ -- edgeList . 'edges'        == 'Data.List.nub' . 'Data.List.sort' -- edgeList . 'transpose'    == 'Data.List.sort' . map 'Data.Tuple.swap' . edgeList -- @-edgeList :: Ord a => Relation a -> [(a, a)]+edgeList :: Relation a -> [(a, a)] edgeList = Set.toAscList . relation  -- | The set of vertices of a given graph.@@ -309,7 +310,7 @@ -- vertexSet . 'vertices' == Set.'Set.fromList' -- vertexSet . 'clique'   == Set.'Set.fromList' -- @-vertexSet :: Ord a => Relation a -> Set.Set a+vertexSet :: Relation a -> Set.Set a vertexSet = domain  -- | The set of vertices of a given graph. Like 'vertexSet' but specialised for@@ -334,36 +335,36 @@ -- edgeSet ('edge' x y) == Set.'Set.singleton' (x,y) -- edgeSet . 'edges'    == Set.'Set.fromList' -- @-edgeSet :: Ord a => Relation a -> Set.Set (a, a)+edgeSet :: Relation a -> Set.Set (a, a) edgeSet = relation  -- | The /preset/ of an element @x@ is the set of elements that are related to--- it on the /left/, i.e. @preset x == { a | aRx }@. In the context of directed+-- it on the /left/, i.e. @preSet x == { a | aRx }@. In the context of directed -- graphs, this corresponds to the set of /direct predecessors/ of vertex @x@. -- Complexity: /O(n + m)/ time and /O(n)/ memory. -- -- @--- preset x 'empty'      == Set.empty--- preset x ('vertex' x) == Set.empty--- preset 1 ('edge' 1 2) == Set.empty--- preset y ('edge' x y) == Set.fromList [x]+-- preSet x 'empty'      == Set.'Set.empty'+-- preSet x ('vertex' x) == Set.'Set.empty'+-- preSet 1 ('edge' 1 2) == Set.'Set.empty'+-- preSet y ('edge' x y) == Set.'Set.fromList' [x] -- @-preset :: Ord a => a -> Relation a -> Set.Set a-preset x = Set.mapMonotonic fst . Set.filter ((== x) . snd) . relation+preSet :: Ord a => a -> Relation a -> Set.Set a+preSet x = Set.mapMonotonic fst . Set.filter ((== x) . snd) . relation  -- | The /postset/ of an element @x@ is the set of elements that are related to--- it on the /right/, i.e. @postset x == { a | xRa }@. In the context of directed+-- it on the /right/, i.e. @postSet x == { a | xRa }@. In the context of directed -- graphs, this corresponds to the set of /direct successors/ of vertex @x@. -- Complexity: /O(n + m)/ time and /O(n)/ memory. -- -- @--- postset x 'empty'      == Set.empty--- postset x ('vertex' x) == Set.empty--- postset x ('edge' x y) == Set.fromList [y]--- postset 2 ('edge' 1 2) == Set.empty+-- postSet x 'empty'      == Set.'Set.empty'+-- postSet x ('vertex' x) == Set.'Set.empty'+-- postSet x ('edge' x y) == Set.'Set.fromList' [y]+-- postSet 2 ('edge' 1 2) == Set.'Set.empty' -- @-postset :: Ord a => a -> Relation a -> Set.Set a-postset x = Set.mapMonotonic snd . Set.filter ((== x) . fst) . relation+postSet :: Ord a => a -> Relation a -> Set.Set a+postSet x = Set.mapMonotonic snd . Set.filter ((== x) . fst) . relation  -- | The /path/ on a list of vertices. -- Complexity: /O((n + m) * log(n))/ time and /O(n + m)/ memory.@@ -393,11 +394,12 @@ -- 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 . 'reverse' == 'transpose' . clique+-- 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 . 'reverse'  == 'transpose' . clique -- @ clique :: Ord a => [a] -> Relation a clique = C.clique@@ -531,7 +533,7 @@ -- gmap id           == id -- gmap f . gmap g   == gmap (f . g) -- @-gmap :: (Ord a, Ord b) => (a -> b) -> Relation a -> Relation b+gmap :: Ord b => (a -> b) -> Relation a -> Relation b gmap f (Relation d r) = Relation (Set.map f d) (Set.map (\(x, y) -> (f x, f y)) r)  -- | Construct the /induced subgraph/ of a given graph by removing the@@ -546,7 +548,7 @@ -- induce p . induce q         == induce (\\x -> p x && q x) -- 'isSubgraphOf' (induce p x) x == True -- @-induce :: Ord a => (a -> Bool) -> Relation a -> Relation a+induce :: (a -> Bool) -> Relation a -> Relation a induce p (Relation d r) = Relation (Set.filter p d) (Set.filter pp r)   where     pp (x, y) = p x && p y@@ -569,7 +571,7 @@ compose x y = Relation (referredToVertexSet r) r   where     d = domain x `Set.union` domain y-    r = Set.unions [ preset z y `setProduct` postset z x | z <- Set.toAscList d ]+    r = Set.unions [ preSet z y `setProduct` postSet z x | z <- Set.toAscList d ]  -- | Compute the /reflexive closure/ of a 'Relation'. -- Complexity: /O(n * log(m))/ time.
src/Algebra/Graph/Relation/Internal.hs view
@@ -123,6 +123,10 @@     abs         = id     negate      = id +instance ToGraph (Relation a) where+    type ToVertex (Relation a) = a+    toGraph (Relation d r) = graph (Set.toList d) (Set.toList r)+ -- | Check if the internal representation of a relation is consistent, i.e. if all -- pairs of elements in the 'relation' refer to existing elements in the 'domain'. -- It should be impossible to create an inconsistent 'Relation', and we use this
src/Algebra/Graph/Relation/Symmetric.hs view
@@ -43,4 +43,4 @@ -- neighbours y ('Algebra.Graph.Class.edge' x y) == Set.'Set.fromList' [x] -- @ neighbours :: Ord a => a -> SymmetricRelation a -> Set.Set a-neighbours x = preset x . toRelation+neighbours x = postSet x . toRelation
test/Algebra/Graph/Test.hs view
@@ -83,12 +83,12 @@     , forAll arbitrary (\v -> vertex v `asTypeOf` x == vertex v * vertex v)                                                 // "Vertex self-loop" ] -transitiveAxioms :: Eq g => GraphTestsuite g+transitiveAxioms :: GraphTestsuite g transitiveAxioms x y z = conjoin     [ axioms x y z     , y == empty || x * y * z == x * y + y * z  // "Closure" ] -preorderAxioms :: (Arbitrary (Vertex g), Eq g, Show (Vertex g)) => GraphTestsuite g+preorderAxioms :: (Arbitrary (Vertex g), Show (Vertex g)) => GraphTestsuite g preorderAxioms x y z = conjoin     [ axioms x y z     , forAll arbitrary (\v -> vertex v `asTypeOf` x == vertex v * vertex v)
+ test/Algebra/Graph/Test/API.hs view
@@ -0,0 +1,340 @@+{-# LANGUAGE ConstrainedClassMethods, RankNTypes #-}+-----------------------------------------------------------------------------+-- |+-- Module     : Algebra.Graph.Test.API+-- Copyright  : (c) Andrey Mokhov 2016-2017+-- License    : MIT (see the file LICENSE)+-- Maintainer : andrey.mokhov@gmail.com+-- Stability  : experimental+--+-- Graph manipulation API used for generic testing.+-----------------------------------------------------------------------------+module Algebra.Graph.Test.API (+    -- * Graph manipulation API+    GraphAPI (..)+  ) where++import Data.IntSet (IntSet)+import Data.Set (Set)+import Data.Tree++import Algebra.Graph.Class++import qualified Algebra.Graph.AdjacencyMap    as AdjacencyMap+import qualified Algebra.Graph.Fold            as Fold+import qualified Algebra.Graph                 as Graph+import qualified Algebra.Graph.IntAdjacencyMap as IntAdjacencyMap+import qualified Algebra.Graph.Relation        as Relation+import qualified Data.Set                      as Set+import qualified Data.IntSet                   as IntSet++class Graph g => GraphAPI g where+    edge              :: Vertex g -> Vertex g -> g+    edge              = notImplemented+    vertices          :: [Vertex g] -> g+    vertices          = notImplemented+    edges             :: [(Vertex g, Vertex g)] -> g+    edges             = notImplemented+    overlays          :: [g] -> g+    overlays          = notImplemented+    connects          :: [g] -> g+    connects          = notImplemented+    graph             :: [Vertex g] -> [(Vertex g, Vertex g)] -> g+    graph             = notImplemented+    fromAdjacencyList :: [(Vertex g, [Vertex g])] -> g+    fromAdjacencyList = notImplemented+    foldg             :: r -> (Vertex g -> r) -> (r -> r -> r) -> (r -> r -> r) -> g -> r+    foldg             = notImplemented+    isSubgraphOf      :: g -> g -> Bool+    isSubgraphOf      = notImplemented+    (===)             :: g -> g -> Bool+    (===)             = notImplemented+    isEmpty           :: g -> Bool+    isEmpty           = notImplemented+    size              :: g -> Int+    size              = notImplemented+    hasVertex         :: Vertex g -> g -> Bool+    hasVertex         = notImplemented+    hasEdge           :: Vertex g -> Vertex g -> g -> Bool+    hasEdge           = notImplemented+    vertexCount       :: g -> Int+    vertexCount       = notImplemented+    edgeCount         :: g -> Int+    edgeCount         = notImplemented+    vertexList        :: g -> [Vertex g]+    vertexList        = notImplemented+    edgeList          :: g -> [(Vertex g, Vertex g)]+    edgeList          = notImplemented+    adjacencyList     :: g -> [(Vertex g, [Vertex g])]+    adjacencyList     = notImplemented+    vertexSet         :: g -> Set (Vertex g)+    vertexSet         = notImplemented+    vertexIntSet      :: Vertex g ~ Int => g -> IntSet+    vertexIntSet      = notImplemented+    edgeSet           :: g -> Set (Vertex g, Vertex g)+    edgeSet           = notImplemented+    preSet            :: Vertex g -> g -> Set (Vertex g)+    preSet            = notImplemented+    postSet           :: Vertex g -> g -> Set (Vertex g)+    postSet           = notImplemented+    postIntSet        :: Vertex g ~ Int => Int -> g -> IntSet+    postIntSet        = notImplemented+    path              :: [Vertex g] -> g+    path              = notImplemented+    circuit           :: [Vertex g] -> g+    circuit           = notImplemented+    clique            :: [Vertex g] -> g+    clique            = notImplemented+    biclique          :: [Vertex g] -> [Vertex g] -> g+    biclique          = notImplemented+    star              :: Vertex g -> [Vertex g] -> g+    star              = notImplemented+    tree              :: Tree (Vertex g) -> g+    tree              = notImplemented+    forest            :: Forest (Vertex g) -> g+    forest            = notImplemented+    mesh              :: Vertex g ~ (a, b) => [a] -> [b] -> g+    mesh              = notImplemented+    torus             :: Vertex g ~ (a, b) => [a] -> [b] -> g+    torus             = notImplemented+    deBruijn          :: Vertex g ~ [a] => Int -> [a] -> g+    deBruijn          = notImplemented+    removeVertex      :: Vertex g -> g -> g+    removeVertex      = notImplemented+    removeEdge        :: Vertex g -> Vertex g -> g -> g+    removeEdge        = notImplemented+    replaceVertex     :: Vertex g -> Vertex g -> g -> g+    replaceVertex     = notImplemented+    mergeVertices     :: (Vertex g -> Bool) -> Vertex g -> g -> g+    mergeVertices     = notImplemented+    splitVertex       :: Vertex g -> [Vertex g] -> g -> g+    splitVertex       = notImplemented+    transpose         :: g -> g+    transpose         = notImplemented+    gmap              :: Vertex g ~ Int => (Int -> Int) -> g -> g+    gmap              = notImplemented+    induce            :: (Vertex g -> Bool) -> g -> g+    induce            = notImplemented+    bind              :: Vertex g ~ Int => g -> (Int -> g) -> g+    bind              = notImplemented+    simplify          :: g -> g+    simplify          = notImplemented+    box               :: forall a b f. (Vertex (f a) ~ a, Vertex (f b) ~ b, Vertex (f (a, b)) ~ (a, b), g ~ f (a, b)) => f a -> f b -> f (a, b)+    box               = notImplemented+    dfsForest         :: g -> Forest (Vertex g)+    dfsForest         = notImplemented+    dfsForestFrom     :: [Vertex g] -> g -> Forest (Vertex g)+    dfsForestFrom     = notImplemented+    dfs               :: [Vertex g] -> g -> [Vertex g]+    dfs               = notImplemented+    topSort           :: g -> Maybe [Vertex g]+    topSort           = notImplemented+    isTopSort         :: [Vertex g] -> g -> Bool+    isTopSort         = notImplemented++notImplemented :: a+notImplemented = error "Not implemented"++instance Ord a => GraphAPI (AdjacencyMap.AdjacencyMap a) where+    edge              = AdjacencyMap.edge+    vertices          = AdjacencyMap.vertices+    edges             = AdjacencyMap.edges+    overlays          = AdjacencyMap.overlays+    connects          = AdjacencyMap.connects+    graph             = AdjacencyMap.graph+    fromAdjacencyList = AdjacencyMap.fromAdjacencyList+    isSubgraphOf      = AdjacencyMap.isSubgraphOf+    isEmpty           = AdjacencyMap.isEmpty+    hasVertex         = AdjacencyMap.hasVertex+    hasEdge           = AdjacencyMap.hasEdge+    vertexCount       = AdjacencyMap.vertexCount+    edgeCount         = AdjacencyMap.edgeCount+    vertexList        = AdjacencyMap.vertexList+    edgeList          = AdjacencyMap.edgeList+    adjacencyList     = AdjacencyMap.adjacencyList+    vertexSet         = AdjacencyMap.vertexSet+    vertexIntSet      = IntSet.fromAscList . Set.toAscList . AdjacencyMap.vertexSet+    edgeSet           = AdjacencyMap.edgeSet+    postSet           = AdjacencyMap.postSet+    path              = AdjacencyMap.path+    circuit           = AdjacencyMap.circuit+    clique            = AdjacencyMap.clique+    biclique          = AdjacencyMap.biclique+    star              = AdjacencyMap.star+    tree              = AdjacencyMap.tree+    forest            = AdjacencyMap.forest+    removeVertex      = AdjacencyMap.removeVertex+    removeEdge        = AdjacencyMap.removeEdge+    replaceVertex     = AdjacencyMap.replaceVertex+    mergeVertices     = AdjacencyMap.mergeVertices+    transpose         = AdjacencyMap.transpose+    gmap              = AdjacencyMap.gmap+    induce            = AdjacencyMap.induce+    dfsForest         = AdjacencyMap.dfsForest+    dfsForestFrom     = AdjacencyMap.dfsForestFrom+    dfs               = AdjacencyMap.dfs+    topSort           = AdjacencyMap.topSort+    isTopSort         = AdjacencyMap.isTopSort++instance Ord a => GraphAPI (Fold.Fold a) where+    edge          = Fold.edge+    vertices      = Fold.vertices+    edges         = Fold.edges+    overlays      = Fold.overlays+    connects      = Fold.connects+    graph         = Fold.graph+    foldg         = Fold.foldg+    isSubgraphOf  = Fold.isSubgraphOf+    isEmpty       = Fold.isEmpty+    size          = Fold.size+    hasVertex     = Fold.hasVertex+    hasEdge       = Fold.hasEdge+    vertexCount   = Fold.vertexCount+    edgeCount     = Fold.edgeCount+    vertexList    = Fold.vertexList+    edgeList      = Fold.edgeList+    vertexSet     = Fold.vertexSet+    vertexIntSet  = Fold.vertexIntSet+    edgeSet       = Fold.edgeSet+    path          = Fold.path+    circuit       = Fold.circuit+    clique        = Fold.clique+    biclique      = Fold.biclique+    star          = Fold.star+    tree          = Fold.tree+    forest        = Fold.forest+    mesh          = Fold.mesh+    torus         = Fold.torus+    deBruijn      = Fold.deBruijn+    removeVertex  = Fold.removeVertex+    removeEdge    = Fold.removeEdge+    replaceVertex = Fold.replaceVertex+    mergeVertices = Fold.mergeVertices+    splitVertex   = Fold.splitVertex+    transpose     = Fold.transpose+    gmap          = fmap+    induce        = Fold.induce+    bind          = (>>=)+    simplify      = Fold.simplify+    box           = Fold.box++instance Ord a => GraphAPI (Graph.Graph a) where+    edge          = Graph.edge+    vertices      = Graph.vertices+    edges         = Graph.edges+    overlays      = Graph.overlays+    connects      = Graph.connects+    graph         = Graph.graph+    foldg         = Graph.foldg+    isSubgraphOf  = Graph.isSubgraphOf+    (===)         = (Graph.===)+    isEmpty       = Graph.isEmpty+    size          = Graph.size+    hasVertex     = Graph.hasVertex+    hasEdge       = Graph.hasEdge+    vertexCount   = Graph.vertexCount+    edgeCount     = Graph.edgeCount+    vertexList    = Graph.vertexList+    edgeList      = Graph.edgeList+    vertexSet     = Graph.vertexSet+    vertexIntSet  = Graph.vertexIntSet+    edgeSet       = Graph.edgeSet+    path          = Graph.path+    circuit       = Graph.circuit+    clique        = Graph.clique+    biclique      = Graph.biclique+    star          = Graph.star+    tree          = Graph.tree+    forest        = Graph.forest+    mesh          = Graph.mesh+    torus         = Graph.torus+    deBruijn      = Graph.deBruijn+    removeVertex  = Graph.removeVertex+    removeEdge    = Graph.removeEdge+    replaceVertex = Graph.replaceVertex+    mergeVertices = Graph.mergeVertices+    splitVertex   = Graph.splitVertex+    transpose     = Graph.transpose+    gmap          = fmap+    induce        = Graph.induce+    bind          = (>>=)+    simplify      = Graph.simplify+    box           = Graph.box++instance GraphAPI IntAdjacencyMap.IntAdjacencyMap where+    edge              = IntAdjacencyMap.edge+    vertices          = IntAdjacencyMap.vertices+    edges             = IntAdjacencyMap.edges+    overlays          = IntAdjacencyMap.overlays+    connects          = IntAdjacencyMap.connects+    graph             = IntAdjacencyMap.graph+    fromAdjacencyList = IntAdjacencyMap.fromAdjacencyList+    isSubgraphOf      = IntAdjacencyMap.isSubgraphOf+    isEmpty           = IntAdjacencyMap.isEmpty+    hasVertex         = IntAdjacencyMap.hasVertex+    hasEdge           = IntAdjacencyMap.hasEdge+    vertexCount       = IntAdjacencyMap.vertexCount+    edgeCount         = IntAdjacencyMap.edgeCount+    vertexList        = IntAdjacencyMap.vertexList+    edgeList          = IntAdjacencyMap.edgeList+    postIntSet        = IntAdjacencyMap.postIntSet+    adjacencyList     = IntAdjacencyMap.adjacencyList+    vertexSet         = Set.fromAscList . IntSet.toAscList . IntAdjacencyMap.vertexIntSet+    vertexIntSet      = IntAdjacencyMap.vertexIntSet+    edgeSet           = IntAdjacencyMap.edgeSet+    path              = IntAdjacencyMap.path+    circuit           = IntAdjacencyMap.circuit+    clique            = IntAdjacencyMap.clique+    biclique          = IntAdjacencyMap.biclique+    star              = IntAdjacencyMap.star+    tree              = IntAdjacencyMap.tree+    forest            = IntAdjacencyMap.forest+    removeVertex      = IntAdjacencyMap.removeVertex+    removeEdge        = IntAdjacencyMap.removeEdge+    replaceVertex     = IntAdjacencyMap.replaceVertex+    mergeVertices     = IntAdjacencyMap.mergeVertices+    transpose         = IntAdjacencyMap.transpose+    gmap              = IntAdjacencyMap.gmap+    induce            = IntAdjacencyMap.induce+    dfsForest         = IntAdjacencyMap.dfsForest+    dfsForestFrom     = IntAdjacencyMap.dfsForestFrom+    dfs               = IntAdjacencyMap.dfs+    topSort           = IntAdjacencyMap.topSort+    isTopSort         = IntAdjacencyMap.isTopSort++instance Ord a => GraphAPI (Relation.Relation a) where+    edge              = Relation.edge+    vertices          = Relation.vertices+    edges             = Relation.edges+    overlays          = Relation.overlays+    connects          = Relation.connects+    graph             = Relation.graph+    fromAdjacencyList = Relation.fromAdjacencyList+    isSubgraphOf      = Relation.isSubgraphOf+    isEmpty           = Relation.isEmpty+    hasVertex         = Relation.hasVertex+    hasEdge           = Relation.hasEdge+    vertexCount       = Relation.vertexCount+    edgeCount         = Relation.edgeCount+    vertexList        = Relation.vertexList+    edgeList          = Relation.edgeList+    preSet            = Relation.preSet+    postSet           = Relation.postSet+    adjacencyList     = AdjacencyMap.adjacencyList . toGraph+    vertexSet         = Relation.vertexSet+    vertexIntSet      = IntSet.fromAscList . Set.toAscList . Relation.vertexSet+    edgeSet           = Relation.edgeSet+    path              = Relation.path+    circuit           = Relation.circuit+    clique            = Relation.clique+    biclique          = Relation.biclique+    star              = Relation.star+    tree              = Relation.tree+    forest            = Relation.forest+    removeVertex      = Relation.removeVertex+    removeEdge        = Relation.removeEdge+    replaceVertex     = Relation.replaceVertex+    mergeVertices     = Relation.mergeVertices+    transpose         = Relation.transpose+    gmap              = Relation.gmap+    induce            = Relation.induce
test/Algebra/Graph/Test/AdjacencyMap.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ViewPatterns #-} ----------------------------------------------------------------------------- -- | -- Module     : Algebra.Graph.Test.AdjacencyMap@@ -7,26 +6,25 @@ -- Maintainer : andrey.mokhov@gmail.com -- Stability  : experimental ----- Testsuite for 'AdjacencyMap'.---+-- Testsuite for "Algebra.Graph.AdjacencyMap". ----------------------------------------------------------------------------- module Algebra.Graph.Test.AdjacencyMap (     -- * Testsuite     testAdjacencyMap   ) where -import Data.Tree- import Algebra.Graph.AdjacencyMap import Algebra.Graph.AdjacencyMap.Internal import Algebra.Graph.Test+import Algebra.Graph.Test.Generic  import qualified Data.Graph as KL import qualified Data.Set   as Set +t :: Testsuite+t = testsuite "AdjacencyMap." empty+ type AI = AdjacencyMap Int-type II = Int -> Int-type IB = Int -> Bool  testAdjacencyMap :: IO () testAdjacencyMap = do@@ -39,578 +37,20 @@     test "Consistency of fromAdjacencyList" $ \xs ->         consistent (fromAdjacencyList xs :: AI) -    putStrLn "\n============ AdjacencyMap.Show ============"-    test "show (empty     :: AdjacencyMap Int) == \"empty\"" $-          show (empty     :: AdjacencyMap Int) == "empty"--    test "show (1         :: AdjacencyMap Int) == \"vertex 1\"" $-          show (1         :: AdjacencyMap Int) == "vertex 1"--    test "show (1 + 2     :: AdjacencyMap Int) == \"vertices [1,2]\"" $-          show (1 + 2     :: AdjacencyMap Int) == "vertices [1,2]"--    test "show (1 * 2     :: AdjacencyMap Int) == \"edge 1 2\"" $-          show (1 * 2     :: AdjacencyMap Int) == "edge 1 2"--    test "show (1 * 2 * 3 :: AdjacencyMap Int) == \"edges [(1,2),(1,3),(2,3)]\"" $-          show (1 * 2 * 3 :: AdjacencyMap Int) == "edges [(1,2),(1,3),(2,3)]"--    test "show (1 * 2 + 3 :: AdjacencyMap Int) == \"graph [1,2,3] [(1,2)]\"" $-          show (1 * 2 + 3 :: AdjacencyMap Int) == "graph [1,2,3] [(1,2)]"--    putStrLn "\n============ AdjacencyMap.empty ============"-    test "isEmpty     empty == True" $-          isEmpty    (empty :: AI) == True--    test "hasVertex x empty == False" $ \(x :: Int) ->-          hasVertex x empty == False--    test "vertexCount empty == 0" $-          vertexCount(empty :: AI) == 0--    test "edgeCount   empty == 0" $-          edgeCount  (empty :: AI) == 0--    putStrLn "\n============ AdjacencyMap.vertex ============"-    test "isEmpty     (vertex x) == False" $ \(x :: Int) ->-          isEmpty     (vertex x) == False--    test "hasVertex x (vertex x) == True" $ \(x :: Int) ->-          hasVertex x (vertex x) == True--    test "hasVertex 1 (vertex 2) == False" $-          hasVertex 1 (vertex 2 :: AI) == False--    test "vertexCount (vertex x) == 1" $ \(x :: Int) ->-          vertexCount (vertex x) == 1--    test "edgeCount   (vertex x) == 0" $ \(x :: Int) ->-          edgeCount   (vertex x) == 0--    putStrLn "\n============ AdjacencyMap.edge ============"-    test "edge x y               == connect (vertex x) (vertex y)" $ \(x :: Int) y ->-         (edge x y :: AI)        == connect (vertex x) (vertex y)--    test "hasEdge x y (edge x y) == True" $ \(x :: Int) y ->-          hasEdge x y (edge x y) == True--    test "edgeCount   (edge x y) == 1" $ \(x :: Int) y ->-          edgeCount   (edge x y) == 1--    test "vertexCount (edge 1 1) == 1" $-          vertexCount (edge 1 1 :: AI) == 1--    test "vertexCount (edge 1 2) == 2" $-          vertexCount (edge 1 2 :: AI) == 2--    putStrLn "\n============ AdjacencyMap.overlay ============"-    test "isEmpty     (overlay x y) == isEmpty   x   && isEmpty   y" $ \(x :: AI) y ->-          isEmpty     (overlay x y) == (isEmpty   x   && isEmpty   y)--    test "hasVertex z (overlay x y) == hasVertex z x || hasVertex z y" $ \(x :: AI) y z ->-          hasVertex z (overlay x y) == (hasVertex z x || hasVertex z y)--    test "vertexCount (overlay x y) >= vertexCount x" $ \(x :: AI) y ->-          vertexCount (overlay x y) >= vertexCount x--    test "vertexCount (overlay x y) <= vertexCount x + vertexCount y" $ \(x :: AI) y ->-          vertexCount (overlay x y) <= vertexCount x + vertexCount y--    test "edgeCount   (overlay x y) >= edgeCount x" $ \(x :: AI) y ->-          edgeCount   (overlay x y) >= edgeCount x--    test "edgeCount   (overlay x y) <= edgeCount x   + edgeCount y" $ \(x :: AI) y ->-          edgeCount   (overlay x y) <= edgeCount x   + edgeCount y--    test "vertexCount (overlay 1 2) == 2" $-          vertexCount (overlay 1 2 :: AI) == 2--    test "edgeCount   (overlay 1 2) == 0" $-          edgeCount   (overlay 1 2 :: AI) == 0--    putStrLn "\n============ AdjacencyMap.connect ============"-    test "isEmpty     (connect x y) == isEmpty   x   && isEmpty   y" $ \(x :: AI) y ->-          isEmpty     (connect x y) == (isEmpty   x   && isEmpty   y)--    test "hasVertex z (connect x y) == hasVertex z x || hasVertex z y" $ \(x :: AI) y z ->-          hasVertex z (connect x y) == (hasVertex z x || hasVertex z y)--    test "vertexCount (connect x y) >= vertexCount x" $ \(x :: AI) y ->-          vertexCount (connect x y) >= vertexCount x--    test "vertexCount (connect x y) <= vertexCount x + vertexCount y" $ \(x :: AI) y ->-          vertexCount (connect x y) <= vertexCount x + vertexCount y--    test "edgeCount   (connect x y) >= edgeCount x" $ \(x :: AI) y ->-          edgeCount   (connect x y) >= edgeCount x--    test "edgeCount   (connect x y) >= edgeCount y" $ \(x :: AI) y ->-          edgeCount   (connect x y) >= edgeCount y--    test "edgeCount   (connect x y) >= vertexCount x * vertexCount y" $ \(x :: AI) y ->-          edgeCount   (connect x y) >= vertexCount x * vertexCount y--    test "edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y" $ \(x :: AI) y ->-          edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y--    test "vertexCount (connect 1 2) == 2" $-          vertexCount (connect 1 2 :: AI) == 2--    test "edgeCount   (connect 1 2) == 1" $-          edgeCount   (connect 1 2 :: AI) == 1--    putStrLn "\n============ AdjacencyMap.vertices ============"-    test "vertices []            == empty" $-          vertices []            == (empty :: AI)--    test "vertices [x]           == vertex x" $ \(x :: Int) ->-          vertices [x]           == (vertex x :: AI)--    test "hasVertex x . vertices == elem x" $ \x (xs :: [Int]) ->-         (hasVertex x . vertices) xs == elem x xs--    test "vertexCount . vertices == length . nub" $ \(xs :: [Int]) ->-         (vertexCount . vertices) xs == (length . nubOrd) xs--    test "vertexSet   . vertices == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet   . vertices) xs == Set.fromList xs--    putStrLn "\n============ AdjacencyMap.edges ============"-    test "edges []          == empty" $-          edges []          == (empty :: AI)--    test "edges [(x,y)]     == edge x y" $ \(x :: Int) y ->-          edges [(x,y)]     == (edge x y :: AI)--    test "edgeCount . edges == length . nub" $ \(xs :: [(Int, Int)]) ->-         (edgeCount . edges) xs == (length . nubOrd) xs--    putStrLn "\n============ AdjacencyMap.overlays ============"-    test "overlays []        == empty" $-          overlays []        == (empty :: AI)--    test "overlays [x]       == x" $ \(x :: AI) ->-          overlays [x]       == x--    test "overlays [x,y]     == overlay x y" $ \(x :: AI) y ->-          overlays [x,y]     == overlay x y--    test "isEmpty . overlays == all isEmpty" $ mapSize (min 10) $ \(xs :: [AI]) ->-         (isEmpty . overlays) xs == all isEmpty xs--    putStrLn "\n============ AdjacencyMap.connects ============"-    test "connects []        == empty" $-          connects []        == (empty :: AI)--    test "connects [x]       == x" $ \(x :: AI) ->-          connects [x]       == x--    test "connects [x,y]     == connect x y" $ \(x :: AI) y ->-          connects [x,y]     == connect x y--    test "isEmpty . connects == all isEmpty" $ mapSize (min 10) $ \(xs :: [AI]) ->-         (isEmpty . connects) xs == all isEmpty xs--    putStrLn "\n============ AdjacencyMap.graph ============"-    test "graph []  []      == empty" $-          graph []  []      == (empty :: AI)--    test "graph [x] []      == vertex x" $ \(x :: Int) ->-          graph [x] []      == (vertex x :: AI)--    test "graph []  [(x,y)] == edge x y" $ \(x :: Int) y ->-          graph []  [(x,y)] == (edge x y :: AI)--    test "graph vs  es      == overlay (vertices vs) (edges es)" $ \(vs :: [Int]) es ->-          graph vs  es      == (overlay (vertices vs) (edges es) :: AI)--    putStrLn "\n============ AdjacencyMap.fromAdjacencyList ============"-    test "fromAdjacencyList []                                  == empty" $-          fromAdjacencyList []                                  == (empty :: AI)--    test "fromAdjacencyList [(x, [])]                           == vertex x" $ \(x :: Int) ->-          fromAdjacencyList [(x, [])]                           == vertex x--    test "fromAdjacencyList [(x, [y])]                          == edge x y" $ \(x :: Int) y ->-          fromAdjacencyList [(x, [y])]                          == edge x y--    test "fromAdjacencyList . adjacencyList                     == id" $ \(x :: AI) ->-         (fromAdjacencyList . adjacencyList) x                  == x--    test "overlay (fromAdjacencyList xs) (fromAdjacencyList ys) == fromAdjacencyList (xs ++ ys)" $ \xs ys ->-          overlay (fromAdjacencyList xs) (fromAdjacencyList ys) ==(fromAdjacencyList (xs ++ ys) :: AI)--    putStrLn "\n============ AdjacencyMap.isSubgraphOf ============"-    test "isSubgraphOf empty         x             == True" $ \(x :: AI) ->-          isSubgraphOf empty         x             == True--    test "isSubgraphOf (vertex x)    empty         == False" $ \x ->-          isSubgraphOf (vertex x)   (empty :: AI)   == False--    test "isSubgraphOf x             (overlay x y) == True" $ \(x :: AI) y ->-          isSubgraphOf x             (overlay x y) == True--    test "isSubgraphOf (overlay x y) (connect x y) == True" $ \(x :: AI) y ->-          isSubgraphOf (overlay x y) (connect x y) == True--    test "isSubgraphOf (path xs)     (circuit xs)  == True" $ \xs ->-          isSubgraphOf (path xs :: AI)(circuit xs)  == True--    putStrLn "\n============ AdjacencyMap.isEmpty ============"-    test "isEmpty empty                       == True" $-          isEmpty (empty :: AI)                == True--    test "isEmpty (overlay empty empty)       == True" $-          isEmpty (overlay empty empty :: AI)  == True--    test "isEmpty (vertex x)                  == False" $ \(x :: Int) ->-          isEmpty (vertex x)                  == False--    test "isEmpty (removeVertex x $ vertex x) == True" $ \(x :: Int) ->-          isEmpty (removeVertex x $ vertex x) == True--    test "isEmpty (removeEdge x y $ edge x y) == False" $ \(x :: Int) y ->-          isEmpty (removeEdge x y $ edge x y) == False--    putStrLn "\n============ AdjacencyMap.hasVertex ============"-    test "hasVertex x empty            == False" $ \(x :: Int) ->-          hasVertex x empty            == False--    test "hasVertex x (vertex x)       == True" $ \(x :: Int) ->-          hasVertex x (vertex x)       == True--    test "hasVertex x . removeVertex x == const False" $ \(x :: Int) y ->-          hasVertex x (removeVertex x y)==const False y--    putStrLn "\n============ AdjacencyMap.hasEdge ============"-    test "hasEdge x y empty            == False" $ \(x :: Int) y ->-          hasEdge x y empty            == False--    test "hasEdge x y (vertex z)       == False" $ \(x :: Int) y z ->-          hasEdge x y (vertex z)       == False--    test "hasEdge x y (edge x y)       == True" $ \(x :: Int) y ->-          hasEdge x y (edge x y)       == True--    test "hasEdge x y . removeEdge x y == const False" $ \(x :: Int) y z ->-          hasEdge x y (removeEdge x y z)==const False z--    putStrLn "\n============ AdjacencyMap.vertexCount ============"-    test "vertexCount empty      == 0" $-          vertexCount (empty :: AI) == 0--    test "vertexCount (vertex x) == 1" $ \(x :: Int) ->-          vertexCount (vertex x) == 1--    test "vertexCount            == length . vertexList" $ \(x :: AI) ->-          vertexCount x          == (length . vertexList) x--    putStrLn "\n============ AdjacencyMap.edgeCount ============"-    test "edgeCount empty      == 0" $-          edgeCount (empty :: AI) == 0--    test "edgeCount (vertex x) == 0" $ \(x :: Int) ->-          edgeCount (vertex x) == 0--    test "edgeCount (edge x y) == 1" $ \(x :: Int) y ->-          edgeCount (edge x y) == 1--    test "edgeCount            == length . edgeList" $ \(x :: AI) ->-          edgeCount x          == (length . edgeList) x--    putStrLn "\n============ AdjacencyMap.vertexList ============"-    test "vertexList empty      == []" $-          vertexList (empty :: AI) == []--    test "vertexList (vertex x) == [x]" $ \(x :: Int) ->-          vertexList (vertex x) == [x]--    test "vertexList . vertices == nub . sort" $ \(xs :: [Int]) ->-         (vertexList . vertices) xs == (nubOrd . sort) xs--    putStrLn "\n============ AdjacencyMap.edgeList ============"-    test "edgeList empty          == []" $-          edgeList (empty :: AI )  == []--    test "edgeList (vertex x)     == []" $ \(x :: Int) ->-          edgeList (vertex x)     == []--    test "edgeList (edge x y)     == [(x,y)]" $ \(x :: Int) y ->-          edgeList (edge x y)     == [(x,y)]--    test "edgeList (star 2 [3,1]) == [(2,1), (2,3)]" $-          edgeList (star 2 [3,1]) == [(2,1), (2,3 :: Int)]--    test "edgeList . edges        == nub . sort" $ \(xs :: [(Int, Int)]) ->-         (edgeList . edges) xs    == (nubOrd . sort) xs--    putStrLn "\n============ AdjacencyMap.adjacencyList ============"-    test "adjacencyList empty          == []" $-          adjacencyList (empty :: AI)  == []--    test "adjacencyList (vertex x)     == [(x, [])]" $ \(x :: Int) ->-          adjacencyList (vertex x)     == [(x, [])]--    test "adjacencyList (edge 1 2)     == [(1, [2]), (2, [])]" $-          adjacencyList (edge 1 (2 :: Int)) == [(1, [2]), (2, [])]--    test "adjacencyList (star 2 [3,1]) == [(1, []), (2, [1,3]), (3, [])]" $-          adjacencyList (star 2 [3,1::Int]) == [(1, []), (2, [1,3]), (3, [])]--    putStrLn "\n============ AdjacencyMap.vertexSet ============"-    test "vertexSet empty      == Set.empty" $-          vertexSet(empty :: AI)== Set.empty--    test "vertexSet . vertex   == Set.singleton" $ \(x :: Int) ->-         (vertexSet . vertex) x== Set.singleton x--    test "vertexSet . vertices == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet . vertices) xs == Set.fromList xs--    test "vertexSet . clique   == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet . clique) xs == Set.fromList xs--    putStrLn "\n============ AdjacencyMap.edgeSet ============"-    test "edgeSet empty      == Set.empty" $-          edgeSet (empty :: AI) == Set.empty--    test "edgeSet (vertex x) == Set.empty" $ \(x :: Int) ->-          edgeSet (vertex x) == Set.empty--    test "edgeSet (edge x y) == Set.singleton (x,y)" $ \(x :: Int) y ->-          edgeSet (edge x y) == Set.singleton (x,y)--    test "edgeSet . edges    == Set.fromList" $ \(xs :: [(Int, Int)]) ->-         (edgeSet . edges) xs== Set.fromList xs--    putStrLn "\n============ AdjacencyMap.postset ============"-    test "postset x empty      == Set.empty" $ \(x :: Int) ->-          postset x empty      == Set.empty--    test "postset x (vertex x) == Set.empty" $ \(x :: Int) ->-          postset x (vertex x) == Set.empty--    test "postset x (edge x y) == Set.fromList [y]" $ \(x :: Int) y ->-          postset x (edge x y) == Set.fromList [y]--    test "postset 2 (edge 1 2) == Set.empty" $-          postset 2 (edge 1 2) ==(Set.empty :: Set.Set Int)--    putStrLn "\n============ AdjacencyMap.path ============"-    test "path []    == empty" $-          path []    == (empty :: AI)--    test "path [x]   == vertex x" $ \(x :: Int) ->-          path [x]   == (vertex x :: AI)--    test "path [x,y] == edge x y" $ \(x :: Int) y ->-          path [x,y] == (edge x y :: AI)--    putStrLn "\n============ AdjacencyMap.circuit ============"-    test "circuit []    == empty" $-          circuit []    == (empty :: AI)--    test "circuit [x]   == edge x x" $ \(x :: Int) ->-          circuit [x]   == (edge x x :: AI)--    test "circuit [x,y] == edges [(x,y), (y,x)]" $ \(x :: Int) y ->-          circuit [x,y] == (edges [(x,y), (y,x)] :: AI)--    putStrLn "\n============ AdjacencyMap.clique ============"-    test "clique []      == empty" $-          clique []      == (empty :: AI)--    test "clique [x]     == vertex x" $ \(x :: Int) ->-          clique [x]     == (vertex x :: AI)--    test "clique [x,y]   == edge x y" $ \(x :: Int) y ->-          clique [x,y]   == (edge x y :: AI)--    test "clique [x,y,z] == edges [(x,y), (x,z), (y,z)]" $ \(x :: Int) y z ->-          clique [x,y,z] == (edges [(x,y), (x,z), (y,z)] :: AI)--    putStrLn "\n============ AdjacencyMap.biclique ============"-    test "biclique []      []      == empty" $-          biclique []      []      == (empty :: AI)--    test "biclique [x]     []      == vertex x" $ \(x :: Int) ->-          biclique [x]     []      == (vertex x :: AI)--    test "biclique []      [y]     == vertex y" $ \(y :: Int) ->-          biclique []      [y]     == (vertex y :: AI)--    test "biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]" $ \(x1 :: Int) x2 y1 y2 ->-          biclique [x1,x2] [y1,y2] == (edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)] :: AI)--    test "biclique xs      ys      == connect (vertices xs) (vertices ys)" $ \(xs :: [Int]) ys ->-          biclique xs      ys      == connect (vertices xs) (vertices ys)--    putStrLn "\n============ AdjacencyMap.star ============"-    test "star x []    == vertex x" $ \(x :: Int) ->-          star x []    == (vertex x :: AI)--    test "star x [y]   == edge x y" $ \(x :: Int) y ->-          star x [y]   == (edge x y :: AI)--    test "star x [y,z] == edges [(x,y), (x,z)]" $ \(x :: Int) y z ->-          star x [y,z] == (edges [(x,y), (x,z)] :: AI)--    putStrLn "\n============ AdjacencyMap.tree ============"-    test "tree (Node x [])                                         == vertex x" $ \(x :: Int) ->-          tree (Node x [])                                         == vertex x--    test "tree (Node x [Node y [Node z []]])                       == path [x,y,z]" $ \(x :: Int) y z ->-          tree (Node x [Node y [Node z []]])                       == path [x,y,z]--    test "tree (Node x [Node y [], Node z []])                     == star x [y,z]" $ \(x :: Int) y z ->-          tree (Node x [Node y [], Node z []])                     == star x [y,z]--    test "tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5)]" $-          tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5::Int)]--    putStrLn "\n============ AdjacencyMap.forest ============"-    test "forest []                                                  == empty" $-          forest []                                                  == (empty :: AI)--    test "forest [x]                                                 == tree x" $ \(x :: Tree Int) ->-          forest [x]                                                 == tree x--    test "forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5)]" $-          forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5::Int)]--    test "forest                                                     == overlays . map tree" $ \(x :: Forest Int) ->-         (forest x)                                                  ==(overlays . map tree) x--    putStrLn "\n============ AdjacencyMap.removeVertex ============"-    test "removeVertex x (vertex x)       == empty" $ \(x :: Int) ->-          removeVertex x (vertex x)       == (empty :: AI)--    test "removeVertex x . removeVertex x == removeVertex x" $ \x (y :: AI) ->-         (removeVertex x . removeVertex x)y==(removeVertex x y :: AI)--    putStrLn "\n============ AdjacencyMap.removeEdge ============"-    test "removeEdge x y (edge x y)       == vertices [x, y]" $ \(x :: Int) y ->-          removeEdge x y (edge x y)       == (vertices [x, y] :: AI)--    test "removeEdge x y . removeEdge x y == removeEdge x y" $ \(x :: Int) y z ->-         (removeEdge x y . removeEdge x y)z==(removeEdge x y z :: AI)--    test "removeEdge x y . removeVertex x == removeVertex x" $ \(x :: Int) y z ->-         (removeEdge x y . removeVertex x)z==(removeVertex x z :: AI)--    test "removeEdge 1 1 (1 * 1 * 2 * 2)  == 1 * 2 * 2" $-          removeEdge 1 1 (1 * 1 * 2 * 2)  == (1 * 2 * (2 :: AI))--    test "removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2" $-          removeEdge 1 2 (1 * 1 * 2 * 2)  == (1 * 1 + 2 * (2 :: AI))--    putStrLn "\n============ AdjacencyMap.replaceVertex ============"-    test "replaceVertex x x            == id" $ \x (y :: AI) ->-          replaceVertex x x y          == y--    test "replaceVertex x y (vertex x) == vertex y" $ \x (y :: Int) ->-          replaceVertex x y (vertex x) == (vertex y :: AI)--    test "replaceVertex x y            == mergeVertices (== x) y" $ \x y z ->-          replaceVertex x y z          == (mergeVertices (== x) y z :: AI)--    putStrLn "\n============ AdjacencyMap.mergeVertices ============"-    test "mergeVertices (const False) x    == id" $ \x (y :: AI) ->-          mergeVertices (const False) x y  == y--    test "mergeVertices (== x) y           == replaceVertex x y" $ \x y (z :: AI) ->-          mergeVertices (== x) y z         == (replaceVertex x y z :: AI)--    test "mergeVertices even 1 (0 * 2)     == 1 * 1" $-          mergeVertices even 1 (0 * 2)     == (1 * 1 :: AI)--    test "mergeVertices odd  1 (3 + 4 * 5) == 4 * 1" $-          mergeVertices odd  1 (3 + 4 * 5) == (4 * 1 :: AI)--    putStrLn "\n============ AdjacencyMap.gmap ============"-    test "gmap f empty      == empty" $ \(apply -> f :: II) ->-          gmap f empty      == empty--    test "gmap f (vertex x) == vertex (f x)" $ \(apply -> f :: II) x ->-          gmap f (vertex x) == vertex (f x)--    test "gmap f (edge x y) == edge (f x) (f y)" $ \(apply -> f :: II) x y ->-          gmap f (edge x y) == edge (f x) (f y)--    test "gmap id           == id" $ \x ->-          gmap id x         == (x :: AI)--    test "gmap f . gmap g   == gmap (f . g)" $ \(apply -> f :: II) (apply -> g :: II) x ->-         (gmap f . gmap g) x== gmap (f . g) x--    putStrLn "\n============ AdjacencyMap.induce ============"-    test "induce (const True)  x      == x" $ \(x :: AI) ->-          induce (const True)  x      == x--    test "induce (const False) x      == empty" $ \(x :: AI) ->-          induce (const False) x      == (empty :: AI)--    test "induce (/= x)               == removeVertex x" $ \x (y :: AI) ->-          induce (/= x) y             == (removeVertex x y :: AI)--    test "induce p . induce q         == induce (\\x -> p x && q x)" $ \(apply -> p :: IB) (apply -> q :: IB) (y :: AI) ->-         (induce p . induce q) y      == (induce (\x -> p x && q x) y :: AI)--    test "isSubgraphOf (induce p x) x == True" $ \(apply -> p :: IB) (x :: AI) ->-          isSubgraphOf (induce p x) x == True--    putStrLn "\n============ AdjacencyMap.dfsForest ============"-    test "forest (dfsForest $ edge 1 1)         == vertex 1" $-          forest (dfsForest $ edge 1 (1 :: Int))==(vertex 1 :: AI)--    test "forest (dfsForest $ edge 1 2)         == edge 1 2" $-          forest (dfsForest $ edge 1 (2 :: Int))==(edge 1 2 :: AI)--    test "forest (dfsForest $ edge 2 1)         == vertices [1, 2]" $-          forest (dfsForest $ edge 2 (1 :: Int))==(vertices [1, 2] :: AI)--    test "isSubgraphOf (forest $ dfsForest x) x == True" $ \(x :: AI) ->-          isSubgraphOf (forest $ dfsForest x) x == True--    test "dfsForest . forest . dfsForest        == dfsForest" $ \(x :: AI) ->-         (dfsForest . forest . dfsForest) x     == dfsForest x--    test "dfsForest $ 3 * (1 + 4) * (1 + 5)     == <correct result>" $-          dfsForest  (3 * (1 + 4) * (1 + 5))    == [ Node { rootLabel = 1 :: Int-                                                   , subForest = [ Node { rootLabel = 5-                                                                        , subForest = [] }]}-                                                   , Node { rootLabel = 3-                                                   , subForest = [ Node { rootLabel = 4-                                                                        , subForest = [] }]}]--    putStrLn "\n============ AdjacencyMap.topSort ============"-    test "topSort (1 * 2 + 3 * 1)             == Just [3,1,2]" $-          topSort (1 * 2 + 3 * 1)             == Just [3,1,2 :: Int]--    test "topSort (1 * 2 + 2 * 1)             == Nothing" $-          topSort (1 * 2 + 2 * 1 :: AI)       == Nothing--    test "fmap (flip isTopSort x) (topSort x) /= Just False" $ \(x :: AI) ->-          fmap (flip isTopSort x) (topSort x) /= Just False--    putStrLn "\n============ AdjacencyMap.isTopSort  ============"-    test "isTopSort [3, 1, 2] (1 * 2 + 3 * 1) == True" $-          isTopSort [3, 1, 2] (1 * 2 + 3 * 1 :: AI) == True--    test "isTopSort [1, 2, 3] (1 * 2 + 3 * 1) == False" $-          isTopSort [1, 2, 3] (1 * 2 + 3 * 1 :: AI) == False--    test "isTopSort []        (1 * 2 + 3 * 1) == False" $-          isTopSort []        (1 * 2 + 3 * 1 :: AI) == False--    test "isTopSort []        empty           == True" $-          isTopSort []       (empty :: AI)    == True--    test "isTopSort [x]       (vertex x)      == True" $ \(x :: Int) ->-          isTopSort [x]       (vertex x)      == True--    test "isTopSort [x]       (edge x x)      == False" $ \(x :: Int) ->-          isTopSort [x]       (edge x x)      == False+    testShow              t+    testBasicPrimitives   t+    testFromAdjacencyList t+    testIsSubgraphOf      t+    testProperties        t+    testAdjacencyList     t+    testPostSet           t+    testGraphFamilies     t+    testTransformations   t+    testDfsForest         t+    testDfsForestFrom     t+    testDfs               t+    testTopSort           t+    testIsTopSort         t      putStrLn "\n============ AdjacencyMap.scc ============"     test "scc empty               == empty" $@@ -631,14 +71,11 @@                                            , (Set.fromList [3]  , Set.fromList [1,4])                                            , (Set.fromList [3]  , Set.fromList [5 :: Int])] -    putStrLn "\n============ AdjacencyMap.GraphKL ============"-    test "map (getVertex h) (vertices $ getGraph h) == Set.toAscList (vertexSet g)"-      $ \(g :: AI) -> let h = graphKL g in-        map (getVertex h) (KL.vertices $ getGraph h) == Set.toAscList (vertexSet g)--    test "map (\\(x, y) -> (getVertex h x, getVertex h y)) (edges $ getGraph h) == edgeList g"-      $ \(g :: AI) -> let h = graphKL g in-        map (\(x, y) -> (getVertex h x, getVertex h y)) (KL.edges $ getGraph h) == edgeList g+    putStrLn "\n============ AdjacencyMap.Internal.GraphKL ============"+    test "map (fromVertexKL h) (vertices $ toGraphKL h) == vertexList g"+      $ \(g :: AI) -> let h = mkGraphKL (adjacencyMap g) in+          map (fromVertexKL h) (KL.vertices $ toGraphKL h) == vertexList g -    test "fromGraphKL . graphKL == id" $ \(x :: AI) ->-        (fromGraphKL . graphKL) x == x+    test "map (\\(x, y) -> (fromVertexKL h x, fromVertexKL h y)) (edges $ toGraphKL h) == edgeList g"+      $ \(g :: AI) -> let h = mkGraphKL (adjacencyMap g) in+          map ( \(x, y) -> (fromVertexKL h x, fromVertexKL h y)) (KL.edges $ toGraphKL h) == edgeList g
test/Algebra/Graph/Test/Arbitrary.hs view
@@ -20,15 +20,16 @@  import Algebra.Graph import Algebra.Graph.AdjacencyMap.Internal+import Algebra.Graph.Export import Algebra.Graph.Fold (Fold) import Algebra.Graph.IntAdjacencyMap.Internal import Algebra.Graph.Relation.Internal import Algebra.Graph.Relation.InternalDerived -import qualified Algebra.Graph.Class             as C-import qualified Algebra.Graph.AdjacencyMap      as AdjacencyMap-import qualified Algebra.Graph.IntAdjacencyMap   as IntAdjacencyMap-import qualified Algebra.Graph.Relation          as Relation+import qualified Algebra.Graph.Class           as C+import qualified Algebra.Graph.AdjacencyMap    as AdjacencyMap+import qualified Algebra.Graph.IntAdjacencyMap as IntAdjacencyMap+import qualified Algebra.Graph.Relation        as Relation  -- | Generate an arbitrary 'Graph' value of a specified size. arbitraryGraph :: (C.Graph g, Arbitrary (C.Vertex g)) => Gen g@@ -102,3 +103,6 @@             root     <- arbitrary             children <- replicateM subTrees (go subSize)             return $ Node root children++instance Arbitrary s => Arbitrary (Doc s) where+    arbitrary = (mconcat . map literal) <$> arbitrary
+ test/Algebra/Graph/Test/Export.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module     : Algebra.Graph.Test.Export+-- Copyright  : (c) Andrey Mokhov 2016-2017+-- License    : MIT (see the file LICENSE)+-- Maintainer : andrey.mokhov@gmail.com+-- Stability  : experimental+--+-- Testsuite for "Algebra.Graph.Export" and "Algebra.Graph.Export.Dot".+-----------------------------------------------------------------------------+module Algebra.Graph.Test.Export (+    -- * Testsuite+    testExport+  ) where++import Prelude+import Data.Monoid++import Algebra.Graph (Graph, circuit)+import Algebra.Graph.Export hiding (unlines)+import Algebra.Graph.Export.Dot (Attribute (..))+import Algebra.Graph.Test++import qualified Algebra.Graph.Export     as E+import qualified Algebra.Graph.Export.Dot as ED++testExport :: IO ()+testExport = do+    putStrLn "\n============ Export.literal ============"+    test "literal \"Hello, \" <> literal \"World!\" == literal \"Hello, World!\"" $+          literal "Hello, " <> literal "World!" == literal ("Hello, World!" :: String)++    test "literal \"I am just a string literal\"  == \"I am just a string literal\"" $+          literal "I am just a string literal"  == ("I am just a string literal" :: Doc String)++    test "literal mempty                        == mempty" $+          literal mempty                        == (mempty :: Doc String)++    test "render . literal                      == id" $ \(x :: String) ->+         (render . literal) x                   == x++    test "literal . render                      == id" $ \(xs :: [String]) -> let x = mconcat (map literal xs) in+         (literal . render) x                   == x++    putStrLn "\n============ Export.render ============"+    test "render (literal \"al\" <> literal \"ga\") == \"alga\"" $+          render (literal "al" <> literal "ga") == ("alga" :: String)++    test "render mempty                         == mempty" $+          render mempty                         == (mempty :: Doc String)++    putStrLn "\n============ Export.<+> ============"+    test "x <+> mempty         == x" $ \(x :: Doc String) ->+          x <+> mempty         == x++    test "mempty <+> x         == x" $ \(x :: Doc String) ->+          mempty <+> x         == x++    test "x <+> (y <+> z)      == (x <+> y) <+> z" $ \(x :: Doc String) y z ->+          x <+> (y <+> z)      == (x <+> y) <+> z++    test "\"name\" <+> \"surname\" == \"name surname\"" $+          "name" <+> "surname" == ("name surname" :: Doc String)++    putStrLn "\n============ Export.brackets ============"+    test "brackets \"i\"    == \"[i]\"" $+          brackets "i"    == ("[i]" :: Doc String)++    test "brackets mempty == \"[]\"" $+          brackets mempty == ("[]" :: Doc String)++    putStrLn "\n============ Export.doubleQuotes ============"+    test "doubleQuotes \"/path/with spaces\"   == \"\\\"/path/with spaces\\\"\"" $+          doubleQuotes "/path/with spaces"    == ("\"/path/with spaces\"" :: Doc String)++    test "doubleQuotes (doubleQuotes mempty) == \"\\\"\\\"\\\"\\\"\"" $+          doubleQuotes (doubleQuotes mempty) == ("\"\"\"\"" :: Doc String)++    putStrLn "\n============ Export.indent ============"+    test "indent 0        == id" $ \(x :: String) ->+         (indent 0) (literal x) == literal x++    test "indent 1 mempty == \" \"" $+          indent 1 mempty == (" " :: Doc String)++    putStrLn "\n============ Export.unlines ============"+    test "unlines []                    == mempty" $+        E.unlines []                    == (mempty :: Doc String)++    test "unlines [mempty]              == \"\\n\"" $+        E.unlines [mempty]              == ("\n" :: Doc String)++    test "unlines [\"title\", \"subtitle\"] == \"title\\nsubtitle\\n\"" $+        E.unlines ["title",    "subtitle" ] == ("title\nsubtitle\n" :: Doc String)++    putStrLn "\n============ Export.export ============"+    let vDoc x   = literal (show x) <> "\n"+        eDoc x y = literal (show x) <> " -> " <> literal (show y) <> "\n"+    test "render $ export vDoc eDoc (1 + 2 * (3 + 4) :: Graph Int)" $+         (render (export vDoc eDoc (1 + 2 * (3 + 4) :: Graph Int)) :: String) ==+            unlines [ "1"+                    , "2"+                    , "3"+                    , "4"+                    , "2 -> 3"+                    , "2 -> 4" ]++    putStrLn "\n============ Export.Dot.export ============"+    let style = ED.Style+            { ED.graphName               = "Example"+            , ED.preamble                = "  // This is an example\n"+            , ED.graphAttributes         = ["label" := "Example", "labelloc" := "top"]+            , ED.defaultVertexAttributes = ["shape" := "circle"]+            , ED.defaultEdgeAttributes   = mempty+            , ED.vertexName              = \x   -> "v" ++ show x+            , ED.vertexAttributes        = \x   -> ["color" := "blue"   | odd x      ]+            , ED.edgeAttributes          = \x y -> ["style" := "dashed" | odd (x * y)] }+    test "export style (1 * 2 + 3 * 4 * 5 :: Graph Int)" $+        (ED.export style (1 * 2 + 3 * 4 * 5 :: Graph Int) :: String) ==+            unlines [ "digraph Example"+                    , "{"+                    , "  // This is an example"+                    , ""+                    , "  graph [label=\"Example\" labelloc=\"top\"]"+                    , "  node [shape=\"circle\"]"+                    , "  \"v1\" [color=\"blue\"]"+                    , "  \"v2\""+                    , "  \"v3\" [color=\"blue\"]"+                    , "  \"v4\""+                    , "  \"v5\" [color=\"blue\"]"+                    , "  \"v1\" -> \"v2\""+                    , "  \"v3\" -> \"v4\""+                    , "  \"v3\" -> \"v5\" [style=\"dashed\"]"+                    , "  \"v4\" -> \"v5\""+                    , "}" ]++    putStrLn "\n============ Export.Dot.exportAsIs ============"+    test "exportAsIs (circuit [\"a\", \"b\", \"c\"] :: Graph String)" $+        (ED.exportAsIs (circuit ["a", "b", "c"] :: Graph String) :: String) ==+            unlines [ "digraph"+                    , "{"+                    , "  \"a\""+                    , "  \"b\""+                    , "  \"c\""+                    , "  \"a\" -> \"b\""+                    , "  \"b\" -> \"c\""+                    , "  \"c\" -> \"a\""+                    , "}" ]++    putStrLn "\n============ Export.Dot.exportViaShow ============"+    test "exportViaShow (1 + 2 * (3 + 4) :: Graph Int)" $+        (ED.exportViaShow (1 + 2 * (3 + 4) :: Graph Int) :: String) ==+            unlines [ "digraph"+                    , "{"+                    , "  \"1\""+                    , "  \"2\""+                    , "  \"3\""+                    , "  \"4\""+                    , "  \"2\" -> \"3\""+                    , "  \"2\" -> \"4\""+                    , "}" ]
test/Algebra/Graph/Test/Fold.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ViewPatterns #-} ----------------------------------------------------------------------------- -- | -- Module     : Algebra.Graph.Test.Fold@@ -7,497 +6,39 @@ -- Maintainer : andrey.mokhov@gmail.com -- Stability  : experimental ----- Testsuite for 'Fold' and polymorphic functions defined in+-- Testsuite for "Algebra.Graph.Fold" and polymorphic functions defined in -- "Algebra.Graph.Class".--- ----------------------------------------------------------------------------- module Algebra.Graph.Test.Fold (     -- * Testsuite     testFold   ) where -import Data.Foldable-import Data.Tree-import Data.Tuple- import Algebra.Graph.Fold import Algebra.Graph.Test+import Algebra.Graph.Test.Generic -import qualified Data.Set    as Set-import qualified Data.IntSet as IntSet+t :: Testsuite+t = testsuite "Fold." (empty :: Fold Int) +h :: HTestsuite+h = hTestsuite "Fold." (empty :: Fold Int)+ type F  = Fold Int-type II = Int -> Int-type IB = Int -> Bool-type IF = Int -> F  testFold :: IO () testFold = do     putStrLn "\n============ Fold ============"     test "Axioms of graphs"   $ (axioms   :: GraphTestsuite F) -    putStrLn "\n============ Fold.Show ============"-    test "show (empty     :: Fold Int) == \"empty\"" $-          show (empty     :: Fold Int) == "empty"--    test "show (1         :: Fold Int) == \"vertex 1\"" $-          show (1         :: Fold Int) == "vertex 1"--    test "show (1 + 2     :: Fold Int) == \"vertices [1,2]\"" $-          show (1 + 2     :: Fold Int) == "vertices [1,2]"--    test "show (1 * 2     :: Fold Int) == \"edge 1 2\"" $-          show (1 * 2     :: Fold Int) == "edge 1 2"--    test "show (1 * 2 * 3 :: Fold Int) == \"edges [(1,2),(1,3),(2,3)]\"" $-          show (1 * 2 * 3 :: Fold Int) == "edges [(1,2),(1,3),(2,3)]"--    test "show (1 * 2 + 3 :: Fold Int) == \"graph [1,2,3] [(1,2)]\"" $-          show (1 * 2 + 3 :: Fold Int) == "graph [1,2,3] [(1,2)]"--    putStrLn "\n============ Fold.empty ============"-    test "isEmpty     empty == True" $-          isEmpty    (empty :: F) == True--    test "hasVertex x empty == False" $ \(x :: Int) ->-          hasVertex x empty == False--    test "vertexCount empty == 0" $-          vertexCount(empty :: F) == 0--    test "edgeCount   empty == 0" $-          edgeCount  (empty :: F) == 0--    test "size        empty == 1" $-          size       (empty :: F) == 1--    putStrLn "\n============ Fold.vertex ============"-    test "isEmpty     (vertex x) == False" $ \(x :: Int) ->-          isEmpty     (vertex x) == False--    test "hasVertex x (vertex x) == True" $ \(x :: Int) ->-          hasVertex x (vertex x) == True--    test "hasVertex 1 (vertex 2) == False" $-          hasVertex 1 (vertex 2 :: F) == False--    test "vertexCount (vertex x) == 1" $ \(x :: Int) ->-          vertexCount (vertex x) == 1--    test "edgeCount   (vertex x) == 0" $ \(x :: Int) ->-          edgeCount   (vertex x) == 0--    test "size        (vertex x) == 1" $ \(x :: Int) ->-          size        (vertex x) == 1--    putStrLn "\n============ Fold.edge ============"-    test "edge x y               == connect (vertex x) (vertex y)" $ \(x :: Int) y ->-         (edge x y :: F)         == connect (vertex x) (vertex y)--    test "hasEdge x y (edge x y) == True" $ \(x :: Int) y ->-          hasEdge x y (edge x y) == True--    test "edgeCount   (edge x y) == 1" $ \(x :: Int) y ->-          edgeCount   (edge x y) == 1--    test "vertexCount (edge 1 1) == 1" $-          vertexCount (edge 1 1 :: F) == 1--    test "vertexCount (edge 1 2) == 2" $-          vertexCount (edge 1 2 :: F) == 2--    putStrLn "\n============ Fold.overlay ============"-    test "isEmpty     (overlay x y) == isEmpty   x   && isEmpty   y" $ \(x :: F) y ->-          isEmpty     (overlay x y) == (isEmpty   x   && isEmpty   y)--    test "hasVertex z (overlay x y) == hasVertex z x || hasVertex z y" $ \(x :: F) y z ->-          hasVertex z (overlay x y) == (hasVertex z x || hasVertex z y)--    test "vertexCount (overlay x y) >= vertexCount x" $ \(x :: F) y ->-          vertexCount (overlay x y) >= vertexCount x--    test "vertexCount (overlay x y) <= vertexCount x + vertexCount y" $ \(x :: F) y ->-          vertexCount (overlay x y) <= vertexCount x + vertexCount y--    test "edgeCount   (overlay x y) >= edgeCount x" $ \(x :: F) y ->-          edgeCount   (overlay x y) >= edgeCount x--    test "edgeCount   (overlay x y) <= edgeCount x   + edgeCount y" $ \(x :: F) y ->-          edgeCount   (overlay x y) <= edgeCount x   + edgeCount y--    test "size        (overlay x y) == size x        + size y" $ \(x :: F) y ->-          size        (overlay x y) == size x        + size y--    test "vertexCount (overlay 1 2) == 2" $-          vertexCount (overlay 1 2 :: F) == 2--    test "edgeCount   (overlay 1 2) == 0" $-          edgeCount   (overlay 1 2 :: F) == 0--    putStrLn "\n============ Fold.connect ============"-    test "isEmpty     (connect x y) == isEmpty   x   && isEmpty   y" $ \(x :: F) y ->-          isEmpty     (connect x y) == (isEmpty   x   && isEmpty   y)--    test "hasVertex z (connect x y) == hasVertex z x || hasVertex z y" $ \(x :: F) y z ->-          hasVertex z (connect x y) == (hasVertex z x || hasVertex z y)--    test "vertexCount (connect x y) >= vertexCount x" $ \(x :: F) y ->-          vertexCount (connect x y) >= vertexCount x--    test "vertexCount (connect x y) <= vertexCount x + vertexCount y" $ \(x :: F) y ->-          vertexCount (connect x y) <= vertexCount x + vertexCount y--    test "edgeCount   (connect x y) >= edgeCount x" $ \(x :: F) y ->-          edgeCount   (connect x y) >= edgeCount x--    test "edgeCount   (connect x y) >= edgeCount y" $ \(x :: F) y ->-          edgeCount   (connect x y) >= edgeCount y--    test "edgeCount   (connect x y) >= vertexCount x * vertexCount y" $ \(x :: F) y ->-          edgeCount   (connect x y) >= vertexCount x * vertexCount y--    test "edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y" $ \(x :: F) y ->-          edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y--    test "size        (connect x y) == size x        + size y" $ \(x :: F) y ->-          size        (connect x y) == size x        + size y--    test "vertexCount (connect 1 2) == 2" $-          vertexCount (connect 1 2 :: F) == 2--    test "edgeCount   (connect 1 2) == 1" $-          edgeCount   (connect 1 2 :: F) == 1--    putStrLn "\n============ Fold.vertices ============"-    test "vertices []            == empty" $-          vertices []            == (empty :: F)--    test "vertices [x]           == vertex x" $ \(x :: Int) ->-          vertices [x]           == (vertex x :: F)--    test "hasVertex x . vertices == elem x" $ \x (xs :: [Int]) ->-         (hasVertex x . vertices) xs == elem x xs--    test "vertexCount . vertices == length . nub" $ \(xs :: [Int]) ->-         (vertexCount . vertices) xs == (length . nubOrd) xs--    test "vertexSet   . vertices == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet   . vertices) xs == Set.fromList xs--    putStrLn "\n============ Fold.edges ============"-    test "edges []          == empty" $-          edges []          == (empty :: F)--    test "edges [(x,y)]     == edge x y" $ \(x :: Int) y ->-          edges [(x,y)]     == (edge x y :: F)--    test "edgeCount . edges == length . nub" $ \(xs :: [(Int, Int)]) ->-         (edgeCount . edges) xs == (length . nubOrd) xs--    putStrLn "\n============ Fold.overlays ============"-    test "overlays []        == empty" $-          overlays []        == (empty :: F)--    test "overlays [x]       == x" $ \(x :: F) ->-          overlays [x]       == x--    test "overlays [x,y]     == overlay x y" $ \(x :: F) y ->-          overlays [x,y]     == overlay x y--    test "isEmpty . overlays == all isEmpty" $ \(xs :: [F]) ->-         (isEmpty . overlays) xs == all isEmpty xs--    putStrLn "\n============ Fold.connects ============"-    test "connects []        == empty" $-          connects []        == (empty :: F)--    test "connects [x]       == x" $ \(x :: F) ->-          connects [x]       == x--    test "connects [x,y]     == connect x y" $ \(x :: F) y ->-          connects [x,y]     == connect x y--    test "isEmpty . connects == all isEmpty" $ \(xs :: [F]) ->-         (isEmpty . connects) xs == all isEmpty xs--    putStrLn "\n============ Fold.graph ============"-    test "graph []  []      == empty" $-          graph []  []      == (empty :: F)--    test "graph [x] []      == vertex x" $ \(x :: Int) ->-          graph [x] []      == (vertex x :: F)--    test "graph []  [(x,y)] == edge x y" $ \(x :: Int) y ->-          graph []  [(x,y)] == (edge x y :: F)--    test "graph vs  es      == overlay (vertices vs) (edges es)" $ \(vs :: [Int]) es ->-          graph vs  es      == (overlay (vertices vs) (edges es) :: F)--    putStrLn "\n============ Fold.foldg ============"-    test "foldg empty vertex        overlay connect        == id" $ \(x :: F) ->-          foldg empty vertex        overlay connect x      == x--    test "foldg empty vertex        overlay (flip connect) == transpose" $ \(x :: F) ->-          foldg empty vertex        overlay (flip connect)x== (transpose x :: F)--    test "foldg []    return        (++)    (++)           == toList" $ \(x :: F) ->-          foldg []    return        (++)    (++) x         == toList x--    test "foldg 0     (const 1)     (+)     (+)            == length" $ \(x :: F) ->-          foldg 0     (const 1)     (+)     (+) x          == length x--    test "foldg 1     (const 1)     (+)     (+)            == size" $ \(x :: F) ->-          foldg 1     (const 1)     (+)     (+) x          == size x--    test "foldg True  (const False) (&&)    (&&)           == isEmpty" $ \(x :: F) ->-          foldg True  (const False) (&&)    (&&) x         == isEmpty x--    putStrLn "\n============ Fold.isSubgraphOf ============"-    test "isSubgraphOf empty         x             == True" $ \(x :: F) ->-          isSubgraphOf empty         x             == True--    test "isSubgraphOf (vertex x)    empty         == False" $ \x ->-          isSubgraphOf (vertex x)   (empty :: F)   == False--    test "isSubgraphOf x             (overlay x y) == True" $ \(x :: F) y ->-          isSubgraphOf x             (overlay x y) == True--    test "isSubgraphOf (overlay x y) (connect x y) == True" $ \(x :: F) y ->-          isSubgraphOf (overlay x y) (connect x y) == True--    test "isSubgraphOf (path xs)     (circuit xs)  == True" $ \xs ->-          isSubgraphOf (path xs :: F)(circuit xs)  == True--    putStrLn "\n============ Fold.isEmpty ============"-    test "isEmpty empty                       == True" $-          isEmpty (empty :: F)                == True--    test "isEmpty (overlay empty empty)       == True" $-          isEmpty (overlay empty empty :: F)  == True--    test "isEmpty (vertex x)                  == False" $ \(x :: Int) ->-          isEmpty (vertex x)                  == False--    test "isEmpty (removeVertex x $ vertex x) == True" $ \(x :: Int) ->-          isEmpty (removeVertex x $ vertex x) == True--    test "isEmpty (removeEdge x y $ edge x y) == False" $ \(x :: Int) y ->-          isEmpty (removeEdge x y $ edge x y) == False--    putStrLn "\n============ Fold.size ============"-    test "size empty         == 1" $-          size (empty :: F)  == 1--    test "size (vertex x)    == 1" $ \(x :: Int) ->-          size (vertex x)    == 1--    test "size (overlay x y) == size x + size y" $ \(x :: F) y ->-          size (overlay x y) == size x + size y--    test "size (connect x y) == size x + size y" $ \(x :: F) y ->-          size (connect x y) == size x + size y--    test "size x             >= 1" $ \(x :: F) ->-          size x             >= 1--    test "size x             >= vertexCount x" $ \(x :: F) ->-          size x             >= vertexCount x--    putStrLn "\n============ Fold.hasVertex ============"-    test "hasVertex x empty            == False" $ \(x :: Int) ->-          hasVertex x empty            == False--    test "hasVertex x (vertex x)       == True" $ \(x :: Int) ->-          hasVertex x (vertex x)       == True--    test "hasVertex x . removeVertex x == const False" $ \(x :: Int) y ->-          hasVertex x (removeVertex x y)==const False y--    putStrLn "\n============ Fold.hasEdge ============"-    test "hasEdge x y empty            == False" $ \(x :: Int) y ->-          hasEdge x y empty            == False--    test "hasEdge x y (vertex z)       == False" $ \(x :: Int) y z ->-          hasEdge x y (vertex z)       == False--    test "hasEdge x y (edge x y)       == True" $ \(x :: Int) y ->-          hasEdge x y (edge x y)       == True--    test "hasEdge x y . removeEdge x y == const False" $ \(x :: Int) y z ->-          hasEdge x y (removeEdge x y z)==const False z--    putStrLn "\n============ Fold.vertexCount ============"-    test "vertexCount empty      == 0" $-          vertexCount (empty :: F) == 0--    test "vertexCount (vertex x) == 1" $ \(x :: Int) ->-          vertexCount (vertex x) == 1--    test "vertexCount            == length . vertexList" $ \(x :: F) ->-          vertexCount x          == (length . vertexList) x--    putStrLn "\n============ Fold.edgeCount ============"-    test "edgeCount empty      == 0" $-          edgeCount (empty :: F) == 0--    test "edgeCount (vertex x) == 0" $ \(x :: Int) ->-          edgeCount (vertex x) == 0--    test "edgeCount (edge x y) == 1" $ \(x :: Int) y ->-          edgeCount (edge x y) == 1--    test "edgeCount            == length . edgeList" $ \(x :: F) ->-          edgeCount x          == (length . edgeList) x--    putStrLn "\n============ Fold.vertexList ============"-    test "vertexList empty      == []" $-          vertexList (empty :: F) == []--    test "vertexList (vertex x) == [x]" $ \(x :: Int) ->-          vertexList (vertex x) == [x]--    test "vertexList . vertices == nub . sort" $ \(xs :: [Int]) ->-         (vertexList . vertices) xs == (nubOrd . sort) xs--    putStrLn "\n============ Fold.edgeList ============"-    test "edgeList empty          == []" $-          edgeList (empty :: F )  == []--    test "edgeList (vertex x)     == []" $ \(x :: Int) ->-          edgeList (vertex x)     == []--    test "edgeList (edge x y)     == [(x,y)]" $ \(x :: Int) y ->-          edgeList (edge x y)     == [(x,y)]--    test "edgeList (star 2 [3,1]) == [(2,1), (2,3)]" $-          edgeList (star 2 [3,1]) == [(2,1), (2,3 :: Int)]--    test "edgeList . edges        == nub . sort" $ \(xs :: [(Int, Int)]) ->-         (edgeList . edges) xs    == (nubOrd . sort) xs--    putStrLn "\n============ Fold.vertexSet ============"-    test "vertexSet empty      == Set.empty" $-          vertexSet(empty :: F)== Set.empty--    test "vertexSet . vertex   == Set.singleton" $ \(x :: Int) ->-         (vertexSet . vertex) x== Set.singleton x--    test "vertexSet . vertices == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet . vertices) xs == Set.fromList xs--    test "vertexSet . clique   == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet . clique) xs == Set.fromList xs--    putStrLn "\n============ Fold.vertexIntSet ============"-    test "vertexIntSet empty      == IntSet.empty" $-          vertexIntSet(empty :: F)== IntSet.empty--    test "vertexIntSet . vertex   == IntSet.singleton" $ \(x :: Int) ->-         (vertexIntSet . vertex) x== IntSet.singleton x--    test "vertexIntSet . vertices == IntSet.fromList" $ \(xs :: [Int]) ->-         (vertexIntSet . vertices) xs == IntSet.fromList xs--    test "vertexIntSet . clique   == IntSet.fromList" $ \(xs :: [Int]) ->-         (vertexIntSet . clique) xs == IntSet.fromList xs--    putStrLn "\n============ Fold.edgeSet ============"-    test "edgeSet empty      == Set.empty" $-          edgeSet (empty :: F) == Set.empty--    test "edgeSet (vertex x) == Set.empty" $ \(x :: Int) ->-          edgeSet (vertex x) == Set.empty--    test "edgeSet (edge x y) == Set.singleton (x,y)" $ \(x :: Int) y ->-          edgeSet (edge x y) == Set.singleton (x,y)--    test "edgeSet . edges    == Set.fromList" $ \(xs :: [(Int, Int)]) ->-         (edgeSet . edges) xs== Set.fromList xs--    putStrLn "\n============ Fold.path ============"-    test "path []    == empty" $-          path []    == (empty :: F)--    test "path [x]   == vertex x" $ \(x :: Int) ->-          path [x]   == (vertex x :: F)--    test "path [x,y] == edge x y" $ \(x :: Int) y ->-          path [x,y] == (edge x y :: F)--    putStrLn "\n============ Fold.circuit ============"-    test "circuit []    == empty" $-          circuit []    == (empty :: F)--    test "circuit [x]   == edge x x" $ \(x :: Int) ->-          circuit [x]   == (edge x x :: F)--    test "circuit [x,y] == edges [(x,y), (y,x)]" $ \(x :: Int) y ->-          circuit [x,y] == (edges [(x,y), (y,x)] :: F)--    putStrLn "\n============ Fold.clique ============"-    test "clique []      == empty" $-          clique []      == (empty :: F)--    test "clique [x]     == vertex x" $ \(x :: Int) ->-          clique [x]     == (vertex x :: F)--    test "clique [x,y]   == edge x y" $ \(x :: Int) y ->-          clique [x,y]   == (edge x y :: F)--    test "clique [x,y,z] == edges [(x,y), (x,z), (y,z)]" $ \(x :: Int) y z ->-          clique [x,y,z] == (edges [(x,y), (x,z), (y,z)] :: F)--    putStrLn "\n============ Fold.biclique ============"-    test "biclique []      []      == empty" $-          biclique []      []      == (empty :: F)--    test "biclique [x]     []      == vertex x" $ \x ->-          biclique [x]     []      == (vertex x :: F)--    test "biclique []      [y]     == vertex y" $ \y ->-          biclique []      [y]     == (vertex y :: F)--    test "biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]" $ \x1 x2 y1 y2 ->-          biclique [x1,x2] [y1,y2] == (edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)] :: F)--    test "biclique xs      ys      == connect (vertices xs) (vertices ys)" $ \xs ys ->-          biclique xs      ys      == (connect (vertices xs) (vertices ys) :: F)--    putStrLn "\n============ Fold.star ============"-    test "star x []    == vertex x" $ \(x :: Int) ->-          star x []    == (vertex x :: F)--    test "star x [y]   == edge x y" $ \(x :: Int) y ->-          star x [y]   == (edge x y :: F)--    test "star x [y,z] == edges [(x,y), (x,z)]" $ \(x :: Int) y z ->-          star x [y,z] == (edges [(x,y), (x,z)] :: F)--    putStrLn "\n============ Fold.tree ============"-    test "tree (Node x [])                                         == vertex x" $ \x ->-          tree (Node x [])                                         ==(vertex x :: F)--    test "tree (Node x [Node y [Node z []]])                       == path [x,y,z]" $ \x y z ->-          tree (Node x [Node y [Node z []]])                       ==(path [x,y,z] :: F)--    test "tree (Node x [Node y [], Node z []])                     == star x [y,z]" $ \x y z ->-          tree (Node x [Node y [], Node z []])                     ==(star x [y,z] :: F)--    test "tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5)]" $-          tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) ==(edges [(1,2), (1,3), (3,4), (3,5)] :: F)--    putStrLn "\n============ Fold.forest ============"-    test "forest []                                                  == empty" $-          forest []                                                  == (empty :: F)--    test "forest [x]                                                 == tree x" $ \x ->-          forest [x]                                                 == (tree x :: F)--    test "forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5)]" $-          forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] ==(edges [(1,2), (1,3), (4,5)] :: F)--    test "forest                                                     == overlays . map tree" $ \x ->-         (forest x)                                                  ==((overlays . map tree) x :: F)+    testShow            t+    testBasicPrimitives t+    testFoldg           h+    testIsSubgraphOf    t+    testSize            t+    testProperties      t+    testGraphFamilies   t+    testTransformations t      putStrLn "\n============ Fold.mesh ============"     test "mesh xs     []   == empty" $ \xs ->@@ -550,159 +91,18 @@                     deBruijn 2 "01"             ==(edges [ ("00","00"), ("00","01"), ("01","10"), ("01","11")                                                          , ("10","00"), ("10","01"), ("11","10"), ("11","11") ] :: Fold String) +    test "          transpose   (deBruijn n xs) == gmap reverse $ deBruijn n xs" $ mapSize (min 5) $ \(NonNegative n) (xs :: [Int]) ->+                    transpose   (deBruijn n xs) == ((gmap reverse $ deBruijn n xs) :: Fold [Int])+     test "          vertexCount (deBruijn n xs) == (length $ nub xs)^n" $ mapSize (min 5) $ \(NonNegative n) (xs :: [Int]) ->                     vertexCount (deBruijn n xs) == (length $ nubOrd xs)^n      test "n > 0 ==> edgeCount   (deBruijn n xs) == (length $ nub xs)^(n + 1)" $ mapSize (min 5) $ \(NonNegative n) (xs :: [Int]) ->           n > 0 ==> edgeCount   (deBruijn n xs) == (length $ nubOrd xs)^(n + 1) -    putStrLn "\n============ Fold.removeVertex ============"-    test "removeVertex x (vertex x)       == empty" $ \(x :: Int) ->-          removeVertex x (vertex x)       == (empty :: F)--    test "removeVertex x . removeVertex x == removeVertex x" $ \x (y :: F) ->-         (removeVertex x . removeVertex x)y==(removeVertex x y :: F)--    putStrLn "\n============ Fold.removeEdge ============"-    test "removeEdge x y (edge x y)       == vertices [x, y]" $ \(x :: Int) y ->-          removeEdge x y (edge x y)       == (vertices [x, y] :: F)--    test "removeEdge x y . removeEdge x y == removeEdge x y" $ \(x :: Int) y z ->-         (removeEdge x y . removeEdge x y)z==(removeEdge x y z :: F)--    test "removeEdge x y . removeVertex x == removeVertex x" $ \(x :: Int) y z ->-         (removeEdge x y . removeVertex x)z==(removeVertex x z :: F)--    test "removeEdge 1 1 (1 * 1 * 2 * 2)  == 1 * 2 * 2" $-          removeEdge 1 1 (1 * 1 * 2 * 2)  == (1 * 2 * (2 :: F))--    test "removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2" $-          removeEdge 1 2 (1 * 1 * 2 * 2)  == (1 * 1 + 2 * (2 :: F))--    putStrLn "\n============ Fold.replaceVertex ============"-    test "replaceVertex x x            == id" $ \x (y :: F) ->-          replaceVertex x x y          == y--    test "replaceVertex x y (vertex x) == vertex y" $ \x (y :: Int) ->-          replaceVertex x y (vertex x) == (vertex y :: F)--    test "replaceVertex x y            == mergeVertices (== x) y" $ \x y z ->-          replaceVertex x y z          == (mergeVertices (== x) y z :: F)--    putStrLn "\n============ Fold.mergeVertices ============"-    test "mergeVertices (const False) x    == id" $ \x (y :: F) ->-          mergeVertices (const False) x y  == y--    test "mergeVertices (== x) y           == replaceVertex x y" $ \x y (z :: F) ->-          mergeVertices (== x) y z         == (replaceVertex x y z :: F)--    test "mergeVertices even 1 (0 * 2)     == 1 * 1" $-          mergeVertices even 1 (0 * 2)     == (1 * 1 :: F)--    test "mergeVertices odd  1 (3 + 4 * 5) == 4 * 1" $-          mergeVertices odd  1 (3 + 4 * 5) == (4 * 1 :: F)--    putStrLn "\n============ Fold.splitVertex ============"-    test "splitVertex x []                   == removeVertex x" $ \x (y :: F) ->-         (splitVertex x []) y                == (removeVertex x y :: F)--    test "splitVertex x [x]                  == id" $ \x (y :: F) ->-         (splitVertex x [x]) y               == y--    test "splitVertex x [y]                  == replaceVertex x y" $ \x y (z :: F) ->-         (splitVertex x [y]) z               == (replaceVertex x y z :: F)--    test "splitVertex 1 [0, 1] $ 1 * (2 + 3) == (0 + 1) * (2 + 3)" $-         (splitVertex 1 [0, 1] $ 1 * (2 + 3))== ((0 + 1) * (2 + 3 :: F))--    putStrLn "\n============ Fold.transpose ============"-    test "transpose empty       == empty" $-          transpose empty       == (empty :: F)--    test "transpose (vertex x)  == vertex x" $ \(x :: Int) ->-          transpose (vertex x)  == (vertex x :: F)--    test "transpose (edge x y)  == edge y x" $ \(x :: Int) y ->-          transpose (edge x y)  == (edge y x :: F)--    test "transpose . transpose == id" $ \(x :: F) ->-         (transpose . transpose) x == x--    test "transpose . path      == path    . reverse" $ \(xs :: [Int]) ->-         (transpose . path) xs  == ((path . reverse) xs :: F)--    test "transpose . circuit   == circuit . reverse" $ \(xs :: [Int]) ->-         (transpose . circuit) xs == ((circuit . reverse) xs :: F)--    test "transpose . clique    == clique  . reverse" $ \(xs :: [Int]) ->-         (transpose . clique) xs == ((clique . reverse) xs :: F)--    test "transpose (box x y)   == box (transpose x) (transpose y)" $ mapSize (min 10) $ \(x :: F) (y :: F) ->-          transpose (box x y)   == (box (transpose x) (transpose y) :: Fold (Int, Int))--    test "edgeList . transpose  == sort . map swap . edgeList" $ \(x :: F) ->-         (edgeList . transpose) x == (sort . map swap . edgeList) x--    putStrLn "\n============ Fold.gmap ============"-    test "gmap f empty      == empty" $ \(apply -> f :: II) ->-          gmap f empty      == (empty :: F)--    test "gmap f (vertex x) == vertex (f x)" $ \(apply -> f :: II) x ->-          gmap f (vertex x) == (vertex (f x) :: F)--    test "gmap f (edge x y) == edge (f x) (f y)" $ \(apply -> f :: II) x y ->-          gmap f (edge x y) == (edge (f x) (f y) :: F)--    test "gmap id           == id" $ \(x :: F) ->-          gmap id x         == x--    test "gmap f . gmap g   == gmap (f . g)" $ \(apply -> f :: II) (apply -> g :: II) (x :: F) ->-         (gmap f . gmap g) x== (gmap (f . g) x :: F)--    putStrLn "\n============ Fold.bind ============"-    test "bind empty f         == empty" $ \(apply -> f :: IF) ->-          bind empty f         == empty--    test "bind (vertex x) f    == f x" $ \(apply -> f :: IF) x ->-          bind (vertex x) f    == f x--    test "bind (edge x y) f    == connect (f x) (f y)" $ \(apply -> f :: IF) x y ->-          bind (edge x y) f    == connect (f x) (f y)--    test "bind (vertices xs) f == overlays (map f xs)" $ mapSize (min 10) $ \xs (apply -> f :: IF) ->-          bind (vertices xs) f == overlays (map f xs)--    test "bind x (const empty) == empty" $ \(x :: F) ->-          bind x (const empty) == (empty :: F)--    test "bind x vertex        == x" $ \(x :: F) ->-          bind x vertex        == x--    test "bind (bind x f) g    == bind x (\\y -> bind (f y) g)" $ mapSize (min 10) $ \x (apply -> f :: IF) (apply -> g :: IF) ->-          bind (bind x f) g    == bind x (\y -> bind (f y) g)--    putStrLn "\n============ Fold.induce ============"-    test "induce (const True)  x      == x" $ \(x :: F) ->-          induce (const True)  x      == x--    test "induce (const False) x      == empty" $ \(x :: F) ->-          induce (const False) x      == (empty :: F)--    test "induce (/= x)               == removeVertex x" $ \x (y :: F) ->-          induce (/= x) y             == (removeVertex x y :: F)--    test "induce p . induce q         == induce (\\x -> p x && q x)" $ \(apply -> p :: IB) (apply -> q :: IB) (y :: F) ->-         (induce p . induce q) y      == (induce (\x -> p x && q x) y :: F)--    test "isSubgraphOf (induce p x) x == True" $ \(apply -> p :: IB) (x :: F) ->-          isSubgraphOf (induce p x) x == True--    putStrLn "\n============ Fold.simplify ============"-    test "simplify              == id" $ \(x :: F) ->-          simplify x            == x--    test "size (simplify x)     <= size x" $ \(x :: F) ->-          size (simplify x)     <= size x+    testSplitVertex t+    testBind        t+    testSimplify    t      putStrLn "\n============ Fold.box ============"     let unit = fmap $ \(a, ()) -> a@@ -722,6 +122,9 @@     let assoc = fmap $ \(a, (b, c)) -> ((a, b), c)     test "box x (box y z)     ~~ box (box x y) z" $ mapSize (min 10) $ \(x :: F) (y :: F) (z :: F) ->       assoc (box x (box y z)) == (box (box x y) z :: Fold ((Int, Int), Int))++    test "transpose   (box x y) == box (transpose x) (transpose y)" $ mapSize (min 10) $ \(x :: F) (y :: F) ->+          transpose   (box x y) == (box (transpose x) (transpose y) :: Fold (Int, Int))      test "vertexCount (box x y) == vertexCount x * vertexCount y" $ mapSize (min 10) $ \(x :: F) (y :: F) ->           vertexCount (box x y) == vertexCount x * vertexCount y
+ test/Algebra/Graph/Test/Generic.hs view
@@ -0,0 +1,983 @@+{-# LANGUAGE GADTs, RankNTypes, ViewPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module     : Algebra.Graph.Test.Generic+-- Copyright  : (c) Andrey Mokhov 2016-2017+-- License    : MIT (see the file LICENSE)+-- Maintainer : andrey.mokhov@gmail.com+-- Stability  : experimental+--+-- Generic graph API testing.+-----------------------------------------------------------------------------+module Algebra.Graph.Test.Generic (+    -- * Generic tests+    Testsuite, testsuite, HTestsuite, hTestsuite, testShow, testFromAdjacencyList,+    testBasicPrimitives, testFoldg, testIsSubgraphOf, testSize, testProperties,+    testAdjacencyList, testPreSet, testPostSet, testPostIntSet, testGraphFamilies,+    testTransformations, testDfsForest, testDfsForestFrom, testDfs, testTopSort,+    testIsTopSort, testSplitVertex, testBind, testSimplify+  ) where++import Data.Foldable+import Data.List (nub, sort)+import Data.Tree+import Data.Tuple++import Algebra.Graph.Class (Graph (..))+import Algebra.Graph.Test+import Algebra.Graph.Test.API++import qualified Data.Set    as Set+import qualified Data.IntSet as IntSet++data Testsuite where+    Testsuite :: (Arbitrary g, Eq g, GraphAPI g, Num g, Show g, Vertex g ~ Int)+              => String -> (forall r. (g -> r) -> g -> r) -> Testsuite++testsuite :: (Arbitrary g, Eq g, GraphAPI g, Num g, Show g, Vertex g ~ Int)+          => String -> g -> Testsuite+testsuite prefix g = Testsuite prefix (\f x -> f (x `asTypeOf` g))++data HTestsuite where+    HTestsuite :: (Arbitrary g, Eq g, GraphAPI g, Num g, Show g, Vertex g ~ Int,+                   g ~ f Int, Foldable f)+               => String -> (forall r. (g -> r) -> g -> r) -> HTestsuite++hTestsuite :: (Arbitrary g, Eq g, GraphAPI g, Num g, Show g, Vertex g ~ Int,+               g ~ f Int, Foldable f) => String -> g -> HTestsuite+hTestsuite prefix g = HTestsuite prefix (\f x -> f (x `asTypeOf` g))++testBasicPrimitives :: Testsuite -> IO ()+testBasicPrimitives = mconcat [ testEmpty+                              , testVertex+                              , testEdge+                              , testOverlay+                              , testConnect+                              , testVertices+                              , testEdges+                              , testOverlays+                              , testConnects+                              , testGraph ]++testProperties :: Testsuite -> IO ()+testProperties = mconcat [ testIsEmpty+                         , testHasVertex+                         , testHasEdge+                         , testVertexCount+                         , testEdgeCount+                         , testVertexList+                         , testEdgeList+                         , testVertexSet+                         , testVertexIntSet+                         , testEdgeSet ]++testGraphFamilies :: Testsuite -> IO ()+testGraphFamilies = mconcat [ testPath+                            , testCircuit+                            , testClique+                            , testBiclique+                            , testStar+                            , testTree+                            , testForest ]++testTransformations :: Testsuite -> IO ()+testTransformations = mconcat [ testRemoveVertex+                              , testRemoveEdge+                              , testReplaceVertex+                              , testMergeVertices+                              , testTranspose+                              , testGmap+                              , testInduce ]++testShow :: Testsuite -> IO ()+testShow (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "Show ============"+    test "show (empty     :: IntAdjacencyMap) == \"empty\"" $+          show % empty                        == "empty"++    test "show (1         :: IntAdjacencyMap) == \"vertex 1\"" $+          show % 1                            == "vertex 1"++    test "show (1 + 2     :: IntAdjacencyMap) == \"vertices [1,2]\"" $+          show % (1 + 2)                      == "vertices [1,2]"++    test "show (1 * 2     :: IntAdjacencyMap) == \"edge 1 2\"" $+          show % (1 * 2)                      == "edge 1 2"++    test "show (1 * 2 * 3 :: IntAdjacencyMap) == \"edges [(1,2),(1,3),(2,3)]\"" $+          show % (1 * 2 * 3)                  == "edges [(1,2),(1,3),(2,3)]"++    test "show (1 * 2 + 3 :: IntAdjacencyMap) == \"graph [1,2,3] [(1,2)]\"" $+          show % (1 * 2 + 3)                  == "graph [1,2,3] [(1,2)]"++testEmpty :: Testsuite -> IO ()+testEmpty (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "empty ============"+    test "isEmpty     empty == True" $+          isEmpty   % empty == True++    test "hasVertex x empty == False" $ \x ->+          hasVertex x % empty == False++    test "vertexCount empty == 0" $+          vertexCount % empty == 0++    test "edgeCount   empty == 0" $+          edgeCount % empty == 0++testVertex :: Testsuite -> IO ()+testVertex (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "vertex ============"+    test "isEmpty     (vertex x) == False" $ \x ->+          isEmpty    % vertex x  == False++    test "hasVertex x (vertex x) == True" $ \x ->+          hasVertex x % vertex x == True++    test "hasVertex 1 (vertex 2) == False" $+          hasVertex 1 % vertex 2 == False++    test "vertexCount (vertex x) == 1" $ \x ->+          vertexCount % vertex x == 1++    test "edgeCount   (vertex x) == 0" $ \x ->+          edgeCount  % vertex x  == 0++testEdge :: Testsuite -> IO ()+testEdge (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "edge ============"+    test "edge x y               == connect (vertex x) (vertex y)" $ \x y ->+          edge x y               == connect (vertex x) % (vertex y)++    test "hasEdge x y (edge x y) == True" $ \x y ->+          hasEdge x y % (edge x y) == True++    test "edgeCount   (edge x y) == 1" $ \x y ->+          edgeCount % (edge x y) == 1++    test "vertexCount (edge 1 1) == 1" $+          vertexCount % (edge 1 1) == 1++    test "vertexCount (edge 1 2) == 2" $+          vertexCount % (edge 1 2) == 2++testOverlay :: Testsuite -> IO ()+testOverlay (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "overlay ============"+    test "isEmpty     (overlay x y) == isEmpty   x   && isEmpty   y" $ \x y ->+          isEmpty   % (overlay x y) == (isEmpty   x   && isEmpty   y)++    test "hasVertex z (overlay x y) == hasVertex z x || hasVertex z y" $ \x y z ->+          hasVertex z % (overlay x y) == (hasVertex z x || hasVertex z y)++    test "vertexCount (overlay x y) >= vertexCount x" $ \x y ->+          vertexCount % (overlay x y) >= vertexCount x++    test "vertexCount (overlay x y) <= vertexCount x + vertexCount y" $ \x y ->+          vertexCount % (overlay x y) <= vertexCount x + vertexCount y++    test "edgeCount   (overlay x y) >= edgeCount x" $ \x y ->+          edgeCount % (overlay x y) >= edgeCount x++    test "edgeCount   (overlay x y) <= edgeCount x   + edgeCount y" $ \x y ->+          edgeCount % (overlay x y) <= edgeCount x   + edgeCount y++    test "vertexCount (overlay 1 2) == 2" $+          vertexCount % (overlay 1 2) == 2++    test "edgeCount   (overlay 1 2) == 0" $+          edgeCount % (overlay 1 2) == 0++testConnect :: Testsuite -> IO ()+testConnect (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "connect ============"+    test "isEmpty     (connect x y) == isEmpty   x   && isEmpty   y" $ \x y ->+          isEmpty    % connect x y  == (isEmpty   x   && isEmpty   y)++    test "hasVertex z (connect x y) == hasVertex z x || hasVertex z y" $ \x y z ->+          hasVertex z % connect x y == (hasVertex z x || hasVertex z y)++    test "vertexCount (connect x y) >= vertexCount x" $ \x y ->+          vertexCount % connect x y >= vertexCount x++    test "vertexCount (connect x y) <= vertexCount x + vertexCount y" $ \x y ->+          vertexCount % connect x y <= vertexCount x + vertexCount y++    test "edgeCount   (connect x y) >= edgeCount x" $ \x y ->+          edgeCount  % connect x y  >= edgeCount x++    test "edgeCount   (connect x y) >= edgeCount y" $ \x y ->+          edgeCount  % connect x y  >= edgeCount y++    test "edgeCount   (connect x y) >= vertexCount x * vertexCount y" $ \x y ->+          edgeCount  % connect x y  >= vertexCount x * vertexCount y++    test "edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y" $ \x y ->+          edgeCount  % connect x y  <= vertexCount x * vertexCount y + edgeCount x + edgeCount y++    test "vertexCount (connect 1 2) == 2" $+          vertexCount % connect 1 2 == 2++    test "edgeCount   (connect 1 2) == 1" $+          edgeCount  % connect 1 2  == 1++testVertices :: Testsuite -> IO ()+testVertices (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "vertices ============"+    test "vertices []            == empty" $+          vertices []            == id % empty++    test "vertices [x]           == vertex x" $ \x ->+          vertices [x]           == id % vertex x++    test "hasVertex x . vertices == elem x" $ \x xs ->+          hasVertex x % vertices xs == elem x xs++    test "vertexCount . vertices == length . nub" $ \xs ->+          vertexCount % vertices xs == (length . nubOrd) xs++    test "vertexSet   . vertices == Set.fromList" $ \xs ->+          vertexSet % vertices xs == Set.fromList xs++testEdges :: Testsuite -> IO ()+testEdges (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "edges ============"+    test "edges []          == empty" $+          edges []          == id % empty++    test "edges [(x,y)]     == edge x y" $ \x y ->+          edges [(x,y)]     == id % edge x y++    test "edgeCount . edges == length . nub" $ \xs ->+          edgeCount % edges xs == (length . nubOrd) xs++testOverlays :: Testsuite -> IO ()+testOverlays (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "overlays ============"+    test "overlays []        == empty" $+          overlays []        == id % empty++    test "overlays [x]       == x" $ \x ->+          overlays [x]       == id % x++    test "overlays [x,y]     == overlay x y" $ \x y ->+          overlays [x,y]     == id % overlay x y++    test "isEmpty . overlays == all isEmpty" $ mapSize (min 10) $ \xs ->+          isEmpty % overlays xs == all isEmpty xs++testConnects :: Testsuite -> IO ()+testConnects (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "connects ============"+    test "connects []        == empty" $+          connects []        == id % empty++    test "connects [x]       == x" $ \x ->+          connects [x]       == id % x++    test "connects [x,y]     == connect x y" $ \x y ->+          connects [x,y]     == id % connect x y++    test "isEmpty . connects == all isEmpty" $ mapSize (min 10) $ \xs ->+          isEmpty % connects xs == all isEmpty xs++testGraph :: Testsuite -> IO ()+testGraph (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "graph ============"+    test "graph []  []      == empty" $+          graph []  []      == id % empty++    test "graph [x] []      == vertex x" $ \x ->+          graph [x] []      == id % vertex x++    test "graph []  [(x,y)] == edge x y" $ \x y ->+          graph []  [(x,y)] == id % edge x y++    test "graph vs  es      == overlay (vertices vs) (edges es)" $ \vs es ->+          graph vs  es      == overlay (vertices vs) % edges es++testFromAdjacencyList :: Testsuite -> IO ()+testFromAdjacencyList (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "fromAdjacencyList ============"+    test "fromAdjacencyList []                                  == empty" $+          fromAdjacencyList []                                  == id % empty++    test "fromAdjacencyList [(x, [])]                           == vertex x" $ \x ->+          fromAdjacencyList [(x, [])]                           == id % vertex x++    test "fromAdjacencyList [(x, [y])]                          == edge x y" $ \x y ->+          fromAdjacencyList [(x, [y])]                          == id % edge x y++    test "fromAdjacencyList . adjacencyList                     == id" $ \x ->+         (fromAdjacencyList . adjacencyList) % x                == x++    test "overlay (fromAdjacencyList xs) (fromAdjacencyList ys) == fromAdjacencyList (xs ++ ys)" $ \xs ys ->+          overlay (fromAdjacencyList xs) % fromAdjacencyList ys == fromAdjacencyList (xs ++ ys)++testFoldg :: HTestsuite -> IO ()+testFoldg (HTestsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "foldg ============"+    test "foldg empty vertex        overlay connect        == id" $ \x ->+          foldg empty vertex        overlay connect x      == id % x++    test "foldg empty vertex        overlay (flip connect) == transpose" $ \x ->+          foldg empty vertex        overlay (flip connect)x== transpose % x++    test "foldg []    return        (++)    (++)           == toList" $ \x ->+          foldg []    return        (++)    (++) x         == toList % x++    test "foldg 0     (const 1)     (+)     (+)            == length" $ \x ->+          foldg 0     (const 1)     (+)     (+) x          == length % x++    test "foldg 1     (const 1)     (+)     (+)            == size" $ \x ->+          foldg 1     (const 1)     (+)     (+) x          == size % x++    test "foldg True  (const False) (&&)    (&&)           == isEmpty" $ \x ->+          foldg True  (const False) (&&)    (&&) x         == isEmpty % x++testIsSubgraphOf :: Testsuite -> IO ()+testIsSubgraphOf (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "isSubgraphOf ============"+    test "isSubgraphOf empty         x             == True" $ \x ->+          isSubgraphOf empty       % x             == True++    test "isSubgraphOf (vertex x)    empty         == False" $ \x ->+          isSubgraphOf (vertex x)  % empty         == False++    test "isSubgraphOf x             (overlay x y) == True" $ \x y ->+          isSubgraphOf x            % overlay x y  == True++    test "isSubgraphOf (overlay x y) (connect x y) == True" $ \x y ->+          isSubgraphOf (overlay x y) % connect x y == True++    test "isSubgraphOf (path xs)     (circuit xs)  == True" $ \xs ->+          isSubgraphOf (path xs)    % circuit xs   == True++testIsEmpty :: Testsuite -> IO ()+testIsEmpty (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "isEmpty ============"+    test "isEmpty empty                       == True" $+          isEmpty % empty                     == True++    test "isEmpty (overlay empty empty)       == True" $+          isEmpty % overlay empty empty       == True++    test "isEmpty (vertex x)                  == False" $ \x ->+          isEmpty % vertex x                  == False++    test "isEmpty (removeVertex x $ vertex x) == True" $ \x ->+          isEmpty (removeVertex x % vertex x) == True++    test "isEmpty (removeEdge x y $ edge x y) == False" $ \x y ->+          isEmpty (removeEdge x y % edge x y) == False++testSize :: Testsuite -> IO ()+testSize (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "size ============"+    test "size empty         == 1" $+          size % empty       == 1++    test "size (vertex x)    == 1" $ \x ->+          size % vertex x    == 1++    test "size (overlay x y) == size x + size y" $ \x y ->+          size % overlay x y == size x + size y++    test "size (connect x y) == size x + size y" $ \x y ->+          size % connect x y == size x + size y++    test "size x             >= 1" $ \x ->+          size % x           >= 1++    test "size x             >= vertexCount x" $ \x ->+          size % x           >= vertexCount x++testHasVertex :: Testsuite -> IO ()+testHasVertex (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "hasVertex ============"+    test "hasVertex x empty            == False" $ \x ->+          hasVertex x % empty          == False++    test "hasVertex x (vertex x)       == True" $ \x ->+          hasVertex x % vertex x     == True++    test "hasVertex x . removeVertex x == const False" $ \x y ->+         (hasVertex x . removeVertex x) y == const False % y++testHasEdge :: Testsuite -> IO ()+testHasEdge (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "hasEdge ============"+    test "hasEdge x y empty            == False" $ \x y ->+          hasEdge x y % empty          == False++    test "hasEdge x y (vertex z)       == False" $ \x y z ->+          hasEdge x y % vertex z       == False++    test "hasEdge x y (edge x y)       == True" $ \x y ->+          hasEdge x y % edge x y       == True++    test "hasEdge x y . removeEdge x y == const False" $ \x y z ->+         (hasEdge x y . removeEdge x y) z == const False % z++    test "hasEdge x y                  == elem (x,y) . edgeList" $ \x y z -> do+        (u, v) <- elements ((x, y) : edgeList z)+        return $ hasEdge u v z == elem (u, v) (edgeList % z)++testVertexCount :: Testsuite -> IO ()+testVertexCount (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "vertexCount ============"+    test "vertexCount empty      == 0" $+          vertexCount % empty    == 0++    test "vertexCount (vertex x) == 1" $ \x ->+          vertexCount % vertex x == 1++    test "vertexCount            == length . vertexList" $ \x ->+          vertexCount % x        == (length . vertexList) x++testEdgeCount :: Testsuite -> IO ()+testEdgeCount (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "edgeCount ============"+    test "edgeCount empty      == 0" $+          edgeCount % empty    == 0++    test "edgeCount (vertex x) == 0" $ \x ->+          edgeCount % vertex x == 0++    test "edgeCount (edge x y) == 1" $ \x y ->+          edgeCount % edge x y == 1++    test "edgeCount            == length . edgeList" $ \x ->+          edgeCount % x        == (length . edgeList) x++testVertexList :: Testsuite -> IO ()+testVertexList (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "vertexList ============"+    test "vertexList empty      == []" $+          vertexList % empty    == []++    test "vertexList (vertex x) == [x]" $ \x ->+          vertexList % vertex x == [x]++    test "vertexList . vertices == nub . sort" $ \xs ->+          vertexList % vertices xs == (nubOrd . sort) xs++testEdgeList :: Testsuite -> IO ()+testEdgeList (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "edgeList ============"+    test "edgeList empty          == []" $+          edgeList % empty        == []++    test "edgeList (vertex x)     == []" $ \x ->+          edgeList % vertex x     == []++    test "edgeList (edge x y)     == [(x,y)]" $ \x y ->+          edgeList % edge x y     == [(x,y)]++    test "edgeList (star 2 [3,1]) == [(2,1), (2,3)]" $+          edgeList % star 2 [3,1] == [(2,1), (2,3)]++    test "edgeList . edges        == nub . sort" $ \xs ->+          edgeList % edges xs     == (nubOrd . sort) xs++testAdjacencyList :: Testsuite -> IO ()+testAdjacencyList (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "adjacencyList ============"+    test "adjacencyList empty          == []" $+          adjacencyList % empty        == []++    test "adjacencyList (vertex x)     == [(x, [])]" $ \x ->+          adjacencyList % vertex x     == [(x, [])]++    test "adjacencyList (edge 1 2)     == [(1, [2]), (2, [])]" $+          adjacencyList % edge 1 2     == [(1, [2]), (2, [])]++    test "adjacencyList (star 2 [3,1]) == [(1, []), (2, [1,3]), (3, [])]" $+          adjacencyList % star 2 [3,1] == [(1, []), (2, [1,3]), (3, [])]++testVertexSet :: Testsuite -> IO ()+testVertexSet (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "vertexSet ============"+    test "vertexSet empty      == Set.empty" $+          vertexSet % empty    == Set.empty++    test "vertexSet . vertex   == Set.singleton" $ \x ->+          vertexSet % vertex x == Set.singleton x++    test "vertexSet . vertices == Set.fromList" $ \xs ->+          vertexSet % vertices xs == Set.fromList xs++    test "vertexSet . clique   == Set.fromList" $ \xs ->+          vertexSet % clique xs == Set.fromList xs++testVertexIntSet :: Testsuite -> IO ()+testVertexIntSet (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "vertexIntSet ============"+    test "vertexIntSet empty      == IntSet.empty" $+          vertexIntSet % empty    == IntSet.empty++    test "vertexIntSet . vertex   == IntSet.singleton" $ \x ->+          vertexIntSet % vertex x == IntSet.singleton x++    test "vertexIntSet . vertices == IntSet.fromList" $ \xs ->+          vertexIntSet % vertices xs == IntSet.fromList xs++    test "vertexIntSet . clique   == IntSet.fromList" $ \xs ->+          vertexIntSet % clique xs == IntSet.fromList xs++testEdgeSet :: Testsuite -> IO ()+testEdgeSet (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "edgeSet ============"+    test "edgeSet empty      == Set.empty" $+          edgeSet % empty    == Set.empty++    test "edgeSet (vertex x) == Set.empty" $ \x ->+          edgeSet % vertex x == Set.empty++    test "edgeSet (edge x y) == Set.singleton (x,y)" $ \x y ->+          edgeSet % edge x y == Set.singleton (x,y)++    test "edgeSet . edges    == Set.fromList" $ \xs ->+          edgeSet % edges xs == Set.fromList xs++testPreSet :: Testsuite -> IO ()+testPreSet (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "preSet ============"+    test "preSet x empty      == Set.empty" $ \x ->+          preSet x % empty    == Set.empty++    test "preSet x (vertex x) == Set.empty" $ \x ->+          preSet x % vertex x == Set.empty++    test "preSet 1 (edge 1 2) == Set.empty" $+          preSet 1 % edge 1 2 == Set.empty++    test "preSet y (edge x y) == Set.fromList [x]" $ \x y ->+          preSet y % edge x y == Set.fromList [x]++testPostSet :: Testsuite -> IO ()+testPostSet (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "postSet ============"+    test "postSet x empty      == Set.empty" $ \x ->+          postSet x % empty    == Set.empty++    test "postSet x (vertex x) == Set.empty" $ \x ->+          postSet x % vertex x == Set.empty++    test "postSet x (edge x y) == Set.fromList [y]" $ \x y ->+          postSet x % edge x y == Set.fromList [y]++    test "postSet 2 (edge 1 2) == Set.empty" $+          postSet 2 % edge 1 2 == Set.empty++testPostIntSet :: Testsuite -> IO ()+testPostIntSet (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "postIntSet ============"+    test "postIntSet x empty      == IntSet.empty" $ \x ->+          postIntSet x % empty    == IntSet.empty++    test "postIntSet x (vertex x) == IntSet.empty" $ \x ->+          postIntSet x % vertex x == IntSet.empty++    test "postIntSet x (edge x y) == IntSet.fromList [y]" $ \x y ->+          postIntSet x % edge x y == IntSet.fromList [y]++    test "postIntSet 2 (edge 1 2) == IntSet.empty" $+          postIntSet 2 % edge 1 2 == IntSet.empty++testPath :: Testsuite -> IO ()+testPath (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "path ============"+    test "path []    == empty" $+          path []    == id % empty++    test "path [x]   == vertex x" $ \x ->+          path [x]   == id % vertex x++    test "path [x,y] == edge x y" $ \x y ->+          path [x,y] == id % edge x y++testCircuit :: Testsuite -> IO ()+testCircuit (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "circuit ============"+    test "circuit []    == empty" $+          circuit []    == id % empty++    test "circuit [x]   == edge x x" $ \x ->+          circuit [x]   == id % edge x x++    test "circuit [x,y] == edges [(x,y), (y,x)]" $ \x y ->+          circuit [x,y] == id % edges [(x,y), (y,x)]++testClique :: Testsuite -> IO ()+testClique (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "clique ============"+    test "clique []         == empty" $+          clique []         == id % empty++    test "clique [x]        == vertex x" $ \x ->+          clique [x]        == id % vertex x++    test "clique [x,y]      == edge x y" $ \x y ->+          clique [x,y]      == id % edge x y++    test "clique [x,y,z]    == edges [(x,y), (x,z), (y,z)]" $ \x y z ->+          clique [x,y,z]    == id % edges [(x,y), (x,z), (y,z)]++    test "clique (xs ++ ys) == connect (clique xs) (clique ys)" $ \xs ys ->+          clique (xs ++ ys) == connect (clique xs) % (clique ys)++testBiclique :: Testsuite -> IO ()+testBiclique (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "biclique ============"+    test "biclique []      []      == empty" $+          biclique []      []      == id % empty++    test "biclique [x]     []      == vertex x" $ \x ->+          biclique [x]     []      == id % vertex x++    test "biclique []      [y]     == vertex y" $ \y ->+          biclique []      [y]     == id % vertex y++    test "biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]" $ \(x1) x2 y1 y2 ->+          biclique [x1,x2] [y1,y2] == id % edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]++    test "biclique xs      ys      == connect (vertices xs) (vertices ys)" $ \xs ys ->+          biclique xs      ys      == connect (vertices xs) % (vertices ys)++testStar :: Testsuite -> IO ()+testStar (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "star ============"+    test "star x []    == vertex x" $ \x ->+          star x []    == id % vertex x++    test "star x [y]   == edge x y" $ \x y ->+          star x [y]   == id % edge x y++    test "star x [y,z] == edges [(x,y), (x,z)]" $ \x y z ->+          star x [y,z] == id % edges [(x,y), (x,z)]++testTree :: Testsuite -> IO ()+testTree (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "tree ============"+    test "tree (Node x [])                                         == vertex x" $ \x ->+          tree (Node x [])                                         == id % vertex x++    test "tree (Node x [Node y [Node z []]])                       == path [x,y,z]" $ \x y z ->+          tree (Node x [Node y [Node z []]])                       == id % path [x,y,z]++    test "tree (Node x [Node y [], Node z []])                     == star x [y,z]" $ \x y z ->+          tree (Node x [Node y [], Node z []])                     == id % star x [y,z]++    test "tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5)]" $+          tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == id % edges [(1,2), (1,3), (3,4), (3,5)]++testForest :: Testsuite -> IO ()+testForest (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "forest ============"+    test "forest []                                                  == empty" $+          forest []                                                  == id % empty++    test "forest [x]                                                 == tree x" $ \x ->+          forest [x]                                                 == id % tree x++    test "forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5)]" $+          forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == id % edges [(1,2), (1,3), (4,5)]++    test "forest                                                     == overlays . map tree" $ \x ->+         (forest x)                                                  == id % (overlays . map tree) x++testRemoveVertex :: Testsuite -> IO ()+testRemoveVertex (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "removeVertex ============"+    test "removeVertex x (vertex x)       == empty" $ \x ->+          removeVertex x % vertex x       == empty++    test "removeVertex x . removeVertex x == removeVertex x" $ \x y ->+         (removeVertex x . removeVertex x) y == removeVertex x % y++testRemoveEdge :: Testsuite -> IO ()+testRemoveEdge (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "removeEdge ============"+    test "removeEdge x y (edge x y)       == vertices [x, y]" $ \x y ->+          removeEdge x y % edge x y       == vertices [x, y]++    test "removeEdge x y . removeEdge x y == removeEdge x y" $ \x y z ->+         (removeEdge x y . removeEdge x y) z == removeEdge x y % z++    test "removeEdge x y . removeVertex x == removeVertex x" $ \x y z ->+         (removeEdge x y . removeVertex x) z == removeVertex x % z++    test "removeEdge 1 1 (1 * 1 * 2 * 2)  == 1 * 2 * 2" $+          removeEdge 1 1 % (1 * 1 * 2 * 2) == 1 * 2 * 2++    test "removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2" $+          removeEdge 1 2 % (1 * 1 * 2 * 2) == 1 * 1 + 2 * 2++testReplaceVertex :: Testsuite -> IO ()+testReplaceVertex (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "replaceVertex ============"+    test "replaceVertex x x            == id" $ \x y ->+          replaceVertex x x % y        == y++    test "replaceVertex x y (vertex x) == vertex y" $ \x y ->+          replaceVertex x y % vertex x == vertex y++    test "replaceVertex x y            == mergeVertices (== x) y" $ \x y z ->+          replaceVertex x y % z        == mergeVertices (== x) y z++testMergeVertices :: Testsuite -> IO ()+testMergeVertices (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "mergeVertices ============"+    test "mergeVertices (const False) x    == id" $ \x y ->+          mergeVertices (const False) x % y == y++    test "mergeVertices (== x) y           == replaceVertex x y" $ \x y z ->+          mergeVertices (== x) y % z       == replaceVertex x y z++    test "mergeVertices even 1 (0 * 2)     == 1 * 1" $+          mergeVertices even 1 % (0 * 2)   == 1 * 1++    test "mergeVertices odd  1 (3 + 4 * 5) == 4 * 1" $+          mergeVertices odd  1 % (3 + 4 * 5) == 4 * 1++testTranspose :: Testsuite -> IO ()+testTranspose (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "transpose ============"+    test "transpose empty       == empty" $+          transpose % empty     == empty++    test "transpose (vertex x)  == vertex x" $ \x ->+          transpose % (vertex x) == vertex x++    test "transpose (edge x y)  == edge y x" $ \x y ->+          transpose % (edge x y) == edge y x++    test "transpose . transpose == id" $ \x ->+         (transpose . transpose) % x == x++    test "transpose . path      == path    . reverse" $ \xs ->+          transpose % (path xs) == (path . reverse) xs++    test "transpose . circuit   == circuit . reverse" $ \xs ->+          transpose % (circuit xs) == (circuit . reverse) xs++    test "transpose . clique    == clique  . reverse" $ \xs ->+          transpose % (clique xs) == (clique . reverse) xs++    test "edgeList . transpose  == sort . map swap . edgeList" $ \x ->+          edgeList % (transpose x) == (sort . map swap . edgeList) x++testGmap :: Testsuite -> IO ()+testGmap (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "gmap ============"+    test "gmap f empty      == empty" $ \(apply -> f) ->+          gmap f % empty      == empty++    test "gmap f (vertex x) == vertex (f x)" $ \(apply -> f) x ->+          gmap f % vertex x == vertex (f x)++    test "gmap f (edge x y) == edge (f x) (f y)" $ \(apply -> f) x y ->+          gmap f % edge x y == edge (f x) (f y)++    test "gmap id           == id" $ \x ->+          gmap id % x       == x++    test "gmap f . gmap g   == gmap (f . g)" $ \(apply -> f) (apply -> g) x ->+         (gmap f . gmap g) x == gmap (f . g) % x++testInduce :: Testsuite -> IO ()+testInduce (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "induce ============"+    test "induce (const True)  x      == x" $ \x ->+          induce (const True) % x     == x++    test "induce (const False) x      == empty" $ \x ->+          induce (const False) % x    == empty++    test "induce (/= x)               == removeVertex x" $ \x y ->+          induce (/= x) % y           == removeVertex x y++    test "induce p . induce q         == induce (\\x -> p x && q x)" $ \(apply -> p) (apply -> q) y ->+         (induce p . induce q) % y    == induce (\x -> p x && q x) y++    test "isSubgraphOf (induce p x) x == True" $ \(apply -> p) x ->+          isSubgraphOf (induce p x) % x == True++testSplitVertex :: Testsuite -> IO ()+testSplitVertex (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "splitVertex ============"+    test "splitVertex x []                   == removeVertex x" $ \x y ->+          splitVertex x [] % y               == removeVertex x y++    test "splitVertex x [x]                  == id" $ \x y ->+          splitVertex x [x] % y              == y++    test "splitVertex x [y]                  == replaceVertex x y" $ \x y z ->+          splitVertex x [y] % z              == replaceVertex x y z++    test "splitVertex 1 [0, 1] $ 1 * (2 + 3) == (0 + 1) * (2 + 3)" $+          splitVertex 1 [0, 1] % (1 * (2 + 3)) == (0 + 1) * (2 + 3)++testBind :: Testsuite -> IO ()+testBind (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "bind ============"+    test "bind empty f         == empty" $ \(apply -> f) ->+          bind empty f         == id % empty++    test "bind (vertex x) f    == f x" $ \(apply -> f) x ->+          bind (vertex x) f    == id % f x++    test "bind (edge x y) f    == connect (f x) (f y)" $ \(apply -> f) x y ->+          bind (edge x y) f    == connect (f x) % (f y)++    test "bind (vertices xs) f == overlays (map f xs)" $ mapSize (min 10) $ \xs (apply -> f) ->+          bind (vertices xs) f == id % overlays (map f xs)++    test "bind x (const empty) == empty" $ \x ->+          bind x (const empty) == id % empty++    test "bind x vertex        == x" $ \x ->+          bind x vertex        == id % x++    test "bind (bind x f) g    == bind x (\\y -> bind (f y) g)" $ mapSize (min 10) $ \x (apply -> f) (apply -> g) ->+          bind (bind x f) g    == bind (id % x) (\y -> bind (f y) g)++testSimplify :: Testsuite -> IO ()+testSimplify (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "simplify ============"+    test "simplify              == id" $ \x ->+          simplify % x          == x++    test "size (simplify x)     <= size x" $ \x ->+          size % simplify x     <= size x+++testDfsForest :: Testsuite -> IO ()+testDfsForest (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "dfsForest ============"+    test "forest (dfsForest $ edge 1 1)         == vertex 1" $+          forest (dfsForest % edge 1 1)         == id % vertex 1++    test "forest (dfsForest $ edge 1 2)         == edge 1 2" $+          forest (dfsForest % edge 1 2)         == id % edge 1 2++    test "forest (dfsForest $ edge 2 1)         == vertices [1, 2]" $+          forest (dfsForest % edge 2 1)         == id % vertices [1, 2]++    test "isSubgraphOf (forest $ dfsForest x) x == True" $ \x ->+          isSubgraphOf (forest $ dfsForest x) % x == True++    test "dfsForest . forest . dfsForest        == dfsForest" $ \x ->+          dfsForest % (forest $ dfsForest x)    == dfsForest % x++    test "dfsForest (vertices vs)               == map (\\v -> Node v []) (nub $ sort vs)" $ \vs ->+          dfsForest % (vertices vs)             == map (\v -> Node v []) (nub $ sort vs)++    test "dfsForest $ 3 * (1 + 4) * (1 + 5)     == <correct result>" $+          dfsForest % (3 * (1 + 4) * (1 + 5))   == [ Node { rootLabel = 1+                                                   , subForest = [ Node { rootLabel = 5+                                                                        , subForest = [] }]}+                                                   , Node { rootLabel = 3+                                                   , subForest = [ Node { rootLabel = 4+                                                                        , subForest = [] }]}]++testDfsForestFrom :: Testsuite -> IO ()+testDfsForestFrom (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "dfsForestFrom ============"+    test "forest (dfsForestFrom [1]    $ edge 1 1)     == vertex 1" $+          forest (dfsForestFrom [1]    % edge 1 1)     == id % vertex 1++    test "forest (dfsForestFrom [1]    $ edge 1 2)     == edge 1 2" $+          forest (dfsForestFrom [1]    % edge 1 2)     == id % edge 1 2++    test "forest (dfsForestFrom [2]    $ edge 1 2)     == vertex 2" $+          forest (dfsForestFrom [2]    % edge 1 2)     == id % vertex 2++    test "forest (dfsForestFrom [3]    $ edge 1 2)     == empty" $+          forest (dfsForestFrom [3]    % edge 1 2)     == id % empty++    test "forest (dfsForestFrom [2, 1] $ edge 1 2)     == vertices [1, 2]" $+          forest (dfsForestFrom [2, 1] % edge 1 2)     == id % vertices [1, 2]++    test "isSubgraphOf (forest $ dfsForestFrom vs x) x == True" $ \vs x ->+          isSubgraphOf (forest $ dfsForestFrom vs x) % x == True++    test "dfsForestFrom (vertexList x) x               == dfsForest x" $ \x ->+          dfsForestFrom (vertexList x) % x             == dfsForest % x++    test "dfsForestFrom vs             (vertices vs)   == map (\\v -> Node v []) (nub vs)" $ \vs ->+          dfsForestFrom vs           % (vertices vs)   == map (\v -> Node v []) (nub vs)++    test "dfsForestFrom []             x               == []" $ \x ->+          dfsForestFrom []           % x               == []++    test "dfsForestFrom [1, 4] $ 3 * (1 + 4) * (1 + 5) == <correct result>" $+          dfsForestFrom [1, 4] % (3 * (1 + 4) * (1 + 5)) == [ Node { rootLabel = 1+                                                                   , subForest = [ Node { rootLabel = 5+                                                                                        , subForest = [] }]}+                                                            , Node { rootLabel = 4+                                                                   , subForest = [] }]++testDfs :: Testsuite -> IO ()+testDfs (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "dfs ============"+    test "dfs [1]    $ edge 1 1                == [1]" $+          dfs [1]    % edge 1 1                == [1]++    test "dfs [1]    $ edge 1 2                == [1, 2]" $+          dfs [1]    % edge 1 2                == [1, 2]++    test "dfs [2]    $ edge 1 2                == [2]" $+          dfs [2]    % edge 1 2                == [2]++    test "dfs [3]    $ edge 1 2                == []" $+          dfs [3]    % edge 1 2                == []++    test "dfs [1, 2] $ edge 1 2                == [1, 2]" $+          dfs [1, 2] % edge 1 2                == [1, 2]++    test "dfs [2, 1] $ edge 1 2                == [2, 1]" $+          dfs [2, 1] % edge 1 2                == [2, 1]++    test "dfs []     $ x                       == []" $ \x ->+          dfs []     % x                       == []++    test "dfs [1, 4] $ 3 * (1 + 4) * (1 + 5)   == [1, 5, 4]" $+          dfs [1, 4] % (3 * (1 + 4) * (1 + 5))   == [1, 5, 4]++    test "isSubgraphOf (vertices $ dfs vs x) x == True" $ \vs x ->+          isSubgraphOf (vertices $ dfs vs x) % x == True++testTopSort :: Testsuite -> IO ()+testTopSort (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "topSort ============"+    test "topSort (1 * 2 + 3 * 1)             == Just [3,1,2]" $+          topSort % (1 * 2 + 3 * 1)           == Just [3,1,2]++    test "topSort (1 * 2 + 2 * 1)             == Nothing" $+          topSort % (1 * 2 + 2 * 1)           == Nothing++    test "fmap (flip isTopSort x) (topSort x) /= Just False" $ \x ->+          fmap (flip isTopSort x) (topSort % x) /= Just False++testIsTopSort :: Testsuite -> IO ()+testIsTopSort (Testsuite prefix (%)) = do+    putStrLn $ "\n============ " ++ prefix ++ "isTopSort ============"+    test "isTopSort [3, 1, 2] (1 * 2 + 3 * 1) == True" $+          isTopSort [3, 1, 2] % (1 * 2 + 3 * 1) == True++    test "isTopSort [1, 2, 3] (1 * 2 + 3 * 1) == False" $+          isTopSort [1, 2, 3] % (1 * 2 + 3 * 1) == False++    test "isTopSort []        (1 * 2 + 3 * 1) == False" $+          isTopSort []      % (1 * 2 + 3 * 1) == False++    test "isTopSort []        empty           == True" $+          isTopSort []      % empty           == True++    test "isTopSort [x]       (vertex x)      == True" $ \x ->+          isTopSort [x]      % vertex x       == True++    test "isTopSort [x]       (edge x x)      == False" $ \x ->+          isTopSort [x]      % edge x x       == False
test/Algebra/Graph/Test/Graph.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ViewPatterns #-} ----------------------------------------------------------------------------- -- | -- Module     : Algebra.Graph.Test.Graph@@ -7,29 +6,25 @@ -- Maintainer : andrey.mokhov@gmail.com -- Stability  : experimental ----- Testsuite for 'Graph' and polymorphic functions defined in+-- Testsuite for "Algebra.Graph" and polymorphic functions defined in -- "Algebra.Graph.HigherKinded.Class".--- ----------------------------------------------------------------------------- module Algebra.Graph.Test.Graph (     -- * Testsuite     testGraph   ) where -import Data.Foldable-import Data.Tree-import Data.Tuple- import Algebra.Graph import Algebra.Graph.Test+import Algebra.Graph.Test.Generic -import qualified Data.Set    as Set-import qualified Data.IntSet as IntSet+t :: Testsuite+t = testsuite "Graph." empty +h :: HTestsuite+h = hTestsuite "Graph." empty+ type G  = Graph Int-type II = Int -> Int-type IB = Int -> Bool-type IG = Int -> G  testGraph :: IO () testGraph = do@@ -37,218 +32,13 @@     test "Axioms of graphs"   $ (axioms   :: GraphTestsuite G)     test "Theorems of graphs" $ (theorems :: GraphTestsuite G) -    putStrLn "\n============ Graph.empty ============"-    test "isEmpty     empty == True" $-          isEmpty    (empty :: G) == True--    test "hasVertex x empty == False" $ \(x :: Int) ->-          hasVertex x empty == False--    test "vertexCount empty == 0" $-          vertexCount(empty :: G) == 0--    test "edgeCount   empty == 0" $-          edgeCount  (empty :: G) == 0--    test "size        empty == 1" $-          size       (empty :: G) == 1--    putStrLn "\n============ Graph.vertex ============"-    test "isEmpty     (vertex x) == False" $ \(x :: Int) ->-          isEmpty     (vertex x) == False--    test "hasVertex x (vertex x) == True" $ \(x :: Int) ->-          hasVertex x (vertex x) == True--    test "hasVertex 1 (vertex 2) == False" $-          hasVertex 1 (vertex 2 :: G) == False--    test "vertexCount (vertex x) == 1" $ \(x :: Int) ->-          vertexCount (vertex x) == 1--    test "edgeCount   (vertex x) == 0" $ \(x :: Int) ->-          edgeCount   (vertex x) == 0--    test "size        (vertex x) == 1" $ \(x :: Int) ->-          size        (vertex x) == 1--    putStrLn "\n============ Graph.edge ============"-    test "edge x y               == connect (vertex x) (vertex y)" $ \(x :: Int) y ->-          edge x y               == connect (vertex x) (vertex y)--    test "hasEdge x y (edge x y) == True" $ \(x :: Int) y ->-          hasEdge x y (edge x y) == True--    test "edgeCount   (edge x y) == 1" $ \(x :: Int) y ->-          edgeCount   (edge x y) == 1--    test "vertexCount (edge 1 1) == 1" $-          vertexCount (edge 1 1 :: G) == 1--    test "vertexCount (edge 1 2) == 2" $-          vertexCount (edge 1 2 :: G) == 2--    putStrLn "\n============ Graph.overlay ============"-    test "isEmpty     (overlay x y) == isEmpty   x   && isEmpty   y" $ \(x :: G) y ->-          isEmpty     (overlay x y) ==(isEmpty   x   && isEmpty   y)--    test "hasVertex z (overlay x y) == hasVertex z x || hasVertex z y" $ \(x :: G) y z ->-          hasVertex z (overlay x y) ==(hasVertex z x || hasVertex z y)--    test "vertexCount (overlay x y) >= vertexCount x" $ \(x :: G) y ->-          vertexCount (overlay x y) >= vertexCount x--    test "vertexCount (overlay x y) <= vertexCount x + vertexCount y" $ \(x :: G) y ->-          vertexCount (overlay x y) <= vertexCount x + vertexCount y--    test "edgeCount   (overlay x y) >= edgeCount x" $ \(x :: G) y ->-          edgeCount   (overlay x y) >= edgeCount x--    test "edgeCount   (overlay x y) <= edgeCount x   + edgeCount y" $ \(x :: G) y ->-          edgeCount   (overlay x y) <= edgeCount x   + edgeCount y--    test "size        (overlay x y) == size x        + size y" $ \(x :: G) y ->-          size        (overlay x y) == size x        + size y--    test "vertexCount (overlay 1 2) == 2" $-          vertexCount (overlay 1 2 :: G) == 2--    test "edgeCount   (overlay 1 2) == 0" $-          edgeCount   (overlay 1 2 :: G) == 0--    putStrLn "\n============ Graph.connect ============"-    test "isEmpty     (connect x y) == isEmpty   x   && isEmpty   y" $ \(x :: G) y ->-          isEmpty     (connect x y) ==(isEmpty   x   && isEmpty   y)--    test "hasVertex z (connect x y) == hasVertex z x || hasVertex z y" $ \(x :: G) y z ->-          hasVertex z (connect x y) ==(hasVertex z x || hasVertex z y)--    test "vertexCount (connect x y) >= vertexCount x" $ \(x :: G) y ->-          vertexCount (connect x y) >= vertexCount x--    test "vertexCount (connect x y) <= vertexCount x + vertexCount y" $ \(x :: G) y ->-          vertexCount (connect x y) <= vertexCount x + vertexCount y--    test "edgeCount   (connect x y) >= edgeCount x" $ \(x :: G) y ->-          edgeCount   (connect x y) >= edgeCount x--    test "edgeCount   (connect x y) >= edgeCount y" $ \(x :: G) y ->-          edgeCount   (connect x y) >= edgeCount y--    test "edgeCount   (connect x y) >= vertexCount x * vertexCount y" $ \(x :: G) y ->-          edgeCount   (connect x y) >= vertexCount x * vertexCount y--    test "edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y" $ \(x :: G) y ->-          edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y--    test "size        (connect x y) == size x        + size y" $ \(x :: G) y ->-          size        (connect x y) == size x        + size y--    test "vertexCount (connect 1 2) == 2" $-          vertexCount (connect 1 2 :: G) == 2--    test "edgeCount   (connect 1 2) == 1" $-          edgeCount   (connect 1 2 :: G) == 1--    putStrLn "\n============ Graph.vertices ============"-    test "vertices []            == empty" $-          vertices []            == (empty :: G)--    test "vertices [x]           == vertex x" $ \(x :: Int) ->-          vertices [x]           == vertex x--    test "hasVertex x . vertices == elem x" $ \x (xs :: [Int]) ->-         (hasVertex x . vertices) xs == elem x xs--    test "vertexCount . vertices == length . nub" $ \(xs :: [Int]) ->-         (vertexCount . vertices) xs == (length . nubOrd) xs--    test "vertexSet   . vertices == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet   . vertices) xs == Set.fromList xs--    putStrLn "\n============ Graph.edges ============"-    test "edges []          == empty" $-          edges []          ==(empty :: G)--    test "edges [(x,y)]     == edge x y" $ \(x :: Int) y ->-          edges [(x,y)]     == edge x y--    test "edgeCount . edges == length . nub" $ \(xs :: [(Int, Int)]) ->-         (edgeCount . edges) xs == (length . nubOrd) xs--    putStrLn "\n============ Graph.overlays ============"-    test "overlays []        == empty" $-          overlays []        ==(empty :: G)--    test "overlays [x]       == x" $ \(x :: G) ->-          overlays [x]       == x--    test "overlays [x,y]     == overlay x y" $ \(x :: G) y ->-          overlays [x,y]     == overlay x y--    test "isEmpty . overlays == all isEmpty" $ \(xs :: [G]) ->-         (isEmpty . overlays) xs == all isEmpty xs--    putStrLn "\n============ Graph.connects ============"-    test "connects []        == empty" $-          connects []        ==(empty :: G)--    test "connects [x]       == x" $ \(x :: G) ->-          connects [x]       == x--    test "connects [x,y]     == connect x y" $ \(x :: G) y ->-          connects [x,y]     == connect x y--    test "isEmpty . connects == all isEmpty" $ \(xs :: [G]) ->-         (isEmpty . connects) xs == all isEmpty xs--    putStrLn "\n============ Graph.graph ============"-    test "graph []  []      == empty" $-          graph []  []      ==(empty :: G)--    test "graph [x] []      == vertex x" $ \(x :: Int) ->-          graph [x] []      == vertex x--    test "graph []  [(x,y)] == edge x y" $ \(x :: Int) y ->-          graph []  [(x,y)] == edge x y--    test "graph vs  es      == overlay (vertices vs) (edges es)" $ \(vs :: [Int]) es ->-          graph vs  es      == overlay (vertices vs) (edges es)--    putStrLn "\n============ Graph.foldg ============"-    test "foldg empty vertex        overlay connect        == id" $ \(x :: G) ->-          foldg empty vertex        overlay connect x      == x--    test "foldg empty vertex        overlay (flip connect) == transpose" $ \(x :: G) ->-          foldg empty vertex        overlay (flip connect)x== transpose x--    test "foldg []    return        (++)    (++)           == toList" $ \(x :: G) ->-          foldg []    return        (++)    (++) x         == toList x--    test "foldg 0     (const 1)     (+)     (+)            == length" $ \(x :: G) ->-          foldg 0     (const 1)     (+)     (+) x          == length x--    test "foldg 1     (const 1)     (+)     (+)            == size" $ \(x :: G) ->-          foldg 1     (const 1)     (+)     (+) x          == size x--    test "foldg True  (const False) (&&)    (&&)           == isEmpty" $ \(x :: G) ->-          foldg True  (const False) (&&)    (&&) x         == isEmpty x--    putStrLn "\n============ Graph.isSubgraphOf ============"-    test "isSubgraphOf empty         x             == True" $ \(x :: G) ->-          isSubgraphOf empty         x             == True--    test "isSubgraphOf (vertex x)    empty         == False" $ \x ->-          isSubgraphOf (vertex x)   (empty :: G)   == False--    test "isSubgraphOf x             (overlay x y) == True" $ \(x :: G) y ->-          isSubgraphOf x             (overlay x y) == True--    test "isSubgraphOf (overlay x y) (connect x y) == True" $ \(x :: G) y ->-          isSubgraphOf (overlay x y) (connect x y) == True--    test "isSubgraphOf (path xs)     (circuit xs)  == True" $ \xs ->-          isSubgraphOf (path xs :: G)(circuit xs)  == True+    testBasicPrimitives t+    testFoldg           h+    testIsSubgraphOf    t+    testSize            t+    testProperties      t+    testGraphFamilies   t+    testTransformations t      putStrLn "\n============ Graph.(===) ============"     test "    x === x         == True" $ \(x :: G) ->@@ -266,237 +56,6 @@     test "x + y === x * y     == False" $ \(x :: G) y ->          (x + y === x * y)    == False -    putStrLn "\n============ Graph.isEmpty ============"-    test "isEmpty empty                       == True" $-          isEmpty (empty :: G)                == True--    test "isEmpty (overlay empty empty)       == True" $-          isEmpty (overlay empty empty :: G)  == True--    test "isEmpty (vertex x)                  == False" $ \(x :: Int) ->-          isEmpty (vertex x)                  == False--    test "isEmpty (removeVertex x $ vertex x) == True" $ \(x :: Int) ->-          isEmpty (removeVertex x $ vertex x) == True--    test "isEmpty (removeEdge x y $ edge x y) == False" $ \(x :: Int) y ->-          isEmpty (removeEdge x y $ edge x y) == False--    putStrLn "\n============ Graph.size ============"-    test "size empty         == 1" $-          size (empty :: G)  == 1--    test "size (vertex x)    == 1" $ \(x :: Int) ->-          size (vertex x)    == 1--    test "size (overlay x y) == size x + size y" $ \(x :: G) y ->-          size (overlay x y) == size x + size y--    test "size (connect x y) == size x + size y" $ \(x :: G) y ->-          size (connect x y) == size x + size y--    test "size x             >= 1" $ \(x :: G) ->-          size x             >= 1--    test "size x             >= vertexCount x" $ \(x :: G) ->-          size x             >= vertexCount x--    putStrLn "\n============ Graph.hasVertex ============"-    test "hasVertex x empty            == False" $ \(x :: Int) ->-          hasVertex x empty            == False--    test "hasVertex x (vertex x)       == True" $ \(x :: Int) ->-          hasVertex x (vertex x)       == True--    test "hasVertex x . removeVertex x == const False" $ \(x :: Int) y ->-          hasVertex x (removeVertex x y)==const False y--    putStrLn "\n============ Graph.hasEdge ============"-    test "hasEdge x y empty            == False" $ \(x :: Int) y ->-          hasEdge x y empty            == False--    test "hasEdge x y (vertex z)       == False" $ \(x :: Int) y z ->-          hasEdge x y (vertex z)       == False--    test "hasEdge x y (edge x y)       == True" $ \(x :: Int) y ->-          hasEdge x y (edge x y)       == True--    test "hasEdge x y . removeEdge x y == const False" $ \(x :: Int) y z ->-          hasEdge x y (removeEdge x y z)==const False z--    putStrLn "\n============ Graph.vertexCount ============"-    test "vertexCount empty      == 0" $-          vertexCount (empty :: G) == 0--    test "vertexCount (vertex x) == 1" $ \(x :: Int) ->-          vertexCount (vertex x) == 1--    test "vertexCount            == length . vertexList" $ \(x :: G) ->-          vertexCount x          ==(length . vertexList) x--    putStrLn "\n============ Graph.edgeCount ============"-    test "edgeCount empty      == 0" $-          edgeCount (empty :: G) == 0--    test "edgeCount (vertex x) == 0" $ \(x :: Int) ->-          edgeCount (vertex x) == 0--    test "edgeCount (edge x y) == 1" $ \(x :: Int) y ->-          edgeCount (edge x y) == 1--    test "edgeCount            == length . edgeList" $ \(x :: G) ->-          edgeCount x          == (length . edgeList) x--    putStrLn "\n============ Graph.vertexList ============"-    test "vertexList empty      == []" $-          vertexList (empty :: G) == []--    test "vertexList (vertex x) == [x]" $ \(x :: Int) ->-          vertexList (vertex x) == [x]--    test "vertexList . vertices == nub . sort" $ \(xs :: [Int]) ->-         (vertexList . vertices) xs == (nubOrd . sort) xs--    putStrLn "\n============ Graph.edgeList ============"-    test "edgeList empty          == []" $-          edgeList (empty :: G )  == []--    test "edgeList (vertex x)     == []" $ \(x :: Int) ->-          edgeList (vertex x)     == []--    test "edgeList (edge x y)     == [(x,y)]" $ \(x :: Int) y ->-          edgeList (edge x y)     == [(x,y)]--    test "edgeList (star 2 [3,1]) == [(2,1), (2,3)]" $-          edgeList (star 2 [3,1]) == [(2,1), (2,3 :: Int)]--    test "edgeList . edges        == nub . sort" $ \(xs :: [(Int, Int)]) ->-         (edgeList . edges) xs    ==(nubOrd . sort) xs--    putStrLn "\n============ Graph.vertexSet ============"-    test "vertexSet empty      == Set.empty" $-          vertexSet(empty :: G)== Set.empty--    test "vertexSet . vertex   == Set.singleton" $ \(x :: Int) ->-         (vertexSet . vertex) x== Set.singleton x--    test "vertexSet . vertices == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet . vertices) xs == Set.fromList xs--    test "vertexSet . clique   == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet . clique) xs == Set.fromList xs--    putStrLn "\n============ Graph.vertexIntSet ============"-    test "vertexIntSet empty      == IntSet.empty" $-          vertexIntSet(empty :: G)== IntSet.empty--    test "vertexIntSet . vertex   == IntSet.singleton" $ \(x :: Int) ->-         (vertexIntSet . vertex) x== IntSet.singleton x--    test "vertexIntSet . vertices == IntSet.fromList" $ \(xs :: [Int]) ->-         (vertexIntSet . vertices) xs == IntSet.fromList xs--    test "vertexIntSet . clique   == IntSet.fromList" $ \(xs :: [Int]) ->-         (vertexIntSet . clique) xs == IntSet.fromList xs--    putStrLn "\n============ Graph.edgeSet ============"-    test "edgeSet empty      == Set.empty" $-          edgeSet (empty :: G) == Set.empty--    test "edgeSet (vertex x) == Set.empty" $ \(x :: Int) ->-          edgeSet (vertex x) == Set.empty--    test "edgeSet (edge x y) == Set.singleton (x,y)" $ \(x :: Int) y ->-          edgeSet (edge x y) == Set.singleton (x,y)--    test "edgeSet . edges    == Set.fromList" $ \(xs :: [(Int, Int)]) ->-         (edgeSet . edges) xs== Set.fromList xs--    putStrLn "\n============ Graph.path ============"-    test "path []    == empty" $-          path []    ==(empty :: G)--    test "path [x]   == vertex x" $ \(x :: Int) ->-          path [x]   == vertex x--    test "path [x,y] == edge x y" $ \(x :: Int) y ->-          path [x,y] == edge x y--    putStrLn "\n============ Graph.circuit ============"-    test "circuit []    == empty" $-          circuit []    ==(empty :: G)--    test "circuit [x]   == edge x x" $ \(x :: Int) ->-          circuit [x]   == edge x x--    test "circuit [x,y] == edges [(x,y), (y,x)]" $ \(x :: Int) y ->-          circuit [x,y] == edges [(x,y), (y,x)]--    putStrLn "\n============ Graph.clique ============"-    test "clique []      == empty" $-          clique []      ==(empty :: G)--    test "clique [x]     == vertex x" $ \(x :: Int) ->-          clique [x]     == vertex x--    test "clique [x,y]   == edge x y" $ \(x :: Int) y ->-          clique [x,y]   == edge x y--    test "clique [x,y,z] == edges [(x,y), (x,z), (y,z)]" $ \(x :: Int) y z ->-          clique [x,y,z] == edges [(x,y), (x,z), (y,z)]--    putStrLn "\n============ Graph.biclique ============"-    test "biclique []      []      == empty" $-          biclique []      []      ==(empty :: G)--    test "biclique [x]     []      == vertex x" $ \(x :: Int) ->-          biclique [x]     []      == vertex x--    test "biclique []      [y]     == vertex y" $ \(y :: Int) ->-          biclique []      [y]     == vertex y--    test "biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]" $ \(x1 :: Int) x2 y1 y2 ->-          biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]--    test "biclique xs      ys      == connect (vertices xs) (vertices ys)" $ \(xs :: [Int]) ys ->-          biclique xs      ys      == connect (vertices xs) (vertices ys)--    putStrLn "\n============ Graph.star ============"-    test "star x []    == vertex x" $ \(x :: Int) ->-          star x []    == vertex x--    test "star x [y]   == edge x y" $ \(x :: Int) y ->-          star x [y]   == edge x y--    test "star x [y,z] == edges [(x,y), (x,z)]" $ \(x :: Int) y z ->-          star x [y,z] == edges [(x,y), (x,z)]--    putStrLn "\n============ Graph.tree ============"-    test "tree (Node x [])                                         == vertex x" $ \(x :: Int) ->-          tree (Node x [])                                         == vertex x--    test "tree (Node x [Node y [Node z []]])                       == path [x,y,z]" $ \(x :: Int) y z ->-          tree (Node x [Node y [Node z []]])                       == path [x,y,z]--    test "tree (Node x [Node y [], Node z []])                     == star x [y,z]" $ \(x :: Int) y z ->-          tree (Node x [Node y [], Node z []])                     == star x [y,z]--    test "tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5)]" $-          tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5::Int)]--    putStrLn "\n============ Graph.forest ============"-    test "forest []                                                  == empty" $-          forest []                                                  == (empty :: G)--    test "forest [x]                                                 == tree x" $ \(x :: Tree Int) ->-          forest [x]                                                 == tree x--    test "forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5)]" $-          forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5::Int)]--    test "forest                                                     == overlays . map tree" $ \(x :: Forest Int) ->-         (forest x)                                                  ==(overlays . map tree) x-     putStrLn "\n============ Graph.mesh ============"     test "mesh xs     []   == empty" $ \xs ->           mesh xs     []   == (empty :: Graph (Int, Int))@@ -548,174 +107,18 @@                     deBruijn 2 "01"             == edges [ ("00","00"), ("00","01"), ("01","10"), ("01","11")                                                          , ("10","00"), ("10","01"), ("11","10"), ("11","11") ] +    test "          transpose   (deBruijn n xs) == fmap reverse $ deBruijn n xs" $ mapSize (min 5) $ \(NonNegative n) (xs :: [Int]) ->+                    transpose   (deBruijn n xs) == (fmap reverse $ deBruijn n xs)+     test "          vertexCount (deBruijn n xs) == (length $ nub xs)^n" $ mapSize (min 5) $ \(NonNegative n) (xs :: [Int]) ->                     vertexCount (deBruijn n xs) == (length $ nubOrd xs)^n      test "n > 0 ==> edgeCount   (deBruijn n xs) == (length $ nub xs)^(n + 1)" $ mapSize (min 5) $ \(NonNegative n) (xs :: [Int]) ->           n > 0 ==> edgeCount   (deBruijn n xs) == (length $ nubOrd xs)^(n + 1) -    putStrLn "\n============ Graph.removeVertex ============"-    test "removeVertex x (vertex x)       == empty" $ \(x :: Int) ->-          removeVertex x (vertex x)       == empty--    test "removeVertex x . removeVertex x == removeVertex x" $ \x (y :: G) ->-         (removeVertex x . removeVertex x)y==removeVertex x y--    putStrLn "\n============ Graph.removeEdge ============"-    test "removeEdge x y (edge x y)       == vertices [x, y]" $ \(x :: Int) y ->-          removeEdge x y (edge x y)       == vertices [x, y]--    test "removeEdge x y . removeEdge x y == removeEdge x y" $ \(x :: Int) y z ->-         (removeEdge x y . removeEdge x y)z==removeEdge x y z--    test "removeEdge x y . removeVertex x == removeVertex x" $ \(x :: Int) y z ->-         (removeEdge x y . removeVertex x)z==removeVertex x z--    test "removeEdge 1 1 (1 * 1 * 2 * 2)  == 1 * 2 * 2" $-          removeEdge 1 1 (1 * 1 * 2 * 2)  ==(1 * 2 * (2 :: G))--    test "removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2" $-          removeEdge 1 2 (1 * 1 * 2 * 2)  ==(1 * 1 + 2 * (2 :: G))--    putStrLn "\n============ Graph.replaceVertex ============"-    test "replaceVertex x x            == id" $ \x (y :: G) ->-          replaceVertex x x y          == y--    test "replaceVertex x y (vertex x) == vertex y" $ \x (y :: Int) ->-          replaceVertex x y (vertex x) == vertex y--    test "replaceVertex x y            == mergeVertices (== x) y" $ \x y z ->-          replaceVertex x y z          == mergeVertices (== x) y (z :: G)--    putStrLn "\n============ Graph.mergeVertices ============"-    test "mergeVertices (const False) x    == id" $ \x (y :: G) ->-          mergeVertices (const False) x y  == y--    test "mergeVertices (== x) y           == replaceVertex x y" $ \x y (z :: G) ->-          mergeVertices (== x) y z         == replaceVertex x y z--    test "mergeVertices even 1 (0 * 2)     == 1 * 1" $-          mergeVertices even 1 (0 * 2)     ==(1 * 1 :: G)--    test "mergeVertices odd  1 (3 + 4 * 5) == 4 * 1" $-          mergeVertices odd  1 (3 + 4 * 5) ==(4 * 1 :: G)--    putStrLn "\n============ Graph.splitVertex ============"-    test "splitVertex x []                   == removeVertex x" $ \x (y :: G) ->-         (splitVertex x []) y                == removeVertex x y--    test "splitVertex x [x]                  == id" $ \x (y :: G) ->-         (splitVertex x [x]) y               == y--    test "splitVertex x [y]                  == replaceVertex x y" $ \x y (z :: G) ->-         (splitVertex x [y]) z               == replaceVertex x y z--    test "splitVertex 1 [0, 1] $ 1 * (2 + 3) == (0 + 1) * (2 + 3)" $-         (splitVertex 1 [0, 1] $ 1 * (2 + 3))==((0 + 1) * (2 + 3 :: G))--    putStrLn "\n============ Graph.transpose ============"-    test "transpose empty       == empty" $-          transpose empty       ==(empty :: G)--    test "transpose (vertex x)  == vertex x" $ \(x :: Int) ->-          transpose (vertex x)  == vertex x--    test "transpose (edge x y)  == edge y x" $ \(x :: Int) y ->-          transpose (edge x y)  == edge y x--    test "transpose . transpose == id" $ \(x :: G) ->-         (transpose . transpose) x == x--    test "transpose . path      == path    . reverse" $ \(xs :: [Int]) ->-         (transpose . path) xs  == (path . reverse) xs--    test "transpose . circuit   == circuit . reverse" $ \(xs :: [Int]) ->-         (transpose . circuit) xs == (circuit . reverse) xs--    test "transpose . clique    == clique  . reverse" $ \(xs :: [Int]) ->-         (transpose . clique) xs == (clique . reverse) xs--    test "transpose (box x y)   == box (transpose x) (transpose y)" $ mapSize (min 10) $ \(x :: G) (y :: G) ->-          transpose (box x y)   == box (transpose x) (transpose y)--    test "edgeList . transpose  == sort . map swap . edgeList" $ \(x :: G) ->-         (edgeList . transpose) x == (sort . map swap . edgeList) x--    putStrLn "\n============ Graph.fmap ============"-    test "fmap f empty      == empty" $ \(apply -> f :: II) ->-          fmap f empty      == empty--    test "fmap f (vertex x) == vertex (f x)" $ \(apply -> f :: II) x ->-          fmap f (vertex x) == vertex (f x)--    test "fmap f (edge x y) == edge (f x) (f y)" $ \(apply -> f :: II) x y ->-          fmap f (edge x y) == edge (f x) (f y)--    test "fmap id           == id" $ \(x :: G) ->-          fmap id x         == x--    test "fmap f . fmap g   == fmap (f . g)" $ \(apply -> f :: II) (apply -> g :: II) (x :: G) ->-         (fmap f . fmap g) x== fmap (f . g) x--    putStrLn "\n============ Graph.>>= ============"-    test "empty >>= f       == empty" $ \(apply -> f :: IG) ->-         (empty >>= f)      == empty--    test "vertex x >>= f    == f x" $ \(apply -> f :: IG) x ->-         (vertex x >>= f)   == f x--    test "edge x y   >>= f  == connect (f x) (f y)" $ \(apply -> f :: IG) x y ->-         (edge x y   >>= f) == connect (f x) (f y)--    test "vertices xs >>= f == overlays (map f xs)" $ mapSize (min 10) $ \xs (apply -> f :: IG) ->-         (vertices xs >>= f)== overlays (map f xs)--    test "x >>= const empty == empty" $ \(x :: G) ->-         (x >>= const empty)==(empty :: G)--    test "x >>= vertex      == x" $ \(x :: G) ->-         (x >>= vertex)     == x--    test "(x >>= f) >>= g   == x >>= (\\y -> f y >>= g)" $ mapSize (min 10) $ \x (apply -> f :: IG) (apply -> g :: IG) ->-         ((x >>= f) >>= g)  ==(x >>= (\y  -> f y >>= g))--    putStrLn "\n============ Graph.induce ============"-    test "induce (const True)  x      == x" $ \(x :: G) ->-          induce (const True)  x      == x--    test "induce (const False) x      == empty" $ \(x :: G) ->-          induce (const False) x      == empty--    test "induce (/= x)               == removeVertex x" $ \x (y :: G) ->-          induce (/= x) y             == removeVertex x y--    test "induce p . induce q         == induce (\\x -> p x && q x)" $ \(apply -> p :: IB) (apply -> q :: IB) (y :: G) ->-         (induce p . induce q) y      == induce (\x -> p x && q x) y--    test "isSubgraphOf (induce p x) x == True" $ \(apply -> p :: IB) (x :: G) ->-          isSubgraphOf (induce p x) x == True--    putStrLn "\n============ Graph.simplify ============"-    test "simplify              == id" $ \(x :: G) ->-          simplify x            == x--    test "size (simplify x)     <= size x" $ \(x :: G) ->-          size (simplify x)     <= size x--    test "simplify empty       === empty" $-          simplify (empty :: G)=== empty--    test "simplify 1           === 1" $-          simplify 1           === (1 :: G)--    test "simplify (1 + 1)     === 1" $-          simplify (1 + 1)     === (1 :: G)--    test "simplify (1 + 2 + 1) === 1 + 2" $-          simplify (1 + 2 + 1) === (1 + 2 :: G)--    test "simplify (1 * 1 * 1) === 1 * 1" $-          simplify (1 * 1 * 1) === (1 * 1 :: G)+    testSplitVertex t+    testBind        t+    testSimplify    t      putStrLn "\n============ Graph.box ============"     let unit = fmap $ \(a, ()) -> a@@ -736,10 +139,11 @@     test "box x (box y z)       ~~ box (box x y) z" $ mapSize (min 10) $ \(x :: G) (y :: G) (z :: G) ->       assoc (box x (box y z))   == box (box x y) z +    test "transpose   (box x y) == box (transpose x) (transpose y)" $ mapSize (min 10) $ \(x :: G) (y :: G) ->+          transpose   (box x y) == box (transpose x) (transpose y)+     test "vertexCount (box x y) == vertexCount x * vertexCount y" $ mapSize (min 10) $ \(x :: G) (y :: G) ->           vertexCount (box x y) == vertexCount x * vertexCount y      test "edgeCount   (box x y) <= vertexCount x * edgeCount y + edgeCount x * vertexCount y" $ mapSize (min 10) $ \(x :: G) (y :: G) ->           edgeCount   (box x y) <= vertexCount x * edgeCount y + edgeCount x * vertexCount y--
test/Algebra/Graph/Test/IntAdjacencyMap.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ViewPatterns #-} ----------------------------------------------------------------------------- -- | -- Module     : Algebra.Graph.Test.IntAdjacencyMap@@ -7,24 +6,24 @@ -- Maintainer : andrey.mokhov@gmail.com -- Stability  : experimental ----- Testsuite for 'IntAdjacencyMap'.---+-- Testsuite for "Algebra.Graph.IntAdjacencyMap". ----------------------------------------------------------------------------- module Algebra.Graph.Test.IntAdjacencyMap (     -- * Testsuite     testIntAdjacencyMap   ) where -import Data.Tree- import Algebra.Graph.IntAdjacencyMap import Algebra.Graph.IntAdjacencyMap.Internal import Algebra.Graph.Test+import Algebra.Graph.Test.Generic  import qualified Data.Graph  as KL import qualified Data.IntSet as IntSet-import qualified Data.Set    as Set +t :: Testsuite+t = testsuite "IntAdjacencyMap." empty+ testIntAdjacencyMap :: IO () testIntAdjacencyMap = do     putStrLn "\n============ IntAdjacencyMap ============"@@ -36,587 +35,26 @@     test "Consistency of fromAdjacencyList" $ \xs ->         consistent (fromAdjacencyList xs) -    putStrLn "\n============ IntAdjacencyMap.Show ============"-    test "show (empty     :: IntAdjacencyMap) == \"empty\"" $-          show (empty     :: IntAdjacencyMap) == "empty"--    test "show (1         :: IntAdjacencyMap) == \"vertex 1\"" $-          show (1         :: IntAdjacencyMap) == "vertex 1"--    test "show (1 + 2     :: IntAdjacencyMap) == \"vertices [1,2]\"" $-          show (1 + 2     :: IntAdjacencyMap) == "vertices [1,2]"--    test "show (1 * 2     :: IntAdjacencyMap) == \"edge 1 2\"" $-          show (1 * 2     :: IntAdjacencyMap) == "edge 1 2"--    test "show (1 * 2 * 3 :: IntAdjacencyMap) == \"edges [(1,2),(1,3),(2,3)]\"" $-          show (1 * 2 * 3 :: IntAdjacencyMap) == "edges [(1,2),(1,3),(2,3)]"--    test "show (1 * 2 + 3 :: IntAdjacencyMap) == \"graph [1,2,3] [(1,2)]\"" $-          show (1 * 2 + 3 :: IntAdjacencyMap) == "graph [1,2,3] [(1,2)]"--    putStrLn "\n============ IntAdjacencyMap.empty ============"-    test "isEmpty     empty == True" $-          isEmpty     empty == True--    test "hasVertex x empty == False" $ \x ->-          hasVertex x empty == False--    test "vertexCount empty == 0" $-          vertexCount empty == 0--    test "edgeCount   empty == 0" $-          edgeCount   empty == 0--    putStrLn "\n============ IntAdjacencyMap.vertex ============"-    test "isEmpty     (vertex x) == False" $ \x ->-          isEmpty     (vertex x) == False--    test "hasVertex x (vertex x) == True" $ \x ->-          hasVertex x (vertex x) == True--    test "hasVertex 1 (vertex 2) == False" $-          hasVertex 1 (vertex 2) == False--    test "vertexCount (vertex x) == 1" $ \x ->-          vertexCount (vertex x) == 1--    test "edgeCount   (vertex x) == 0" $ \x ->-          edgeCount   (vertex x) == 0--    putStrLn "\n============ IntAdjacencyMap.edge ============"-    test "edge x y               == connect (vertex x) (vertex y)" $ \x y ->-          edge x y               == connect (vertex x) (vertex y)--    test "hasEdge x y (edge x y) == True" $ \x y ->-          hasEdge x y (edge x y) == True--    test "edgeCount   (edge x y) == 1" $ \x y ->-          edgeCount   (edge x y) == 1--    test "vertexCount (edge 1 1) == 1" $-          vertexCount (edge 1 1) == 1--    test "vertexCount (edge 1 2) == 2" $-          vertexCount (edge 1 2) == 2--    putStrLn "\n============ IntAdjacencyMap.overlay ============"-    test "isEmpty     (overlay x y) == isEmpty   x   && isEmpty   y" $ \x y ->-          isEmpty     (overlay x y) == (isEmpty  x   && isEmpty   y)--    test "hasVertex z (overlay x y) == hasVertex z x || hasVertex z y" $ \x y z ->-          hasVertex z (overlay x y) == (hasVertex z x|| hasVertex z y)--    test "vertexCount (overlay x y) >= vertexCount x" $ \x y ->-          vertexCount (overlay x y) >= vertexCount x--    test "vertexCount (overlay x y) <= vertexCount x + vertexCount y" $ \x y ->-          vertexCount (overlay x y) <= vertexCount x + vertexCount y--    test "edgeCount   (overlay x y) >= edgeCount x" $ \x y ->-          edgeCount   (overlay x y) >= edgeCount x--    test "edgeCount   (overlay x y) <= edgeCount x   + edgeCount y" $ \x y ->-          edgeCount   (overlay x y) <= edgeCount x   + edgeCount y--    test "vertexCount (overlay 1 2) == 2" $-          vertexCount (overlay 1 2) == 2--    test "edgeCount   (overlay 1 2) == 0" $-          edgeCount   (overlay 1 2) == 0--    putStrLn "\n============ IntAdjacencyMap.connect ============"-    test "isEmpty     (connect x y) == isEmpty   x   && isEmpty   y" $ \x y ->-          isEmpty     (connect x y) == (isEmpty  x   && isEmpty   y)--    test "hasVertex z (connect x y) == hasVertex z x || hasVertex z y" $ \x y z ->-          hasVertex z (connect x y) == (hasVertex z x || hasVertex z y)--    test "vertexCount (connect x y) >= vertexCount x" $ \x y ->-          vertexCount (connect x y) >= vertexCount x--    test "vertexCount (connect x y) <= vertexCount x + vertexCount y" $ \x y ->-          vertexCount (connect x y) <= vertexCount x + vertexCount y--    test "edgeCount   (connect x y) >= edgeCount x" $ \x y ->-          edgeCount   (connect x y) >= edgeCount x--    test "edgeCount   (connect x y) >= edgeCount y" $ \x y ->-          edgeCount   (connect x y) >= edgeCount y--    test "edgeCount   (connect x y) >= vertexCount x * vertexCount y" $ \x y ->-          edgeCount   (connect x y) >= vertexCount x * vertexCount y--    test "edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y" $ \x y ->-          edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y--    test "vertexCount (connect 1 2) == 2" $-          vertexCount (connect 1 2) == 2--    test "edgeCount   (connect 1 2) == 1" $-          edgeCount   (connect 1 2) == 1--    putStrLn "\n============ IntAdjacencyMap.vertices ============"-    test "vertices []            == empty" $-          vertices []            == empty--    test "vertices [x]           == vertex x" $ \x ->-          vertices [x]           == vertex x--    test "hasVertex x . vertices == elem x" $ \x xs ->-         (hasVertex x . vertices) xs == elem x xs--    test "vertexCount . vertices == length . nub" $ \xs ->-         (vertexCount . vertices) xs == (length . nubOrd) xs--    test "vertexSet   . vertices == IntSet.fromList" $ \xs ->-         (vertexSet   . vertices) xs == IntSet.fromList xs--    putStrLn "\n============ IntAdjacencyMap.edges ============"-    test "edges []          == empty" $-          edges []          ==  empty--    test "edges [(x,y)]     == edge x y" $ \x y ->-          edges [(x,y)]     == edge x y--    test "edgeCount . edges == length . nub" $ \xs ->-         (edgeCount . edges) xs == (length . nubOrd) xs--    putStrLn "\n============ IntAdjacencyMap.overlays ============"-    test "overlays []        == empty" $-          overlays []        == empty--    test "overlays [x]       == x" $ \x ->-          overlays [x]       == x--    test "overlays [x,y]     == overlay x y" $ \x y ->-          overlays [x,y]     == overlay x y--    test "isEmpty . overlays == all isEmpty" $ mapSize (min 10) $ \xs ->-         (isEmpty . overlays) xs == all isEmpty xs--    putStrLn "\n============ IntAdjacencyMap.connects ============"-    test "connects []        == empty" $-          connects []        == empty--    test "connects [x]       == x" $ \x ->-          connects [x]       == x--    test "connects [x,y]     == connect x y" $ \x y ->-          connects [x,y]     == connect x y--    test "isEmpty . connects == all isEmpty" $ mapSize (min 10) $ \xs ->-         (isEmpty . connects) xs == all isEmpty xs--    putStrLn "\n============ IntAdjacencyMap.graph ============"-    test "graph []  []      == empty" $-          graph []  []      == empty--    test "graph [x] []      == vertex x" $ \x ->-          graph [x] []      == vertex x--    test "graph []  [(x,y)] == edge x y" $ \x y ->-          graph []  [(x,y)] == edge x y--    test "graph vs  es      == overlay (vertices vs) (edges es)" $ \(vs :: [Int]) es ->-          graph vs  es      == overlay (vertices vs) (edges es)--    putStrLn "\n============ IntAdjacencyMap.fromAdjacencyList ============"-    test "fromAdjacencyList []                                  == empty" $-          fromAdjacencyList []                                  == empty--    test "fromAdjacencyList [(x, [])]                           == vertex x" $ \x ->-          fromAdjacencyList [(x, [])]                           == vertex x--    test "fromAdjacencyList [(x, [y])]                          == edge x y" $ \x y ->-          fromAdjacencyList [(x, [y])]                          == edge x y--    test "fromAdjacencyList . adjacencyList                     == id" $ \x ->-         (fromAdjacencyList . adjacencyList) x                  == x--    test "overlay (fromAdjacencyList xs) (fromAdjacencyList ys) == fromAdjacencyList (xs ++ ys)" $ \xs ys ->-          overlay (fromAdjacencyList xs) (fromAdjacencyList ys) == fromAdjacencyList (xs ++ ys)--    putStrLn "\n============ IntAdjacencyMap.isSubgraphOf ============"-    test "isSubgraphOf empty         x             == True" $ \x ->-          isSubgraphOf empty         x             == True--    test "isSubgraphOf (vertex x)    empty         == False" $ \x ->-          isSubgraphOf (vertex x)    empty         == False--    test "isSubgraphOf x             (overlay x y) == True" $ \x y ->-          isSubgraphOf x             (overlay x y) == True--    test "isSubgraphOf (overlay x y) (connect x y) == True" $ \x y ->-          isSubgraphOf (overlay x y) (connect x y) == True--    test "isSubgraphOf (path xs)     (circuit xs)  == True" $ \xs ->-          isSubgraphOf (path xs)     (circuit xs)  == True--    putStrLn "\n============ IntAdjacencyMap.isEmpty ============"-    test "isEmpty empty                       == True" $-          isEmpty empty                       == True--    test "isEmpty (overlay empty empty)       == True" $-          isEmpty (overlay empty empty)       == True--    test "isEmpty (vertex x)                  == False" $ \x ->-          isEmpty (vertex x)                  == False--    test "isEmpty (removeVertex x $ vertex x) == True" $ \x ->-          isEmpty (removeVertex x $ vertex x) == True--    test "isEmpty (removeEdge x y $ edge x y) == False" $ \x y ->-          isEmpty (removeEdge x y $ edge x y) == False--    putStrLn "\n============ IntAdjacencyMap.hasVertex ============"-    test "hasVertex x empty            == False" $ \x ->-          hasVertex x empty            == False--    test "hasVertex x (vertex x)       == True" $ \x ->-          hasVertex x (vertex x)       == True--    test "hasVertex x . removeVertex x == const False" $ \x y ->-          hasVertex x (removeVertex x y)==const False y--    putStrLn "\n============ IntAdjacencyMap.hasEdge ============"-    test "hasEdge x y empty            == False" $ \x y ->-          hasEdge x y empty            == False--    test "hasEdge x y (vertex z)       == False" $ \x y z ->-          hasEdge x y (vertex z)       == False--    test "hasEdge x y (edge x y)       == True" $ \x y ->-          hasEdge x y (edge x y)       == True--    test "hasEdge x y . removeEdge x y == const False" $ \x y z ->-          hasEdge x y (removeEdge x y z)==const False z--    putStrLn "\n============ IntAdjacencyMap.vertexCount ============"-    test "vertexCount empty      == 0" $-          vertexCount empty      == 0--    test "vertexCount (vertex x) == 1" $ \x ->-          vertexCount (vertex x) == 1--    test "vertexCount            == length . vertexList" $ \x ->-          vertexCount x          == (length . vertexList) x--    putStrLn "\n============ IntAdjacencyMap.edgeCount ============"-    test "edgeCount empty      == 0" $-          edgeCount empty      == 0--    test "edgeCount (vertex x) == 0" $ \x ->-          edgeCount (vertex x) == 0--    test "edgeCount (edge x y) == 1" $ \x y ->-          edgeCount (edge x y) == 1--    test "edgeCount            == length . edgeList" $ \x ->-          edgeCount x          == (length . edgeList) x--    putStrLn "\n============ IntAdjacencyMap.vertexList ============"-    test "vertexList empty      == []" $-          vertexList empty      == []--    test "vertexList (vertex x) == [x]" $ \x ->-          vertexList (vertex x) == [x]--    test "vertexList . vertices == nub . sort" $ \xs ->-         (vertexList . vertices) xs == (nubOrd . sort) xs--    putStrLn "\n============ IntAdjacencyMap.edgeList ============"-    test "edgeList empty          == []" $-          edgeList empty          == []--    test "edgeList (vertex x)     == []" $ \x ->-          edgeList (vertex x)     == []--    test "edgeList (edge x y)     == [(x,y)]" $ \x y ->-          edgeList (edge x y)     == [(x,y)]--    test "edgeList (star 2 [3,1]) == [(2,1), (2,3)]" $-          edgeList (star 2 [3,1]) == [(2,1), (2,3)]--    test "edgeList . edges        == nub . sort" $ \xs ->-         (edgeList . edges) xs    == (nubOrd . sort) xs--    putStrLn "\n============ IntAdjacencyMap.adjacencyList ============"-    test "adjacencyList empty          == []" $-          adjacencyList empty          == []--    test "adjacencyList (vertex x)     == [(x, [])]" $ \x ->-          adjacencyList (vertex x)     == [(x, [])]--    test "adjacencyList (edge 1 2)     == [(1, [2]), (2, [])]" $-          adjacencyList (edge 1 2)     == [(1, [2]), (2, [])]--    test "adjacencyList (star 2 [3,1]) == [(1, []), (2, [1,3]), (3, [])]" $-          adjacencyList (star 2 [3,1]) == [(1, []), (2, [1,3]), (3, [])]--    putStrLn "\n============ IntAdjacencyMap.vertexSet ============"-    test "vertexSet empty      == IntSet.empty" $-          vertexSet empty      == IntSet.empty--    test "vertexSet . vertex   == IntSet.singleton" $ \x ->-         (vertexSet . vertex) x== IntSet.singleton x--    test "vertexSet . vertices == IntSet.fromList" $ \xs ->-         (vertexSet . vertices) xs == IntSet.fromList xs--    test "vertexSet . clique   == IntSet.fromList" $ \xs ->-         (vertexSet . clique) xs == IntSet.fromList xs--    putStrLn "\n============ IntAdjacencyMap.edgeSet ============"-    test "edgeSet empty      == Set.empty" $-          edgeSet empty      == Set.empty--    test "edgeSet (vertex x) == Set.empty" $ \x ->-          edgeSet (vertex x) == Set.empty--    test "edgeSet (edge x y) == Set.singleton (x,y)" $ \x y ->-          edgeSet (edge x y) == Set.singleton (x,y)--    test "edgeSet . edges    == Set.fromList" $ \xs ->-         (edgeSet . edges) xs== Set.fromList xs--    putStrLn "\n============ IntAdjacencyMap.postset ============"-    test "postset x empty      == IntSet.empty" $ \x ->-          postset x empty      == IntSet.empty--    test "postset x (vertex x) == IntSet.empty" $ \x ->-          postset x (vertex x) == IntSet.empty--    test "postset x (edge x y) == IntSet.fromList [y]" $ \x y ->-          postset x (edge x y) == IntSet.fromList [y]--    test "postset 2 (edge 1 2) == IntSet.empty" $-          postset 2 (edge 1 2) == IntSet.empty--    putStrLn "\n============ IntAdjacencyMap.path ============"-    test "path []    == empty" $-          path []    == empty--    test "path [x]   == vertex x" $ \x ->-          path [x]   == vertex x--    test "path [x,y] == edge x y" $ \x y ->-          path [x,y] == edge x y--    putStrLn "\n============ IntAdjacencyMap.circuit ============"-    test "circuit []    == empty" $-          circuit []    == empty--    test "circuit [x]   == edge x x" $ \x ->-          circuit [x]   == edge x x--    test "circuit [x,y] == edges [(x,y), (y,x)]" $ \x y ->-          circuit [x,y] == edges [(x,y), (y,x)]--    putStrLn "\n============ IntAdjacencyMap.clique ============"-    test "clique []      == empty" $-          clique []      == empty--    test "clique [x]     == vertex x" $ \x ->-          clique [x]     == vertex x--    test "clique [x,y]   == edge x y" $ \x y ->-          clique [x,y]   == edge x y--    test "clique [x,y,z] == edges [(x,y), (x,z), (y,z)]" $ \x y z ->-          clique [x,y,z] == edges [(x,y), (x,z), (y,z)]--    putStrLn "\n============ IntAdjacencyMap.biclique ============"-    test "biclique []      []      == empty" $-          biclique []      []      == empty--    test "biclique [x]     []      == vertex x" $ \x ->-          biclique [x]     []      == vertex x--    test "biclique []      [y]     == vertex y" $ \(y) ->-          biclique []      [y]     == vertex y--    test "biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]" $ \(x1) x2 y1 y2 ->-          biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]--    test "biclique xs      ys      == connect (vertices xs) (vertices ys)" $ \xs ys ->-          biclique xs      ys      == connect (vertices xs) (vertices ys)--    putStrLn "\n============ IntAdjacencyMap.star ============"-    test "star x []    == vertex x" $ \x ->-          star x []    == vertex x--    test "star x [y]   == edge x y" $ \x y ->-          star x [y]   == edge x y--    test "star x [y,z] == edges [(x,y), (x,z)]" $ \x y z ->-          star x [y,z] == edges [(x,y), (x,z)]--    putStrLn "\n============ IntAdjacencyMap.tree ============"-    test "tree (Node x [])                                         == vertex x" $ \x ->-          tree (Node x [])                                         == vertex x--    test "tree (Node x [Node y [Node z []]])                       == path [x,y,z]" $ \x y z ->-          tree (Node x [Node y [Node z []]])                       == path [x,y,z]--    test "tree (Node x [Node y [], Node z []])                     == star x [y,z]" $ \x y z ->-          tree (Node x [Node y [], Node z []])                     == star x [y,z]--    test "tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5)]" $-          tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5)]--    putStrLn "\n============ IntAdjacencyMap.forest ============"-    test "forest []                                                  == empty" $-          forest []                                                  == empty--    test "forest [x]                                                 == tree x" $ \x ->-          forest [x]                                                 == tree x--    test "forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5)]" $-          forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5)]--    test "forest                                                     == overlays . map tree" $ \x ->-         (forest x)                                                  ==(overlays . map tree) x--    putStrLn "\n============ IntAdjacencyMap.removeVertex ============"-    test "removeVertex x (vertex x)       == empty" $ \x ->-          removeVertex x (vertex x)       == empty--    test "removeVertex x . removeVertex x == removeVertex x" $ \x (y) ->-         (removeVertex x . removeVertex x)y==removeVertex x y--    putStrLn "\n============ IntAdjacencyMap.removeEdge ============"-    test "removeEdge x y (edge x y)       == vertices [x, y]" $ \x y ->-          removeEdge x y (edge x y)       == vertices [x, y]--    test "removeEdge x y . removeEdge x y == removeEdge x y" $ \x y z ->-         (removeEdge x y . removeEdge x y)z==removeEdge x y z--    test "removeEdge x y . removeVertex x == removeVertex x" $ \x y z ->-         (removeEdge x y . removeVertex x)z==removeVertex x z--    test "removeEdge 1 1 (1 * 1 * 2 * 2)  == 1 * 2 * 2" $-          removeEdge 1 1 (1 * 1 * 2 * 2)  == 1 * 2 * 2--    test "removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2" $-          removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2--    putStrLn "\n============ IntAdjacencyMap.replaceVertex ============"-    test "replaceVertex x x            == id" $ \x (y) ->-          replaceVertex x x y          == y--    test "replaceVertex x y (vertex x) == vertex y" $ \x (y) ->-          replaceVertex x y (vertex x) == vertex y--    test "replaceVertex x y            == mergeVertices (== x) y" $ \x y z ->-          replaceVertex x y z          == mergeVertices (== x) y z--    putStrLn "\n============ IntAdjacencyMap.mergeVertices ============"-    test "mergeVertices (const False) x    == id" $ \x (y) ->-          mergeVertices (const False) x y  == y--    test "mergeVertices (== x) y           == replaceVertex x y" $ \x y (z) ->-          mergeVertices (== x) y z         == replaceVertex x y z--    test "mergeVertices even 1 (0 * 2)     == 1 * 1" $-          mergeVertices even 1 (0 * 2)     == 1 * 1--    test "mergeVertices odd  1 (3 + 4 * 5) == 4 * 1" $-          mergeVertices odd  1 (3 + 4 * 5) == 4 * 1--    putStrLn "\n============ IntAdjacencyMap.gmap ============"-    test "gmap f empty      == empty" $ \(apply -> f) ->-          gmap f empty      == empty--    test "gmap f (vertex x) == vertex (f x)" $ \(apply -> f) x ->-          gmap f (vertex x) == vertex (f x)--    test "gmap f (edge x y) == edge (f x) (f y)" $ \(apply -> f) x y ->-          gmap f (edge x y) == edge (f x) (f y)--    test "gmap id           == id" $ \x ->-          gmap id x         == x--    test "gmap f . gmap g   == gmap (f . g)" $ \(apply -> f) (apply -> g) x ->-         (gmap f . gmap g) x== gmap (f . g) x--    putStrLn "\n============ IntAdjacencyMap.induce ============"-    test "induce (const True)  x      == x" $ \x ->-          induce (const True)  x      == x--    test "induce (const False) x      == empty" $ \x ->-          induce (const False) x      == empty--    test "induce (/= x)               == removeVertex x" $ \x (y) ->-          induce (/= x) y             == removeVertex x y--    test "induce p . induce q         == induce (\\x -> p x && q x)" $ \(apply -> p) (apply -> q) (y) ->-         (induce p . induce q) y      == induce (\x -> p x && q x) y--    test "isSubgraphOf (induce p x) x == True" $ \(apply -> p) x ->-          isSubgraphOf (induce p x) x == True--    putStrLn "\n============ IntAdjacencyMap.dfsForest ============"-    test "forest (dfsForest $ edge 1 1)         == vertex 1" $-          forest (dfsForest $ edge 1 1)         == vertex 1--    test "forest (dfsForest $ edge 1 2)         == edge 1 2" $-          forest (dfsForest $ edge 1 2)         == edge 1 2--    test "forest (dfsForest $ edge 2 1)         == vertices [1, 2]" $-          forest (dfsForest $ edge 2 1)         == vertices [1, 2]--    test "isSubgraphOf (forest $ dfsForest x) x == True" $ \x ->-          isSubgraphOf (forest $ dfsForest x) x == True--    test "dfsForest . forest . dfsForest        == dfsForest" $ \x ->-         (dfsForest . forest . dfsForest) x     == dfsForest x--    test "dfsForest $ 3 * (1 + 4) * (1 + 5)     == <correct result>" $-          dfsForest  (3 * (1 + 4) * (1 + 5))    == [ Node { rootLabel = 1-                                                   , subForest = [ Node { rootLabel = 5-                                                                        , subForest = [] }]}-                                                   , Node { rootLabel = 3-                                                   , subForest = [ Node { rootLabel = 4-                                                                        , subForest = [] }]}]--    putStrLn "\n============ IntAdjacencyMap.topSort ============"-    test "topSort (1 * 2 + 3 * 1)             == Just [3,1,2]" $-          topSort (1 * 2 + 3 * 1)             == Just [3,1,2]--    test "topSort (1 * 2 + 2 * 1)             == Nothing" $-          topSort (1 * 2 + 2 * 1)             == Nothing--    test "fmap (flip isTopSort x) (topSort x) /= Just False" $ \x ->-          fmap (flip isTopSort x) (topSort x) /= Just False--    putStrLn "\n============ IntAdjacencyMap.isTopSort  ============"-    test "isTopSort [3, 1, 2] (1 * 2 + 3 * 1) == True" $-          isTopSort [3, 1, 2] (1 * 2 + 3 * 1) == True--    test "isTopSort [1, 2, 3] (1 * 2 + 3 * 1) == False" $-          isTopSort [1, 2, 3] (1 * 2 + 3 * 1) == False--    test "isTopSort []        (1 * 2 + 3 * 1) == False" $-          isTopSort []        (1 * 2 + 3 * 1) == False--    test "isTopSort []        empty           == True" $-          isTopSort []        empty    == True--    test "isTopSort [x]       (vertex x)      == True" $ \x ->-          isTopSort [x]       (vertex x)      == True--    test "isTopSort [x]       (edge x x)      == False" $ \x ->-          isTopSort [x]       (edge x x)      == False--    putStrLn "\n============ IntAdjacencyMap.GraphKL ============"-    test "map (getVertex h) (vertices $ getGraph h) == IntSet.toAscList (vertexSet g)"-      $ \g -> let h = graphKL g in-        map (getVertex h) (KL.vertices $ getGraph h) == IntSet.toAscList (vertexSet g)+    testShow              t+    testBasicPrimitives   t+    testFromAdjacencyList t+    testIsSubgraphOf      t+    testProperties        t+    testAdjacencyList     t+    testPostIntSet        t+    testGraphFamilies     t+    testTransformations   t+    testDfsForest         t+    testDfsForestFrom     t+    testDfs               t+    testTopSort           t+    testIsTopSort         t -    test "map (\\(x, y) -> (getVertex h x, getVertex h y)) (edges $ getGraph h) == edgeList g"-      $ \g -> let h = graphKL g in-        map (\(x, y) -> (getVertex h x, getVertex h y)) (KL.edges $ getGraph h) == edgeList g+    putStrLn "\n============ IntAdjacencyMap.Internal.GraphKL ============"+    test "map (fromVertexKL h) (vertices $ toGraphKL h) == IntSet.toAscList (vertexIntSet g)"+      $ \g -> let h = mkGraphKL (adjacencyMap g) in+        map (fromVertexKL h) (KL.vertices $ toGraphKL h) == IntSet.toAscList (vertexIntSet g) -    test "fromGraphKL . graphKL == id" $ \x ->-        (fromGraphKL . graphKL) x == x+    test "map (\\(x, y) -> (fromVertexKL h x, fromVertexKL h y)) (edges $ toGraphKL h) == edgeList g"+      $ \g -> let h = mkGraphKL (adjacencyMap g) in+        map (\(x, y) -> (fromVertexKL h x, fromVertexKL h y)) (KL.edges $ toGraphKL h) == edgeList g
test/Algebra/Graph/Test/Relation.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE ViewPatterns #-} ----------------------------------------------------------------------------- -- | -- Module     : Algebra.Graph.Test.Relation@@ -7,17 +6,13 @@ -- Maintainer : andrey.mokhov@gmail.com -- Stability  : experimental ----- Testsuite for 'Relation'.---+-- Testsuite for "Algebra.Graph.Relation". ----------------------------------------------------------------------------- module Algebra.Graph.Test.Relation (     -- * Testsuite     testRelation   ) where -import Data.Tree-import Data.Tuple- import Algebra.Graph.Relation import Algebra.Graph.Relation.Internal import Algebra.Graph.Relation.Preorder@@ -25,13 +20,15 @@ import Algebra.Graph.Relation.Symmetric import Algebra.Graph.Relation.Transitive import Algebra.Graph.Test+import Algebra.Graph.Test.Generic  import qualified Algebra.Graph.Class as C import qualified Data.Set            as Set +t :: Testsuite+t = testsuite "Relation." empty+ type RI = Relation Int-type II = Int -> Int-type IB = Int -> Bool  sizeLimit :: Testable prop => prop -> Property sizeLimit = mapSize (min 10)@@ -47,547 +44,16 @@     test "Consistency of fromAdjacencyList" $ \xs ->         consistent (fromAdjacencyList xs :: RI) -    putStrLn "\n============ Relation.Show ============"-    test "show (empty     :: Relation Int) == \"empty\"" $-          show (empty     :: Relation Int) == "empty"--    test "show (1         :: Relation Int) == \"vertex 1\"" $-          show (1         :: Relation Int) == "vertex 1"--    test "show (1 + 2     :: Relation Int) == \"vertices [1,2]\"" $-          show (1 + 2     :: Relation Int) == "vertices [1,2]"--    test "show (1 * 2     :: Relation Int) == \"edge 1 2\"" $-          show (1 * 2     :: Relation Int) == "edge 1 2"--    test "show (1 * 2 * 3 :: Relation Int) == \"edges [(1,2),(1,3),(2,3)]\"" $-          show (1 * 2 * 3 :: Relation Int) == "edges [(1,2),(1,3),(2,3)]"--    test "show (1 * 2 + 3 :: Relation Int) == \"graph [1,2,3] [(1,2)]\"" $-          show (1 * 2 + 3 :: Relation Int) == "graph [1,2,3] [(1,2)]"--    putStrLn "\n============ Relation.empty ============"-    test "isEmpty     empty == True" $-          isEmpty    (empty :: RI) == True--    test "hasVertex x empty == False" $ \(x :: Int) ->-          hasVertex x empty == False--    test "vertexCount empty == 0" $-          vertexCount(empty :: RI) == 0--    test "edgeCount   empty == 0" $-          edgeCount  (empty :: RI) == 0--    putStrLn "\n============ Relation.vertex ============"-    test "isEmpty     (vertex x) == False" $ \(x :: Int) ->-          isEmpty     (vertex x) == False--    test "hasVertex x (vertex x) == True" $ \(x :: Int) ->-          hasVertex x (vertex x) == True--    test "hasVertex 1 (vertex 2) == False" $-          hasVertex 1 (vertex 2 :: RI) == False--    test "vertexCount (vertex x) == 1" $ \(x :: Int) ->-          vertexCount (vertex x) == 1--    test "edgeCount   (vertex x) == 0" $ \(x :: Int) ->-          edgeCount   (vertex x) == 0--    putStrLn "\n============ Relation.edge ============"-    test "edge x y               == connect (vertex x) (vertex y)" $ \(x :: Int) y ->-         (edge x y :: RI)        == connect (vertex x) (vertex y)--    test "hasEdge x y (edge x y) == True" $ \(x :: Int) y ->-          hasEdge x y (edge x y) == True--    test "edgeCount   (edge x y) == 1" $ \(x :: Int) y ->-          edgeCount   (edge x y) == 1--    test "vertexCount (edge 1 1) == 1" $-          vertexCount (edge 1 1 :: RI) == 1--    test "vertexCount (edge 1 2) == 2" $-          vertexCount (edge 1 2 :: RI) == 2--    putStrLn "\n============ Relation.overlay ============"-    test "isEmpty     (overlay x y) == isEmpty   x   && isEmpty   y" $ \(x :: RI) y ->-          isEmpty     (overlay x y) == (isEmpty   x   && isEmpty   y)--    test "hasVertex z (overlay x y) == hasVertex z x || hasVertex z y" $ \(x :: RI) y z ->-          hasVertex z (overlay x y) == (hasVertex z x || hasVertex z y)--    test "vertexCount (overlay x y) >= vertexCount x" $ \(x :: RI) y ->-          vertexCount (overlay x y) >= vertexCount x--    test "vertexCount (overlay x y) <= vertexCount x + vertexCount y" $ \(x :: RI) y ->-          vertexCount (overlay x y) <= vertexCount x + vertexCount y--    test "edgeCount   (overlay x y) >= edgeCount x" $ \(x :: RI) y ->-          edgeCount   (overlay x y) >= edgeCount x--    test "edgeCount   (overlay x y) <= edgeCount x   + edgeCount y" $ \(x :: RI) y ->-          edgeCount   (overlay x y) <= edgeCount x   + edgeCount y--    test "vertexCount (overlay 1 2) == 2" $-          vertexCount (overlay 1 2 :: RI) == 2--    test "edgeCount   (overlay 1 2) == 0" $-          edgeCount   (overlay 1 2 :: RI) == 0--    putStrLn "\n============ Relation.connect ============"-    test "isEmpty     (connect x y) == isEmpty   x   && isEmpty   y" $ \(x :: RI) y ->-          isEmpty     (connect x y) == (isEmpty   x   && isEmpty   y)--    test "hasVertex z (connect x y) == hasVertex z x || hasVertex z y" $ \(x :: RI) y z ->-          hasVertex z (connect x y) == (hasVertex z x || hasVertex z y)--    test "vertexCount (connect x y) >= vertexCount x" $ \(x :: RI) y ->-          vertexCount (connect x y) >= vertexCount x--    test "vertexCount (connect x y) <= vertexCount x + vertexCount y" $ \(x :: RI) y ->-          vertexCount (connect x y) <= vertexCount x + vertexCount y--    test "edgeCount   (connect x y) >= edgeCount x" $ \(x :: RI) y ->-          edgeCount   (connect x y) >= edgeCount x--    test "edgeCount   (connect x y) >= edgeCount y" $ \(x :: RI) y ->-          edgeCount   (connect x y) >= edgeCount y--    test "edgeCount   (connect x y) >= vertexCount x * vertexCount y" $ \(x :: RI) y ->-          edgeCount   (connect x y) >= vertexCount x * vertexCount y--    test "edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y" $ \(x :: RI) y ->-          edgeCount   (connect x y) <= vertexCount x * vertexCount y + edgeCount x + edgeCount y--    test "vertexCount (connect 1 2) == 2" $-          vertexCount (connect 1 2 :: RI) == 2--    test "edgeCount   (connect 1 2) == 1" $-          edgeCount   (connect 1 2 :: RI) == 1--    putStrLn "\n============ Relation.vertices ============"-    test "vertices []            == empty" $-          vertices []            == (empty :: RI)--    test "vertices [x]           == vertex x" $ \(x :: Int) ->-          vertices [x]           == (vertex x :: RI)--    test "hasVertex x . vertices == elem x" $ \x (xs :: [Int]) ->-         (hasVertex x . vertices) xs == elem x xs--    test "vertexCount . vertices == length . nub" $ \(xs :: [Int]) ->-         (vertexCount . vertices) xs == (length . nubOrd) xs--    test "vertexSet   . vertices == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet   . vertices) xs == Set.fromList xs--    putStrLn "\n============ Relation.edges ============"-    test "edges []          == empty" $-          edges []          == (empty :: RI)--    test "edges [(x,y)]     == edge x y" $ \(x :: Int) y ->-          edges [(x,y)]     == (edge x y :: RI)--    test "edgeCount . edges == length . nub" $ \(xs :: [(Int, Int)]) ->-         (edgeCount . edges) xs == (length . nubOrd) xs--    putStrLn "\n============ Relation.overlays ============"-    test "overlays []        == empty" $-          overlays []        == (empty :: RI)--    test "overlays [x]       == x" $ \(x :: RI) ->-          overlays [x]       == x--    test "overlays [x,y]     == overlay x y" $ \(x :: RI) y ->-          overlays [x,y]     == overlay x y--    test "isEmpty . overlays == all isEmpty" $ mapSize (min 10) $ \(xs :: [RI]) ->-         (isEmpty . overlays) xs == all isEmpty xs--    putStrLn "\n============ Relation.connects ============"-    test "connects []        == empty" $-          connects []        == (empty :: RI)--    test "connects [x]       == x" $ \(x :: RI) ->-          connects [x]       == x--    test "connects [x,y]     == connect x y" $ \(x :: RI) y ->-          connects [x,y]     == connect x y--    test "isEmpty . connects == all isEmpty" $ mapSize (min 10) $ \(xs :: [RI]) ->-         (isEmpty . connects) xs == all isEmpty xs--    putStrLn "\n============ Relation.graph ============"-    test "graph []  []      == empty" $-          graph []  []      == (empty :: RI)--    test "graph [x] []      == vertex x" $ \(x :: Int) ->-          graph [x] []      == (vertex x :: RI)--    test "graph []  [(x,y)] == edge x y" $ \(x :: Int) y ->-          graph []  [(x,y)] == (edge x y :: RI)--    test "graph vs  es      == overlay (vertices vs) (edges es)" $ \(vs :: [Int]) es ->-          graph vs  es      == (overlay (vertices vs) (edges es) :: RI)--    putStrLn "\n============ Relation.fromAdjacencyList ============"-    test "fromAdjacencyList []                                  == empty" $-          fromAdjacencyList []                                  == (empty :: RI)--    test "fromAdjacencyList [(x, [])]                           == vertex x" $ \(x :: Int) ->-          fromAdjacencyList [(x, [])]                           == vertex x--    test "fromAdjacencyList [(x, [y])]                          == edge x y" $ \(x :: Int) y ->-          fromAdjacencyList [(x, [y])]                          == edge x y--    test "overlay (fromAdjacencyList xs) (fromAdjacencyList ys) == fromAdjacencyList (xs ++ ys)" $ \xs ys ->-          overlay (fromAdjacencyList xs) (fromAdjacencyList ys) ==(fromAdjacencyList (xs ++ ys) :: RI)--    putStrLn "\n============ Relation.isSubgraphOf ============"-    test "isSubgraphOf empty         x             == True" $ \(x :: RI) ->-          isSubgraphOf empty         x             == True--    test "isSubgraphOf (vertex x)    empty         == False" $ \x ->-          isSubgraphOf (vertex x)   (empty :: RI)   == False--    test "isSubgraphOf x             (overlay x y) == True" $ \(x :: RI) y ->-          isSubgraphOf x             (overlay x y) == True--    test "isSubgraphOf (overlay x y) (connect x y) == True" $ \(x :: RI) y ->-          isSubgraphOf (overlay x y) (connect x y) == True--    test "isSubgraphOf (path xs)     (circuit xs)  == True" $ \xs ->-          isSubgraphOf (path xs :: RI)(circuit xs)  == True--    putStrLn "\n============ Relation.isEmpty ============"-    test "isEmpty empty                       == True" $-          isEmpty (empty :: RI)                == True--    test "isEmpty (overlay empty empty)       == True" $-          isEmpty (overlay empty empty :: RI)  == True--    test "isEmpty (vertex x)                  == False" $ \(x :: Int) ->-          isEmpty (vertex x)                  == False--    test "isEmpty (removeVertex x $ vertex x) == True" $ \(x :: Int) ->-          isEmpty (removeVertex x $ vertex x) == True--    test "isEmpty (removeEdge x y $ edge x y) == False" $ \(x :: Int) y ->-          isEmpty (removeEdge x y $ edge x y) == False--    putStrLn "\n============ Relation.hasVertex ============"-    test "hasVertex x empty            == False" $ \(x :: Int) ->-          hasVertex x empty            == False--    test "hasVertex x (vertex x)       == True" $ \(x :: Int) ->-          hasVertex x (vertex x)       == True--    test "hasVertex x . removeVertex x == const False" $ \(x :: Int) y ->-          hasVertex x (removeVertex x y)==const False y--    putStrLn "\n============ Relation.hasEdge ============"-    test "hasEdge x y empty            == False" $ \(x :: Int) y ->-          hasEdge x y empty            == False--    test "hasEdge x y (vertex z)       == False" $ \(x :: Int) y z ->-          hasEdge x y (vertex z)       == False--    test "hasEdge x y (edge x y)       == True" $ \(x :: Int) y ->-          hasEdge x y (edge x y)       == True--    test "hasEdge x y . removeEdge x y == const False" $ \(x :: Int) y z ->-          hasEdge x y (removeEdge x y z)==const False z--    putStrLn "\n============ Relation.vertexCount ============"-    test "vertexCount empty      == 0" $-          vertexCount (empty :: RI) == 0--    test "vertexCount (vertex x) == 1" $ \(x :: Int) ->-          vertexCount (vertex x) == 1--    test "vertexCount            == length . vertexList" $ \(x :: RI) ->-          vertexCount x          == (length . vertexList) x--    putStrLn "\n============ Relation.edgeCount ============"-    test "edgeCount empty      == 0" $-          edgeCount (empty :: RI) == 0--    test "edgeCount (vertex x) == 0" $ \(x :: Int) ->-          edgeCount (vertex x) == 0--    test "edgeCount (edge x y) == 1" $ \(x :: Int) y ->-          edgeCount (edge x y) == 1--    test "edgeCount            == length . edgeList" $ \(x :: RI) ->-          edgeCount x          == (length . edgeList) x--    putStrLn "\n============ Relation.vertexList ============"-    test "vertexList empty      == []" $-          vertexList (empty :: RI) == []--    test "vertexList (vertex x) == [x]" $ \(x :: Int) ->-          vertexList (vertex x) == [x]--    test "vertexList . vertices == nub . sort" $ \(xs :: [Int]) ->-         (vertexList . vertices) xs == (nubOrd . sort) xs--    putStrLn "\n============ Relation.edgeList ============"-    test "edgeList empty          == []" $-          edgeList (empty :: RI )  == []--    test "edgeList (vertex x)     == []" $ \(x :: Int) ->-          edgeList (vertex x)     == []--    test "edgeList (edge x y)     == [(x,y)]" $ \(x :: Int) y ->-          edgeList (edge x y)     == [(x,y)]--    test "edgeList (star 2 [3,1]) == [(2,1), (2,3)]" $-          edgeList (star 2 [3,1]) == [(2,1), (2,3 :: Int)]--    test "edgeList . edges        == nub . sort" $ \(xs :: [(Int, Int)]) ->-         (edgeList . edges) xs    == (nubOrd . sort) xs--    putStrLn "\n============ Relation.vertexSet ============"-    test "vertexSet empty      == Set.empty" $-          vertexSet(empty :: RI)== Set.empty--    test "vertexSet . vertex   == Set.singleton" $ \(x :: Int) ->-         (vertexSet . vertex) x== Set.singleton x--    test "vertexSet . vertices == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet . vertices) xs == Set.fromList xs--    test "vertexSet . clique   == Set.fromList" $ \(xs :: [Int]) ->-         (vertexSet . clique) xs == Set.fromList xs--    putStrLn "\n============ Relation.edgeSet ============"-    test "edgeSet empty      == Set.empty" $-          edgeSet (empty :: RI) == Set.empty--    test "edgeSet (vertex x) == Set.empty" $ \(x :: Int) ->-          edgeSet (vertex x) == Set.empty--    test "edgeSet (edge x y) == Set.singleton (x,y)" $ \(x :: Int) y ->-          edgeSet (edge x y) == Set.singleton (x,y)--    test "edgeSet . edges    == Set.fromList" $ \(xs :: [(Int, Int)]) ->-         (edgeSet . edges) xs== Set.fromList xs--    putStrLn "\n============ Relation.preset ============"-    test "preset x empty      == Set.empty" $ \(x :: Int) ->-          preset x empty      == Set.empty--    test "preset x (vertex x) == Set.empty" $ \(x :: Int) ->-          preset x (vertex x) == Set.empty--    test "preset 1 (edge 1 2) == Set.empty" $-          preset 1 (edge 1 2) ==(Set.empty :: Set.Set Int)--    test "preset y (edge x y) == Set.fromList [x]" $ \(x :: Int) y ->-          preset y (edge x y) ==(Set.fromList [x] :: Set.Set Int)--    putStrLn "\n============ Relation.postset ============"-    test "postset x empty      == Set.empty" $ \(x :: Int) ->-          postset x empty      == Set.empty--    test "postset x (vertex x) == Set.empty" $ \(x :: Int) ->-          postset x (vertex x) == Set.empty--    test "postset x (edge x y) == Set.fromList [y]" $ \(x :: Int) y ->-          postset x (edge x y) == Set.fromList [y]--    test "postset 2 (edge 1 2) == Set.empty" $-          postset 2 (edge 1 2) ==(Set.empty :: Set.Set Int)--    putStrLn "\n============ Relation.path ============"-    test "path []    == empty" $-          path []    == (empty :: RI)--    test "path [x]   == vertex x" $ \(x :: Int) ->-          path [x]   == (vertex x :: RI)--    test "path [x,y] == edge x y" $ \(x :: Int) y ->-          path [x,y] == (edge x y :: RI)--    putStrLn "\n============ Relation.circuit ============"-    test "circuit []    == empty" $-          circuit []    == (empty :: RI)--    test "circuit [x]   == edge x x" $ \(x :: Int) ->-          circuit [x]   == (edge x x :: RI)--    test "circuit [x,y] == edges [(x,y), (y,x)]" $ \(x :: Int) y ->-          circuit [x,y] == (edges [(x,y), (y,x)] :: RI)--    putStrLn "\n============ Relation.clique ============"-    test "clique []      == empty" $-          clique []      == (empty :: RI)--    test "clique [x]     == vertex x" $ \(x :: Int) ->-          clique [x]     == (vertex x :: RI)--    test "clique [x,y]   == edge x y" $ \(x :: Int) y ->-          clique [x,y]   == (edge x y :: RI)--    test "clique [x,y,z] == edges [(x,y), (x,z), (y,z)]" $ \(x :: Int) y z ->-          clique [x,y,z] == (edges [(x,y), (x,z), (y,z)] :: RI)--    putStrLn "\n============ Relation.biclique ============"-    test "biclique []      []      == empty" $-          biclique []      []      == (empty :: RI)--    test "biclique [x]     []      == vertex x" $ \(x :: Int) ->-          biclique [x]     []      == (vertex x :: RI)--    test "biclique []      [y]     == vertex y" $ \(y :: Int) ->-          biclique []      [y]     == (vertex y :: RI)--    test "biclique [x1,x2] [y1,y2] == edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)]" $ \(x1 :: Int) x2 y1 y2 ->-          biclique [x1,x2] [y1,y2] == (edges [(x1,y1), (x1,y2), (x2,y1), (x2,y2)] :: RI)--    test "biclique xs      ys      == connect (vertices xs) (vertices ys)" $ \(xs :: [Int]) ys ->-          biclique xs      ys      == connect (vertices xs) (vertices ys)--    putStrLn "\n============ Relation.star ============"-    test "star x []    == vertex x" $ \(x :: Int) ->-          star x []    == (vertex x :: RI)--    test "star x [y]   == edge x y" $ \(x :: Int) y ->-          star x [y]   == (edge x y :: RI)--    test "star x [y,z] == edges [(x,y), (x,z)]" $ \(x :: Int) y z ->-          star x [y,z] == (edges [(x,y), (x,z)] :: RI)--    putStrLn "\n============ Relation.tree ============"-    test "tree (Node x [])                                         == vertex x" $ \(x :: Int) ->-          tree (Node x [])                                         == vertex x--    test "tree (Node x [Node y [Node z []]])                       == path [x,y,z]" $ \(x :: Int) y z ->-          tree (Node x [Node y [Node z []]])                       == path [x,y,z]--    test "tree (Node x [Node y [], Node z []])                     == star x [y,z]" $ \(x :: Int) y z ->-          tree (Node x [Node y [], Node z []])                     == star x [y,z]--    test "tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5)]" $-          tree (Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]) == edges [(1,2), (1,3), (3,4), (3,5::Int)]--    putStrLn "\n============ Relation.forest ============"-    test "forest []                                                  == empty" $-          forest []                                                  == (empty :: RI)--    test "forest [x]                                                 == tree x" $ \(x :: Tree Int) ->-          forest [x]                                                 == tree x--    test "forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5)]" $-          forest [Node 1 [Node 2 [], Node 3 []], Node 4 [Node 5 []]] == edges [(1,2), (1,3), (4,5::Int)]--    test "forest                                                     == overlays . map tree" $ \(x :: Forest Int) ->-         (forest x)                                                  ==(overlays . map tree) x--    putStrLn "\n============ Relation.removeVertex ============"-    test "removeVertex x (vertex x)       == empty" $ \(x :: Int) ->-          removeVertex x (vertex x)       == (empty :: RI)--    test "removeVertex x . removeVertex x == removeVertex x" $ \x (y :: RI) ->-         (removeVertex x . removeVertex x)y==(removeVertex x y :: RI)--    putStrLn "\n============ Relation.removeEdge ============"-    test "removeEdge x y (edge x y)       == vertices [x, y]" $ \(x :: Int) y ->-          removeEdge x y (edge x y)       == (vertices [x, y] :: RI)--    test "removeEdge x y . removeEdge x y == removeEdge x y" $ \(x :: Int) y z ->-         (removeEdge x y . removeEdge x y)z==(removeEdge x y z :: RI)--    test "removeEdge x y . removeVertex x == removeVertex x" $ \(x :: Int) y z ->-         (removeEdge x y . removeVertex x)z==(removeVertex x z :: RI)--    test "removeEdge 1 1 (1 * 1 * 2 * 2)  == 1 * 2 * 2" $-          removeEdge 1 1 (1 * 1 * 2 * 2)  == (1 * 2 * (2 :: RI))--    test "removeEdge 1 2 (1 * 1 * 2 * 2)  == 1 * 1 + 2 * 2" $-          removeEdge 1 2 (1 * 1 * 2 * 2)  == (1 * 1 + 2 * (2 :: RI))--    putStrLn "\n============ Relation.replaceVertex ============"-    test "replaceVertex x x            == id" $ \x (y :: RI) ->-          replaceVertex x x y          == y--    test "replaceVertex x y (vertex x) == vertex y" $ \x (y :: Int) ->-          replaceVertex x y (vertex x) == (vertex y :: RI)--    test "replaceVertex x y            == mergeVertices (== x) y" $ \x y z ->-          replaceVertex x y z          == (mergeVertices (== x) y z :: RI)--    putStrLn "\n============ Relation.mergeVertices ============"-    test "mergeVertices (const False) x    == id" $ \x (y :: RI) ->-          mergeVertices (const False) x y  == y--    test "mergeVertices (== x) y           == replaceVertex x y" $ \x y (z :: RI) ->-          mergeVertices (== x) y z         == (replaceVertex x y z :: RI)--    test "mergeVertices even 1 (0 * 2)     == 1 * 1" $-          mergeVertices even 1 (0 * 2)     == (1 * 1 :: RI)--    test "mergeVertices odd  1 (3 + 4 * 5) == 4 * 1" $-          mergeVertices odd  1 (3 + 4 * 5) == (4 * 1 :: RI)--    putStrLn "\n============ Relation.transpose ============"-    test "transpose empty       == empty" $-          transpose empty       ==(empty :: RI)--    test "transpose (vertex x)  == vertex x" $ \(x :: Int) ->-          transpose (vertex x)  == vertex x--    test "transpose (edge x y)  == edge y x" $ \(x :: Int) y ->-          transpose (edge x y)  == edge y x--    test "transpose . transpose == id" $ \(x :: RI) ->-         (transpose . transpose) x == x--    test "transpose . path      == path    . reverse" $ \(xs :: [Int]) ->-         (transpose . path) xs  == (path . reverse) xs--    test "transpose . circuit   == circuit . reverse" $ \(xs :: [Int]) ->-         (transpose . circuit) xs == (circuit . reverse) xs--    test "transpose . clique    == clique  . reverse" $ \(xs :: [Int]) ->-         (transpose . clique) xs == (clique . reverse) xs--    test "edgeList . transpose  == sort . map swap . edgeList" $ \(x :: RI) ->-         (edgeList . transpose) x == (sort . map swap . edgeList) x--    putStrLn "\n============ Relation.gmap ============"-    test "gmap f empty      == empty" $ \(apply -> f :: II) ->-          gmap f empty      == empty--    test "gmap f (vertex x) == vertex (f x)" $ \(apply -> f :: II) x ->-          gmap f (vertex x) == vertex (f x)--    test "gmap f (edge x y) == edge (f x) (f y)" $ \(apply -> f :: II) x y ->-          gmap f (edge x y) == edge (f x) (f y)--    test "gmap id           == id" $ \x ->-          gmap id x         == (x :: RI)--    test "gmap f . gmap g   == gmap (f . g)" $ \(apply -> f :: II) (apply -> g :: II) x ->-         (gmap f . gmap g) x== gmap (f . g) x--    putStrLn "\n============ Relation.induce ============"-    test "induce (const True)  x      == x" $ \(x :: RI) ->-          induce (const True)  x      == x--    test "induce (const False) x      == empty" $ \(x :: RI) ->-          induce (const False) x      == (empty :: RI)--    test "induce (/= x)               == removeVertex x" $ \x (y :: RI) ->-          induce (/= x) y             == (removeVertex x y :: RI)--    test "induce p . induce q         == induce (\\x -> p x && q x)" $ \(apply -> p :: IB) (apply -> q :: IB) (y :: RI) ->-         (induce p . induce q) y      == (induce (\x -> p x && q x) y :: RI)--    test "isSubgraphOf (induce p x) x == True" $ \(apply -> p :: IB) (x :: RI) ->-          isSubgraphOf (induce p x) x == True+    testShow              t+    testBasicPrimitives   t+    testFromAdjacencyList t+    testIsSubgraphOf      t+    testProperties        t+    testAdjacencyList     t+    testPreSet            t+    testPostSet           t+    testGraphFamilies     t+    testTransformations   t      putStrLn "\n============ Relation.compose ============"     test "compose empty            x                == empty" $ \(x :: RI) ->
test/Main.hs view
@@ -1,4 +1,5 @@ import Algebra.Graph.Test.AdjacencyMap+import Algebra.Graph.Test.Export import Algebra.Graph.Test.Fold import Algebra.Graph.Test.Graph import Algebra.Graph.Test.IntAdjacencyMap@@ -7,6 +8,7 @@ main :: IO () main = do     testAdjacencyMap+    testExport     testFold     testGraph     testIntAdjacencyMap