|
| 1 | +{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-} |
| 2 | + |
| 3 | +-- (c) 2002 by Martin Erwig [see file COPYRIGHT] |
| 4 | +-- | Static IOArray-based Graphs |
| 5 | +module Data.Graph.Inductive.Monad.STArray( |
| 6 | + -- * Graph Representation |
| 7 | + SGr(..), GraphRep, Context', USGr, |
| 8 | + defaultGraphSize, emptyN, |
| 9 | + -- * Utilities |
| 10 | + removeDel, |
| 11 | +) where |
| 12 | + |
| 13 | +import Data.Graph.Inductive.Graph |
| 14 | +import Data.Graph.Inductive.Monad |
| 15 | + |
| 16 | +import Control.Monad |
| 17 | +import Control.Monad.ST |
| 18 | +import Data.Array |
| 19 | +import Data.Array.ST |
| 20 | +import System.IO.Unsafe |
| 21 | + |
| 22 | + |
| 23 | + |
| 24 | +---------------------------------------------------------------------- |
| 25 | +-- GRAPH REPRESENTATION |
| 26 | +---------------------------------------------------------------------- |
| 27 | + |
| 28 | +newtype SGr s a b = SGr (GraphRep s a b) |
| 29 | + |
| 30 | +type GraphRep s a b = (Int,Array Node (Context' a b),STArray s Node Bool) |
| 31 | +type Context' a b = Maybe (Adj b,a,Adj b) |
| 32 | + |
| 33 | +type USGr s = SGr s () () |
| 34 | + |
| 35 | + |
| 36 | +---------------------------------------------------------------------- |
| 37 | +-- CLASS INSTANCES |
| 38 | +---------------------------------------------------------------------- |
| 39 | + |
| 40 | +-- Show |
| 41 | +-- |
| 42 | +showGraph :: (Show a,Show b) => GraphRep RealWorld a b -> String |
| 43 | +showGraph (_,a,m) = concatMap showAdj (indices a) |
| 44 | + where showAdj v | unsafeST (readArray m v) = "" |
| 45 | + | otherwise = case a!v of |
| 46 | + Nothing -> "" |
| 47 | + Just (_,l,s) -> '\n':show v++":"++show l++"->"++show s' |
| 48 | + where s' = unsafeST (removeDel m s) |
| 49 | + |
| 50 | +unsafeST :: ST RealWorld a -> a |
| 51 | +unsafeST = unsafePerformIO . stToIO |
| 52 | + |
| 53 | +instance (Show a,Show b) => Show (SGr RealWorld a b) where |
| 54 | + show (SGr g) = showGraph g |
| 55 | + |
| 56 | +instance (Show a,Show b) => Show (ST RealWorld (SGr RealWorld a b)) where |
| 57 | + show g = unsafeST (do {(SGr g') <- g; return (showGraph g')}) |
| 58 | + |
| 59 | +{- |
| 60 | +run :: Show (IO a) => IO a -> IO () |
| 61 | +run x = seq x (print x) |
| 62 | +-} |
| 63 | + |
| 64 | +-- GraphM |
| 65 | +-- |
| 66 | +instance GraphM (ST s) (SGr s) where |
| 67 | + emptyM = emptyN defaultGraphSize |
| 68 | + isEmptyM g = do {SGr (n,_,_) <- g; return (n==0)} |
| 69 | + matchM v g = do g'@(SGr (n,a,m)) <- g |
| 70 | + case a!v of |
| 71 | + Nothing -> return (Nothing,g') |
| 72 | + Just (pr,l,su) -> |
| 73 | + do b <- readArray m v |
| 74 | + if b then return (Nothing,g') else |
| 75 | + do s <- removeDel m su |
| 76 | + p' <- removeDel m pr |
| 77 | + let p = filter ((/=v).snd) p' |
| 78 | + writeArray m v True |
| 79 | + return (Just (p,v,l,s),SGr (n-1,a,m)) |
| 80 | + mkGraphM vs es = do m <- newArray (1,n) False |
| 81 | + return (SGr (n,pr,m)) |
| 82 | + where nod = array bnds (map (\(v,l)->(v,Just ([],l,[]))) vs) |
| 83 | + su = accum addSuc nod (map (\(v,w,l)->(v,(l,w))) es) |
| 84 | + pr = accum addPre su (map (\(v,w,l)->(w,(l,v))) es) |
| 85 | + bnds = (minimum vs',maximum vs') |
| 86 | + vs' = map fst vs |
| 87 | + n = length vs |
| 88 | + addSuc (Just (p,l',s)) (l,w) = Just (p,l',(l,w):s) |
| 89 | + addSuc Nothing _ = error "mkGraphM (SGr): addSuc Nothing" |
| 90 | + addPre (Just (p,l',s)) (l,w) = Just ((l,w):p,l',s) |
| 91 | + addPre Nothing _ = error "mkGraphM (SGr): addPre Nothing" |
| 92 | + labNodesM g = do (SGr (_,a,m)) <- g |
| 93 | + let getLNode vs (_,Nothing) = return vs |
| 94 | + getLNode vs (v,Just (_,l,_)) = |
| 95 | + do b <- readArray m v |
| 96 | + return (if b then vs else (v,l):vs) |
| 97 | + foldM getLNode [] (assocs a) |
| 98 | + |
| 99 | +defaultGraphSize :: Int |
| 100 | +defaultGraphSize = 100 |
| 101 | + |
| 102 | +emptyN :: Int -> ST s (SGr s a b) |
| 103 | +emptyN n = do m <- newArray (1,n) False |
| 104 | + return (SGr (0,array (1,n) [(i,Nothing) | i <- [1..n]],m)) |
| 105 | + |
| 106 | +---------------------------------------------------------------------- |
| 107 | +-- UTILITIES |
| 108 | +---------------------------------------------------------------------- |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | +-- | filter list (of successors\/predecessors) through a boolean ST array |
| 113 | +-- representing deleted marks |
| 114 | +removeDel :: STArray s Node Bool -> Adj b -> ST s (Adj b) |
| 115 | +removeDel m = filterM (\(_,v)->do {b<-readArray m v;return (not b)}) |
0 commit comments