Commit 52bc2f5f authored by Kai Zhang's avatar Kai Zhang

v0.4.0

parent f67af377
Revision history for haskell-igraph
===================================
v0.4.0 -- 2018-04-20
-------------------
* A new attribute interface written in C. The graph attributes are now directly serialized into bytestring using "cereal" (before we used the `Show` instance).
name: haskell-igraph name: haskell-igraph
version: 0.4.0-dev version: 0.4.0
synopsis: Imcomplete igraph bindings synopsis: Haskell interface of the igraph library.
description: This is an attempt to create a complete bindings for the description: igraph<"http://igraph.org/c/"> is a library for creating
igraph<"http://igraph.org/c/"> library. and manipulating large graphs. This package provides the Haskell
interface of igraph.
license: MIT license: MIT
license-file: LICENSE license-file: LICENSE
author: Kai Zhang author: Kai Zhang
...@@ -12,9 +13,11 @@ category: Math ...@@ -12,9 +13,11 @@ category: Math
build-type: Simple build-type: Simple
cabal-version: >=1.24 cabal-version: >=1.24
extra-source-files: extra-source-files:
cbits/haskell_igraph.h include/haskell_igraph.h
cbits/bytestring.h include/bytestring.h
cbits/haskell_attributes.h include/haskell_attributes.h
README.md
ChangeLog.md
Flag graphics Flag graphics
Description: Enable graphics output Description: Enable graphics output
...@@ -22,8 +25,19 @@ Flag graphics ...@@ -22,8 +25,19 @@ Flag graphics
library library
exposed-modules: exposed-modules:
IGraph
IGraph.Types
IGraph.Mutable
IGraph.Clique
IGraph.Structure
IGraph.Isomorphism
IGraph.Community
IGraph.Read
IGraph.Motif
IGraph.Layout
IGraph.Generators
IGraph.Exporter.GEXF
IGraph.Internal.Initialization IGraph.Internal.Initialization
IGraph.Internal.C2HS
IGraph.Internal.Constants IGraph.Internal.Constants
IGraph.Internal.Arpack IGraph.Internal.Arpack
IGraph.Internal.Data IGraph.Internal.Data
...@@ -36,18 +50,9 @@ library ...@@ -36,18 +50,9 @@ library
IGraph.Internal.Clique IGraph.Internal.Clique
IGraph.Internal.Community IGraph.Internal.Community
IGraph.Internal.Layout IGraph.Internal.Layout
IGraph
IGraph.Types other-modules:
IGraph.Mutable IGraph.Internal.C2HS
IGraph.Clique
IGraph.Structure
IGraph.Isomorphism
IGraph.Community
IGraph.Read
IGraph.Motif
IGraph.Layout
IGraph.Generators
IGraph.Exporter.GEXF
if flag(graphics) if flag(graphics)
exposed-modules: IGraph.Exporter.Graphics exposed-modules: IGraph.Exporter.Graphics
...@@ -78,7 +83,7 @@ library ...@@ -78,7 +83,7 @@ library
cbits/haskell_igraph.c cbits/haskell_igraph.c
cbits/haskell_attributes.c cbits/haskell_attributes.c
cbits/bytestring.c cbits/bytestring.c
include-dirs: cbits include-dirs: include
test-suite tests test-suite tests
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
......
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiParamTypeClasses #-}
module IGraph module IGraph
( LGraph(..) ( Graph(..)
, LGraph(..)
, U(..) , U(..)
, D(..) , D(..)
, Graph(..)
, decodeC , decodeC
, empty , empty
, mkGraph , mkGraph
...@@ -37,7 +37,6 @@ import Control.Monad.Primitive ...@@ -37,7 +37,6 @@ import Control.Monad.Primitive
import Control.Monad.ST (runST) import Control.Monad.ST (runST)
import qualified Data.ByteString as B import qualified Data.ByteString as B
import Data.Conduit.Cereal import Data.Conduit.Cereal
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import qualified Data.HashMap.Strict as M import qualified Data.HashMap.Strict as M
import qualified Data.HashSet as S import qualified Data.HashSet as S
...@@ -45,7 +44,7 @@ import Data.List (sortBy) ...@@ -45,7 +44,7 @@ import Data.List (sortBy)
import Data.Maybe import Data.Maybe
import Data.Ord (comparing) import Data.Ord (comparing)
import Data.Serialize import Data.Serialize
import Foreign (with, castPtr) import Foreign (castPtr, with)
import System.IO.Unsafe (unsafePerformIO) import System.IO.Unsafe (unsafePerformIO)
import IGraph.Internal.Attribute import IGraph.Internal.Attribute
...@@ -57,68 +56,63 @@ import IGraph.Mutable ...@@ -57,68 +56,63 @@ import IGraph.Mutable
import IGraph.Types import IGraph.Types
class MGraph d => Graph d where class MGraph d => Graph d where
-- | Graph is directed or not.
isDirected :: LGraph d v e -> Bool isDirected :: LGraph d v e -> Bool
isD :: d -> Bool isD :: d -> Bool
-- | Return the number of nodes in a graph.
nNodes :: LGraph d v e -> Int nNodes :: LGraph d v e -> Int
nNodes (LGraph g _) = unsafePerformIO $ igraphVcount g nNodes (LGraph g _) = unsafePerformIO $ igraphVcount g
{-# INLINE nNodes #-} {-# INLINE nNodes #-}
nodes :: LGraph d v e -> [Int] -- | Return all nodes. @nodes gr == [0 .. nNodes gr - 1]@.
nodes :: LGraph d v e -> [Node]
nodes gr = [0 .. nNodes gr - 1] nodes gr = [0 .. nNodes gr - 1]
{-# INLINE nodes #-} {-# INLINE nodes #-}
-- | Return the number of edges in a graph.
nEdges :: LGraph d v e -> Int nEdges :: LGraph d v e -> Int
nEdges (LGraph g _) = unsafePerformIO $ igraphEcount g nEdges (LGraph g _) = unsafePerformIO $ igraphEcount g
{-# INLINE nEdges #-} {-# INLINE nEdges #-}
-- | Return all edges.
edges :: LGraph d v e -> [Edge] edges :: LGraph d v e -> [Edge]
edges gr@(LGraph g _) = unsafePerformIO $ mapM (igraphEdge g) [0..n-1] edges gr@(LGraph g _) = unsafePerformIO $ mapM (igraphEdge g) [0..n-1]
where where
n = nEdges gr n = nEdges gr
{-# INLINE edges #-} {-# INLINE edges #-}
-- | Whether a edge exists in the graph.
hasEdge :: LGraph d v e -> Edge -> Bool hasEdge :: LGraph d v e -> Edge -> Bool
hasEdge (LGraph g _) (fr, to) = unsafePerformIO $ do hasEdge (LGraph g _) (fr, to) = unsafePerformIO $ do
i <- igraphGetEid g fr to True False i <- igraphGetEid g fr to True False
return $ i >= 0 return $ i >= 0
{-# INLINE hasEdge #-} {-# INLINE hasEdge #-}
-- | Return the label of given node.
nodeLab :: Serialize v => LGraph d v e -> Node -> v nodeLab :: Serialize v => LGraph d v e -> Node -> v
nodeLab (LGraph g _) i = unsafePerformIO $ nodeLab (LGraph g _) i = unsafePerformIO $
igraphHaskellAttributeVAS g vertexAttr i >>= fromBS igraphHaskellAttributeVAS g vertexAttr i >>= fromBS
{-# INLINE nodeLab #-} {-# INLINE nodeLab #-}
nodeLabMaybe :: Serialize v => LGraph d v e -> Node -> Maybe v -- | Return all nodes that are associated with given label.
nodeLabMaybe gr@(LGraph g _) i = unsafePerformIO $ do
x <- igraphHaskellAttributeHasAttr g IgraphAttributeVertex vertexAttr
return $ if x
then Just $ nodeLab gr i
else Nothing
{-# INLINE nodeLabMaybe #-}
getNodes :: (Hashable v, Eq v) => LGraph d v e -> v -> [Node] getNodes :: (Hashable v, Eq v) => LGraph d v e -> v -> [Node]
getNodes gr x = M.lookupDefault [] x $ _labelToNode gr getNodes gr x = M.lookupDefault [] x $ _labelToNode gr
{-# INLINE getNodes #-} {-# INLINE getNodes #-}
-- | Return the label of given edge.
edgeLab :: Serialize e => LGraph d v e -> Edge -> e edgeLab :: Serialize e => LGraph d v e -> Edge -> e
edgeLab (LGraph g _) (fr,to) = unsafePerformIO $ edgeLab (LGraph g _) (fr,to) = unsafePerformIO $
igraphGetEid g fr to True True >>= igraphGetEid g fr to True True >>=
igraphHaskellAttributeEAS g edgeAttr >>= fromBS igraphHaskellAttributeEAS g edgeAttr >>= fromBS
{-# INLINE edgeLab #-} {-# INLINE edgeLab #-}
edgeLabMaybe :: Serialize e => LGraph d v e -> Edge -> Maybe e -- | Find the edge by edge ID.
edgeLabMaybe gr@(LGraph g _) i = unsafePerformIO $ do
x <- igraphHaskellAttributeHasAttr g IgraphAttributeEdge edgeAttr
return $ if x
then Just $ edgeLab gr i
else Nothing
{-# INLINE edgeLabMaybe #-}
getEdgeByEid :: LGraph d v e -> Int -> Edge getEdgeByEid :: LGraph d v e -> Int -> Edge
getEdgeByEid gr@(LGraph g _) i = unsafePerformIO $ igraphEdge g i getEdgeByEid gr@(LGraph g _) i = unsafePerformIO $ igraphEdge g i
{-# INLINE getEdgeByEid #-} {-# INLINE getEdgeByEid #-}
-- | Find the edge label by edge ID.
edgeLabByEid :: Serialize e => LGraph d v e -> Int -> e edgeLabByEid :: Serialize e => LGraph d v e -> Int -> e
edgeLabByEid (LGraph g _) i = unsafePerformIO $ edgeLabByEid (LGraph g _) i = unsafePerformIO $
igraphHaskellAttributeEAS g edgeAttr i >>= fromBS igraphHaskellAttributeEAS g edgeAttr i >>= fromBS
...@@ -132,6 +126,12 @@ instance Graph D where ...@@ -132,6 +126,12 @@ instance Graph D where
isDirected = const True isDirected = const True
isD = const True isD = const True
-- | Graph with labeled nodes and edges.
data LGraph d v e = LGraph
{ _graph :: IGraph
, _labelToNode :: M.HashMap v [Node]
}
instance (Graph d, Serialize v, Serialize e, Hashable v, Eq v) instance (Graph d, Serialize v, Serialize e, Hashable v, Eq v)
=> Serialize (LGraph d v e) where => Serialize (LGraph d v e) where
put gr = do put gr = do
...@@ -149,6 +149,8 @@ instance (Graph d, Serialize v, Serialize e, Hashable v, Eq v) ...@@ -149,6 +149,8 @@ instance (Graph d, Serialize v, Serialize e, Hashable v, Eq v)
es <- replicateM ne get es <- replicateM ne get
return $ mkGraph nds es return $ mkGraph nds es
-- | Decode a graph from a stream of inputs. This may be more memory efficient
-- than standard @decode@ function.
decodeC :: ( PrimMonad m, MonadThrow m, Graph d decodeC :: ( PrimMonad m, MonadThrow m, Graph d
, Serialize v, Serialize e, Hashable v, Eq v ) , Serialize v, Serialize e, Hashable v, Eq v )
=> ConduitT B.ByteString o m (LGraph d v e) => ConduitT B.ByteString o m (LGraph d v e)
...@@ -158,12 +160,16 @@ decodeC = do ...@@ -158,12 +160,16 @@ decodeC = do
ne <- sinkGet get ne <- sinkGet get
conduitGet2 get .| deserializeGraph nds ne conduitGet2 get .| deserializeGraph nds ne
-- | Create a empty graph.
empty :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e) empty :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e)
=> LGraph d v e => LGraph d v e
empty = runST $ new 0 >>= unsafeFreeze empty = runST $ new 0 >>= unsafeFreeze
-- | Create a graph.
mkGraph :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e) mkGraph :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e)
=> [v] -> [LEdge e] -> LGraph d v e => [v] -- ^ Nodes. Each will be assigned a ID from 0 to N.
-> [LEdge e] -- ^ Labeled edges.
-> LGraph d v e
mkGraph vattr es = runST $ do mkGraph vattr es = runST $ do
g <- new 0 g <- new 0
addLNodes vattr g addLNodes vattr g
...@@ -172,6 +178,7 @@ mkGraph vattr es = runST $ do ...@@ -172,6 +178,7 @@ mkGraph vattr es = runST $ do
where where
n = length vattr n = length vattr
-- | Create a graph from labeled edges.
fromLabeledEdges :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e) fromLabeledEdges :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e)
=> [((v, v), e)] -> LGraph d v e => [((v, v), e)] -> LGraph d v e
fromLabeledEdges es = mkGraph labels es' fromLabeledEdges es = mkGraph labels es'
...@@ -181,7 +188,7 @@ fromLabeledEdges es = mkGraph labels es' ...@@ -181,7 +188,7 @@ fromLabeledEdges es = mkGraph labels es'
labels = S.toList $ S.fromList $ concat [ [a,b] | ((a,b),_) <- es ] labels = S.toList $ S.fromList $ concat [ [a,b] | ((a,b),_) <- es ]
labelToId = M.fromList $ zip labels [0..] labelToId = M.fromList $ zip labels [0..]
-- | Deserialize a graph. -- | Create a graph from a stream of labeled edges.
fromLabeledEdges' :: (PrimMonad m, Graph d, Hashable v, Serialize v, Eq v, Serialize e) fromLabeledEdges' :: (PrimMonad m, Graph d, Hashable v, Serialize v, Eq v, Serialize e)
=> a -- ^ Input, usually a file => a -- ^ Input, usually a file
-> (a -> ConduitT () ((v, v), e) m ()) -- ^ deserialize the input into a stream of edges -> (a -> ConduitT () ((v, v), e) m ()) -- ^ deserialize the input into a stream of edges
...@@ -213,8 +220,7 @@ deserializeGraph nds ne = do ...@@ -213,8 +220,7 @@ deserializeGraph nds ne = do
let f i ((fr, to), attr) = unsafePrimToPrim $ do let f i ((fr, to), attr) = unsafePrimToPrim $ do
igraphVectorSet evec (i*2) $ fromIntegral fr igraphVectorSet evec (i*2) $ fromIntegral fr
igraphVectorSet evec (i*2+1) $ fromIntegral to igraphVectorSet evec (i*2+1) $ fromIntegral to
unsafeUseAsCStringLen (encode attr) $ \bs -> with (BSLen bs) $ \ptr -> asBS attr $ \bs -> with bs $ \ptr -> bsvectorSet bsvec i $ castPtr ptr
bsvectorSet bsvec i $ castPtr ptr
return $ i + 1 return $ i + 1
foldMC f 0 foldMC f 0
gr@(MLGraph g) <- new 0 gr@(MLGraph g) <- new 0
...@@ -225,6 +231,15 @@ deserializeGraph nds ne = do ...@@ -225,6 +231,15 @@ deserializeGraph nds ne = do
unsafeFreeze gr unsafeFreeze gr
{-# INLINE deserializeGraph #-} {-# INLINE deserializeGraph #-}
-- | Convert a mutable graph to immutable graph.
freeze :: (Hashable v, Eq v, Serialize v, PrimMonad m)
=> MLGraph (PrimState m) d v e -> m (LGraph d v e)
freeze (MLGraph g) = do
g' <- unsafePrimToPrim $ igraphCopy g
unsafeFreeze (MLGraph g')
-- | Convert a mutable graph to immutable graph. The original graph may not be
-- used afterwards.
unsafeFreeze :: (Hashable v, Eq v, Serialize v, PrimMonad m) unsafeFreeze :: (Hashable v, Eq v, Serialize v, PrimMonad m)
=> MLGraph (PrimState m) d v e -> m (LGraph d v e) => MLGraph (PrimState m) d v e -> m (LGraph d v e)
unsafeFreeze (MLGraph g) = unsafePrimToPrim $ do unsafeFreeze (MLGraph g) = unsafePrimToPrim $ do
...@@ -234,19 +249,15 @@ unsafeFreeze (MLGraph g) = unsafePrimToPrim $ do ...@@ -234,19 +249,15 @@ unsafeFreeze (MLGraph g) = unsafePrimToPrim $ do
return $ LGraph g $ M.fromListWith (++) $ zip labels $ map return [0..nV-1] return $ LGraph g $ M.fromListWith (++) $ zip labels $ map return [0..nV-1]
where where
freeze :: (Hashable v, Eq v, Serialize v, PrimMonad m) -- | Create a mutable graph.
=> MLGraph (PrimState m) d v e -> m (LGraph d v e) thaw :: (PrimMonad m, Graph d) => LGraph d v e -> m (MLGraph (PrimState m) d v e)
freeze (MLGraph g) = do thaw (LGraph g _) = unsafePrimToPrim . liftM MLGraph . igraphCopy $ g
g' <- unsafePrimToPrim $ igraphCopy g
unsafeFreeze (MLGraph g')
-- | Create a mutable graph. The original graph may not be used afterwards.
unsafeThaw :: PrimMonad m => LGraph d v e -> m (MLGraph (PrimState m) d v e) unsafeThaw :: PrimMonad m => LGraph d v e -> m (MLGraph (PrimState m) d v e)
unsafeThaw (LGraph g _) = return $ MLGraph g unsafeThaw (LGraph g _) = return $ MLGraph g
thaw :: (PrimMonad m, Graph d) => LGraph d v e -> m (MLGraph (PrimState m) d v e) -- | Find all neighbors of the given node.
thaw (LGraph g _) = unsafePrimToPrim . liftM MLGraph . igraphCopy $ g
-- | Find all neighbors of the given node
neighbors :: LGraph d v e -> Node -> [Node] neighbors :: LGraph d v e -> Node -> [Node]
neighbors gr i = unsafePerformIO $ do neighbors gr i = unsafePerformIO $ do
vs <- igraphVsAdj i IgraphAll vs <- igraphVsAdj i IgraphAll
...@@ -296,8 +307,7 @@ mapEdges f gr = runST $ do ...@@ -296,8 +307,7 @@ mapEdges f gr = runST $ do
setEdgeAttr x (f e $ edgeLabByEid gr x) gr' setEdgeAttr x (f e $ edgeLabByEid gr x) gr'
unsafeFreeze gr' unsafeFreeze gr'
-- | Keep nodes that satisfy the constraint.
-- | Keep nodes that satisfy the constraint
filterEdges :: (Hashable v, Eq v, Serialize v, Graph d) filterEdges :: (Hashable v, Eq v, Serialize v, Graph d)
=> (LGraph d v e -> Edge -> Bool) -> LGraph d v e -> LGraph d v e => (LGraph d v e -> Edge -> Bool) -> LGraph d v e -> LGraph d v e
filterEdges f gr = runST $ do filterEdges f gr = runST $ do
...@@ -306,7 +316,7 @@ filterEdges f gr = runST $ do ...@@ -306,7 +316,7 @@ filterEdges f gr = runST $ do
delEdges deleted gr' delEdges deleted gr'
unsafeFreeze gr' unsafeFreeze gr'
-- | Map a function over the node labels in a graph -- | Map a function over the node labels in a graph.
nmap :: (Graph d, Serialize v, Hashable u, Serialize u, Eq u) nmap :: (Graph d, Serialize v, Hashable u, Serialize u, Eq u)
=> ((Node, v) -> u) -> LGraph d v e -> LGraph d u e => ((Node, v) -> u) -> LGraph d v e -> LGraph d u e
nmap fn gr = unsafePerformIO $ do nmap fn gr = unsafePerformIO $ do
...@@ -317,7 +327,7 @@ nmap fn gr = unsafePerformIO $ do ...@@ -317,7 +327,7 @@ nmap fn gr = unsafePerformIO $ do
with bs (igraphHaskellAttributeVASSet g vertexAttr i) with bs (igraphHaskellAttributeVASSet g vertexAttr i)
unsafeFreeze (MLGraph g) unsafeFreeze (MLGraph g)
-- | Map a function over the edge labels in a graph -- | Map a function over the edge labels in a graph.
emap :: (Graph d, Serialize v, Hashable v, Eq v, Serialize e1, Serialize e2) emap :: (Graph d, Serialize v, Hashable v, Eq v, Serialize e1, Serialize e2)
=> ((Edge, e1) -> e2) -> LGraph d v e1 -> LGraph d v e2 => ((Edge, e1) -> e2) -> LGraph d v e1 -> LGraph d v e2
emap fn gr = unsafePerformIO $ do emap fn gr = unsafePerformIO $ do
......
...@@ -38,12 +38,20 @@ withEdgeAttr :: (CString -> IO a) -> IO a ...@@ -38,12 +38,20 @@ withEdgeAttr :: (CString -> IO a) -> IO a
withEdgeAttr = withCString edgeAttr withEdgeAttr = withCString edgeAttr
{-# INLINE withEdgeAttr #-} {-# INLINE withEdgeAttr #-}
-- | Mutable labeled graph.
newtype MLGraph m d v e = MLGraph IGraph
class MGraph d where class MGraph d where
-- | Create a new graph.
new :: PrimMonad m => Int -> m (MLGraph (PrimState m) d v e) new :: PrimMonad m => Int -> m (MLGraph (PrimState m) d v e)
addNodes :: PrimMonad m => Int -> MLGraph(PrimState m) d v e -> m () -- | Add nodes to the graph.
addNodes :: PrimMonad m
=> Int -- ^ The number of new nodes.
-> MLGraph(PrimState m) d v e -> m ()
addNodes n (MLGraph g) = unsafePrimToPrim $ igraphAddVertices g n nullPtr addNodes n (MLGraph g) = unsafePrimToPrim $ igraphAddVertices g n nullPtr
-- | Add nodes with labels to the graph.
addLNodes :: (Serialize v, PrimMonad m) addLNodes :: (Serialize v, PrimMonad m)
=> [v] -- ^ vertices' labels => [v] -- ^ vertices' labels
-> MLGraph (PrimState m) d v e -> m () -> MLGraph (PrimState m) d v e -> m ()
...@@ -54,6 +62,7 @@ class MGraph d where ...@@ -54,6 +62,7 @@ class MGraph d where
where where
n = length labels n = length labels
-- | Delete nodes from the graph.
delNodes :: PrimMonad m => [Int] -> MLGraph (PrimState m) d v e -> m () delNodes :: PrimMonad m => [Int] -> MLGraph (PrimState m) d v e -> m ()
delNodes ns (MLGraph g) = unsafePrimToPrim $ do delNodes ns (MLGraph g) = unsafePrimToPrim $ do
vptr <- fromList $ map fromIntegral ns vptr <- fromList $ map fromIntegral ns
...@@ -61,6 +70,7 @@ class MGraph d where ...@@ -61,6 +70,7 @@ class MGraph d where
igraphDeleteVertices g vsptr igraphDeleteVertices g vsptr
return () return ()
-- | Add edges to the graph.
addEdges :: PrimMonad m => [(Int, Int)] -> MLGraph (PrimState m) d v e -> m () addEdges :: PrimMonad m => [(Int, Int)] -> MLGraph (PrimState m) d v e -> m ()
addEdges es (MLGraph g) = unsafePrimToPrim $ do addEdges es (MLGraph g) = unsafePrimToPrim $ do
vec <- fromList xs vec <- fromList xs
...@@ -68,6 +78,7 @@ class MGraph d where ...@@ -68,6 +78,7 @@ class MGraph d where
where where
xs = concatMap ( \(a,b) -> [fromIntegral a, fromIntegral b] ) es xs = concatMap ( \(a,b) -> [fromIntegral a, fromIntegral b] ) es
-- | Add edges with labels to the graph.
addLEdges :: (PrimMonad m, Serialize e) => [LEdge e] -> MLGraph (PrimState m) d v e -> m () addLEdges :: (PrimMonad m, Serialize e) => [LEdge e] -> MLGraph (PrimState m) d v e -> m ()
addLEdges es (MLGraph g) = unsafePrimToPrim $ withEdgeAttr $ \eattr -> addLEdges es (MLGraph g) = unsafePrimToPrim $ withEdgeAttr $ \eattr ->
asBSVector vs $ \bsvec -> with (mkStrRec eattr bsvec) $ \ptr -> do asBSVector vs $ \bsvec -> with (mkStrRec eattr bsvec) $ \ptr -> do
...@@ -77,6 +88,7 @@ class MGraph d where ...@@ -77,6 +88,7 @@ class MGraph d where
where where
(xs, vs) = unzip $ map ( \((a,b),v) -> ([fromIntegral a, fromIntegral b], v) ) es (xs, vs) = unzip $ map ( \((a,b),v) -> ([fromIntegral a, fromIntegral b], v) ) es
-- | Delete edges from the graph.
delEdges :: PrimMonad m => [(Int, Int)] -> MLGraph (PrimState m) d v e -> m () delEdges :: PrimMonad m => [(Int, Int)] -> MLGraph (PrimState m) d v e -> m ()
instance MGraph U where instance MGraph U where
...@@ -99,6 +111,7 @@ instance MGraph D where ...@@ -99,6 +111,7 @@ instance MGraph D where
igraphDeleteEdges g esptr igraphDeleteEdges g esptr
return () return ()
-- | Set node attribute.
setNodeAttr :: (PrimMonad m, Serialize v) setNodeAttr :: (PrimMonad m, Serialize v)
=> Int -- ^ Node id => Int -- ^ Node id
-> v -> v
...@@ -109,9 +122,10 @@ setNodeAttr nodeId x (MLGraph gr) = unsafePrimToPrim $ asBS x $ \bs -> ...@@ -109,9 +122,10 @@ setNodeAttr nodeId x (MLGraph gr) = unsafePrimToPrim $ asBS x $ \bs ->
err <- igraphHaskellAttributeVASSet gr vertexAttr nodeId bsptr err <- igraphHaskellAttributeVASSet gr vertexAttr nodeId bsptr
when (err /= 0) $ error "Fail to set node attribute!" when (err /= 0) $ error "Fail to set node attribute!"
setEdgeAttr :: (PrimMonad m, Serialize v) -- | Set edge attribute.
setEdgeAttr :: (PrimMonad m, Serialize e)
=> Int -- ^ Edge id => Int -- ^ Edge id
-> v -> e
-> MLGraph (PrimState m) d v e -> MLGraph (PrimState m) d v e
-> m () -> m ()
setEdgeAttr edgeId x (MLGraph gr) = unsafePrimToPrim $ asBS x $ \bs -> setEdgeAttr edgeId x (MLGraph gr) = unsafePrimToPrim $ asBS x $ \bs ->
......
...@@ -35,7 +35,7 @@ inducedSubgraph gr vs = unsafePerformIO $ do ...@@ -35,7 +35,7 @@ inducedSubgraph gr vs = unsafePerformIO $ do
igraphHaskellAttributeVAS g' vertexAttr i >>= fromBS igraphHaskellAttributeVAS g' vertexAttr i >>= fromBS
return $ LGraph g' $ M.fromListWith (++) $ zip labels $ map return [0..nV-1] return $ LGraph g' $ M.fromListWith (++) $ zip labels $ map return [0..nV-1]
-- | closeness centrality -- | Closeness centrality
closeness :: [Int] -- ^ vertices closeness :: [Int] -- ^ vertices
-> LGraph d v e -> LGraph d v e
-> Maybe [Double] -- ^ optional edge weights -> Maybe [Double] -- ^ optional edge weights
...@@ -52,7 +52,7 @@ closeness vs gr ws mode normal = unsafePerformIO $ do ...@@ -52,7 +52,7 @@ closeness vs gr ws mode normal = unsafePerformIO $ do
igraphCloseness (_graph gr) vptr vsptr mode ws' normal igraphCloseness (_graph gr) vptr vsptr mode ws' normal
toList vptr toList vptr
-- | betweenness centrality -- | Betweenness centrality
betweenness :: [Int] betweenness :: [Int]
-> LGraph d v e -> LGraph d v e
-> Maybe [Double] -> Maybe [Double]
...@@ -67,7 +67,7 @@ betweenness vs gr ws = unsafePerformIO $ do ...@@ -67,7 +67,7 @@ betweenness vs gr ws = unsafePerformIO $ do
igraphBetweenness (_graph gr) vptr vsptr True ws' False igraphBetweenness (_graph gr) vptr vsptr True ws' False
toList vptr toList vptr
-- | eigenvector centrality -- | Eigenvector centrality
eigenvectorCentrality :: LGraph d v e eigenvectorCentrality :: LGraph d v e
-> Maybe [Double] -> Maybe [Double]
-> [Double] -> [Double]
...@@ -103,6 +103,7 @@ pagerank gr ws d ...@@ -103,6 +103,7 @@ pagerank gr ws d
n = nNodes gr n = nNodes gr
m = nEdges gr m = nEdges gr
-- | Personalized PageRank.
personalizedPagerank :: Graph d personalizedPagerank :: Graph d
=> LGraph d v e => LGraph d v e
-> [Double] -- ^ reset probability -> [Double] -- ^ reset probability
......
...@@ -9,14 +9,8 @@ type Node = Int ...@@ -9,14 +9,8 @@ type Node = Int
type Edge = (Node, Node) type Edge = (Node, Node)
type LEdge a = (Edge, a) type LEdge a = (Edge, a)
data U = U -- | Undirected graph.
data D = D data U
-- | Mutable labeled graph -- | Directed graph.
newtype MLGraph m d v e = MLGraph IGraph data D
-- | graph with labeled nodes and edges
data LGraph d v e = LGraph
{ _graph :: IGraph
, _labelToNode :: M.HashMap v [Node]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment