{-# LANGUAGE LambdaCase #-}
-----------------------------------------------------------------------------
-- |
-- Module     : Algebra.Graph.AdjacencyMap.Algorithm
-- Copyright  : (c) Andrey Mokhov 2016-2022
-- License    : MIT (see the file LICENSE)
-- Maintainer : [email protected]
-- Stability  : unstable
--
-- __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 provides basic graph algorithms, such as /depth-first search/,
-- implemented for the "Algebra.Graph.AdjacencyMap" data type.
-----------------------------------------------------------------------------
module Algebra.Graph.AdjacencyMap.Algorithm (
    -- * Algorithms
    bfsForest, bfs, dfsForest, dfsForestFrom, dfs, reachable,
    topSort, isAcyclic, scc,

    -- * Correctness properties
    isDfsForestOf, isTopSortOf,

    -- * Type synonyms
    Cycle
    ) where

import Control.Monad
import Control.Monad.Trans.Cont
import Control.Monad.Trans.State.Strict
import Data.Foldable (for_)
import Data.Either
import Data.List.NonEmpty (NonEmpty(..), (<|))
import Data.Maybe
import Data.Tree

import Algebra.Graph.AdjacencyMap
import Algebra.Graph.Internal

import qualified Algebra.Graph.NonEmpty.AdjacencyMap as NonEmpty
import qualified Data.Array                          as Array
import qualified Data.List                           as List
import qualified Data.Map.Strict                     as Map
import qualified Data.Set                            as Set

-- | Compute the /breadth-first search/ forest of a graph, such that adjacent
-- vertices are explored in increasing order according to their 'Ord' instance.
-- The search is seeded by a list of vertices that will become the roots of the
-- resulting forest. Duplicates in the list will have their first occurrence
-- explored and subsequent ones ignored. The seed vertices that do not belong to
-- the graph are also ignored.
--
-- Complexity: /O((L + m) * log n)/ time and /O(n)/ space, where /L/ is the
-- number of seed vertices.
--
-- @
-- 'forest' $ bfsForest ('edge' 1 2) [0]        == 'empty'
-- 'forest' $ bfsForest ('edge' 1 2) [1]        == 'edge' 1 2
-- 'forest' $ bfsForest ('edge' 1 2) [2]        == 'vertex' 2
-- 'forest' $ bfsForest ('edge' 1 2) [0,1,2]    == 'vertices' [1,2]
-- 'forest' $ bfsForest ('edge' 1 2) [2,1,0]    == 'vertices' [1,2]
-- 'forest' $ bfsForest ('edge' 1 1) [1]        == 'vertex' 1
-- 'isSubgraphOf' ('forest' $ bfsForest x vs) x == True
-- bfsForest x ('vertexList' x)               == 'map' (\\v -> Node v []) ('Data.List.nub' $ 'vertexList' x)
-- bfsForest x []                           == []
-- bfsForest 'empty' vs                       == []
-- bfsForest (3 * (1 + 4) * (1 + 5)) [1,4]  == [ Node { rootLabel = 1
--                                                    , subForest = [ Node { rootLabel = 5
--                                                                         , subForest = [] }]}
--                                             , Node { rootLabel = 4
--                                                    , subForest = [] }]
-- 'forest' $ bfsForest ('circuit' [1..5] + 'circuit' [5,4..1]) [3] == 'path' [3,2,1] + 'path' [3,4,5]
--
-- @
bfsForest :: Ord a => AdjacencyMap a -> [a] -> Forest a
bfsForest :: forall a. Ord a => AdjacencyMap a -> [a] -> Forest a
bfsForest AdjacencyMap a
x [a]
vs = forall s a. State s a -> s -> a
evalState ([a] -> StateT (Set a) Identity [Tree a]
explore [ a
v | a
v <- [a]
vs, forall a. Ord a => a -> AdjacencyMap a -> Bool
hasVertex a
v AdjacencyMap a
x ]) forall a. Set a
Set.empty
  where
    explore :: [a] -> StateT (Set a) Identity [Tree a]
explore = forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM forall {m :: * -> *} {a}.
(Monad m, Ord a) =>
a -> StateT (Set a) m Bool
discovered forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (m :: * -> *) b a.
Monad m =>
(b -> m (a, [b])) -> [b] -> m [Tree a]
unfoldForestM_BF a -> StateT (Set a) Identity (a, [a])
walk
    walk :: a -> StateT (Set a) Identity (a, [a])
walk a
v = (a
v,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> StateT (Set a) Identity [a]
adjacentM a
v
    adjacentM :: a -> StateT (Set a) Identity [a]
adjacentM a
v = forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM forall {m :: * -> *} {a}.
(Monad m, Ord a) =>
a -> StateT (Set a) m Bool
discovered forall a b. (a -> b) -> a -> b
$ forall a. Set a -> [a]
Set.toList (forall a. Ord a => a -> AdjacencyMap a -> Set a
postSet a
v AdjacencyMap a
x)
    discovered :: a -> StateT (Set a) m Bool
discovered a
v = do Bool
new <- forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => a -> Set a -> Bool
Set.member a
v)
                      forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
new forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' (forall a. Ord a => a -> Set a -> Set a
Set.insert a
v)
                      forall (m :: * -> *) a. Monad m => a -> m a
return Bool
new

-- | A version of 'bfsForest' where the resulting forest is converted to a level
-- structure. Adjacent vertices are explored in the increasing order according
-- to their 'Ord' instance. Flattening the result via @'concat'@ @.@ @'bfs'@ @x@
-- gives an enumeration of reachable vertices in the breadth-first search order.
--
-- Complexity: /O((L + m) * min(n,W))/ time and /O(n)/ space, where /L/ is the
-- number of seed vertices.
--
-- @
-- bfs ('edge' 1 2) [0]                == []
-- bfs ('edge' 1 2) [1]                == [[1], [2]]
-- bfs ('edge' 1 2) [2]                == [[2]]
-- bfs ('edge' 1 2) [1,2]              == [[1,2]]
-- bfs ('edge' 1 2) [2,1]              == [[2,1]]
-- bfs ('edge' 1 1) [1]                == [[1]]
-- bfs 'empty' vs                      == []
-- bfs x []                          == []
-- bfs (1 * 2 + 3 * 4 + 5 * 6) [1,2] == [[1,2]]
-- bfs (1 * 2 + 3 * 4 + 5 * 6) [1,3] == [[1,3], [2,4]]
-- bfs (3 * (1 + 4) * (1 + 5)) [3]   == [[3], [1,4,5]]
--
-- bfs ('circuit' [1..5] + 'circuit' [5,4..1]) [3]          == [[2], [1,3], [5,4]]
-- 'concat' $ bfs ('circuit' [1..5] + 'circuit' [5,4..1]) [3] == [3,2,4,1,5]
-- 'map' 'concat' . 'List.transpose' . 'map' 'levels' . 'bfsForest' x    == bfs x
-- @
bfs :: Ord a => AdjacencyMap a -> [a] -> [[a]]
bfs :: forall a. Ord a => AdjacencyMap a -> [a] -> [[a]]
bfs AdjacencyMap a
x = forall a b. (a -> b) -> [a] -> [b]
map forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [[a]] -> [[a]]
List.transpose forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a. Tree a -> [[a]]
levels forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => AdjacencyMap a -> [a] -> Forest a
bfsForest AdjacencyMap a
x

dfsForestFromImpl :: Ord a => AdjacencyMap a -> [a] -> Forest a
dfsForestFromImpl :: forall a. Ord a => AdjacencyMap a -> [a] -> Forest a
dfsForestFromImpl AdjacencyMap a
g [a]
vs = forall s a. State s a -> s -> a
evalState ([a] -> StateT (Set a) Identity [Tree a]
explore [a]
vs) forall a. Set a
Set.empty
  where
    explore :: [a] -> StateT (Set a) Identity [Tree a]
explore (a
v:[a]
vs) = forall {m :: * -> *} {a}.
(Monad m, Ord a) =>
a -> StateT (Set a) m Bool
discovered a
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Bool
True -> (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> StateT (Set a) Identity (Tree a)
walk a
v forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [a] -> StateT (Set a) Identity [Tree a]
explore [a]
vs
      Bool
False -> [a] -> StateT (Set a) Identity [Tree a]
explore [a]
vs
    explore [] = forall (m :: * -> *) a. Monad m => a -> m a
return []
    walk :: a -> StateT (Set a) Identity (Tree a)
walk a
v = forall a. a -> [Tree a] -> Tree a
Node a
v forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a] -> StateT (Set a) Identity [Tree a]
explore (a -> [a]
adjacent a
v)
    adjacent :: a -> [a]
adjacent a
v = forall a. Set a -> [a]
Set.toList (forall a. Ord a => a -> AdjacencyMap a -> Set a
postSet a
v AdjacencyMap a
g)
    discovered :: a -> StateT (Set a) m Bool
discovered a
v = do Bool
new <- forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => a -> Set a -> Bool
Set.member a
v)
                      forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
new forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' (forall a. Ord a => a -> Set a -> Set a
Set.insert a
v)
                      forall (m :: * -> *) a. Monad m => a -> m a
return Bool
new

-- | Compute the /depth-first search/ forest of a graph, where adjacent vertices
-- are explored in the increasing order according to their 'Ord' instance.
--
-- Complexity: /O((n + m) * min(n,W))/ time and /O(n)/ space.
--
-- @
-- 'forest' $ dfsForest 'empty'              == 'empty'
-- 'forest' $ dfsForest ('edge' 1 1)         == 'vertex' 1
-- 'forest' $ dfsForest ('edge' 1 2)         == 'edge' 1 2
-- 'forest' $ dfsForest ('edge' 2 1)         == 'vertices' [1,2]
-- 'isSubgraphOf' ('forest' $ dfsForest x) x == True
-- 'isDfsForestOf' (dfsForest x) x         == True
-- dfsForest . 'forest' . dfsForest        == dfsForest
-- dfsForest ('vertices' vs)               == 'map' (\\v -> Node v []) ('Data.List.nub' $ 'Data.List.sort' vs)
-- dfsForest $ 3 * (1 + 4) * (1 + 5)     == [ Node { rootLabel = 1
--                                                 , subForest = [ Node { rootLabel = 5
--                                                                      , subForest = [] }]}
--                                          , Node { rootLabel = 3
--                                                 , subForest = [ Node { rootLabel = 4
--                                                                      , subForest = [] }]}]
-- 'forest' (dfsForest $ 'circuit' [1..5] + 'circuit' [5,4..1]) == 'path' [1,2,3,4,5]
-- @
dfsForest :: Ord a => AdjacencyMap a -> Forest a
dfsForest :: forall a. Ord a => AdjacencyMap a -> Forest a
dfsForest AdjacencyMap a
g = forall a. Ord a => AdjacencyMap a -> [a] -> Forest a
dfsForestFromImpl AdjacencyMap a
g (forall a. AdjacencyMap a -> [a]
vertexList AdjacencyMap a
g)

-- | Compute the /depth-first search/ forest of a graph starting from the given
-- seed vertices, where adjacent vertices are explored in the increasing order
-- according to their 'Ord' instance. Note that the resulting forest does not
-- necessarily span the whole graph, as some vertices may be unreachable. The
-- seed vertices which do not belong to the graph are ignored.
--
-- Complexity: /O((L + m) * log n)/ time and /O(n)/ space, where /L/ is the
-- number of seed vertices.
--
-- @
-- 'forest' $ dfsForestFrom 'empty'      vs             == 'empty'
-- 'forest' $ dfsForestFrom ('edge' 1 1) [1]            == 'vertex' 1
-- 'forest' $ dfsForestFrom ('edge' 1 2) [0]            == 'empty'
-- 'forest' $ dfsForestFrom ('edge' 1 2) [1]            == 'edge' 1 2
-- 'forest' $ dfsForestFrom ('edge' 1 2) [2]            == 'vertex' 2
-- 'forest' $ dfsForestFrom ('edge' 1 2) [1,2]          == 'edge' 1 2
-- 'forest' $ dfsForestFrom ('edge' 1 2) [2,1]          == 'vertices' [1,2]
-- 'isSubgraphOf' ('forest' $ dfsForestFrom x vs) x     == True
-- 'isDfsForestOf' (dfsForestFrom x ('vertexList' x)) x == True
-- dfsForestFrom x ('vertexList' x)                   == 'dfsForest' x
-- dfsForestFrom x []                               == []
-- dfsForestFrom (3 * (1 + 4) * (1 + 5)) [1,4]      == [ Node { rootLabel = 1
--                                                            , subForest = [ Node { rootLabel = 5
--                                                                                 , subForest = [] }
--                                                     , Node { rootLabel = 4
--                                                            , subForest = [] }]
-- 'forest' $ dfsForestFrom ('circuit' [1..5] + 'circuit' [5,4..1]) [3] == 'path' [3,2,1,5,4]
-- @
dfsForestFrom :: Ord a => AdjacencyMap a -> [a] -> Forest a
dfsForestFrom :: forall a. Ord a => AdjacencyMap a -> [a] -> Forest a
dfsForestFrom AdjacencyMap a
g [a]
vs = forall a. Ord a => AdjacencyMap a -> [a] -> Forest a
dfsForestFromImpl AdjacencyMap a
g [ a
v | a
v <- [a]
vs, forall a. Ord a => a -> AdjacencyMap a -> Bool
hasVertex a
v AdjacencyMap a
g ]

-- | Return the list vertices visited by the /depth-first search/ in a graph,
-- starting from the given seed vertices. Adjacent vertices are explored in the
-- increasing order according to their 'Ord' instance.
--
-- Complexity: /O((L + m) * log n)/ time and /O(n)/ space, where /L/ is the
-- number of seed vertices.
--
-- @
-- dfs 'empty'      vs    == []
-- dfs ('edge' 1 1) [1]   == [1]
-- dfs ('edge' 1 2) [0]   == []
-- dfs ('edge' 1 2) [1]   == [1,2]
-- dfs ('edge' 1 2) [2]   == [2]
-- dfs ('edge' 1 2) [1,2] == [1,2]
-- dfs ('edge' 1 2) [2,1] == [2,1]
-- dfs x          []    == []
--
-- 'Data.List.and' [ 'hasVertex' v x | v <- dfs x vs ]       == True
-- dfs (3 * (1 + 4) * (1 + 5)) [1,4]           == [1,5,4]
-- dfs ('circuit' [1..5] + 'circuit' [5,4..1]) [3] == [3,2,1,5,4]
-- @
dfs :: Ord a => AdjacencyMap a -> [a] -> [a]
dfs :: forall a. Ord a => AdjacencyMap a -> [a] -> [a]
dfs AdjacencyMap a
x = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall a. Tree a -> [a]
flatten forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => AdjacencyMap a -> [a] -> Forest a
dfsForestFrom AdjacencyMap a
x

-- | Return the list of vertices /reachable/ from a source vertex in a graph.
-- The vertices in the resulting list appear in the /depth-first search order/.
--
-- Complexity: /O(m * log n)/ time and /O(n)/ space.
--
-- @
-- reachable 'empty'              x == []
-- reachable ('vertex' 1)         1 == [1]
-- reachable ('edge' 1 1)         1 == [1]
-- reachable ('edge' 1 2)         0 == []
-- reachable ('edge' 1 2)         1 == [1,2]
-- reachable ('edge' 1 2)         2 == [2]
-- reachable ('path'    [1..8]  ) 4 == [4..8]
-- reachable ('circuit' [1..8]  ) 4 == [4..8] ++ [1..3]
-- reachable ('clique'  [8,7..1]) 8 == [8] ++ [1..7]
--
-- 'Data.List.and' [ 'hasVertex' v x | v <- reachable x y ] == True
-- @
reachable :: Ord a => AdjacencyMap a -> a -> [a]
reachable :: forall a. Ord a => AdjacencyMap a -> a -> [a]
reachable AdjacencyMap a
x a
y = forall a. Ord a => AdjacencyMap a -> [a] -> [a]
dfs AdjacencyMap a
x [a
y]

type Cycle = NonEmpty
type Result a = Either (Cycle a) [a]
data NodeState = Entered | Exited
data S a = S { forall a. S a -> Map a a
parent :: Map.Map a a
             , forall a. S a -> Map a NodeState
entry  :: Map.Map a NodeState
             , forall a. S a -> [a]
order  :: [a] }

topSortImpl :: Ord a => AdjacencyMap a -> StateT (S a) (Cont (Result a)) (Result a)
topSortImpl :: forall a.
Ord a =>
AdjacencyMap a -> StateT (S a) (Cont (Result a)) (Result a)
topSortImpl AdjacencyMap a
g = forall (m :: * -> *) a s b.
CallCC m (a, s) (b, s) -> CallCC (StateT s m) a b
liftCallCC' forall {k} a (r :: k) (m :: k -> *) b.
((a -> ContT r m b) -> ContT r m a) -> ContT r m a
callCC forall a b. (a -> b) -> a -> b
$ \Result a -> StateT (S a) (Cont (Result a)) ()
cyclic ->
  do let vertices :: [a]
vertices = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [(k, a)]
Map.toDescList forall a b. (a -> b) -> a -> b
$ forall a. AdjacencyMap a -> Map a (Set a)
adjacencyMap AdjacencyMap a
g
         adjacent :: a -> [a]
adjacent = forall a. Set a -> [a]
Set.toDescList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Ord a => a -> AdjacencyMap a -> Set a
postSet AdjacencyMap a
g
         dfsRoot :: a -> StateT (S a) (Cont (Result a)) ()
dfsRoot a
x = forall {m :: * -> *} {k}.
(Monad m, Ord k) =>
k -> StateT (S k) m (Maybe NodeState)
nodeState a
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
           Maybe NodeState
Nothing -> forall {m :: * -> *} {a}.
(Monad m, Ord a) =>
a -> StateT (S a) m ()
enterRoot a
x forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> StateT (S a) (Cont (Result a)) ()
dfs a
x forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall {m :: * -> *} {a}.
(Monad m, Ord a) =>
a -> StateT (S a) m ()
exit a
x
           Maybe NodeState
_       -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
         dfs :: a -> StateT (S a) (Cont (Result a)) ()
dfs a
x = forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (a -> [a]
adjacent a
x) forall a b. (a -> b) -> a -> b
$ \a
y ->
                   forall {m :: * -> *} {k}.
(Monad m, Ord k) =>
k -> StateT (S k) m (Maybe NodeState)
nodeState a
y forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
                     Maybe NodeState
Nothing      -> forall {m :: * -> *} {a}.
(Monad m, Ord a) =>
a -> a -> StateT (S a) m ()
enter a
x a
y forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> StateT (S a) (Cont (Result a)) ()
dfs a
y forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall {m :: * -> *} {a}.
(Monad m, Ord a) =>
a -> StateT (S a) m ()
exit a
y
                     Just NodeState
Exited  -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
                     Just NodeState
Entered -> Result a -> StateT (S a) (Cont (Result a)) ()
cyclic forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. Ord a => a -> a -> Map a a -> NonEmpty a
retrace a
x a
y forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets forall a. S a -> Map a a
parent
     forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [a]
vertices a -> StateT (S a) (Cont (Result a)) ()
dfsRoot
     forall a b. b -> Either a b
Right forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets forall a. S a -> [a]
order
  where
    nodeState :: k -> StateT (S k) m (Maybe NodeState)
nodeState k
v = forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets (forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup k
v forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. S a -> Map a NodeState
entry)
    enter :: a -> a -> StateT (S a) m ()
enter a
u a
v = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' (\(S Map a a
m Map a NodeState
n [a]
vs) -> forall a. Map a a -> Map a NodeState -> [a] -> S a
S (forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert a
v a
u Map a a
m)
                                          (forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert a
v NodeState
Entered Map a NodeState
n)
                                          [a]
vs)
    enterRoot :: a -> StateT (S a) m ()
enterRoot a
v = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' (\(S Map a a
m Map a NodeState
n [a]
vs) -> forall a. Map a a -> Map a NodeState -> [a] -> S a
S Map a a
m (forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert a
v NodeState
Entered Map a NodeState
n) [a]
vs)
    exit :: a -> StateT (S a) m ()
exit a
v = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' (\(S Map a a
m Map a NodeState
n [a]
vs) -> forall a. Map a a -> Map a NodeState -> [a] -> S a
S Map a a
m (forall k a.
Ord k =>
(Maybe a -> Maybe a) -> k -> Map k a -> Map k a
Map.alter (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap NodeState -> NodeState
leave) a
v Map a NodeState
n) (a
vforall a. a -> [a] -> [a]
:[a]
vs))
      where leave :: NodeState -> NodeState
leave = \case
              NodeState
Entered -> NodeState
Exited
              NodeState
Exited  -> forall a. HasCallStack => [Char] -> a
error [Char]
"Internal error: dfs search order violated"
    retrace :: a -> a -> Map a a -> NonEmpty a
retrace a
curr a
head Map a a
parent = NonEmpty a -> NonEmpty a
aux (a
curr forall a. a -> [a] -> NonEmpty a
:| []) where
      aux :: NonEmpty a -> NonEmpty a
aux xs :: NonEmpty a
xs@(a
curr :| [a]
_)
        | a
head forall a. Eq a => a -> a -> Bool
== a
curr = NonEmpty a
xs
        | Bool
otherwise = NonEmpty a -> NonEmpty a
aux (Map a a
parent forall k a. Ord k => Map k a -> k -> a
Map.! a
curr forall a. a -> NonEmpty a -> NonEmpty a
<| NonEmpty a
xs)

-- | Compute a topological sort of a graph or discover a cycle.
--
-- Vertices are explored in the decreasing order according to their 'Ord'
-- instance. This gives the lexicographically smallest topological ordering in
-- the case of success. In the case of failure, the cycle is characterized by
-- being the lexicographically smallest up to rotation with respect to
-- @Ord@ @(Dual@ @Int)@ in the first connected component of the graph containing
-- a cycle, where the connected components are ordered by their largest vertex
-- with respect to @Ord a@.
--
-- Complexity: /O((n + m) * min(n,W))/ time and /O(n)/ space.
--
-- @
-- topSort (1 * 2 + 3 * 1)                    == Right [3,1,2]
-- topSort ('path' [1..5])                      == Right [1..5]
-- topSort (3 * (1 * 4 + 2 * 5))              == Right [3,1,2,4,5]
-- topSort (1 * 2 + 2 * 1)                    == Left (2 ':|' [1])
-- topSort ('path' [5,4..1] + 'edge' 2 4)         == Left (4 ':|' [3,2])
-- topSort ('circuit' [1..3])                   == Left (3 ':|' [1,2])
-- topSort ('circuit' [1..3] + 'circuit' [3,2,1]) == Left (3 ':|' [2])
-- topSort (1 * 2 + (5 + 2) * 1 + 3 * 4 * 3)  == Left (1 ':|' [2])
-- fmap ('flip' 'isTopSortOf' x) (topSort x)      /= Right False
-- 'isRight' . topSort                          == 'isAcyclic'
-- topSort . 'vertices'                         == Right . 'nub' . 'sort'
-- @
topSort :: Ord a => AdjacencyMap a -> Either (Cycle a) [a]
topSort :: forall a. Ord a => AdjacencyMap a -> Either (Cycle a) [a]
topSort AdjacencyMap a
g = forall r a. Cont r a -> (a -> r) -> r
runCont (forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (forall a.
Ord a =>
AdjacencyMap a -> StateT (S a) (Cont (Result a)) (Result a)
topSortImpl AdjacencyMap a
g) forall {a}. S a
initialState) forall a. a -> a
id
  where
    initialState :: S a
initialState = forall a. Map a a -> Map a NodeState -> [a] -> S a
S forall k a. Map k a
Map.empty forall k a. Map k a
Map.empty []

-- | Check if a given graph is /acyclic/.
--
--   Complexity: /O((n+m)*log n)/ time and /O(n)/ space.
--
-- @
-- isAcyclic (1 * 2 + 3 * 1) == True
-- isAcyclic (1 * 2 + 2 * 1) == False
-- isAcyclic . 'circuit'       == 'null'
-- isAcyclic                 == 'isRight' . 'topSort'
-- @
isAcyclic :: Ord a => AdjacencyMap a -> Bool
isAcyclic :: forall a. Ord a => AdjacencyMap a -> Bool
isAcyclic = forall a b. Either a b -> Bool
isRight forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => AdjacencyMap a -> Either (Cycle a) [a]
topSort

-- | Compute the /condensation/ of a graph, where each vertex corresponds to a
-- /strongly-connected component/ of the original graph. Note that component
-- graphs are non-empty, and are therefore of type
-- "Algebra.Graph.NonEmpty.AdjacencyMap".
--
-- Details about the implementation can be found at
-- <https://github.com/jitwit/alga-notes/blob/master/gabow.org gabow-notes>.
--
-- Complexity: /O((n+m)*log n)/ time and /O(n+m)/ space.
--
-- @
-- scc 'empty'               == 'empty'
-- scc ('vertex' x)          == 'vertex' (NonEmpty.'NonEmpty.vertex' x)
-- scc ('vertices' xs)       == 'vertices' ('map' 'NonEmpty.vertex' xs)
-- scc ('edge' 1 1)          == 'vertex' (NonEmpty.'NonEmpty.edge' 1 1)
-- scc ('edge' 1 2)          == 'edge'   (NonEmpty.'NonEmpty.vertex' 1) (NonEmpty.'NonEmpty.vertex' 2)
-- scc ('circuit' (1:xs))    == 'vertex' (NonEmpty.'NonEmpty.circuit1' (1 'Data.List.NonEmpty.:|' xs))
-- scc (3 * 1 * 4 * 1 * 5) == 'edges'  [ (NonEmpty.'NonEmpty.vertex'  3      , NonEmpty.'NonEmpty.vertex'  5      )
--                                   , (NonEmpty.'NonEmpty.vertex'  3      , NonEmpty.'NonEmpty.clique1' [1,4,1])
--                                   , (NonEmpty.'NonEmpty.clique1' [1,4,1], NonEmpty.'NonEmpty.vertex'  5      ) ]
-- 'isAcyclic' . scc == 'const' True
-- 'isAcyclic' x     == (scc x == 'gmap' NonEmpty.'NonEmpty.vertex' x)
-- @
scc :: Ord a => AdjacencyMap a -> AdjacencyMap (NonEmpty.AdjacencyMap a)
scc :: forall a. Ord a => AdjacencyMap a -> AdjacencyMap (AdjacencyMap a)
scc AdjacencyMap a
g = forall a.
Ord a =>
AdjacencyMap a -> StateSCC a -> AdjacencyMap (AdjacencyMap a)
condense AdjacencyMap a
g forall a b. (a -> b) -> a -> b
$ forall s a. State s a -> s -> s
execState (forall a. Ord a => AdjacencyMap a -> State (StateSCC a) ()
gabowSCC AdjacencyMap a
g) forall {a}. StateSCC a
initialState where
  initialState :: StateSCC a
initialState = forall a.
Int
-> Int
-> [(Int, a)]
-> [a]
-> Map a Int
-> Map a Int
-> [AdjacencyMap a]
-> [(Int, (a, a))]
-> [(a, a)]
-> StateSCC a
SCC Int
0 Int
0 [] [] forall k a. Map k a
Map.empty forall k a. Map k a
Map.empty [] [] []

data StateSCC a
  = SCC { forall a. StateSCC a -> Int
_preorder     :: {-# unpack #-} !Int
        , forall a. StateSCC a -> Int
_component    :: {-# unpack #-} !Int
        , forall a. StateSCC a -> [(Int, a)]
boundaryStack :: [(Int,a)]
        , forall a. StateSCC a -> [a]
_pathStack    :: [a]
        , forall a. StateSCC a -> Map a Int
preorders     :: Map.Map a Int
        , forall a. StateSCC a -> Map a Int
components    :: Map.Map a Int
        , forall a. StateSCC a -> [AdjacencyMap a]
_innerGraphs  :: [AdjacencyMap a]
        , forall a. StateSCC a -> [(Int, (a, a))]
_innerEdges   :: [(Int,(a,a))]
        , forall a. StateSCC a -> [(a, a)]
_outerEdges   :: [(a,a)]
        } deriving (Int -> StateSCC a -> ShowS
forall a. (Show a, Ord a) => Int -> StateSCC a -> ShowS
forall a. (Show a, Ord a) => [StateSCC a] -> ShowS
forall a. (Show a, Ord a) => StateSCC a -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [StateSCC a] -> ShowS
$cshowList :: forall a. (Show a, Ord a) => [StateSCC a] -> ShowS
show :: StateSCC a -> [Char]
$cshow :: forall a. (Show a, Ord a) => StateSCC a -> [Char]
showsPrec :: Int -> StateSCC a -> ShowS
$cshowsPrec :: forall a. (Show a, Ord a) => Int -> StateSCC a -> ShowS
Show)

gabowSCC :: Ord a => AdjacencyMap a -> State (StateSCC a) ()
gabowSCC :: forall a. Ord a => AdjacencyMap a -> State (StateSCC a) ()
gabowSCC AdjacencyMap a
g =
  do let dfs :: a -> StateT (StateSCC a) Identity Bool
dfs a
u = do Int
p_u <- forall {m :: * -> *} {b}.
(Monad m, Ord b) =>
b -> StateT (StateSCC b) m Int
enter a
u
                    forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (forall a. Ord a => a -> AdjacencyMap a -> Set a
postSet a
u AdjacencyMap a
g) forall a b. (a -> b) -> a -> b
$ \a
v -> do
                      forall {m :: * -> *} {k}.
(Monad m, Ord k) =>
k -> StateT (StateSCC k) m (Maybe Int)
preorderId a
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
                        Maybe Int
Nothing  -> do
                          Bool
updated <- a -> StateT (StateSCC a) Identity Bool
dfs a
v
                          if Bool
updated then forall {m :: * -> *} {a}.
Monad m =>
(a, a) -> StateT (StateSCC a) m ()
outedge (a
u,a
v) else forall {m :: * -> *} {a}.
Monad m =>
(Int, (a, a)) -> StateT (StateSCC a) m ()
inedge (Int
p_u,(a
u,a
v))
                        Just Int
p_v -> do
                          Bool
scc_v <- forall {m :: * -> *} {k}.
(Monad m, Ord k) =>
k -> StateT (StateSCC k) m Bool
hasComponent a
v
                          if Bool
scc_v
                            then forall {m :: * -> *} {a}.
Monad m =>
(a, a) -> StateT (StateSCC a) m ()
outedge (a
u,a
v)
                            else forall {m :: * -> *} {a}.
Monad m =>
Int -> StateT (StateSCC a) m ()
popBoundary Int
p_v forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall {m :: * -> *} {a}.
Monad m =>
(Int, (a, a)) -> StateT (StateSCC a) m ()
inedge (Int
p_u,(a
u,a
v))
                    forall {m :: * -> *} {k}.
(Monad m, Ord k) =>
k -> StateT (StateSCC k) m Bool
exit a
u
     forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (forall a. AdjacencyMap a -> [a]
vertexList AdjacencyMap a
g) forall a b. (a -> b) -> a -> b
$ \a
v -> do
       Bool
assigned <- forall {m :: * -> *} {k}.
(Monad m, Ord k) =>
k -> StateT (StateSCC k) m Bool
hasPreorderId a
v
       forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
assigned forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ a -> StateT (StateSCC a) Identity Bool
dfs a
v
  where
    -- called when visiting vertex v. assigns preorder number to v,
    -- adds the (id, v) pair to the boundary stack b, and adds v to
    -- the path stack s.
    enter :: b -> StateT (StateSCC b) m Int
enter b
v = do SCC Int
pre Int
scc [(Int, b)]
bnd [b]
pth Map b Int
pres Map b Int
sccs [AdjacencyMap b]
gs [(Int, (b, b))]
es_i [(b, b)]
es_o <- forall (m :: * -> *) s. Monad m => StateT s m s
get
                 let pre' :: Int
pre' = Int
preforall a. Num a => a -> a -> a
+Int
1
                     bnd' :: [(Int, b)]
bnd' = (Int
pre,b
v)forall a. a -> [a] -> [a]
:[(Int, b)]
bnd
                     pth' :: [b]
pth' = b
vforall a. a -> [a] -> [a]
:[b]
pth
                     pres' :: Map b Int
pres' = forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert b
v Int
pre Map b Int
pres
                 forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put forall a b. (a -> b) -> a -> b
$! forall a.
Int
-> Int
-> [(Int, a)]
-> [a]
-> Map a Int
-> Map a Int
-> [AdjacencyMap a]
-> [(Int, (a, a))]
-> [(a, a)]
-> StateSCC a
SCC Int
pre' Int
scc [(Int, b)]
bnd' [b]
pth' Map b Int
pres' Map b Int
sccs [AdjacencyMap b]
gs [(Int, (b, b))]
es_i [(b, b)]
es_o
                 forall (m :: * -> *) a. Monad m => a -> m a
return Int
pre

    -- called on back edges. pops the boundary stack while the top
    -- vertex has a larger preorder number than p_v.
    popBoundary :: Int -> StateT (StateSCC a) m ()
popBoundary Int
p_v = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify'
      (\(SCC Int
pre Int
scc [(Int, a)]
bnd [a]
pth Map a Int
pres Map a Int
sccs [AdjacencyMap a]
gs [(Int, (a, a))]
es_i [(a, a)]
es_o) ->
         forall a.
Int
-> Int
-> [(Int, a)]
-> [a]
-> Map a Int
-> Map a Int
-> [AdjacencyMap a]
-> [(Int, (a, a))]
-> [(a, a)]
-> StateSCC a
SCC Int
pre Int
scc (forall a. (a -> Bool) -> [a] -> [a]
dropWhile ((forall a. Ord a => a -> a -> Bool
>Int
p_v)forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a b. (a, b) -> a
fst) [(Int, a)]
bnd) [a]
pth Map a Int
pres Map a Int
sccs [AdjacencyMap a]
gs [(Int, (a, a))]
es_i [(a, a)]
es_o)

    -- called when exiting vertex v. if v is the bottom of a scc
    -- boundary, we add a new SCC, otherwise v is part of a larger scc
    -- being constructed and we continue.
    exit :: b -> StateT (StateSCC b) m Bool
exit b
v = do Bool
newComponent <- (b
vforall a. Eq a => a -> a -> Bool
==)forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a b. (a, b) -> b
sndforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. [a] -> a
head forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets forall a. StateSCC a -> [(Int, a)]
boundaryStack
                forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
newComponent forall a b. (a -> b) -> a -> b
$ forall {m :: * -> *} {k}.
(Monad m, Ord k) =>
k -> StateT (StateSCC k) m ()
insertComponent b
v
                forall (m :: * -> *) a. Monad m => a -> m a
return Bool
newComponent

    insertComponent :: k -> StateT (StateSCC k) m ()
insertComponent k
v = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify'
      (\(SCC Int
pre Int
scc [(Int, k)]
bnd [k]
pth Map k Int
pres Map k Int
sccs [AdjacencyMap k]
gs [(Int, (k, k))]
es_i [(k, k)]
es_o) ->
         let ([k]
curr,[k]
v_pth') = forall a. (a -> Bool) -> [a] -> ([a], [a])
span (forall a. Eq a => a -> a -> Bool
/=k
v) [k]
pth
             pth' :: [k]
pth' = forall a. [a] -> [a]
tail [k]
v_pth' -- Here we know that v_pth' starts with v
             ([(Int, (k, k))]
es,[(Int, (k, k))]
es_i') = forall a. (a -> Bool) -> [a] -> ([a], [a])
span ((forall a. Ord a => a -> a -> Bool
>=Int
p_v)forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a b. (a, b) -> a
fst) [(Int, (k, k))]
es_i
             g_i :: AdjacencyMap k
g_i | forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Int, (k, k))]
es = forall a. a -> AdjacencyMap a
vertex k
v
                 | Bool
otherwise = forall a. Ord a => [(a, a)] -> AdjacencyMap a
edges (forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Int, (k, k))]
es)
             p_v :: Int
p_v = forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [(Int, k)]
bnd
             scc' :: Int
scc' = Int
scc forall a. Num a => a -> a -> a
+ Int
1
             bnd' :: [(Int, k)]
bnd' = forall a. [a] -> [a]
tail [(Int, k)]
bnd
             sccs' :: Map k Int
sccs' = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (\Map k Int
sccs k
x -> forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert k
x Int
scc Map k Int
sccs) Map k Int
sccs (k
vforall a. a -> [a] -> [a]
:[k]
curr)
             gs' :: [AdjacencyMap k]
gs' = AdjacencyMap k
g_iforall a. a -> [a] -> [a]
:[AdjacencyMap k]
gs
          in forall a.
Int
-> Int
-> [(Int, a)]
-> [a]
-> Map a Int
-> Map a Int
-> [AdjacencyMap a]
-> [(Int, (a, a))]
-> [(a, a)]
-> StateSCC a
SCC Int
pre Int
scc' [(Int, k)]
bnd' [k]
pth' Map k Int
pres Map k Int
sccs' [AdjacencyMap k]
gs' [(Int, (k, k))]
es_i' [(k, k)]
es_o)

    inedge :: (Int, (a, a)) -> StateT (StateSCC a) m ()
inedge (Int, (a, a))
uv = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify'
      (\(SCC Int
pre Int
scc [(Int, a)]
bnd [a]
pth Map a Int
pres Map a Int
sccs [AdjacencyMap a]
gs [(Int, (a, a))]
es_i [(a, a)]
es_o) ->
         forall a.
Int
-> Int
-> [(Int, a)]
-> [a]
-> Map a Int
-> Map a Int
-> [AdjacencyMap a]
-> [(Int, (a, a))]
-> [(a, a)]
-> StateSCC a
SCC Int
pre Int
scc [(Int, a)]
bnd [a]
pth Map a Int
pres Map a Int
sccs [AdjacencyMap a]
gs ((Int, (a, a))
uvforall a. a -> [a] -> [a]
:[(Int, (a, a))]
es_i) [(a, a)]
es_o)

    outedge :: (a, a) -> StateT (StateSCC a) m ()
outedge (a, a)
uv = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify'
      (\(SCC Int
pre Int
scc [(Int, a)]
bnd [a]
pth Map a Int
pres Map a Int
sccs [AdjacencyMap a]
gs [(Int, (a, a))]
es_i [(a, a)]
es_o) ->
         forall a.
Int
-> Int
-> [(Int, a)]
-> [a]
-> Map a Int
-> Map a Int
-> [AdjacencyMap a]
-> [(Int, (a, a))]
-> [(a, a)]
-> StateSCC a
SCC Int
pre Int
scc [(Int, a)]
bnd [a]
pth Map a Int
pres Map a Int
sccs [AdjacencyMap a]
gs [(Int, (a, a))]
es_i ((a, a)
uvforall a. a -> [a] -> [a]
:[(a, a)]
es_o))

    hasPreorderId :: k -> StateT (StateSCC k) m Bool
hasPreorderId k
v = forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets (forall k a. Ord k => k -> Map k a -> Bool
Map.member k
v forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. StateSCC a -> Map a Int
preorders)
    preorderId :: k -> StateT (StateSCC k) m (Maybe Int)
preorderId    k
v = forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets (forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup k
v forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. StateSCC a -> Map a Int
preorders)
    hasComponent :: k -> StateT (StateSCC k) m Bool
hasComponent  k
v = forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets (forall k a. Ord k => k -> Map k a -> Bool
Map.member k
v forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. StateSCC a -> Map a Int
components)

condense :: Ord a => AdjacencyMap a -> StateSCC a -> AdjacencyMap (NonEmpty.AdjacencyMap a)
condense :: forall a.
Ord a =>
AdjacencyMap a -> StateSCC a -> AdjacencyMap (AdjacencyMap a)
condense AdjacencyMap a
g (SCC Int
_ Int
n [(Int, a)]
_ [a]
_ Map a Int
_ Map a Int
assignment [AdjacencyMap a]
inner [(Int, (a, a))]
_ [(a, a)]
outer)
  | Int
n forall a. Eq a => a -> a -> Bool
== Int
1 = forall a. a -> AdjacencyMap a
vertex forall a b. (a -> b) -> a -> b
$ forall {a}. AdjacencyMap a -> AdjacencyMap a
convert AdjacencyMap a
g
  | Bool
otherwise = forall a b.
(Ord a, Ord b) =>
(a -> b) -> AdjacencyMap a -> AdjacencyMap b
gmap (\Int
c -> Array Int (AdjacencyMap a)
inner' forall i e. Ix i => Array i e -> i -> e
Array.! (Int
nforall a. Num a => a -> a -> a
-Int
1forall a. Num a => a -> a -> a
-Int
c)) AdjacencyMap Int
outer'
  where inner' :: Array Int (AdjacencyMap a)
inner' = forall i e. Ix i => (i, i) -> [e] -> Array i e
Array.listArray (Int
0,Int
nforall a. Num a => a -> a -> a
-Int
1) (forall {a}. AdjacencyMap a -> AdjacencyMap a
convert forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [AdjacencyMap a]
inner)
        outer' :: AdjacencyMap Int
outer' = AdjacencyMap Int
es forall a.
Ord a =>
AdjacencyMap a -> AdjacencyMap a -> AdjacencyMap a
`overlay` AdjacencyMap Int
vs
        vs :: AdjacencyMap Int
vs = forall a. Ord a => [a] -> AdjacencyMap a
vertices [Int
0..Int
nforall a. Num a => a -> a -> a
-Int
1]
        es :: AdjacencyMap Int
es = forall a. Ord a => [(a, a)] -> AdjacencyMap a
edges [ (a -> Int
sccid a
x, a -> Int
sccid a
y) | (a
x,a
y) <- [(a, a)]
outer ]
        sccid :: a -> Int
sccid a
v = Map a Int
assignment forall k a. Ord k => Map k a -> k -> a
Map.! a
v
        convert :: AdjacencyMap a -> AdjacencyMap a
convert = forall a. HasCallStack => Maybe a -> a
fromJust forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. AdjacencyMap a -> Maybe (AdjacencyMap a)
NonEmpty.toNonEmpty

-- | Check if a given forest is a correct /depth-first search/ forest of a graph.
-- The implementation is based on the paper "Depth-First Search and Strong
-- Connectivity in Coq" by François Pottier.
--
-- @
-- isDfsForestOf []                              'empty'            == True
-- isDfsForestOf []                              ('vertex' 1)       == False
-- isDfsForestOf [Node 1 []]                     ('vertex' 1)       == True
-- isDfsForestOf [Node 1 []]                     ('vertex' 2)       == False
-- isDfsForestOf [Node 1 [], Node 1 []]          ('vertex' 1)       == False
-- isDfsForestOf [Node 1 []]                     ('edge' 1 1)       == True
-- isDfsForestOf [Node 1 []]                     ('edge' 1 2)       == False
-- isDfsForestOf [Node 1 [], Node 2 []]          ('edge' 1 2)       == False
-- isDfsForestOf [Node 2 [], Node 1 []]          ('edge' 1 2)       == True
-- isDfsForestOf [Node 1 [Node 2 []]]            ('edge' 1 2)       == True
-- isDfsForestOf [Node 1 [], Node 2 []]          ('vertices' [1,2]) == True
-- isDfsForestOf [Node 2 [], Node 1 []]          ('vertices' [1,2]) == True
-- isDfsForestOf [Node 1 [Node 2 []]]            ('vertices' [1,2]) == False
-- isDfsForestOf [Node 1 [Node 2 [Node 3 []]]]   ('path' [1,2,3])   == True
-- isDfsForestOf [Node 1 [Node 3 [Node 2 []]]]   ('path' [1,2,3])   == False
-- isDfsForestOf [Node 3 [], Node 1 [Node 2 []]] ('path' [1,2,3])   == True
-- isDfsForestOf [Node 2 [Node 3 []], Node 1 []] ('path' [1,2,3])   == True
-- isDfsForestOf [Node 1 [], Node 2 [Node 3 []]] ('path' [1,2,3])   == False
-- @
isDfsForestOf :: Ord a => Forest a -> AdjacencyMap a -> Bool
isDfsForestOf :: forall a. Ord a => Forest a -> AdjacencyMap a -> Bool
isDfsForestOf Forest a
f AdjacencyMap a
am = case Set a -> Forest a -> Maybe (Set a)
go forall a. Set a
Set.empty Forest a
f of
    Just Set a
seen -> Set a
seen forall a. Eq a => a -> a -> Bool
== forall a. AdjacencyMap a -> Set a
vertexSet AdjacencyMap a
am
    Maybe (Set a)
Nothing   -> Bool
False
  where
    go :: Set a -> Forest a -> Maybe (Set a)
go Set a
seen []     = forall a. a -> Maybe a
Just Set a
seen
    go Set a
seen (Tree a
t:Forest a
ts) = do
        let root :: a
root = forall a. Tree a -> a
rootLabel Tree a
t
        forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ a
root forall a. Ord a => a -> Set a -> Bool
`Set.notMember` Set a
seen
        forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ forall a. Ord a => a -> a -> AdjacencyMap a -> Bool
hasEdge a
root (forall a. Tree a -> a
rootLabel Tree a
subTree) AdjacencyMap a
am | Tree a
subTree <- forall a. Tree a -> [Tree a]
subForest Tree a
t ]
        Set a
newSeen <- Set a -> Forest a -> Maybe (Set a)
go (forall a. Ord a => a -> Set a -> Set a
Set.insert a
root Set a
seen) (forall a. Tree a -> [Tree a]
subForest Tree a
t)
        forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ forall a. Ord a => a -> AdjacencyMap a -> Set a
postSet a
root AdjacencyMap a
am forall a. Ord a => Set a -> Set a -> Bool
`Set.isSubsetOf` Set a
newSeen
        Set a -> Forest a -> Maybe (Set a)
go Set a
newSeen Forest a
ts

-- | Check if a given list of vertices is a correct /topological sort/ of a graph.
--
-- @
-- isTopSortOf [3,1,2] (1 * 2 + 3 * 1) == True
-- isTopSortOf [1,2,3] (1 * 2 + 3 * 1) == False
-- isTopSortOf []      (1 * 2 + 3 * 1) == False
-- isTopSortOf []      'empty'           == True
-- isTopSortOf [x]     ('vertex' x)      == True
-- isTopSortOf [x]     ('edge' x x)      == False
-- @
isTopSortOf :: Ord a => [a] -> AdjacencyMap a -> Bool
isTopSortOf :: forall a. Ord a => [a] -> AdjacencyMap a -> Bool
isTopSortOf [a]
xs AdjacencyMap a
m = Set a -> [a] -> Bool
go forall a. Set a
Set.empty [a]
xs
  where
    go :: Set a -> [a] -> Bool
go Set a
seen []     = Set a
seen forall a. Eq a => a -> a -> Bool
== forall k a. Map k a -> Set k
Map.keysSet (forall a. AdjacencyMap a -> Map a (Set a)
adjacencyMap AdjacencyMap a
m)
    go Set a
seen (a
v:[a]
vs) = forall a. Ord a => a -> AdjacencyMap a -> Set a
postSet a
v AdjacencyMap a
m forall a. Ord a => Set a -> Set a -> Set a
`Set.intersection` Set a
newSeen forall a. Eq a => a -> a -> Bool
== forall a. Set a
Set.empty
                  Bool -> Bool -> Bool
&& Set a -> [a] -> Bool
go Set a
newSeen [a]
vs
      where
        newSeen :: Set a
newSeen = forall a. Ord a => a -> Set a -> Set a
Set.insert a
v Set a
seen