{-# LANGUAGE TypeFamilies, PatternGuards, RankNTypes #-}
module Data.Graph.Haggle.Internal.Adapter (
LabeledMGraph(..),
LabeledGraph(..),
newLabeledGraph,
newSizedLabeledGraph,
mapVertexLabel,
mapEdgeLabel,
fromLabeledEdgeList,
ensureEdgeLabelStorage,
ensureNodeLabelStorage,
unsafeGetEdgeLabel
) where
import qualified Control.DeepSeq as DS
import Control.Monad ( liftM )
import qualified Control.Monad.Primitive as P
import qualified Control.Monad.Ref as R
import Control.Monad.ST ( ST, runST )
import Data.Vector ( Vector )
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
import qualified Data.Graph.Haggle.Classes as I
import qualified Data.Graph.Haggle.VertexMap as VM
import qualified Data.Graph.Haggle.Internal.Basic as I
data LabeledMGraph g nl el m =
LMG { rawMGraph :: g m
, nodeLabelStorage :: R.Ref m (MV.MVector (P.PrimState m) nl)
, edgeLabelStorage :: R.Ref m (MV.MVector (P.PrimState m) el)
}
data LabeledGraph g nl el =
LG { rawGraph :: g
, nodeLabelStore :: Vector nl
, edgeLabelStore :: Vector el
}
instance (DS.NFData g, DS.NFData nl, DS.NFData el) => DS.NFData (LabeledGraph g nl el) where
rnf gr = rawGraph gr `DS.deepseq` nodeLabelStore gr `DS.deepseq` edgeLabelStore gr `DS.deepseq` ()
newLabeledGraph :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> m (g m)
-> m (LabeledMGraph g nl el m)
newLabeledGraph newG = do
g <- newG
nstore <- MV.new 128
nref <- R.newRef nstore
estore <- MV.new 128
eref <- R.newRef estore
return LMG { rawMGraph = g
, nodeLabelStorage = nref
, edgeLabelStorage = eref
}
newSizedLabeledGraph :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> (Int -> Int -> m (g m))
-> Int
-> Int
-> m (LabeledMGraph g nl el m)
newSizedLabeledGraph newG szVertices szEdges = do
g <- newG szVertices szEdges
nstore <- MV.new szVertices
nref <- R.newRef nstore
estore <- MV.new szEdges
eref <- R.newRef estore
return LMG { rawMGraph = g
, nodeLabelStorage = nref
, edgeLabelStorage = eref
}
addLabeledVertex :: (I.MGraph g, I.MAddVertex g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m
-> nl
-> m I.Vertex
addLabeledVertex lg nl = do
v <- I.addVertex (rawMGraph lg)
ensureNodeLabelStorage lg
nlVec <- R.readRef (nodeLabelStorage lg)
MV.write nlVec (I.vertexId v) nl
return v
unsafeGetEdgeLabel :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m
-> I.Edge
-> m el
unsafeGetEdgeLabel (LMG _ _ stor) (I.E eid _ _) = do
elVec <- R.readRef stor
MV.unsafeRead elVec eid
{-# INLINE unsafeGetEdgeLabel #-}
getVertexLabel :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m
-> I.Vertex
-> m (Maybe nl)
getVertexLabel lg v = do
nNs <- I.countVertices (rawMGraph lg)
case I.vertexId v >= nNs of
True -> return Nothing
False -> do
nlVec <- R.readRef (nodeLabelStorage lg)
Just `liftM` MV.read nlVec (I.vertexId v)
addLabeledEdge :: (I.MGraph g, I.MAddEdge g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m
-> I.Vertex
-> I.Vertex
-> el
-> m (Maybe I.Edge)
addLabeledEdge lg src dst el = do
e <- I.addEdge (rawMGraph lg) src dst
case e of
Nothing -> return e
Just e' -> do
ensureEdgeLabelStorage lg
elVec <- R.readRef (edgeLabelStorage lg)
MV.write elVec (I.edgeId e') el
return e
getSuccessors :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m
-> I.Vertex
-> m [I.Vertex]
getSuccessors lg = I.getSuccessors (rawMGraph lg)
{-# INLINE getSuccessors #-}
getOutEdges :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m -> I.Vertex -> m [I.Edge]
getOutEdges lg = I.getOutEdges (rawMGraph lg)
{-# INLINE getOutEdges #-}
countVertices :: (I.MGraph g, P.PrimMonad m, R.MonadRef m) => LabeledMGraph g nl el m -> m Int
countVertices = I.countVertices . rawMGraph
{-# INLINE countVertices #-}
countEdges :: (I.MGraph g, P.PrimMonad m, R.MonadRef m) => LabeledMGraph g nl el m -> m Int
countEdges = I.countEdges . rawMGraph
{-# INLINE countEdges #-}
getVertices :: (I.MGraph g, P.PrimMonad m, R.MonadRef m) => LabeledMGraph g nl el m -> m [I.Vertex]
getVertices = I.getVertices . rawMGraph
{-# INLINE getVertices #-}
getPredecessors :: (I.MBidirectional g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m -> I.Vertex -> m [I.Vertex]
getPredecessors lg = I.getPredecessors (rawMGraph lg)
{-# INLINE getPredecessors #-}
getInEdges :: (I.MBidirectional g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m -> I.Vertex -> m [I.Edge]
getInEdges lg = I.getInEdges (rawMGraph lg)
{-# INLINE getInEdges #-}
checkEdgeExists :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m
-> I.Vertex
-> I.Vertex
-> m Bool
checkEdgeExists lg = I.checkEdgeExists (rawMGraph lg)
{-# INLINE checkEdgeExists #-}
freeze :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m
-> m (LabeledGraph (I.ImmutableGraph g) nl el)
freeze lg = do
g' <- I.freeze (rawMGraph lg)
nc <- I.countVertices (rawMGraph lg)
ec <- I.countEdges (rawMGraph lg)
ns <- R.readRef (nodeLabelStorage lg)
es <- R.readRef (edgeLabelStorage lg)
ns' <- V.freeze (MV.take nc ns)
es' <- V.freeze (MV.take ec es)
return LG { rawGraph = g'
, nodeLabelStore = ns'
, edgeLabelStore = es'
}
instance (I.MGraph g) => I.MGraph (LabeledMGraph g nl el) where
type ImmutableGraph (LabeledMGraph g nl el) = LabeledGraph (I.ImmutableGraph g) nl el
getVertices = getVertices
getSuccessors = getSuccessors
getOutEdges = getOutEdges
countEdges = countEdges
countVertices = countVertices
checkEdgeExists = checkEdgeExists
freeze = freeze
instance (I.MBidirectional g) => I.MBidirectional (LabeledMGraph g nl el) where
getPredecessors = getPredecessors
getInEdges = getInEdges
instance (I.MAddEdge g) => I.MLabeledEdge (LabeledMGraph g nl el) where
type MEdgeLabel (LabeledMGraph g nl el) = el
unsafeGetEdgeLabel = unsafeGetEdgeLabel
addLabeledEdge = addLabeledEdge
instance (I.MAddVertex g) => I.MLabeledVertex (LabeledMGraph g nl el) where
type MVertexLabel (LabeledMGraph g nl el) = nl
getVertexLabel = getVertexLabel
addLabeledVertex = addLabeledVertex
vertices :: (I.Graph g) => LabeledGraph g nl el -> [I.Vertex]
vertices = I.vertices . rawGraph
{-# INLINE vertices #-}
edges :: (I.Graph g) => LabeledGraph g nl el -> [I.Edge]
edges = I.edges . rawGraph
{-# INLINE edges #-}
successors :: (I.Graph g) => LabeledGraph g nl el -> I.Vertex -> [I.Vertex]
successors lg = I.successors (rawGraph lg)
{-# INLINE successors #-}
outEdges :: (I.Graph g) => LabeledGraph g nl el -> I.Vertex -> [I.Edge]
outEdges lg = I.outEdges (rawGraph lg)
{-# INLINE outEdges #-}
edgesBetween :: (I.Graph g) => LabeledGraph g nl el -> I.Vertex -> I.Vertex -> [I.Edge]
edgesBetween lg = I.edgesBetween (rawGraph lg)
{-# INLINE edgesBetween #-}
maxVertexId :: (I.Graph g) => LabeledGraph g nl el -> Int
maxVertexId = I.maxVertexId . rawGraph
{-# INLINE maxVertexId #-}
isEmpty :: (I.Graph g) => LabeledGraph g nl el -> Bool
isEmpty = I.isEmpty . rawGraph
{-# INLINE isEmpty #-}
thaw :: (I.Thawable g, P.PrimMonad m, R.MonadRef m)
=> LabeledGraph g nl el
-> m (LabeledMGraph (I.MutableGraph g) nl el m)
thaw lg = do
g' <- I.thaw (rawGraph lg)
nlVec <- V.thaw (nodeLabelStore lg)
elVec <- V.thaw (edgeLabelStore lg)
nref <- R.newRef nlVec
eref <- R.newRef elVec
return LMG { rawMGraph = g'
, nodeLabelStorage = nref
, edgeLabelStorage = eref
}
instance (I.Thawable g) => I.Thawable (LabeledGraph g nl el) where
type MutableGraph (LabeledGraph g nl el) = LabeledMGraph (I.MutableGraph g) nl el
thaw = thaw
instance (I.Graph g) => I.Graph (LabeledGraph g nl el) where
vertices = vertices
edges = edges
successors = successors
outEdges = outEdges
edgesBetween = edgesBetween
maxVertexId = maxVertexId
isEmpty = isEmpty
predecessors :: (I.Bidirectional g) => LabeledGraph g nl el -> I.Vertex -> [I.Vertex]
predecessors lg = I.predecessors (rawGraph lg)
{-# INLINE predecessors #-}
inEdges :: (I.Bidirectional g) => LabeledGraph g nl el -> I.Vertex -> [I.Edge]
inEdges lg = I.inEdges (rawGraph lg)
{-# INLINE inEdges #-}
instance (I.Bidirectional g) => I.Bidirectional (LabeledGraph g nl el) where
predecessors = predecessors
inEdges = inEdges
instance (I.Bidirectional g) => I.BidirectionalEdgeLabel (LabeledGraph g nl el)
edgeLabel :: LabeledGraph g nl el -> I.Edge -> Maybe el
edgeLabel lg e = edgeLabelStore lg V.!? I.edgeId e
{-# INLINE edgeLabel #-}
instance (I.Graph g) => I.HasEdgeLabel (LabeledGraph g nl el) where
type EdgeLabel (LabeledGraph g nl el) = el
edgeLabel = edgeLabel
labeledEdges = labeledEdges
vertexLabel :: LabeledGraph g nl el -> I.Vertex -> Maybe nl
vertexLabel lg v = nodeLabelStore lg V.!? I.vertexId v
{-# INLINE vertexLabel #-}
instance (I.Graph g) => I.HasVertexLabel (LabeledGraph g nl el) where
type VertexLabel (LabeledGraph g nl el) = nl
vertexLabel = vertexLabel
labeledVertices = labeledVertices
labeledVertices :: (I.Graph g) => LabeledGraph g nl el -> [(I.Vertex, nl)]
labeledVertices g = map toLabVert $ I.vertices (rawGraph g)
where
toLabVert v =
let Just lab = vertexLabel g v
in (v, lab)
labeledEdges :: (I.Graph g) => LabeledGraph g nl el -> [(I.Edge, el)]
labeledEdges g = map toLabEdge $ I.edges (rawGraph g)
where
toLabEdge e =
let Just lab = edgeLabel g e
in (e, lab)
mapEdgeLabel :: LabeledGraph g nl el -> (el -> el') -> LabeledGraph g nl el'
mapEdgeLabel g f = g { edgeLabelStore = V.map f (edgeLabelStore g) }
mapVertexLabel :: LabeledGraph g nl el -> (nl -> nl') -> LabeledGraph g nl' el
mapVertexLabel g f = g { nodeLabelStore = V.map f (nodeLabelStore g) }
fromLabeledEdgeList :: (Ord nl, I.MGraph g, I.MAddVertex g, I.MAddEdge g)
=> (forall s . ST s (g (ST s)))
-> [(nl, nl, el)]
-> (LabeledGraph (I.ImmutableGraph g) nl el, VM.VertexMap nl)
fromLabeledEdgeList con es = runST $ do
g <- newLabeledGraph con
vm <- VM.newVertexMapRef
mapM_ (fromListAddEdge g vm) es
g' <- I.freeze g
vm' <- VM.vertexMapFromRef vm
return (g', vm')
fromListAddEdge :: (I.MAddVertex g, I.MAddEdge g, Ord nl, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m
-> VM.VertexMapRef nl m
-> (nl, nl, el)
-> m ()
fromListAddEdge g vm (src, dst, lbl) = do
vsrc <- VM.vertexForLabelRef g vm src
vdst <- VM.vertexForLabelRef g vm dst
_ <- addLabeledEdge g vsrc vdst lbl
return ()
ensureEdgeLabelStorage :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m -> m ()
ensureEdgeLabelStorage lg = do
elVec <- R.readRef (edgeLabelStorage lg)
edgeCount <- I.countEdges (rawMGraph lg)
let cap = MV.length elVec
case cap > edgeCount of
True -> return ()
False -> do
elVec' <- MV.grow elVec cap
R.writeRef (edgeLabelStorage lg) elVec'
ensureNodeLabelStorage :: (I.MGraph g, P.PrimMonad m, R.MonadRef m)
=> LabeledMGraph g nl el m -> m ()
ensureNodeLabelStorage lg = do
nlVec <- R.readRef (nodeLabelStorage lg)
vertCount <- I.countVertices (rawMGraph lg)
let cap = MV.length nlVec
case cap > vertCount of
True -> return ()
False -> do
nlVec' <- MV.grow nlVec cap
R.writeRef (nodeLabelStorage lg) nlVec'