{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
module Data.Graph.AdjacencyList.BFS
(
BFS (..)
, bfs
, adjBFS
, spanningTree
) where
import Data.List
import Data.Tuple
import Data.Maybe
import qualified Data.IntMap as IM
import qualified Data.IntSet as Set
import Data.Graph.AdjacencyList
data BFS = BFS { BFS -> IntSet
frontier :: Set.IntSet
, BFS -> IntMap Int
level :: IM.IntMap Int
, BFS -> IntMap Int
parent :: IM.IntMap Vertex
, BFS -> Int
maxLevel :: Int
, BFS -> [Int]
topSort :: [Vertex]
} deriving (BFS -> BFS -> Bool
(BFS -> BFS -> Bool) -> (BFS -> BFS -> Bool) -> Eq BFS
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BFS -> BFS -> Bool
== :: BFS -> BFS -> Bool
$c/= :: BFS -> BFS -> Bool
/= :: BFS -> BFS -> Bool
Eq, Int -> BFS -> ShowS
[BFS] -> ShowS
BFS -> String
(Int -> BFS -> ShowS)
-> (BFS -> String) -> ([BFS] -> ShowS) -> Show BFS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BFS -> ShowS
showsPrec :: Int -> BFS -> ShowS
$cshow :: BFS -> String
show :: BFS -> String
$cshowList :: [BFS] -> ShowS
showList :: [BFS] -> ShowS
Show)
initialBFS :: Vertex -> BFS
initialBFS :: Int -> BFS
initialBFS Int
s = BFS { frontier :: IntSet
frontier = Int -> IntSet
Set.singleton Int
s
, level :: IntMap Int
level = [(Int, Int)] -> IntMap Int
forall a. [(Int, a)] -> IntMap a
IM.fromList [(Int
s,Int
0)]
, parent :: IntMap Int
parent= IntMap Int
forall a. IntMap a
IM.empty
, maxLevel :: Int
maxLevel = Int
0
, topSort :: [Int]
topSort = []
}
bfs :: Graph -> Vertex -> BFS
bfs :: Graph -> Int -> BFS
bfs Graph
g Int
s =
let vset :: IntSet
vset = [Int] -> IntSet
Set.fromList (Graph -> [Int]
vertices Graph
g)
sbfs :: BFS
sbfs = Int -> BFS
initialBFS Int
s
breadthFirstSearch :: BFS -> BFS
breadthFirstSearch BFS
b =
if IntSet -> Bool
Set.null (BFS -> IntSet
frontier BFS
b) Bool -> Bool -> Bool
|| Bool -> Bool
not (Int -> IntSet -> Bool
Set.member Int
s IntSet
vset)
then BFS
b { topSort = reverse (topSort b) }
else
let oldLevel :: Int
oldLevel = BFS -> Int
maxLevel BFS
b
newLevel :: Int
newLevel = Int
oldLevel Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
oldLevels :: IntMap Int
oldLevels = BFS -> IntMap Int
level BFS
b
oldFrontiers :: IntSet
oldFrontiers = BFS -> IntSet
frontier BFS
b
newParMap :: IntMap Int
newParMap = (IntMap Int -> Int -> IntMap Int)
-> IntMap Int -> IntSet -> IntMap Int
forall a. (a -> Int -> a) -> a -> IntSet -> a
Set.foldl'
(\IntMap Int
acc Int
v ->
(IntMap Int -> Int -> IntMap Int)
-> IntMap Int -> [Int] -> IntMap Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\IntMap Int
acc' Int
n ->
if Int -> IntMap Int -> Bool
forall a. Int -> IntMap a -> Bool
IM.member Int
n IntMap Int
oldLevels Bool -> Bool -> Bool
|| Int -> IntMap Int -> Bool
forall a. Int -> IntMap a -> Bool
IM.member Int
n IntMap Int
acc'
then IntMap Int
acc'
else Int -> Int -> IntMap Int -> IntMap Int
forall a. Int -> a -> IntMap a -> IntMap a
IM.insert Int
n Int
v IntMap Int
acc'
) IntMap Int
acc (Graph -> Neighbors
neighbors Graph
g Int
v)
) IntMap Int
forall a. IntMap a
IM.empty IntSet
oldFrontiers
newFrontiers :: IntSet
newFrontiers = IntMap Int -> IntSet
forall a. IntMap a -> IntSet
IM.keysSet IntMap Int
newParMap
newParents :: IntMap Int
newParents = IntMap Int -> IntMap Int -> IntMap Int
forall a. IntMap a -> IntMap a -> IntMap a
IM.union (BFS -> IntMap Int
parent BFS
b) IntMap Int
newParMap
newLevels :: IntMap Int
newLevels = (IntMap Int -> Int -> IntMap Int)
-> IntMap Int -> IntSet -> IntMap Int
forall a. (a -> Int -> a) -> a -> IntSet -> a
Set.foldl'
(\IntMap Int
ac Int
v -> Int -> Int -> IntMap Int -> IntMap Int
forall a. Int -> a -> IntMap a -> IntMap a
IM.insert Int
v Int
newLevel IntMap Int
ac)
IntMap Int
oldLevels IntSet
newFrontiers
newTopSort :: [Int]
newTopSort = ([Int] -> Neighbors) -> [Int] -> IntSet -> [Int]
forall a. (a -> Int -> a) -> a -> IntSet -> a
Set.foldl' ((Int -> [Int] -> [Int]) -> [Int] -> Neighbors
forall a b c. (a -> b -> c) -> b -> a -> c
flip (:)) (BFS -> [Int]
topSort BFS
b) IntSet
oldFrontiers
bbfs :: BFS
bbfs = BFS -> BFS
breadthFirstSearch (BFS
b { frontier = newFrontiers
, level = newLevels
, parent = newParents
, maxLevel = newLevel
, topSort = newTopSort
})
in BFS
bbfs
in BFS -> BFS
breadthFirstSearch BFS
sbfs
adjBFS :: IM.IntMap [Vertex] -> Vertex -> BFS
adjBFS :: IntMap [Int] -> Int -> BFS
adjBFS IntMap [Int]
neimap Int
s = let b :: BFS
b = BFS -> BFS
breadthFirstSearch BFS
sbfs
in BFS
b { topSort = reverse (topSort b) }
where neighbors :: Neighbors
neighbors Int
v = case Int -> IntMap [Int] -> Maybe [Int]
forall a. Int -> IntMap a -> Maybe a
IM.lookup Int
v IntMap [Int]
neimap of
Maybe [Int]
Nothing -> []
Just [Int]
ns -> [Int]
ns
sbfs :: BFS
sbfs = Int -> BFS
initialBFS Int
s
breadthFirstSearch :: BFS -> BFS
breadthFirstSearch BFS
b
| IntSet -> Bool
Set.null (BFS -> IntSet
frontier BFS
b) = BFS
b
| Bool
otherwise = BFS
bbfs
where oldLevel :: Int
oldLevel = BFS -> Int
maxLevel BFS
b
newLevel :: Int
newLevel = Int
oldLevel Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
oldLevels :: IntMap Int
oldLevels = BFS -> IntMap Int
level BFS
b
oldFrontiers :: IntSet
oldFrontiers = BFS -> IntSet
frontier BFS
b
newParMap :: IntMap Int
newParMap = (IntMap Int -> Int -> IntMap Int)
-> IntMap Int -> IntSet -> IntMap Int
forall a. (a -> Int -> a) -> a -> IntSet -> a
Set.foldl'
(\IntMap Int
acc Int
v ->
(IntMap Int -> Int -> IntMap Int)
-> IntMap Int -> [Int] -> IntMap Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\IntMap Int
acc' Int
n ->
if Int -> IntMap Int -> Bool
forall a. Int -> IntMap a -> Bool
IM.member Int
n IntMap Int
oldLevels Bool -> Bool -> Bool
|| Int -> IntMap Int -> Bool
forall a. Int -> IntMap a -> Bool
IM.member Int
n IntMap Int
acc'
then IntMap Int
acc'
else Int -> Int -> IntMap Int -> IntMap Int
forall a. Int -> a -> IntMap a -> IntMap a
IM.insert Int
n Int
v IntMap Int
acc'
) IntMap Int
acc (Neighbors
neighbors Int
v)
) IntMap Int
forall a. IntMap a
IM.empty IntSet
oldFrontiers
newFrontiers :: IntSet
newFrontiers = IntMap Int -> IntSet
forall a. IntMap a -> IntSet
IM.keysSet IntMap Int
newParMap
newParents :: IntMap Int
newParents = IntMap Int -> IntMap Int -> IntMap Int
forall a. IntMap a -> IntMap a -> IntMap a
IM.union (BFS -> IntMap Int
parent BFS
b) IntMap Int
newParMap
newLevels :: IntMap Int
newLevels = (IntMap Int -> Int -> IntMap Int)
-> IntMap Int -> IntSet -> IntMap Int
forall a. (a -> Int -> a) -> a -> IntSet -> a
Set.foldl'
(\IntMap Int
ac Int
v -> Int -> Int -> IntMap Int -> IntMap Int
forall a. Int -> a -> IntMap a -> IntMap a
IM.insert Int
v Int
newLevel IntMap Int
ac)
IntMap Int
oldLevels IntSet
newFrontiers
newTopSort :: [Int]
newTopSort = ([Int] -> Neighbors) -> [Int] -> IntSet -> [Int]
forall a. (a -> Int -> a) -> a -> IntSet -> a
Set.foldl' ((Int -> [Int] -> [Int]) -> [Int] -> Neighbors
forall a b c. (a -> b -> c) -> b -> a -> c
flip (:)) (BFS -> [Int]
topSort BFS
b) IntSet
oldFrontiers
bbfs :: BFS
bbfs = BFS -> BFS
breadthFirstSearch (BFS
b { frontier = newFrontiers
, level = newLevels
, parent = newParents
, maxLevel = newLevel
, topSort = newTopSort
})
spanningTree :: BFS -> [Edge]
spanningTree :: BFS -> [Edge]
spanningTree BFS
b =
((Int, Int) -> Edge) -> [(Int, Int)] -> [Edge]
forall a b. (a -> b) -> [a] -> [b]
map ((Int, Int) -> Edge
fromTuple ((Int, Int) -> Edge)
-> ((Int, Int) -> (Int, Int)) -> (Int, Int) -> Edge
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int) -> (Int, Int)
forall a b. (a, b) -> (b, a)
swap) ([(Int, Int)] -> [Edge]) -> [(Int, Int)] -> [Edge]
forall a b. (a -> b) -> a -> b
$ IntMap Int -> [(Int, Int)]
forall a. IntMap a -> [(Int, a)]
IM.toList (IntMap Int -> [(Int, Int)]) -> IntMap Int -> [(Int, Int)]
forall a b. (a -> b) -> a -> b
$ BFS -> IntMap Int
parent BFS
b