hoogle-4.0: src/Data/Binary/Defer/Graph.hs
module Data.Binary.Defer.Graph(
Graph, GraphNode, showGraphWith,
searchDijkstraState, searchDijkstraCycle,
Graph_(..), newGraph_,
graphFreeze, graphFollow
) where
import Data.Binary.Defer
import Data.Binary.Defer.Array
import Data.List
import General.Code
import qualified Data.Heap as Heap
import qualified Data.Map as Map
import qualified Data.Set as Set
---------------------------------------------------------------------
-- GRAPH
data Graph n e = Graph (Array (Node n e))
data Node n e = Node {nodeResults :: [n], nodeEdges :: [(e, GraphNode)]}
type GraphNode = Int
showGraphWith :: (Show n, Show e) => (GraphNode -> String) -> Graph n e -> String
showGraphWith showNode (Graph xs) = unlines $ concat $ zipWith f [0..] $ elems xs
where
f i (Node res es) = showNode i : map (" "++) (r : map g es)
where r = if null res then "No results" else unwords (map show res)
g (e,n) = showNode n ++ " ==> " ++ show e
instance (Show n, Show e) => Show (Graph n e) where
show = showGraphWith (\x -> '#':show x)
instance (BinaryDefer n, BinaryDefer e) => BinaryDefer (Graph n e) where
put (Graph a) = put1 a
get = get1 Graph
instance (BinaryDefer n, BinaryDefer e) => BinaryDefer (Node n e) where
put (Node a b) = put2 a b
get = get2 Node
-- Given an initial (cost,state), and how to transform a (cost,state) along an edge
-- return the (cost,state,node) pairs with the invariants that:
-- Items are returned sorted by c
-- No (_,s,n) pair is returned twice
searchDijkstraState :: (Ord c, Ord s) =>
(c,s) -> (e -> (c,s) -> (c,s)) ->
GraphNode -> Graph n e -> [(c,s,n)]
searchDijkstraState (c,s) gen n (Graph xs) = f Set.empty (Heap.singleton c (s,n))
where
f seen next = case Heap.pop next of
Nothing -> []
Just ((c,(s,n)),next)
| (s,n) `Set.member` seen -> f seen next
| otherwise -> [(c,s,n) | n <- ns] ++ f seen2 next2
where Node ns es = xs ! n
seen2 = Set.insert (s,n) seen
next2 = Heap.insertList [(c2,(s2,n)) | (e,n) <- es, let (c2,s2) = gen e (c,s)] next
-- Invariant: No node is reached going through that node
searchDijkstraCycle :: Ord c =>
c -> (e -> c -> Maybe c) ->
GraphNode -> Graph n e -> [(c,n)]
searchDijkstraCycle c gen n (Graph xs) = f (Heap.singleton c (Set.singleton n,n))
where
f next = case Heap.pop next of
Nothing -> []
Just ((c,(s,n)),next) -> [(c,n) | n <- ns] ++ f (Heap.insertList new next)
where Node ns es = xs ! n
new = [ (c2, (Set.insert n s,n))
| (e,n) <- es, not $ n `Set.member` s
, Just c2 <- [gen e c]]
---------------------------------------------------------------------
-- MUTABLE GRAPH
data Graph_ k n e = Graph_ {graphResults :: [(k,n)], graphEdges :: [(k,k,e)]}
deriving Show
newGraph_ :: Graph_ k n e
newGraph_ = Graph_ [] []
graphKeys :: Graph_ k n e -> [k]
graphKeys (Graph_ res es) = map fst res ++ concatMap (\(a,b,c) -> [a,b]) es
-- follow a node, if you create a new node, keep following
graphFollow :: Ord k => (k -> [(k,e)]) -> Graph_ k n e -> Graph_ k n e
graphFollow next g = g{graphEdges = graphEdges g ++ f Set.empty (graphKeys g)}
where
f seen [] = []
f seen (t:odo)
| t `Set.member` seen = f seen odo
| otherwise =
[(t,k,e) | (k,e) <- nxt] ++ f (Set.insert t seen) (map fst nxt ++ odo)
where nxt = next t
graphFreeze :: Ord k => Graph_ k n e -> (Graph n e, Map.Map k GraphNode)
graphFreeze (Graph_ res es) = (g, r)
where
g = Graph $ array $ map snd $ sortFst $ Map.elems mp
r = Map.map fst mp
mp = foldl' addEdge (foldl' addNode Map.empty (reverse res)) (reverse es)
-- mp :: Map (key, (GraphNode, Node n e))
addNode mp (k1,n) = Map.insertWith f k1 new mp
where
new = (Map.size mp, Node [n] [])
f new (i, Node ns es) = (i, Node (n:ns) es)
addEdge mp (k1,k2,e) = Map.insertWith f k1 new mp3
where
-- ensureKey k1 is important, even though ki1 is not needed
-- otherwise k1 may not make it into the map
(mp2,ki1) = ensureKey k1 mp
(mp3,ki2) = ensureKey k2 mp2
new = (Map.size mp, Node [] [(e, ki2)])
f new (i, Node ns es) = (i, Node ns ((e,ki2):es))
ensureKey k mp = case Map.lookup k mp of
Just (y,_) -> (mp, y)
Nothing -> (Map.insert k (n, Node [] []) mp, n)
where n = Map.size mp