Skip to content

Commit

Permalink
Revision in preparation for 0.5 (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
snowleopard authored Feb 2, 2020
1 parent 1d815da commit 4088493
Show file tree
Hide file tree
Showing 29 changed files with 1,261 additions and 1,488 deletions.
17 changes: 9 additions & 8 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ The Alga library was originally developed by

but over time many contributors helped make it much better, including (among others):

* [Adithya Obilisetty](mailto:[email protected]) [@adithyaov](https://github.com/adithyaov)
* [Vasily Alferov](mailto:[email protected]) [@vasalf](https://github.com/vasalf)
* [Piotr Gawryś](mailto:[email protected]) [@Avasil](https://github.com/Avasil)
* [Alexandre Moine](mailto:[email protected]) [@nobrakal](https://github.com/nobrakal)
* [Armando Santos](mailto:[email protected]) [@bolt12](https://github.com/bolt12)
* [Joseph Novakovich](mailto:[email protected]) [@jitwit](https://github.com/jitwit)
* [Piotr Gawryś](mailto:pgawrys2@gmail.com) [@Avasil](https://github.com/Avasil)
* [Vasily Alferov](mailto:vasily.v.alferov@gmail.com) [@vasalf](https://github.com/vasalf)
* [Adithya Obilisetty](mailto:adi.obilisetty@gmail.com) [@adithyaov](https://github.com/adithyaov)
* [Armando Santos](mailto:armandoifsantos@gmail.com) [@bolt12](https://github.com/bolt12)

If you are not on this list, it's not because your contributions are not appreciated, but
because I didn't want to add your name and contact details without your consent. Please fix this
by sending a PR, keeping the list alphabetical.
If you are not on this list, it's not because your contributions are not
appreciated, but because I didn't want to add your name and contact details
without your consent. Please fix this by sending a PR, keeping the list
alphabetical (sorted by last and then first name).

Also see the autogenerated yet still possibly incomplete
[list of contributors](https://github.com/snowleopard/alga/graphs/contributors).

Thank you all for your help!
Thank you all for your help!
Andrey
7 changes: 6 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

## 0.5

* #172, #245: Stop supporting GHC 7.8.4 and GHC 7.10.3.
* #217, #224, #227, #234, #235: Add new BFS, DFS, topological sort, and SCC
algorithms for adjacency maps.
* #228, #247, #254: Improve algebraic graph fusion.
* #207, #218, #255: Add `Bipartite.Undirected.AdjacencyMap`.
* #220, #237, #255: Add `Algebra.Graph.Undirected`.
* #203, #215, #223: Add `Acyclic.AdjacencyMap`.
* #202, #209, #211: Add `induceJust` and `induceJust1`.
* #172, #245: Stop supporting GHC 7.8.4 and GHC 7.10.3.
* #208: Add `fromNonEmpty` to `NonEmpty.AdjacencyMap`.
* #208: Add `fromAdjacencyMap` to `AdjacencyIntMap`.
* #208: Drop `Internal` modules for `AdjacencyIntMap`, `AdjacencyMap`,
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2016-2018 Andrey Mokhov
Copyright (c) 2016-2020 Andrey Mokhov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
5 changes: 3 additions & 2 deletions algebraic-graphs.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ description:
<https://github.com/snowleopard/alga/issues discussions on the library API>.

extra-doc-files:
AUTHORS.md
CHANGES.md
README.md

Expand Down Expand Up @@ -101,7 +102,7 @@ library
Algebra.Graph.AdjacencyIntMap.Algorithm,
Algebra.Graph.AdjacencyMap,
Algebra.Graph.AdjacencyMap.Algorithm,
Algebra.Graph.Bipartite.AdjacencyMap,
Algebra.Graph.Bipartite.Undirected.AdjacencyMap,
Algebra.Graph.Class,
Algebra.Graph.Export,
Algebra.Graph.Export.Dot,
Expand Down Expand Up @@ -133,7 +134,7 @@ test-suite test-alga
Algebra.Graph.Test.AdjacencyIntMap,
Algebra.Graph.Test.AdjacencyMap,
Algebra.Graph.Test.Arbitrary,
Algebra.Graph.Test.Bipartite.AdjacencyMap,
Algebra.Graph.Test.Bipartite.Undirected.AdjacencyMap,
Algebra.Graph.Test.Export,
Algebra.Graph.Test.Generic,
Algebra.Graph.Test.Graph,
Expand Down
8 changes: 4 additions & 4 deletions src/Algebra/Graph.hs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ empty = Empty
--
-- @
-- 'isEmpty' (vertex x) == False
-- 'hasVertex' x (vertex x) == True
-- 'hasVertex' x (vertex y) == (x == y)
-- 'vertexCount' (vertex x) == 1
-- 'edgeCount' (vertex x) == 0
-- 'size' (vertex x) == 1
Expand Down Expand Up @@ -404,6 +404,7 @@ vertices xs = buildg $ \e v o _ -> combineR e o v xs
-- @
-- edges [] == 'empty'
-- edges [(x,y)] == 'edge' x y
-- edges == 'overlays' . 'map' ('uncurry' 'edge')
-- 'edgeCount' . edges == 'length' . 'Data.List.nub'
-- @
edges :: [(a, a)] -> Graph a
Expand Down Expand Up @@ -550,7 +551,7 @@ _ === _ = False

infix 4 ===

-- | Check if a graph is empty. A convenient alias for 'null'.
-- | Check if a graph is empty.
-- Complexity: /O(s)/ time.
--
-- Good consumer.
Expand Down Expand Up @@ -591,8 +592,7 @@ size = foldg 1 (const 1) (+) (+)
--
-- @
-- hasVertex x 'empty' == False
-- hasVertex x ('vertex' x) == True
-- hasVertex 1 ('vertex' 2) == False
-- hasVertex x ('vertex' y) == (x == y)
-- hasVertex x . 'removeVertex' x == 'const' False
-- @
hasVertex :: Eq a => a -> Graph a -> Bool
Expand Down
5 changes: 2 additions & 3 deletions src/Algebra/Graph/Acyclic/AdjacencyMap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ empty = coerce AM.empty
--
-- @
-- 'isEmpty' (vertex x) == False
-- 'hasVertex' x (vertex x) == True
-- 'hasVertex' x (vertex y) == (x == y)
-- 'vertexCount' (vertex x) == 1
-- 'edgeCount' (vertex x) == 0
-- @
Expand Down Expand Up @@ -216,8 +216,7 @@ isEmpty = coerce AM.isEmpty
--
-- @
-- hasVertex x 'empty' == False
-- hasVertex x ('vertex' x) == True
-- hasVertex 1 ('vertex' 2) == False
-- hasVertex x ('vertex' y) == (x == y)
-- hasVertex x . 'removeVertex' x == 'const' False
-- @
hasVertex :: Ord a => a -> AdjacencyMap a -> Bool
Expand Down
6 changes: 3 additions & 3 deletions src/Algebra/Graph/AdjacencyIntMap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ empty = AM IntMap.empty
--
-- @
-- 'isEmpty' (vertex x) == False
-- 'hasVertex' x (vertex x) == True
-- 'hasVertex' x (vertex y) == (x == y)
-- 'vertexCount' (vertex x) == 1
-- 'edgeCount' (vertex x) == 0
-- @
Expand Down Expand Up @@ -318,6 +318,7 @@ vertices = AM . IntMap.fromList . map (\x -> (x, IntSet.empty))
-- @
-- edges [] == 'empty'
-- edges [(x,y)] == 'edge' x y
-- edges == 'overlays' . 'map' ('uncurry' 'edge')
-- 'edgeCount' . edges == 'length' . 'Data.List.nub'
-- 'edgeList' . edges == 'Data.List.nub' . 'Data.List.sort'
-- @
Expand Down Expand Up @@ -385,8 +386,7 @@ isEmpty = IntMap.null . adjacencyIntMap
--
-- @
-- hasVertex x 'empty' == False
-- hasVertex x ('vertex' x) == True
-- hasVertex 1 ('vertex' 2) == False
-- hasVertex x ('vertex' y) == (x == y)
-- hasVertex x . 'removeVertex' x == 'const' False
-- @
hasVertex :: Int -> AdjacencyIntMap -> Bool
Expand Down
6 changes: 3 additions & 3 deletions src/Algebra/Graph/AdjacencyMap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ empty = AM Map.empty
--
-- @
-- 'isEmpty' (vertex x) == False
-- 'hasVertex' x (vertex x) == True
-- 'hasVertex' x (vertex y) == (x == y)
-- 'vertexCount' (vertex x) == 1
-- 'edgeCount' (vertex x) == 0
-- @
Expand Down Expand Up @@ -304,6 +304,7 @@ vertices = AM . Map.fromList . map (\x -> (x, Set.empty))
-- @
-- edges [] == 'empty'
-- edges [(x,y)] == 'edge' x y
-- edges == 'overlays' . 'map' ('uncurry' 'edge')
-- 'edgeCount' . edges == 'length' . 'Data.List.nub'
-- 'edgeList' . edges == 'Data.List.nub' . 'Data.List.sort'
-- @
Expand Down Expand Up @@ -371,8 +372,7 @@ isEmpty = Map.null . adjacencyMap
--
-- @
-- hasVertex x 'empty' == False
-- hasVertex x ('vertex' x) == True
-- hasVertex 1 ('vertex' 2) == False
-- hasVertex x ('vertex' y) == (x == y)
-- hasVertex x . 'removeVertex' x == 'const' False
-- @
hasVertex :: Ord a => a -> AdjacencyMap a -> Bool
Expand Down
25 changes: 13 additions & 12 deletions src/Algebra/Graph/AdjacencyMap/Algorithm.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ module Algebra.Graph.AdjacencyMap.Algorithm (
-- * Algorithms
bfsForest, bfs, dfsForest, dfsForestFrom, dfs, reachable,
topSort, isAcyclic, scc,

-- * Correctness properties
isDfsForestOf, isTopSortOf,

-- * Type synonyms
Cycle
) where
Expand Down Expand Up @@ -50,7 +50,7 @@ import qualified Data.Set as Set
-- argument vertices that will be the roots of the resulting
-- forest. Duplicates in the list will have their first occurrence
-- expanded and subsequent ones ignored. Argument vertices not in
-- the graph are also ignored.
-- the graph are also ignored.
--
-- Let /L/ be the number of seed vertices. Complexity:
-- /O((L+m)*log n)/ time and /O(n)/ space.
Expand All @@ -69,7 +69,7 @@ import qualified Data.Set as Set
-- , Node { rootLabel = 4
-- , subForest = [] }]
-- 'forest' (bfsForest [3] ('circuit' [1..5] + 'circuit' [5,4..1])) == 'path' [3,2,1] + 'path' [3,4,5]
--
--
-- @
bfsForest :: Ord a => [a] -> AdjacencyMap a -> Forest a
bfsForest vs g = evalState (explore [ v | v <- vs, hasVertex v g ]) Set.empty where
Expand All @@ -88,7 +88,7 @@ bfsForest vs g = evalState (explore [ v | v <- vs, hasVertex v g ]) Set.empty wh
--
-- Let /L/ be the number of seed vertices. Complexity:
-- /O((L+m)*log n)/ time and /O(n)/ space.
--
--
-- @
-- bfs vs 'empty' == []
-- bfs [] g == []
Expand Down Expand Up @@ -141,10 +141,10 @@ dfsForest g = dfsForestFrom' (vertexList g) g
-- resulting forest does not necessarily span the whole graph, as
-- some vertices may be unreachable. Any of the given vertices which
-- are not in the graph are ignored.
--
--
-- Let /L/ be the number of seed vertices. Complexity: /O((L+m)*log n)/
-- time and /O(n)/ space.
--
--
-- @
-- dfsForestFrom vs 'empty' == []
-- 'forest' (dfsForestFrom [1] $ 'edge' 1 1) == 'vertex' 1
Expand All @@ -171,7 +171,7 @@ dfsForestFrom' :: Ord a => [a] -> AdjacencyMap a -> Forest a
dfsForestFrom' vs g = evalState (explore vs) Set.empty where
explore (v:vs) = discovered v >>= \case
True -> (:) <$> walk v <*> explore vs
False -> explore vs
False -> explore vs
explore [] = return []
walk v = Node v <$> explore (adjacent v)
adjacent v = Set.toList (postSet v g)
Expand Down Expand Up @@ -205,7 +205,7 @@ dfs vs = dfsForestFrom vs >=> flatten
-- | Compute the list of vertices that are /reachable/ from a given
-- source vertex in a graph. The vertices in the resulting list
-- appear in /depth-first order/.
--
--
-- Complexity: /O(m*log n)/ time and /O(n)/ space.
--
-- @
Expand All @@ -222,7 +222,7 @@ dfs vs = dfsForestFrom vs >=> flatten
reachable :: Ord a => a -> AdjacencyMap a -> [a]
reachable x = dfs [x]

type Cycle = NonEmpty
type Cycle = NonEmpty
data NodeState = Entered | Exited
data S a = S { parent :: Map.Map a a
, entry :: Map.Map a NodeState
Expand Down Expand Up @@ -289,7 +289,7 @@ topSort g = runContT (evalStateT (topSort' g) initialState) id where
initialState = S Map.empty Map.empty []

-- | Check if a given graph is /acyclic/.
--
--
-- Complexity: /O((n+m)*log n)/ time and /O(n)/ space.
--
-- @
Expand Down Expand Up @@ -384,7 +384,8 @@ gabowSCC g =

insertComponent v = modify'
(\(SCC pre scc bnd pth pres sccs gs es_i es_o) ->
let (curr,_v:pth') = span (/=v) pth
let (curr,v_pth') = span (/=v) pth
pth' = tail v_pth' -- Here we know that v_pth' starts with v
(es,es_i') = span ((>=p_v).fst) es_i
g_i | null es = vertex v
| otherwise = edges (snd <$> es)
Expand Down
Loading

0 comments on commit 4088493

Please sign in to comment.