haskell-igraph 0.5.0 → 0.6.0
raw patch · 22 files changed
+1177/−1068 lines, 22 filesdep +singletonsdep −cereal-conduitdep −data-default-classPVP ok
version bump matches the API change (PVP)
Dependencies added: singletons
Dependencies removed: cereal-conduit, data-default-class
API changes (from Hackage documentation)
- IGraph: LGraph :: IGraph -> HashMap v [Node] -> LGraph d v e
- IGraph: class MGraph d => Graph d
- IGraph: data D
- IGraph: data LGraph d v e
- IGraph: data U
- IGraph: decodeC :: (PrimMonad m, MonadThrow m, Graph d, Serialize v, Serialize e, Hashable v, Eq v) => ConduitT ByteString o m (LGraph d v e)
- IGraph: instance (IGraph.Graph d, Data.Serialize.Serialize v, Data.Serialize.Serialize e, Data.Hashable.Class.Hashable v, GHC.Classes.Eq v) => Data.Serialize.Serialize (IGraph.LGraph d v e)
- IGraph: instance IGraph.Graph IGraph.Types.D
- IGraph: instance IGraph.Graph IGraph.Types.U
- IGraph: isD :: Graph d => d -> Bool
- IGraph.Community: CommunityOpt :: CommunityMethod -> Maybe [Double] -> Int -> Int -> Double -> Double -> Double -> Double -> CommunityOpt
- IGraph.Community: [_method] :: CommunityOpt -> CommunityMethod
- IGraph.Community: [_weights] :: CommunityOpt -> Maybe [Double]
- IGraph.Community: data CommunityOpt
- IGraph.Community: instance Data.Default.Class.Default IGraph.Community.CommunityOpt
- IGraph.Internal: asBS :: ByteString -> (Ptr BSLen -> IO a) -> IO a
- IGraph.Internal: bsToByteString :: Ptr BSLen -> IO ByteString
- IGraph.Internal: bsvectorNew :: (Int) -> IO ((BSVector))
- IGraph.Internal: eitToList :: IGraphEit -> IO [Int]
- IGraph.Internal: fromList :: [Double] -> IO Vector
- IGraph.Internal: fromPtrs :: [Ptr ()] -> IO VectorPtr
- IGraph.Internal: fromRowLists :: [[Double]] -> IO Matrix
- IGraph.Internal: igraphEitNew :: (IGraph) -> (IGraphEs) -> IO ((IGraphEit))
- IGraph.Internal: igraphEsAll :: (EdgeOrderType) -> IO ((IGraphEs))
- IGraph.Internal: igraphEsVector :: (Vector) -> IO ((IGraphEs))
- IGraph.Internal: igraphHaskellAttributeEAN :: (IGraph) -> (String) -> (Int) -> IO ((Double))
- IGraph.Internal: igraphHaskellAttributeGAN :: (IGraph) -> (String) -> IO ((Double))
- IGraph.Internal: igraphHaskellAttributeGANSet :: (IGraph) -> (String) -> (Double) -> IO ((Int))
- IGraph.Internal: igraphMatrixNew :: (Int) -> (Int) -> IO ((Matrix))
- IGraph.Internal: igraphStrvectorGet :: (StrVector) -> (Int) -> IO ((String))
- IGraph.Internal: igraphStrvectorNew :: (Int) -> IO ((StrVector))
- IGraph.Internal: igraphVectorNew :: (Int) -> IO ((Vector))
- IGraph.Internal: igraphVectorPtrNew :: (Int) -> IO ((VectorPtr))
- IGraph.Internal: igraphVitNew :: (IGraph) -> (IGraphVs) -> IO ((IGraphVit))
- IGraph.Internal: igraphVsAdj :: (Int) -> (Neimode) -> IO ((IGraphVs))
- IGraph.Internal: igraphVsAll :: IO ((IGraphVs))
- IGraph.Internal: igraphVsVector :: (Vector) -> IO ((IGraphVs))
- IGraph.Internal: toBSVector :: [ByteString] -> IO BSVector
- IGraph.Internal: toStrVector :: [ByteString] -> IO StrVector
- IGraph.Internal: vitToList :: IGraphVit -> IO [Int]
- IGraph.Internal.Types: ArpackOpt :: (ForeignPtr (ArpackOpt)) -> ArpackOpt
- IGraph.Internal.Types: AttributeRecord :: (ForeignPtr (AttributeRecord)) -> AttributeRecord
- IGraph.Internal.Types: BSLen :: (ForeignPtr (BSLen)) -> BSLen
- IGraph.Internal.Types: BSVector :: (ForeignPtr (BSVector)) -> BSVector
- IGraph.Internal.Types: IGraph :: (ForeignPtr (IGraph)) -> IGraph
- IGraph.Internal.Types: IGraphEit :: (ForeignPtr (IGraphEit)) -> IGraphEit
- IGraph.Internal.Types: IGraphVit :: (ForeignPtr (IGraphVit)) -> IGraphVit
- IGraph.Internal.Types: IGraphVs :: (ForeignPtr (IGraphVs)) -> IGraphVs
- IGraph.Internal.Types: Matrix :: (ForeignPtr (Matrix)) -> Matrix
- IGraph.Internal.Types: StrVector :: (ForeignPtr (StrVector)) -> StrVector
- IGraph.Internal.Types: Vector :: (ForeignPtr (Vector)) -> Vector
- IGraph.Internal.Types: VectorPtr :: (ForeignPtr (VectorPtr)) -> VectorPtr
- IGraph.Internal.Types: addBSVectorFinalizer :: Ptr BSVector -> IO BSVector
- IGraph.Internal.Types: addEitFinalizer :: Ptr IGraphEit -> IO IGraphEit
- IGraph.Internal.Types: addEsFinalizer :: Ptr IGraphEs -> IO IGraphEs
- IGraph.Internal.Types: addIGraphFinalizer :: Ptr IGraph -> IO IGraph
- IGraph.Internal.Types: addMatrixFinalizer :: Ptr Matrix -> IO Matrix
- IGraph.Internal.Types: addStrVectorFinalizer :: Ptr StrVector -> IO StrVector
- IGraph.Internal.Types: addVectorFinalizer :: Ptr Vector -> IO Vector
- IGraph.Internal.Types: addVectorPtrFinalizer :: Ptr VectorPtr -> IO VectorPtr
- IGraph.Internal.Types: addVitFinalizer :: Ptr IGraphVit -> IO IGraphVit
- IGraph.Internal.Types: addVsFinalizer :: Ptr IGraphVs -> IO IGraphVs
- IGraph.Internal.Types: allocaBSVector :: (Ptr BSVector -> IO a) -> IO a
- IGraph.Internal.Types: allocaEit :: (Ptr IGraphEit -> IO a) -> IO a
- IGraph.Internal.Types: allocaEs :: (Ptr IGraphEs -> IO a) -> IO a
- IGraph.Internal.Types: allocaIGraph :: (Ptr IGraph -> IO a) -> IO a
- IGraph.Internal.Types: allocaMatrix :: (Ptr Matrix -> IO a) -> IO a
- IGraph.Internal.Types: allocaStrVector :: (Ptr StrVector -> IO a) -> IO a
- IGraph.Internal.Types: allocaVector :: (Ptr Vector -> IO a) -> IO a
- IGraph.Internal.Types: allocaVectorPtr :: (Ptr VectorPtr -> IO a) -> IO a
- IGraph.Internal.Types: allocaVit :: (Ptr IGraphVit -> IO a) -> IO a
- IGraph.Internal.Types: allocaVs :: (Ptr IGraphVs -> IO a) -> IO a
- IGraph.Internal.Types: data IGraphEs
- IGraph.Internal.Types: igraphArpackNew :: IO ((ArpackOpt))
- IGraph.Internal.Types: newtype ArpackOpt
- IGraph.Internal.Types: newtype AttributeRecord
- IGraph.Internal.Types: newtype BSLen
- IGraph.Internal.Types: newtype BSVector
- IGraph.Internal.Types: newtype IGraph
- IGraph.Internal.Types: newtype IGraphEit
- IGraph.Internal.Types: newtype IGraphVit
- IGraph.Internal.Types: newtype IGraphVs
- IGraph.Internal.Types: newtype Matrix
- IGraph.Internal.Types: newtype StrVector
- IGraph.Internal.Types: newtype Vector
- IGraph.Internal.Types: newtype VectorPtr
- IGraph.Internal.Types: withArpackOpt :: ArpackOpt -> (Ptr ArpackOpt -> IO b) -> IO b
- IGraph.Internal.Types: withAttributeRecord :: AttributeRecord -> (Ptr AttributeRecord -> IO b) -> IO b
- IGraph.Internal.Types: withBSLen :: BSLen -> (Ptr BSLen -> IO b) -> IO b
- IGraph.Internal.Types: withBSVector :: BSVector -> (Ptr BSVector -> IO b) -> IO b
- IGraph.Internal.Types: withIGraph :: IGraph -> (Ptr IGraph -> IO b) -> IO b
- IGraph.Internal.Types: withIGraphEit :: IGraphEit -> (Ptr IGraphEit -> IO b) -> IO b
- IGraph.Internal.Types: withIGraphEs :: IGraphEs -> (Ptr IGraphEs -> IO b) -> IO b
- IGraph.Internal.Types: withIGraphVit :: IGraphVit -> (Ptr IGraphVit -> IO b) -> IO b
- IGraph.Internal.Types: withIGraphVs :: IGraphVs -> (Ptr IGraphVs -> IO b) -> IO b
- IGraph.Internal.Types: withMatrix :: Matrix -> (Ptr Matrix -> IO b) -> IO b
- IGraph.Internal.Types: withStrVector :: StrVector -> (Ptr StrVector -> IO b) -> IO b
- IGraph.Internal.Types: withVector :: Vector -> (Ptr Vector -> IO b) -> IO b
- IGraph.Internal.Types: withVectorPtr :: VectorPtr -> (Ptr VectorPtr -> IO b) -> IO b
- IGraph.Mutable: MLGraph :: IGraph -> MLGraph m d v e
- IGraph.Mutable: class MGraph d
- IGraph.Mutable: instance IGraph.Mutable.MGraph IGraph.Types.D
- IGraph.Mutable: instance IGraph.Mutable.MGraph IGraph.Types.U
- IGraph.Mutable: newtype MLGraph m d v e
- IGraph.Structure: personalizedPagerank :: Graph d => LGraph d v e -> [Double] -> Maybe [Double] -> Double -> [Double]
- IGraph.Types: data D
- IGraph.Types: data U
+ IGraph: D :: EdgeType
+ IGraph: Graph :: IGraph -> HashMap v [Node] -> Graph v e
+ IGraph: U :: EdgeType
+ IGraph: data EdgeType
+ IGraph: data Graph (d :: EdgeType) v e
+ IGraph: instance (Data.Singletons.Internal.SingI d, Data.Serialize.Serialize v, Data.Serialize.Serialize e, Data.Hashable.Class.Hashable v, GHC.Classes.Eq v) => Data.Serialize.Serialize (IGraph.Graph d v e)
+ IGraph.Clique: cliqueNumber :: Graph d v e -> Int
+ IGraph.Clique: largestCliques :: Graph d v e -> [[Int]]
+ IGraph.Community: defaultLeadingEigenvector :: CommunityMethod
+ IGraph.Community: defaultSpinglass :: CommunityMethod
+ IGraph.Community: modularity :: Graph d v e -> [[Int]] -> Maybe [Double] -> Double
+ IGraph.Generators: star :: Int -> Graph 'U () ()
+ IGraph.Internal: addIGraphFinalizer :: Ptr IGraph -> IO IGraph
+ IGraph.Internal: allocaArpackOpt :: (Ptr ArpackOpt -> IO a) -> IO a
+ IGraph.Internal: allocaBSVectorN :: Int -> (Ptr BSVector -> IO a) -> IO a
+ IGraph.Internal: allocaIGraph :: (Ptr IGraph -> IO a) -> IO a
+ IGraph.Internal: allocaMatrix :: (Ptr Matrix -> IO a) -> IO a
+ IGraph.Internal: allocaMatrixN :: Int -> Int -> (Ptr Matrix -> IO a) -> IO a
+ IGraph.Internal: allocaVector :: (Ptr Vector -> IO a) -> IO a
+ IGraph.Internal: allocaVectorN :: Int -> (Ptr Vector -> IO a) -> IO a
+ IGraph.Internal: allocaVectorPtr :: (Ptr VectorPtr -> IO a) -> IO a
+ IGraph.Internal: allocaVectorPtrN :: Int -> (Ptr VectorPtr -> IO a) -> IO a
+ IGraph.Internal: data ArpackOpt
+ IGraph.Internal: data AttributeRecord
+ IGraph.Internal: data BSLen
+ IGraph.Internal: data BSVector
+ IGraph.Internal: data EdgeIterator
+ IGraph.Internal: data EdgeSelector
+ IGraph.Internal: data IGraph
+ IGraph.Internal: data Matrix
+ IGraph.Internal: data Vector
+ IGraph.Internal: data VectorPtr
+ IGraph.Internal: data VertexIterator
+ IGraph.Internal: data VertexSelector
+ IGraph.Internal: igraphCreate :: (Ptr Vector) -> (Int) -> (Bool) -> IO ((IGraph))
+ IGraph.Internal: igraphHaskellAttributeVASSetv :: (IGraph) -> (String) -> (Ptr BSVector) -> IO ()
+ IGraph.Internal: iterateEdges :: IGraph -> Ptr EdgeSelector -> (Ptr EdgeIterator -> IO a) -> IO a
+ IGraph.Internal: iterateEdgesC :: IGraph -> Ptr EdgeSelector -> (ConduitT i Int IO () -> IO a) -> IO a
+ IGraph.Internal: iterateVertices :: IGraph -> Ptr VertexSelector -> (Ptr VertexIterator -> IO a) -> IO a
+ IGraph.Internal: iterateVerticesC :: IGraph -> Ptr VertexSelector -> (ConduitT i Int IO () -> IO a) -> IO a
+ IGraph.Internal: toByteString :: Ptr BSLen -> IO ByteString
+ IGraph.Internal: withBSAttr :: String -> Ptr BSVector -> (Ptr AttributeRecord -> IO b) -> IO b
+ IGraph.Internal: withByteString :: ByteString -> (Ptr BSLen -> IO a) -> IO a
+ IGraph.Internal: withByteStrings :: [ByteString] -> (Ptr BSVector -> IO a) -> IO a
+ IGraph.Internal: withEdgeIdsList :: [Int] -> (Ptr EdgeSelector -> IO b) -> IO b
+ IGraph.Internal: withEdgeIdsVector :: Ptr Vector -> (Ptr EdgeSelector -> IO a) -> IO a
+ IGraph.Internal: withEdgesAll :: EdgeOrderType -> (Ptr EdgeSelector -> IO a) -> IO a
+ IGraph.Internal: withIGraph :: IGraph -> (Ptr IGraph -> IO b) -> IO b
+ IGraph.Internal: withList :: Real a => [a] -> (Ptr Vector -> IO b) -> IO b
+ IGraph.Internal: withListMaybe :: Real a => Maybe [a] -> (Ptr Vector -> IO b) -> IO b
+ IGraph.Internal: withPtrs :: [Ptr a] -> (Ptr VectorPtr -> IO b) -> IO b
+ IGraph.Internal: withRowLists :: Real a => [[a]] -> (Ptr Matrix -> IO b) -> IO b
+ IGraph.Internal: withVerticesAdj :: Int -> Neimode -> (Ptr VertexSelector -> IO a) -> IO a
+ IGraph.Internal: withVerticesAll :: (Ptr VertexSelector -> IO a) -> IO a
+ IGraph.Internal: withVerticesList :: Real a => [a] -> (Ptr VertexSelector -> IO b) -> IO b
+ IGraph.Internal: withVerticesVector :: Ptr Vector -> (Ptr VertexSelector -> IO a) -> IO a
+ IGraph.Internal.Constants: IgraphStarIn :: StarMode
+ IGraph.Internal.Constants: IgraphStarMutual :: StarMode
+ IGraph.Internal.Constants: IgraphStarOut :: StarMode
+ IGraph.Internal.Constants: IgraphStarUndirected :: StarMode
+ IGraph.Internal.Constants: IgraphToDirectedArbitrary :: ToDirected
+ IGraph.Internal.Constants: IgraphToDirectedMutual :: ToDirected
+ IGraph.Internal.Constants: data StarMode
+ IGraph.Internal.Constants: data ToDirected
+ IGraph.Internal.Constants: instance GHC.Classes.Eq IGraph.Internal.Constants.StarMode
+ IGraph.Internal.Constants: instance GHC.Classes.Eq IGraph.Internal.Constants.ToDirected
+ IGraph.Internal.Constants: instance GHC.Enum.Enum IGraph.Internal.Constants.StarMode
+ IGraph.Internal.Constants: instance GHC.Enum.Enum IGraph.Internal.Constants.ToDirected
+ IGraph.Internal.Constants: instance GHC.Read.Read IGraph.Internal.Constants.StarMode
+ IGraph.Internal.Constants: instance GHC.Show.Show IGraph.Internal.Constants.StarMode
+ IGraph.Mutable: MGraph :: IGraph -> MGraph m v e
+ IGraph.Mutable: initializeNullAttribute :: PrimMonad m => MGraph (PrimState m) d () () -> m ()
+ IGraph.Mutable: nEdges :: PrimMonad m => MGraph (PrimState m) d v e -> m Int
+ IGraph.Mutable: nNodes :: PrimMonad m => MGraph (PrimState m) d v e -> m Int
+ IGraph.Mutable: newtype MGraph m (d :: EdgeType) v e
+ IGraph.Types: D :: EdgeType
+ IGraph.Types: ShowsPrec_6989586621679101596Sym0KindInference :: ShowsPrec_6989586621679101596Sym0
+ IGraph.Types: ShowsPrec_6989586621679101596Sym1KindInference :: ShowsPrec_6989586621679101596Sym1
+ IGraph.Types: ShowsPrec_6989586621679101596Sym2KindInference :: ShowsPrec_6989586621679101596Sym2
+ IGraph.Types: U :: EdgeType
+ IGraph.Types: data EdgeType
+ IGraph.Types: data ShowsPrec_6989586621679101596Sym0 (l_anSU :: TyFun Nat (TyFun EdgeType (TyFun Symbol Symbol -> Type) -> Type))
+ IGraph.Types: data ShowsPrec_6989586621679101596Sym1 (l_anSS :: Nat) (l_anSR :: TyFun EdgeType (TyFun Symbol Symbol -> Type))
+ IGraph.Types: data ShowsPrec_6989586621679101596Sym2 (l_anSO :: Nat) (l_anSP :: EdgeType) (l_anSN :: TyFun Symbol Symbol)
+ IGraph.Types: instance Data.Serialize.Serialize IGraph.Types.EdgeType
+ IGraph.Types: instance Data.Singletons.Decide.SDecide IGraph.Types.EdgeType
+ IGraph.Types: instance Data.Singletons.Internal.SingI 'IGraph.Types.D
+ IGraph.Types: instance Data.Singletons.Internal.SingI 'IGraph.Types.U
+ IGraph.Types: instance Data.Singletons.Internal.SingKind IGraph.Types.EdgeType
+ IGraph.Types: instance Data.Singletons.Prelude.Eq.PEq IGraph.Types.EdgeType
+ IGraph.Types: instance Data.Singletons.Prelude.Eq.SEq IGraph.Types.EdgeType
+ IGraph.Types: instance Data.Singletons.Prelude.Show.PShow IGraph.Types.EdgeType
+ IGraph.Types: instance Data.Singletons.Prelude.Show.SShow IGraph.Types.EdgeType
+ IGraph.Types: instance Data.Singletons.ShowSing.ShowSing IGraph.Types.EdgeType
+ IGraph.Types: instance Data.Singletons.SuppressUnusedWarnings.SuppressUnusedWarnings IGraph.Types.ShowsPrec_6989586621679101596Sym0
+ IGraph.Types: instance Data.Singletons.SuppressUnusedWarnings.SuppressUnusedWarnings IGraph.Types.ShowsPrec_6989586621679101596Sym1
+ IGraph.Types: instance Data.Singletons.SuppressUnusedWarnings.SuppressUnusedWarnings IGraph.Types.ShowsPrec_6989586621679101596Sym2
+ IGraph.Types: instance GHC.Classes.Eq IGraph.Types.EdgeType
+ IGraph.Types: instance GHC.Generics.Generic IGraph.Types.EdgeType
+ IGraph.Types: instance GHC.Read.Read IGraph.Types.EdgeType
+ IGraph.Types: instance GHC.Show.Show (Data.Singletons.Internal.Sing z)
+ IGraph.Types: instance GHC.Show.Show IGraph.Types.EdgeType
+ IGraph.Types: type DSym0 = D
+ IGraph.Types: type SEdgeType = (Sing :: EdgeType -> Type)
+ IGraph.Types: type ShowsPrec_6989586621679101596Sym3 (t_anSK :: Nat) (t_anSL :: EdgeType) (t_anSM :: Symbol) = ShowsPrec_6989586621679101596 t_anSK t_anSL t_anSM
+ IGraph.Types: type USym0 = U
- IGraph: [_graph] :: LGraph d v e -> IGraph
+ IGraph: [_graph] :: Graph v e -> IGraph
- IGraph: [_labelToNode] :: LGraph d v e -> HashMap v [Node]
+ IGraph: [_labelToNode] :: Graph v e -> HashMap v [Node]
- IGraph: edgeLab :: (Graph d, Serialize e) => LGraph d v e -> Edge -> e
+ IGraph: edgeLab :: Serialize e => Graph d v e -> Edge -> e
- IGraph: edges :: Graph d => LGraph d v e -> [Edge]
+ IGraph: edges :: Graph d v e -> [Edge]
- IGraph: efilter :: (Hashable v, Eq v, Serialize v, Serialize e, Graph d) => (LEdge e -> Bool) -> LGraph d v e -> LGraph d v e
+ IGraph: efilter :: (SingI d, Hashable v, Eq v, Serialize v, Serialize e) => (LEdge e -> Bool) -> Graph d v e -> Graph d v e
- IGraph: emap :: (Graph d, Serialize e1, Serialize e2, Hashable v, Eq v, Serialize v) => (LEdge e1 -> e2) -> LGraph d v e1 -> LGraph d v e2
+ IGraph: emap :: (Serialize e1, Serialize e2, Hashable v, Eq v, Serialize v) => (LEdge e1 -> e2) -> Graph d v e1 -> Graph d v e2
- IGraph: empty :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e) => LGraph d v e
+ IGraph: empty :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e) => Graph d v e
- IGraph: freeze :: (Hashable v, Eq v, Serialize v, PrimMonad m) => MLGraph (PrimState m) d v e -> m (LGraph d v e)
+ IGraph: freeze :: (Hashable v, Eq v, Serialize v, PrimMonad m) => MGraph (PrimState m) d v e -> m (Graph d v e)
- IGraph: fromLabeledEdges :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e) => [((v, v), e)] -> LGraph d v e
+ IGraph: fromLabeledEdges :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e) => [((v, v), e)] -> Graph d v e
- IGraph: fromLabeledEdges' :: (PrimMonad m, Graph d, Hashable v, Serialize v, Eq v, Serialize e) => a -> (a -> ConduitT () ((v, v), e) m ()) -> m (LGraph d v e)
+ IGraph: fromLabeledEdges' :: (MonadUnliftIO m, SingI d, Hashable v, Serialize v, Eq v, Serialize e) => a -> (a -> ConduitT () ((v, v), e) m ()) -> m (Graph d v e)
- IGraph: getEdgeByEid :: Graph d => LGraph d v e -> Int -> Edge
+ IGraph: getEdgeByEid :: Graph d v e -> Int -> Edge
- IGraph: getEdgeLabByEid :: (Graph d, Serialize e) => LGraph d v e -> Int -> e
+ IGraph: getEdgeLabByEid :: Serialize e => Graph d v e -> Int -> e
- IGraph: getNodes :: (Graph d, Hashable v, Eq v) => LGraph d v e -> v -> [Node]
+ IGraph: getNodes :: (Hashable v, Eq v) => Graph d v e -> v -> [Node]
- IGraph: hasEdge :: Graph d => LGraph d v e -> Edge -> Bool
+ IGraph: hasEdge :: Graph d v e -> Edge -> Bool
- IGraph: isDirected :: Graph d => LGraph d v e -> Bool
+ IGraph: isDirected :: forall d v e. SingI d => Graph d v e -> Bool
- IGraph: labEdges :: (Graph d, Serialize e) => LGraph d v e -> [LEdge e]
+ IGraph: labEdges :: Serialize e => Graph d v e -> [LEdge e]
- IGraph: labNodes :: (Graph d, Serialize v) => LGraph d v e -> [LNode v]
+ IGraph: labNodes :: Serialize v => Graph d v e -> [LNode v]
- IGraph: mkGraph :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e) => [v] -> [LEdge e] -> LGraph d v e
+ IGraph: mkGraph :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e) => [v] -> [LEdge e] -> Graph d v e
- IGraph: nEdges :: Graph d => LGraph d v e -> Int
+ IGraph: nEdges :: Graph d v e -> Int
- IGraph: nNodes :: Graph d => LGraph d v e -> Int
+ IGraph: nNodes :: Graph d v e -> Int
- IGraph: neighbors :: LGraph d v e -> Node -> [Node]
+ IGraph: neighbors :: Graph d v e -> Node -> [Node]
- IGraph: nfilter :: (Hashable v, Eq v, Serialize v, Graph d) => (LNode v -> Bool) -> LGraph d v e -> LGraph d v e
+ IGraph: nfilter :: (Hashable v, Eq v, Serialize v) => (LNode v -> Bool) -> Graph d v e -> Graph d v e
- IGraph: nmap :: (Graph d, Serialize v1, Serialize v2, Hashable v2, Eq v2) => (LNode v1 -> v2) -> LGraph d v1 e -> LGraph d v2 e
+ IGraph: nmap :: (Serialize v1, Serialize v2, Hashable v2, Eq v2) => (LNode v1 -> v2) -> Graph d v1 e -> Graph d v2 e
- IGraph: nodeLab :: (Graph d, Serialize v) => LGraph d v e -> Node -> v
+ IGraph: nodeLab :: Serialize v => Graph d v e -> Node -> v
- IGraph: nodes :: Graph d => LGraph d v e -> [Node]
+ IGraph: nodes :: Graph d v e -> [Node]
- IGraph: pre :: LGraph D v e -> Node -> [Node]
+ IGraph: pre :: Graph 'D v e -> Node -> [Node]
- IGraph: suc :: LGraph D v e -> Node -> [Node]
+ IGraph: suc :: Graph 'D v e -> Node -> [Node]
- IGraph: thaw :: (PrimMonad m, Graph d) => LGraph d v e -> m (MLGraph (PrimState m) d v e)
+ IGraph: thaw :: PrimMonad m => Graph d v e -> m (MGraph (PrimState m) d v e)
- IGraph: unsafeFreeze :: (Hashable v, Eq v, Serialize v, PrimMonad m) => MLGraph (PrimState m) d v e -> m (LGraph d v e)
+ IGraph: unsafeFreeze :: (Hashable v, Eq v, Serialize v, PrimMonad m) => MGraph (PrimState m) d v e -> m (Graph d v e)
- IGraph: unsafeThaw :: PrimMonad m => LGraph d v e -> m (MLGraph (PrimState m) d v e)
+ IGraph: unsafeThaw :: PrimMonad m => Graph d v e -> m (MGraph (PrimState m) d v e)
- IGraph.Clique: cliques :: LGraph d v e -> (Int, Int) -> [[Int]]
+ IGraph.Clique: cliques :: Graph d v e -> (Int, Int) -> [[Int]]
- IGraph.Clique: maximalCliques :: LGraph d v e -> (Int, Int) -> [[Int]]
+ IGraph.Clique: maximalCliques :: Graph d v e -> (Int, Int) -> [[Int]]
- IGraph.Community: LeadingEigenvector :: CommunityMethod
+ IGraph.Community: LeadingEigenvector :: Int -> CommunityMethod
- IGraph.Community: Spinglass :: CommunityMethod
+ IGraph.Community: Spinglass :: Int -> Double -> Double -> Double -> Double -> CommunityMethod
- IGraph.Community: [_coolFact] :: CommunityOpt -> Double
+ IGraph.Community: [_coolFact] :: CommunityMethod -> Double
- IGraph.Community: [_gamma] :: CommunityOpt -> Double
+ IGraph.Community: [_gamma] :: CommunityMethod -> Double
- IGraph.Community: [_nIter] :: CommunityOpt -> Int
+ IGraph.Community: [_nIter] :: CommunityMethod -> Int
- IGraph.Community: [_nSpins] :: CommunityOpt -> Int
+ IGraph.Community: [_nSpins] :: CommunityMethod -> Int
- IGraph.Community: [_startTemp] :: CommunityOpt -> Double
+ IGraph.Community: [_startTemp] :: CommunityMethod -> Double
- IGraph.Community: [_stopTemp] :: CommunityOpt -> Double
+ IGraph.Community: [_stopTemp] :: CommunityMethod -> Double
- IGraph.Community: findCommunity :: LGraph U v e -> CommunityOpt -> [[Int]]
+ IGraph.Community: findCommunity :: Graph 'U v e -> Maybe [Double] -> CommunityMethod -> [[Int]]
- IGraph.Exporter.GEXF: genXMLTree :: (ArrowXml a, Graph d) => LGraph d NodeAttr EdgeAttr -> a XmlTree XmlTree
+ IGraph.Exporter.GEXF: genXMLTree :: (SingI d, ArrowXml a) => Graph d NodeAttr EdgeAttr -> a XmlTree XmlTree
- IGraph.Exporter.GEXF: writeGEXF :: Graph d => FilePath -> LGraph d NodeAttr EdgeAttr -> IO ()
+ IGraph.Exporter.GEXF: writeGEXF :: SingI d => FilePath -> Graph d NodeAttr EdgeAttr -> IO ()
- IGraph.Generators: degreeSequenceGame :: [Int] -> [Int] -> IO (LGraph D () ())
+ IGraph.Generators: degreeSequenceGame :: [Int] -> [Int] -> IO (Graph 'D () ())
- IGraph.Generators: erdosRenyiGame :: Graph d => ErdosRenyiModel -> d -> Bool -> IO (LGraph d () ())
+ IGraph.Generators: erdosRenyiGame :: forall d. SingI d => ErdosRenyiModel -> Bool -> IO (Graph d () ())
- IGraph.Generators: full :: (Int) -> (Bool) -> (Bool) -> IO ((IGraph))
+ IGraph.Generators: full :: forall d. SingI d => Int -> Bool -> Graph d () ()
- IGraph.Generators: rewire :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e) => Int -> LGraph d v e -> IO (LGraph d v e)
+ IGraph.Generators: rewire :: (Hashable v, Serialize v, Eq v, Serialize e) => Int -> Graph d v e -> IO (Graph d v e)
- IGraph.Internal: bsvectorSet :: BSVector -> Int -> ByteString -> IO ()
+ IGraph.Internal: bsvectorSet :: Ptr BSVector -> Int -> ByteString -> IO ()
- IGraph.Internal: igraphAddEdges :: (IGraph) -> (Vector) -> (Ptr ()) -> IO ()
+ IGraph.Internal: igraphAddEdges :: (IGraph) -> (Ptr Vector) -> (Ptr ()) -> IO ()
- IGraph.Internal: igraphDeleteEdges :: (IGraph) -> (IGraphEs) -> IO ((Int))
+ IGraph.Internal: igraphDeleteEdges :: (IGraph) -> (Ptr EdgeSelector) -> IO ()
- IGraph.Internal: igraphDeleteVertices :: (IGraph) -> (IGraphVs) -> IO ((Int))
+ IGraph.Internal: igraphDeleteVertices :: (IGraph) -> (Ptr VertexSelector) -> IO ()
- IGraph.Internal: igraphHaskellAttributeEASSet :: (IGraph) -> (String) -> (Int) -> (Ptr BSLen) -> IO ((Int))
+ IGraph.Internal: igraphHaskellAttributeEASSet :: (IGraph) -> (String) -> (Int) -> (Ptr BSLen) -> IO ()
- IGraph.Internal: igraphHaskellAttributeEASSetv :: (IGraph) -> (String) -> (BSVector) -> IO ((Int))
+ IGraph.Internal: igraphHaskellAttributeEASSetv :: (IGraph) -> (String) -> (Ptr BSVector) -> IO ()
- IGraph.Internal: igraphHaskellAttributeVASSet :: (IGraph) -> (String) -> (Int) -> (Ptr BSLen) -> IO ((Int))
+ IGraph.Internal: igraphHaskellAttributeVASSet :: (IGraph) -> (String) -> (Int) -> (Ptr BSLen) -> IO ()
- IGraph.Internal: igraphMatrixCopyTo :: (Matrix) -> (Ptr CDouble) -> IO ()
+ IGraph.Internal: igraphMatrixCopyTo :: (Ptr Matrix) -> (Ptr CDouble) -> IO ()
- IGraph.Internal: igraphMatrixE :: (Matrix) -> (Int) -> (Int) -> IO ((Double))
+ IGraph.Internal: igraphMatrixE :: (Ptr Matrix) -> (Int) -> (Int) -> IO ((Double))
- IGraph.Internal: igraphMatrixFill :: (Matrix) -> (Double) -> IO ()
+ IGraph.Internal: igraphMatrixFill :: (Ptr Matrix) -> (Double) -> IO ()
- IGraph.Internal: igraphMatrixNcol :: (Matrix) -> IO ((Int))
+ IGraph.Internal: igraphMatrixNcol :: (Ptr Matrix) -> IO ((Int))
- IGraph.Internal: igraphMatrixNrow :: (Matrix) -> IO ((Int))
+ IGraph.Internal: igraphMatrixNrow :: (Ptr Matrix) -> IO ((Int))
- IGraph.Internal: igraphMatrixNull :: (Matrix) -> IO ()
+ IGraph.Internal: igraphMatrixNull :: (Ptr Matrix) -> IO ()
- IGraph.Internal: igraphMatrixSet :: (Matrix) -> (Int) -> (Int) -> (Double) -> IO ()
+ IGraph.Internal: igraphMatrixSet :: (Ptr Matrix) -> (Int) -> (Int) -> (Double) -> IO ()
- IGraph.Internal: igraphVectorCopyTo :: (Vector) -> (Ptr CDouble) -> IO ()
+ IGraph.Internal: igraphVectorCopyTo :: (Ptr Vector) -> (Ptr CDouble) -> IO ()
- IGraph.Internal: igraphVectorE :: (Vector) -> (Int) -> (Double)
+ IGraph.Internal: igraphVectorE :: (Ptr Vector) -> (Int) -> IO ((Double))
- IGraph.Internal: igraphVectorFill :: (Vector) -> (Double) -> IO ()
+ IGraph.Internal: igraphVectorFill :: (Ptr Vector) -> (Double) -> IO ()
- IGraph.Internal: igraphVectorNull :: (Vector) -> IO ()
+ IGraph.Internal: igraphVectorNull :: (Ptr Vector) -> IO ()
- IGraph.Internal: igraphVectorSet :: (Vector) -> (Int) -> (Double) -> IO ()
+ IGraph.Internal: igraphVectorSet :: (Ptr Vector) -> (Int) -> (Double) -> IO ()
- IGraph.Internal: igraphVectorSize :: (Vector) -> IO ((Int))
+ IGraph.Internal: igraphVectorSize :: (Ptr Vector) -> IO ((Int))
- IGraph.Internal: igraphVectorTail :: (Vector) -> (Double)
+ IGraph.Internal: igraphVectorTail :: (Ptr Vector) -> IO ((Double))
- IGraph.Internal: toColumnLists :: Matrix -> IO [[Double]]
+ IGraph.Internal: toColumnLists :: Ptr Matrix -> IO [[Double]]
- IGraph.Internal: toList :: Vector -> IO [Double]
+ IGraph.Internal: toList :: Ptr Vector -> IO [Double]
- IGraph.Internal: toLists :: VectorPtr -> IO [[Double]]
+ IGraph.Internal: toLists :: Ptr VectorPtr -> IO [[Double]]
- IGraph.Internal: toRowLists :: Matrix -> IO [[Double]]
+ IGraph.Internal: toRowLists :: Ptr Matrix -> IO [[Double]]
- IGraph.Internal: withAttr :: String -> BSVector -> (Ptr AttributeRecord -> IO a) -> IO a
+ IGraph.Internal: withAttr :: Serialize a => String -> [a] -> (Ptr AttributeRecord -> IO b) -> IO b
- IGraph.Isomorphism: getSubisomorphisms :: Graph d => LGraph d v1 e1 -> LGraph d v2 e2 -> [[Int]]
+ IGraph.Isomorphism: getSubisomorphisms :: Graph d v1 e1 -> Graph d v2 e2 -> [[Int]]
- IGraph.Isomorphism: isoclass3 :: Graph d => d -> [LGraph d () ()]
+ IGraph.Isomorphism: isoclass3 :: forall d. SingI d => [Graph d () ()]
- IGraph.Isomorphism: isoclass4 :: Graph d => d -> [LGraph d () ()]
+ IGraph.Isomorphism: isoclass4 :: forall d. SingI d => [Graph d () ()]
- IGraph.Isomorphism: isoclassCreate :: Graph d => Int -> Int -> d -> LGraph d () ()
+ IGraph.Isomorphism: isoclassCreate :: forall d. SingI d => Int -> Int -> Graph d () ()
- IGraph.Isomorphism: isomorphic :: Graph d => LGraph d v1 e1 -> LGraph d v2 e2 -> Bool
+ IGraph.Isomorphism: isomorphic :: Graph d v1 e1 -> Graph d v2 e2 -> Bool
- IGraph.Layout: getLayout :: Graph d => LGraph d v e -> LayoutMethod -> IO [(Double, Double)]
+ IGraph.Layout: getLayout :: Graph d v e -> LayoutMethod -> IO [(Double, Double)]
- IGraph.Motif: triad :: [LGraph D () ()]
+ IGraph.Motif: triad :: [Graph 'D () ()]
- IGraph.Motif: triadCensus :: (Hashable v, Eq v, Read v) => LGraph d v e -> [Int]
+ IGraph.Motif: triadCensus :: (Hashable v, Eq v, Read v) => Graph d v e -> [Int]
- IGraph.Mutable: addEdges :: (MGraph d, PrimMonad m) => [(Int, Int)] -> MLGraph (PrimState m) d v e -> m ()
+ IGraph.Mutable: addEdges :: PrimMonad m => [(Int, Int)] -> MGraph (PrimState m) d v e -> m ()
- IGraph.Mutable: addLEdges :: (MGraph d, PrimMonad m, Serialize e) => [LEdge e] -> MLGraph (PrimState m) d v e -> m ()
+ IGraph.Mutable: addLEdges :: (PrimMonad m, Serialize e) => [LEdge e] -> MGraph (PrimState m) d v e -> m ()
- IGraph.Mutable: addLNodes :: (MGraph d, Serialize v, PrimMonad m) => [v] -> MLGraph (PrimState m) d v e -> m ()
+ IGraph.Mutable: addLNodes :: (Serialize v, PrimMonad m) => [v] -> MGraph (PrimState m) d v e -> m ()
- IGraph.Mutable: addNodes :: (MGraph d, PrimMonad m) => Int -> MLGraph (PrimState m) d v e -> m ()
+ IGraph.Mutable: addNodes :: PrimMonad m => Int -> MGraph (PrimState m) d v e -> m ()
- IGraph.Mutable: delEdges :: (MGraph d, PrimMonad m) => [(Int, Int)] -> MLGraph (PrimState m) d v e -> m ()
+ IGraph.Mutable: delEdges :: forall m d v e. (SingI d, PrimMonad m) => [(Int, Int)] -> MGraph (PrimState m) d v e -> m ()
- IGraph.Mutable: delNodes :: (MGraph d, PrimMonad m) => [Int] -> MLGraph (PrimState m) d v e -> m ()
+ IGraph.Mutable: delNodes :: PrimMonad m => [Int] -> MGraph (PrimState m) d v e -> m ()
- IGraph.Mutable: new :: (MGraph d, PrimMonad m) => Int -> m (MLGraph (PrimState m) d v e)
+ IGraph.Mutable: new :: forall m d v e. (SingI d, PrimMonad m) => Int -> m (MGraph (PrimState m) d v e)
- IGraph.Mutable: setEdgeAttr :: (PrimMonad m, Serialize e) => Int -> e -> MLGraph (PrimState m) d v e -> m ()
+ IGraph.Mutable: setEdgeAttr :: (PrimMonad m, Serialize e) => Int -> e -> MGraph (PrimState m) d v e -> m ()
- IGraph.Mutable: setNodeAttr :: (PrimMonad m, Serialize v) => Int -> v -> MLGraph (PrimState m) d v e -> m ()
+ IGraph.Mutable: setNodeAttr :: (PrimMonad m, Serialize v) => Int -> v -> MGraph (PrimState m) d v e -> m ()
- IGraph.Read: fromAdjMatrix :: Graph d => ByteString -> LGraph d ByteString ()
+ IGraph.Read: fromAdjMatrix :: SingI d => ByteString -> Graph d ByteString ()
- IGraph.Read: readAdjMatrix :: Graph d => FilePath -> IO (LGraph d ByteString ())
+ IGraph.Read: readAdjMatrix :: SingI d => FilePath -> IO (Graph d ByteString ())
- IGraph.Read: readAdjMatrixWeighted :: Graph d => FilePath -> IO (LGraph d ByteString Double)
+ IGraph.Read: readAdjMatrixWeighted :: SingI d => FilePath -> IO (Graph d ByteString Double)
- IGraph.Structure: betweenness :: [Int] -> LGraph d v e -> Maybe [Double] -> [Double]
+ IGraph.Structure: betweenness :: [Int] -> Graph d v e -> Maybe [Double] -> [Double]
- IGraph.Structure: closeness :: [Int] -> LGraph d v e -> Maybe [Double] -> Neimode -> Bool -> [Double]
+ IGraph.Structure: closeness :: [Int] -> Graph d v e -> Maybe [Double] -> Neimode -> Bool -> [Double]
- IGraph.Structure: eigenvectorCentrality :: LGraph d v e -> Maybe [Double] -> [Double]
+ IGraph.Structure: eigenvectorCentrality :: Graph d v e -> Maybe [Double] -> [Double]
- IGraph.Structure: inducedSubgraph :: (Hashable v, Eq v, Serialize v) => LGraph d v e -> [Int] -> LGraph d v e
+ IGraph.Structure: inducedSubgraph :: (Hashable v, Eq v, Serialize v) => Graph d v e -> [Int] -> Graph d v e
- IGraph.Structure: pagerank :: Graph d => LGraph d v e -> Maybe [Double] -> Double -> [Double]
+ IGraph.Structure: pagerank :: SingI d => Graph d v e -> Maybe [Double] -> Maybe [Double] -> Double -> [Double]
Files
- ChangeLog.md +8/−2
- haskell-igraph.cabal +4/−4
- src/IGraph.hs +171/−176
- src/IGraph/Clique.chs +26/−11
- src/IGraph/Community.chs +98/−78
- src/IGraph/Exporter/GEXF.hs +7/−6
- src/IGraph/Generators.chs +64/−28
- src/IGraph/Internal.chs +457/−253
- src/IGraph/Internal/Constants.chs +6/−0
- src/IGraph/Internal/Types.chs +0/−231
- src/IGraph/Isomorphism.chs +27/−23
- src/IGraph/Layout.chs +24/−24
- src/IGraph/Motif.chs +11/−11
- src/IGraph/Mutable.hs +94/−76
- src/IGraph/Read.hs +8/−7
- src/IGraph/Structure.chs +78/−115
- src/IGraph/Types.hs +28/−6
- tests/Test/Attributes.hs +6/−8
- tests/Test/Basic.hs +8/−7
- tests/Test/Clique.hs +36/−0
- tests/Test/Structure.hs +13/−1
- tests/test.hs +3/−1
ChangeLog.md view
@@ -1,8 +1,14 @@ Revision history for haskell-igraph =================================== +v0.6.0 -- 2018-05-10+--------------------++* Breaking change: Drop `Graph` type class. Change `LGraph` and `MLGraph` to+`Graph` and `MGraph`. The new `Graph` and `MGraph` types are now dependently typed.+ v0.5.0 -- 2018-04-25--------------------+-------------------- * Fix memory leaks. * Interface change: `mapNodes`, `mapEdges`, `filterNodes`, `filterEdges` become@@ -10,6 +16,6 @@ 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).
haskell-igraph.cabal view
@@ -1,5 +1,5 @@ name: haskell-igraph-version: 0.5.0+version: 0.6.0 synopsis: Haskell interface of the igraph library. description: igraph<"http://igraph.org/c/"> is a library for creating and manipulating large graphs. This package provides the Haskell@@ -27,7 +27,6 @@ exposed-modules: IGraph.Internal.Initialization IGraph.Internal.Constants- IGraph.Internal.Types IGraph.Internal IGraph IGraph.Types@@ -56,15 +55,15 @@ , bytestring >= 0.9 , bytestring-lexing >= 0.5 , cereal- , cereal-conduit , colour , conduit >= 1.3.0+ , data-ordlist , primitive , unordered-containers , hashable , hxt , split- , data-default-class+ , singletons extra-libraries: igraph hs-source-dirs: src@@ -87,6 +86,7 @@ Test.Structure Test.Isomorphism Test.Motif+ Test.Clique Test.Utils default-language: Haskell2010
src/IGraph.hs view
@@ -1,11 +1,24 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE ScopedTypeVariables #-}+ module IGraph ( Graph(..)- , LGraph(..)- , U- , D- , decodeC+ , EdgeType(..)+ , isDirected+ , nNodes+ , nodeLab+ , nodes+ , labNodes+ , nEdges+ , edgeLab+ , edges+ , labEdges+ , hasEdge+ , getNodes+ , getEdgeByEid+ , getEdgeLabByEid , empty , mkGraph , fromLabeledEdges@@ -29,11 +42,9 @@ import Conduit import Control.Arrow ((&&&))-import Control.Monad (forM, forM_, liftM, replicateM)+import Control.Monad (forM, forM_, liftM, replicateM, when) import Control.Monad.Primitive import Control.Monad.ST (runST)-import qualified Data.ByteString as B-import Data.Conduit.Cereal import Data.Either (fromRight) import Data.Hashable (Hashable) import qualified Data.HashMap.Strict as M@@ -41,103 +52,26 @@ import Data.List (sortBy) import Data.Ord (comparing) import Data.Serialize-import Foreign (castPtr)+import Data.Singletons (Sing, SingI (..), fromSing)+import Foreign (Ptr, castPtr) import System.IO.Unsafe (unsafePerformIO) import IGraph.Internal import IGraph.Internal.Constants-import IGraph.Mutable+import IGraph.Mutable (MGraph(..))+import qualified IGraph.Mutable as GM import IGraph.Types -class MGraph d => Graph d where- -- | Graph is directed or not.- isDirected :: LGraph d v e -> Bool- isD :: d -> Bool-- -- | Return the number of nodes in a graph.- nNodes :: LGraph d v e -> Int- nNodes (LGraph g _) = unsafePerformIO $ igraphVcount g- {-# INLINE nNodes #-}-- -- | Return all nodes. @nodes gr == [0 .. nNodes gr - 1]@.- nodes :: LGraph d v e -> [Node]- nodes gr = [0 .. nNodes gr - 1]- {-# INLINE nodes #-}-- labNodes :: Serialize v => LGraph d v e -> [LNode v]- labNodes gr = map (\i -> (i, nodeLab gr i)) $ nodes gr- {-# INLINE labNodes #-}-- -- | Return the number of edges in a graph.- nEdges :: LGraph d v e -> Int- nEdges (LGraph g _) = unsafePerformIO $ igraphEcount g- {-# INLINE nEdges #-}-- -- | Return all edges.- edges :: LGraph d v e -> [Edge]- edges gr = map (getEdgeByEid gr) [0 .. nEdges gr - 1]- {-# INLINE edges #-}-- labEdges :: Serialize e => LGraph d v e -> [LEdge e]- labEdges gr = map (getEdgeByEid gr &&& getEdgeLabByEid gr) [0 .. nEdges gr - 1]- {-# INLINE labEdges #-}-- -- | Whether a edge exists in the graph.- hasEdge :: LGraph d v e -> Edge -> Bool- hasEdge (LGraph g _) (fr, to) = unsafePerformIO $ do- i <- igraphGetEid g fr to True False- return $ i >= 0- {-# INLINE hasEdge #-}-- -- | Return the label of given node.- nodeLab :: Serialize v => LGraph d v e -> Node -> v- nodeLab (LGraph g _) i = unsafePerformIO $- igraphHaskellAttributeVAS g vertexAttr i >>= bsToByteString >>=- return . fromRight (error "decode failed") . decode- {-# INLINE nodeLab #-}-- -- | Return all nodes that are associated with given label.- getNodes :: (Hashable v, Eq v) => LGraph d v e -> v -> [Node]- getNodes gr x = M.lookupDefault [] x $ _labelToNode gr- {-# INLINE getNodes #-}-- -- | Return the label of given edge.- edgeLab :: Serialize e => LGraph d v e -> Edge -> e- edgeLab (LGraph g _) (fr,to) = unsafePerformIO $- igraphGetEid g fr to True True >>=- igraphHaskellAttributeEAS g edgeAttr >>= bsToByteString >>=- return . fromRight (error "decode failed") . decode- {-# INLINE edgeLab #-}-- -- | Find the edge by edge ID.- getEdgeByEid :: LGraph d v e -> Int -> Edge- getEdgeByEid (LGraph g _) i = unsafePerformIO $ igraphEdge g i- {-# INLINE getEdgeByEid #-}-- -- | Find the edge label by edge ID.- getEdgeLabByEid :: Serialize e => LGraph d v e -> Int -> e- getEdgeLabByEid (LGraph g _) i = unsafePerformIO $- igraphHaskellAttributeEAS g edgeAttr i >>= bsToByteString >>=- return . fromRight (error "decode failed") . decode- {-# INLINE getEdgeLabByEid #-}--instance Graph U where- isDirected = const False- isD = const False--instance Graph D where- isDirected = const True- isD = const True- -- | Graph with labeled nodes and edges.-data LGraph d v e = LGraph+data Graph (d :: EdgeType) v e = Graph { _graph :: IGraph , _labelToNode :: M.HashMap v [Node] } -instance (Graph d, Serialize v, Serialize e, Hashable v, Eq v)- => Serialize (LGraph d v e) where+instance (SingI d, Serialize v, Serialize e, Hashable v, Eq v)+ => Serialize (Graph d v e) where put gr = do+ put $ fromSing (sing :: Sing d) put $ nNodes gr go (nodeLab gr) (nNodes gr) 0 put $ nEdges gr@@ -146,42 +80,108 @@ go f n i | i >= n = return () | otherwise = put (f i) >> go f n (i+1) get = do+ directed <- get+ when (fromSing (sing :: Sing d) /= directed) $+ error "Incorrect graph type" nn <- get nds <- replicateM nn get ne <- get es <- replicateM ne get 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- , Serialize v, Serialize e, Hashable v, Eq v )- => ConduitT B.ByteString o m (LGraph d v e)-decodeC = do- nn <- sinkGet get- nds <- replicateM nn $ sinkGet get- ne <- sinkGet get- conduitGet2 get .| deserializeGraph nds ne+-- | Is the graph directed or not.+isDirected :: forall d v e. SingI d => Graph d v e -> Bool+isDirected _ = case fromSing (sing :: Sing d) of+ D -> True+ U -> False+{-# INLINE isDirected #-} +-- | Return the number of nodes in a graph.+nNodes :: Graph d v e -> Int+nNodes = unsafePerformIO . igraphVcount . _graph+{-# INLINE nNodes #-}++-- | Return all nodes. @nodes gr == [0 .. nNodes gr - 1]@.+nodes :: Graph d v e -> [Node]+nodes gr = [0 .. nNodes gr - 1]+{-# INLINE nodes #-}++labNodes :: Serialize v => Graph d v e -> [LNode v]+labNodes gr = map (\i -> (i, nodeLab gr i)) $ nodes gr+{-# INLINE labNodes #-}++-- | Return the number of edges in a graph.+nEdges :: Graph d v e -> Int+nEdges = unsafePerformIO . igraphEcount . _graph+{-# INLINE nEdges #-}++ -- | Return all edges.+edges :: Graph d v e -> [Edge]+edges gr = map (getEdgeByEid gr) [0 .. nEdges gr - 1]+{-# INLINE edges #-}++labEdges :: Serialize e => Graph d v e -> [LEdge e]+labEdges gr = map (getEdgeByEid gr &&& getEdgeLabByEid gr) [0 .. nEdges gr - 1]+{-# INLINE labEdges #-}++-- | Whether a edge exists in the graph.+hasEdge :: Graph d v e -> Edge -> Bool+hasEdge gr (fr, to) = unsafePerformIO $ do+ i <- igraphGetEid (_graph gr) fr to True False+ return $ i >= 0+{-# INLINE hasEdge #-}++-- | Return the label of given node.+nodeLab :: Serialize v => Graph d v e -> Node -> v+nodeLab gr i = unsafePerformIO $+ igraphHaskellAttributeVAS (_graph gr) vertexAttr i >>= toByteString >>=+ return . fromRight (error "decode failed") . decode+{-# INLINE nodeLab #-}++-- | Return all nodes that are associated with given label.+getNodes :: (Hashable v, Eq v) => Graph d v e -> v -> [Node]+getNodes gr x = M.lookupDefault [] x $ _labelToNode gr+{-# INLINE getNodes #-}++-- | Return the label of given edge.+edgeLab :: Serialize e => Graph d v e -> Edge -> e+edgeLab (Graph g _) (fr,to) = unsafePerformIO $+ igraphGetEid g fr to True True >>=+ igraphHaskellAttributeEAS g edgeAttr >>= toByteString >>=+ return . fromRight (error "decode failed") . decode+{-# INLINE edgeLab #-}++-- | Find the edge by edge ID.+getEdgeByEid :: Graph d v e -> Int -> Edge+getEdgeByEid (Graph g _) i = unsafePerformIO $ igraphEdge g i+{-# INLINE getEdgeByEid #-}++-- | Find the edge label by edge ID.+getEdgeLabByEid :: Serialize e => Graph d v e -> Int -> e+getEdgeLabByEid (Graph g _) i = unsafePerformIO $+ igraphHaskellAttributeEAS g edgeAttr i >>= toByteString >>=+ return . fromRight (error "decode failed") . decode+{-# INLINE getEdgeLabByEid #-}+ -- | Create a empty graph.-empty :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e)- => LGraph d v e-empty = runST $ new 0 >>= unsafeFreeze+empty :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e)+ => Graph d v e+empty = runST $ GM.new 0 >>= unsafeFreeze -- | Create a graph.-mkGraph :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e)+mkGraph :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e) => [v] -- ^ Nodes. Each will be assigned a ID from 0 to N. -> [LEdge e] -- ^ Labeled edges.- -> LGraph d v e+ -> Graph d v e mkGraph vattr es = runST $ do- g <- new 0- addLNodes vattr g- addLEdges es g+ g <- GM.new 0+ GM.addLNodes vattr g+ GM.addLEdges es g unsafeFreeze g -- | Create a graph from labeled edges.-fromLabeledEdges :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e)- => [((v, v), e)] -> LGraph d v e+fromLabeledEdges :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e)+ => [((v, v), e)] -> Graph d v e fromLabeledEdges es = mkGraph labels es' where es' = flip map es $ \((fr, to), x) -> ((f fr, f to), x)@@ -190,17 +190,20 @@ labelToId = M.fromList $ zip labels [0..] -- | Create a graph from a stream of labeled edges.-fromLabeledEdges' :: (PrimMonad m, Graph d, Hashable v, Serialize v, Eq v, Serialize e)+fromLabeledEdges' :: (MonadUnliftIO m, SingI d, Hashable v, Serialize v, Eq v, Serialize e) => a -- ^ Input, usually a file -> (a -> ConduitT () ((v, v), e) m ()) -- ^ deserialize the input into a stream of edges- -> m (LGraph d v e)+ -> m (Graph d v e) fromLabeledEdges' input mkConduit = do (labelToId, _, ne) <- runConduit $ mkConduit input .| foldlC f (M.empty, 0::Int, 0::Int)- let getId x = M.lookupDefault undefined x labelToId- runConduit $ mkConduit input .|- mapC (\((v1, v2), e) -> ((getId v1, getId v2), e)) .|- deserializeGraph (fst $ unzip $ sortBy (comparing snd) $ M.toList labelToId) ne+ let action evec bsvec = do+ let getId x = M.lookupDefault undefined x labelToId+ runConduit $ mkConduit input .|+ mapC (\((v1, v2), e) -> ((getId v1, getId v2), e)) .|+ deserializeGraph (fst $ unzip $ sortBy (comparing snd) $ M.toList labelToId) evec bsvec+ withRunInIO $ \runInIO -> allocaVectorN (2*ne) $ \evec ->+ allocaBSVectorN ne $ \bsvec -> (runInIO $ action evec bsvec) where f (vs, nn, ne) ((v1, v2), _) = let (vs', nn') = add v1 $ add v2 (vs, nn)@@ -210,110 +213,102 @@ then (m, i) else (M.insert v i m, i + 1) -deserializeGraph :: ( PrimMonad m, Graph d, Hashable v, Serialize v- , Eq v, Serialize e )+deserializeGraph :: (MonadIO m, SingI d, Hashable v, Serialize v, Eq v, Serialize e) => [v]- -> Int -- ^ The number of edges- -> ConduitT (LEdge e) o m (LGraph d v e)-deserializeGraph nds ne = do- evec <- unsafePrimToPrim $ igraphVectorNew $ 2 * ne- bsvec <- unsafePrimToPrim $ bsvectorNew ne- let f i ((fr, to), attr) = unsafePrimToPrim $ do+ -> Ptr Vector -- ^ a vector that is sufficient to hold all edges+ -> Ptr BSVector+ -> ConduitT (LEdge e) o m (Graph d v e)+deserializeGraph nds evec bsvec = do+ let f i ((fr, to), attr) = liftIO $ do igraphVectorSet evec (i*2) $ fromIntegral fr igraphVectorSet evec (i*2+1) $ fromIntegral to bsvectorSet bsvec i $ encode attr return $ i + 1 _ <- foldMC f 0- gr@(MLGraph g) <- new 0- addLNodes nds gr- unsafePrimToPrim $ withAttr edgeAttr bsvec $ \ptr -> do- vptr <- fromPtrs [castPtr ptr]- withVectorPtr vptr (igraphAddEdges g evec . castPtr)- unsafeFreeze gr+ liftIO $ do+ gr@(MGraph g) <- GM.new 0+ GM.addLNodes nds gr+ withBSAttr edgeAttr bsvec $ \ptr ->+ withPtrs [ptr] (igraphAddEdges g evec . castPtr)+ unsafeFreeze gr {-# 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+ => MGraph (PrimState m) d v e -> m (Graph d v e)+freeze (MGraph g) = do g' <- unsafePrimToPrim $ igraphCopy g- unsafeFreeze (MLGraph g')+ unsafeFreeze (MGraph 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)- => MLGraph (PrimState m) d v e -> m (LGraph d v e)-unsafeFreeze (MLGraph g) = unsafePrimToPrim $ do+ => MGraph (PrimState m) d v e -> m (Graph d v e)+unsafeFreeze (MGraph g) = unsafePrimToPrim $ do nV <- igraphVcount g labels <- forM [0 .. nV - 1] $ \i ->- igraphHaskellAttributeVAS g vertexAttr i >>= bsToByteString >>=+ igraphHaskellAttributeVAS g vertexAttr i >>= toByteString >>= return . fromRight (error "decode failed") . decode- return $ LGraph g $ M.fromListWith (++) $ zip labels $ map return [0..nV-1]+ return $ Graph g $ M.fromListWith (++) $ zip labels $ map return [0..nV-1] where -- | Create a mutable graph.-thaw :: (PrimMonad m, Graph d) => LGraph d v e -> m (MLGraph (PrimState m) d v e)-thaw (LGraph g _) = unsafePrimToPrim . liftM MLGraph . igraphCopy $ g+thaw :: PrimMonad m => Graph d v e -> m (MGraph (PrimState m) d v e)+thaw (Graph g _) = unsafePrimToPrim . liftM MGraph . igraphCopy $ 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 (LGraph g _) = return $ MLGraph g+unsafeThaw :: PrimMonad m => Graph d v e -> m (MGraph (PrimState m) d v e)+unsafeThaw (Graph g _) = return $ MGraph g -- | Find all neighbors of the given node.-neighbors :: LGraph d v e -> Node -> [Node]-neighbors gr i = unsafePerformIO $ do- vs <- igraphVsAdj i IgraphAll- vit <- igraphVitNew (_graph gr) vs- vitToList vit+neighbors :: Graph d v e -> Node -> [Node]+neighbors gr i = unsafePerformIO $ withVerticesAdj i IgraphAll $ \vs ->+ iterateVerticesC (_graph gr) vs $ \source -> runConduit $ source .| sinkList -- | Find all nodes that have a link from the given node.-suc :: LGraph D v e -> Node -> [Node]-suc gr i = unsafePerformIO $ do- vs <- igraphVsAdj i IgraphOut- vit <- igraphVitNew (_graph gr) vs- vitToList vit+suc :: Graph 'D v e -> Node -> [Node]+suc gr i = unsafePerformIO $ withVerticesAdj i IgraphOut $ \vs ->+ iterateVerticesC (_graph gr) vs $ \source -> runConduit $ source .| sinkList -- | Find all nodes that link to to the given node.-pre :: LGraph D v e -> Node -> [Node]-pre gr i = unsafePerformIO $ do- vs <- igraphVsAdj i IgraphIn- vit <- igraphVitNew (_graph gr) vs- vitToList vit+pre :: Graph 'D v e -> Node -> [Node]+pre gr i = unsafePerformIO $ withVerticesAdj i IgraphIn $ \vs ->+ iterateVerticesC (_graph gr) vs $ \source -> runConduit $ source .| sinkList -- | Apply a function to change nodes' labels.-nmap :: (Graph d, Serialize v1, Serialize v2, Hashable v2, Eq v2)- => (LNode v1 -> v2) -> LGraph d v1 e -> LGraph d v2 e+nmap :: (Serialize v1, Serialize v2, Hashable v2, Eq v2)+ => (LNode v1 -> v2) -> Graph d v1 e -> Graph d v2 e nmap f gr = runST $ do- (MLGraph gptr) <- thaw gr- let gr' = MLGraph gptr- forM_ (nodes gr) $ \x -> setNodeAttr x (f (x, nodeLab gr x)) gr'+ (MGraph gptr) <- thaw gr+ let gr' = MGraph gptr+ forM_ (nodes gr) $ \x -> GM.setNodeAttr x (f (x, nodeLab gr x)) gr' unsafeFreeze gr' -- | Apply a function to change edges' labels.-emap :: (Graph d, Serialize e1, Serialize e2, Hashable v, Eq v, Serialize v)- => (LEdge e1 -> e2) -> LGraph d v e1 -> LGraph d v e2+emap :: (Serialize e1, Serialize e2, Hashable v, Eq v, Serialize v)+ => (LEdge e1 -> e2) -> Graph d v e1 -> Graph d v e2 emap f gr = runST $ do- (MLGraph gptr) <- thaw gr- let gr' = MLGraph gptr+ (MGraph gptr) <- thaw gr+ let gr' = MGraph gptr forM_ [0 .. nEdges gr - 1] $ \i -> do let lab = f (getEdgeByEid gr i, getEdgeLabByEid gr i)- setEdgeAttr i lab gr'+ GM.setEdgeAttr i lab gr' unsafeFreeze gr' -- | Keep nodes that satisfy the constraint.-nfilter :: (Hashable v, Eq v, Serialize v, Graph d)- => (LNode v -> Bool) -> LGraph d v e -> LGraph d v e+nfilter :: (Hashable v, Eq v, Serialize v)+ => (LNode v -> Bool) -> Graph d v e -> Graph d v e nfilter f gr = runST $ do let deleted = fst $ unzip $ filter (not . f) $ labNodes gr gr' <- thaw gr- delNodes deleted gr'+ GM.delNodes deleted gr' unsafeFreeze gr' -- | Keep edges that satisfy the constraint.-efilter :: (Hashable v, Eq v, Serialize v, Serialize e, Graph d)- => (LEdge e -> Bool) -> LGraph d v e -> LGraph d v e+efilter :: (SingI d, Hashable v, Eq v, Serialize v, Serialize e)+ => (LEdge e -> Bool) -> Graph d v e -> Graph d v e efilter f gr = runST $ do let deleted = fst $ unzip $ filter (not . f) $ labEdges gr gr' <- thaw gr- delEdges deleted gr'+ GM.delEdges deleted gr' unsafeFreeze gr'
src/IGraph/Clique.chs view
@@ -1,35 +1,50 @@ {-# LANGUAGE ForeignFunctionInterface #-} module IGraph.Clique ( cliques+ , largestCliques , maximalCliques+ , cliqueNumber ) where import Control.Applicative ((<$>)) import System.IO.Unsafe (unsafePerformIO) import qualified Foreign.Ptr as C2HSImp+import Foreign import IGraph+import IGraph.Internal.C2HS {#import IGraph.Internal #} #include "haskell_igraph.h" -cliques :: LGraph d v e+cliques :: Graph d v e -> (Int, Int) -- ^ Minimum and maximum size of the cliques to be returned. -- No bound will be used if negative or zero -> [[Int]] -- ^ cliques represented by node ids-cliques gr (lo, hi) = unsafePerformIO $ do- vpptr <- igraphVectorPtrNew 0- _ <- igraphCliques (_graph gr) vpptr lo hi- (map.map) truncate <$> toLists vpptr-{#fun igraph_cliques as ^ { `IGraph', `VectorPtr', `Int', `Int' } -> `Int' #}+cliques gr (lo, hi) = unsafePerformIO $ allocaVectorPtr $ \vptr -> do+ igraphCliques (_graph gr) vptr lo hi+ (map.map) truncate <$> toLists vptr+{#fun igraph_cliques as ^ { `IGraph', castPtr `Ptr VectorPtr', `Int', `Int' } -> `CInt' void- #} -maximalCliques :: LGraph d v e+largestCliques :: Graph d v e -> [[Int]]+largestCliques gr = unsafePerformIO $ allocaVectorPtr $ \vptr -> do+ igraphLargestCliques (_graph gr) vptr+ (map.map) truncate <$> toLists vptr+{#fun igraph_largest_cliques as ^ { `IGraph', castPtr `Ptr VectorPtr' } -> `CInt' void- #}++maximalCliques :: Graph d v e -> (Int, Int) -- ^ Minimum and maximum size of the cliques to be returned. -- No bound will be used if negative or zero -> [[Int]] -- ^ cliques represented by node ids-maximalCliques gr (lo, hi) = unsafePerformIO $ do- vpptr <- igraphVectorPtrNew 0- _ <- igraphMaximalCliques (_graph gr) vpptr lo hi+maximalCliques gr (lo, hi) = unsafePerformIO $ allocaVectorPtr $ \vpptr -> do+ igraphMaximalCliques (_graph gr) vpptr lo hi (map.map) truncate <$> toLists vpptr-{#fun igraph_maximal_cliques as ^ { `IGraph', `VectorPtr', `Int', `Int' } -> `Int' #}+{#fun igraph_maximal_cliques as ^ { `IGraph', castPtr `Ptr VectorPtr', `Int', `Int' } -> `CInt' void- #}++cliqueNumber :: Graph d v e -> Int+cliqueNumber gr = unsafePerformIO $ igraphCliqueNumber $ _graph gr+{#fun igraph_clique_number as ^+ { `IGraph'+ , alloca- `Int' peekIntConv*+ } -> `CInt' void- #}
src/IGraph/Community.chs view
@@ -1,13 +1,17 @@ {-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE DataKinds #-} module IGraph.Community- ( CommunityOpt(..)- , CommunityMethod(..)+ ( modularity , findCommunity+ , CommunityMethod(..)+ , defaultLeadingEigenvector+ , defaultSpinglass ) where -import Data.Default.Class import Data.Function (on) import Data.List (sortBy, groupBy)+import Data.List.Ordered (nubSortBy) import Data.Ord (comparing) import System.IO.Unsafe (unsafePerformIO) @@ -15,99 +19,115 @@ import Foreign.C.Types import IGraph+import IGraph.Internal.C2HS {#import IGraph.Internal #} {#import IGraph.Internal.Constants #} #include "haskell_igraph.h" -data CommunityOpt = CommunityOpt- { _method :: CommunityMethod- , _weights :: Maybe [Double]- , _nIter :: Int -- ^ [LeadingEigenvector] number of iterations, default is 10000- , _nSpins :: Int -- ^ [Spinglass] number of spins, default is 25- , _startTemp :: Double -- ^ [Spinglass] the temperature at the start- , _stopTemp :: Double -- ^ [Spinglass] the algorithm stops at this temperature- , _coolFact :: Double -- ^ [Spinglass] the cooling factor for the simulated annealing- , _gamma :: Double -- ^ [Spinglass] the gamma parameter of the algorithm.- }--data CommunityMethod = LeadingEigenvector- | Spinglass+modularity :: Graph d v e+ -> [[Int]] -- ^ Communities.+ -> Maybe [Double] -- ^ Weights+ -> Double+modularity gr clusters ws+ | length nds /= length (concat clusters) = error "Duplicated nodes"+ | nds /= nodes gr = error "Some nodes were not given community assignments"+ | otherwise = unsafePerformIO $ withList membership $ \membership' ->+ withListMaybe ws (igraphModularity (_graph gr) membership')+ where+ (membership, nds) = unzip $ nubSortBy (comparing snd) $ concat $+ zipWith f [0 :: Int ..] clusters+ where+ f i xs = zip (repeat i) xs+{#fun igraph_modularity as ^+ { `IGraph'+ , castPtr `Ptr Vector'+ , alloca- `Double' peekFloatConv*+ , castPtr `Ptr Vector'+ } -> `CInt' void- #} -instance Default CommunityOpt where- def = CommunityOpt- { _method = LeadingEigenvector- , _weights = Nothing- , _nIter = 10000- , _nSpins = 25- , _startTemp = 1.0- , _stopTemp = 0.01- , _coolFact = 0.99- , _gamma = 1.0+data CommunityMethod =+ LeadingEigenvector+ { _nIter :: Int -- ^ number of iterations, default is 10000 }+ | Spinglass+ { _nSpins :: Int -- ^ number of spins, default is 25+ , _startTemp :: Double -- ^ the temperature at the start+ , _stopTemp :: Double -- ^ the algorithm stops at this temperature+ , _coolFact :: Double -- ^ the cooling factor for the simulated annealing+ , _gamma :: Double -- ^ the gamma parameter of the algorithm.+ } -findCommunity :: LGraph U v e -> CommunityOpt -> [[Int]]-findCommunity gr opt = unsafePerformIO $ do- result <- igraphVectorNew 0- ws <- case _weights opt of- Just w -> fromList w- _ -> fmap Vector $ newForeignPtr_ $ castPtr nullPtr+defaultLeadingEigenvector :: CommunityMethod+defaultLeadingEigenvector = LeadingEigenvector 10000 - _ <- case _method opt of- LeadingEigenvector -> do- ap <- igraphArpackNew- igraphCommunityLeadingEigenvector (_graph gr) ws nullPtr result- (_nIter opt) ap nullPtr False- nullPtr nullPtr nullPtr- nullFunPtr nullPtr- Spinglass ->- igraphCommunitySpinglass (_graph gr) ws nullPtr nullPtr result- nullPtr (_nSpins opt) False (_startTemp opt)- (_stopTemp opt) (_coolFact opt)- IgraphSpincommUpdateConfig (_gamma opt)+defaultSpinglass :: CommunityMethod+defaultSpinglass = Spinglass+ { _nSpins = 25+ , _startTemp = 1.0+ , _stopTemp = 0.01+ , _coolFact = 0.99+ , _gamma = 1.0 }++findCommunity :: Graph 'U v e+ -> Maybe [Double] -- ^ node weights+ -> CommunityMethod -- ^ Community finding algorithms+ -> [[Int]]+findCommunity gr ws method = unsafePerformIO $ allocaVector $ \result ->+ withListMaybe ws $ \ws' -> do+ case method of+ LeadingEigenvector n -> allocaArpackOpt $ \arpack ->+ igraphCommunityLeadingEigenvector (_graph gr) ws' nullPtr result+ n arpack nullPtr False+ nullPtr nullPtr nullPtr+ nullFunPtr nullPtr+ Spinglass{..} -> igraphCommunitySpinglass (_graph gr) ws' nullPtr nullPtr result+ nullPtr _nSpins False _startTemp+ _stopTemp _coolFact+ IgraphSpincommUpdateConfig _gamma IgraphSpincommImpOrig 1.0 - fmap ( map (fst . unzip) . groupBy ((==) `on` snd)- . sortBy (comparing snd) . zip [0..] ) $ toList result+ fmap ( map (fst . unzip) . groupBy ((==) `on` snd)+ . sortBy (comparing snd) . zip [0..] ) $ toList result {#fun igraph_community_spinglass as ^-{ `IGraph'-, `Vector'-, id `Ptr CDouble'-, id `Ptr CDouble'-, `Vector'-, id `Ptr Vector'-, `Int'-, `Bool'-, `Double'-, `Double'-, `Double'-, `SpincommUpdate'-, `Double'-, `SpinglassImplementation'-, `Double'-} -> `Int' #}+ { `IGraph'+ , castPtr `Ptr Vector'+ , id `Ptr CDouble'+ , id `Ptr CDouble'+ , castPtr `Ptr Vector'+ , castPtr `Ptr Vector'+ , `Int'+ , `Bool'+ , `Double'+ , `Double'+ , `Double'+ , `SpincommUpdate'+ , `Double'+ , `SpinglassImplementation'+ , `Double'+ } -> `CInt' void- #} {#fun igraph_community_leading_eigenvector as ^-{ `IGraph'-, `Vector'-, id `Ptr Matrix'-, `Vector'-, `Int'-, `ArpackOpt'-, id `Ptr CDouble'-, `Bool'-, id `Ptr Vector'-, id `Ptr VectorPtr'-, id `Ptr Vector'-, id `T'-, id `Ptr ()'-} -> `Int' #}+ { `IGraph'+ , castPtr `Ptr Vector'+ , castPtr `Ptr Matrix'+ , castPtr `Ptr Vector'+ , `Int'+ , castPtr `Ptr ArpackOpt'+ , id `Ptr CDouble'+ , `Bool'+ , castPtr `Ptr Vector'+ , castPtr `Ptr VectorPtr'+ , castPtr `Ptr Vector'+ , id `T'+ , id `Ptr ()'+ } -> `CInt' void- #} -type T = FunPtr ( Ptr Vector+type T = FunPtr ( Ptr () -> CLong -> CDouble- -> Ptr Vector+ -> Ptr () -> FunPtr (Ptr CDouble -> Ptr CDouble -> CInt -> Ptr () -> IO CInt) -> Ptr () -> Ptr ()
src/IGraph/Exporter/GEXF.hs view
@@ -9,12 +9,13 @@ , writeGEXF ) where -import Data.Colour (AlphaColour, alphaChannel, black,- opaque, over)-import Data.Colour.SRGB (channelBlue, channelGreen,- channelRed, toSRGB24)+import Data.Colour (AlphaColour, alphaChannel, black, opaque,+ over)+import Data.Colour.SRGB (channelBlue, channelGreen, channelRed,+ toSRGB24) import Data.Hashable import Data.Serialize+import Data.Singletons (SingI) import GHC.Generics import IGraph import Text.XML.HXT.Core@@ -71,7 +72,7 @@ , _edgeZindex = 2 } -genXMLTree :: (ArrowXml a, Graph d) => LGraph d NodeAttr EdgeAttr -> a XmlTree XmlTree+genXMLTree :: (SingI d, ArrowXml a) => Graph d NodeAttr EdgeAttr -> a XmlTree XmlTree genXMLTree gr = root [] [gexf] where gexf = mkelem "gexf" [ attr "version" $ txt "1.2"@@ -124,7 +125,7 @@ a = show $ alphaChannel $ _edgeColour at {-# INLINE genXMLTree #-} -writeGEXF :: Graph d => FilePath -> LGraph d NodeAttr EdgeAttr -> IO ()+writeGEXF :: SingI d => FilePath -> Graph d NodeAttr EdgeAttr -> IO () writeGEXF fl gr = runX (genXMLTree gr >>> writeDocument config fl) >> return () where config = [withIndent yes]
src/IGraph/Generators.chs view
@@ -1,46 +1,83 @@ {-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-} module IGraph.Generators ( full+ , star , ErdosRenyiModel(..) , erdosRenyiGame , degreeSequenceGame , rewire ) where -import Control.Monad (when)+import Control.Monad (when, forM_) import Data.Hashable (Hashable) import Data.Serialize (Serialize)+import Data.Singletons (SingI, Sing, sing, fromSing)+import System.IO.Unsafe (unsafePerformIO) import qualified Foreign.Ptr as C2HSImp+import Foreign import IGraph-import IGraph.Mutable+import IGraph.Mutable (MGraph(..))+import qualified IGraph.Mutable as M {#import IGraph.Internal #} {#import IGraph.Internal.Constants #} {# import IGraph.Internal.Initialization #} #include "haskell_igraph.h" -{#fun igraph_full as full+full :: forall d. SingI d+ => Int -- ^ The number of vertices in the graph.+ -> Bool -- ^ Whether to include self-edges (loops)+ -> Graph d () ()+full n hasLoop = unsafePerformIO $ do+ gr <- MGraph <$> igraphFull n directed hasLoop+ M.initializeNullAttribute gr+ unsafeFreeze gr+ where+ directed = case fromSing (sing :: Sing d) of+ D -> True+ U -> False+{#fun igraph_full as ^ { allocaIGraph- `IGraph' addIGraphFinalizer* , `Int', `Bool', `Bool' } -> `CInt' void- #} +-- | Return the Star graph. The center node is always associated with id 0.+star :: Int -- ^ The number of nodes+ -> Graph 'U () ()+star n = unsafePerformIO $ do+ gr <- MGraph <$> igraphStar n IgraphStarUndirected 0+ M.initializeNullAttribute gr+ unsafeFreeze gr+{# fun igraph_star as ^+ { allocaIGraph- `IGraph' addIGraphFinalizer*+ , `Int'+ , `StarMode'+ , `Int'+ } -> `CInt' void- #}+ data ErdosRenyiModel = GNP Int Double | GNM Int Int -erdosRenyiGame :: Graph d+erdosRenyiGame :: forall d. SingI d => ErdosRenyiModel- -> d -- ^ directed -> Bool -- ^ self-loop- -> IO (LGraph d () ())-erdosRenyiGame (GNP n p) d self = do- gp <- igraphInit >> igraphErdosRenyiGame IgraphErdosRenyiGnp n p (isD d) self- unsafeFreeze $ MLGraph gp-erdosRenyiGame (GNM n m) d self = do- gp <- igraphInit >> igraphErdosRenyiGame IgraphErdosRenyiGnm n- (fromIntegral m) (isD d) self- unsafeFreeze $ MLGraph gp+ -> IO (Graph d () ())+erdosRenyiGame model self = do+ igraphInit+ gr <- fmap MGraph $ case model of+ GNP n p -> igraphErdosRenyiGame IgraphErdosRenyiGnp n p directed self+ GNM n m -> igraphErdosRenyiGame IgraphErdosRenyiGnm n (fromIntegral m)+ directed self+ M.initializeNullAttribute gr+ unsafeFreeze gr+ where+ directed = case fromSing (sing :: Sing d) of+ D -> True+ U -> False {#fun igraph_erdos_renyi_game as ^ { allocaIGraph- `IGraph' addIGraphFinalizer* , `ErdosRenyi', `Int', `Double', `Bool', `Bool'@@ -49,25 +86,24 @@ -- | Generates a random graph with a given degree sequence. degreeSequenceGame :: [Int] -- ^ Out degree -> [Int] -- ^ In degree- -> IO (LGraph D () ())-degreeSequenceGame out_deg in_deg = do- out_deg' <- fromList $ map fromIntegral out_deg- in_deg' <- fromList $ map fromIntegral in_deg- gp <- igraphDegreeSequenceGame out_deg' in_deg' IgraphDegseqSimple- unsafeFreeze $ MLGraph gp+ -> IO (Graph 'D () ())+degreeSequenceGame out_deg in_deg = withList out_deg $ \out_deg' ->+ withList in_deg $ \in_deg' -> do+ gr <- MGraph <$> igraphDegreeSequenceGame out_deg' in_deg' IgraphDegseqSimple+ M.initializeNullAttribute gr+ unsafeFreeze gr {#fun igraph_degree_sequence_game as ^ { allocaIGraph- `IGraph' addIGraphFinalizer*- , `Vector', `Vector', `Degseq'+ , castPtr `Ptr Vector', castPtr `Ptr Vector', `Degseq' } -> `CInt' void- #} -- | Randomly rewires a graph while preserving the degree distribution.-rewire :: (Graph d, Hashable v, Serialize v, Eq v, Serialize e)+rewire :: (Hashable v, Serialize v, Eq v, Serialize e) => Int -- ^ Number of rewiring trials to perform.- -> LGraph d v e- -> IO (LGraph d v e)+ -> Graph d v e+ -> IO (Graph d v e) rewire n gr = do- (MLGraph gptr) <- thaw gr- err <- igraphRewire gptr n IgraphRewiringSimple- when (err /= 0) $ error "failed to rewire graph!"- unsafeFreeze $ MLGraph gptr-{#fun igraph_rewire as ^ { `IGraph', `Int', `Rewiring' } -> `Int' #}+ (MGraph gptr) <- thaw gr+ igraphRewire gptr n IgraphRewiringSimple+ unsafeFreeze $ MGraph gptr+{#fun igraph_rewire as ^ { `IGraph', `Int', `Rewiring' } -> `CInt' void-#}
src/IGraph/Internal.chs view
@@ -1,9 +1,12 @@ {-# LANGUAGE ForeignFunctionInterface #-} module IGraph.Internal- ( module IGraph.Internal.Types- -- * Vector type and basic operations- , igraphVectorNew- , fromList+ ( -- * Data structure library: vector, matrix, other data types+ -- ** Igraph vector type and basic operations+ Vector+ , allocaVector+ , allocaVectorN+ , withList+ , withListMaybe , toList , igraphVectorNull , igraphVectorFill@@ -13,27 +16,31 @@ , igraphVectorSize , igraphVectorCopyTo - -- * Pointer vector- , igraphVectorPtrNew- , fromPtrs+ -- ** Igraph pointer vector+ , VectorPtr+ , allocaVectorPtr+ , allocaVectorPtrN+ , withPtrs , toLists - -- * String vector- , igraphStrvectorNew- , igraphStrvectorGet- , toStrVector-- -- * Bytestring- , asBS- , bsToByteString+ -- ** Customized bytestring for storing attributes+ , BSLen+ , withByteString+ , toByteString - -- * Bytestring vector- , bsvectorNew+ -- ** Customized bytestring vector+ , BSVector+ , allocaBSVectorN+ , withByteStrings , bsvectorSet- , toBSVector - -- * Igraph matrix type- , igraphMatrixNew+ -- ** Igraph matrix type+ , Matrix+ , allocaMatrix+ , allocaMatrixN+ , withRowLists+ , toRowLists+ , toColumnLists , igraphMatrixNull , igraphMatrixFill , igraphMatrixE@@ -41,29 +48,40 @@ , igraphMatrixCopyTo , igraphMatrixNrow , igraphMatrixNcol- , fromRowLists- , toRowLists- , toColumnLists - -- * Igraph vertex selector- , igraphVsAll- , igraphVsAdj- , igraphVsVector+ -- * Igraph type and constructors+ , IGraph+ , withIGraph+ , allocaIGraph+ , addIGraphFinalizer+ , igraphNew+ , igraphCreate - -- * Igraph vertex iterator- , igraphVitNew- , vitToList+ -- * Selector and iterator for edge and vertex+ -- ** Igraph vertex selector+ , VertexSelector+ , withVerticesAll+ , withVerticesAdj+ , withVerticesVector+ , withVerticesList - -- * Igraph edge Selector- , igraphEsAll- , igraphEsVector+ -- ** Igraph vertex iterator+ , VertexIterator+ , iterateVertices+ , iterateVerticesC - -- * Igraph edge iterator- , igraphEitNew- , eitToList+ -- ** Igraph edge Selector+ , EdgeSelector+ , withEdgesAll+ , withEdgeIdsVector+ , withEdgeIdsList - -- * IGraph type and basic operations- , igraphNew+ -- ** Igraph edge iterator+ , EdgeIterator+ , iterateEdges+ , iterateEdgesC++ -- * Basic graph operations , igraphCopy , igraphVcount , igraphEcount@@ -75,17 +93,21 @@ , igraphDeleteVertices , igraphDeleteEdges - -- * Igraph attribute record+ -- * Igraph attribute record+ , AttributeRecord , withAttr+ , withBSAttr , igraphHaskellAttributeHasAttr- , igraphHaskellAttributeGANSet- , igraphHaskellAttributeGAN , igraphHaskellAttributeVAS- , igraphHaskellAttributeEAN , igraphHaskellAttributeEAS- , igraphHaskellAttributeEASSetv , igraphHaskellAttributeVASSet+ , igraphHaskellAttributeVASSetv , igraphHaskellAttributeEASSet+ , igraphHaskellAttributeEASSetv++ -- * Igraph arpack options type+ , ArpackOpt+ , allocaArpackOpt ) where import Control.Monad@@ -94,6 +116,9 @@ import Data.ByteString.Unsafe (unsafeUseAsCStringLen) import Data.List (transpose) import Data.List.Split (chunksOf)+import Data.Serialize (Serialize, encode)+import Control.Exception (bracket_)+import Conduit (ConduitT, yield, liftIO) import Foreign import Foreign.C.Types@@ -101,7 +126,6 @@ import IGraph.Internal.C2HS {#import IGraph.Internal.Initialization #}-{#import IGraph.Internal.Types #} {#import IGraph.Internal.Constants #} #include "haskell_attributes.h"@@ -111,20 +135,39 @@ -- Igraph vector -------------------------------------------------------------------------------- -{#fun igraph_vector_init as igraphVectorNew- { allocaVector- `Vector' addVectorFinalizer*- , `Int' } -> `CInt' void- #}+data Vector +-- | Allocate and initialize a vector.+allocaVector :: (Ptr Vector -> IO a) -> IO a+allocaVector fun = allocaBytes {# sizeof igraph_vector_t #} $ \vec ->+ bracket_ (igraphVectorInit vec 0) (igraphVectorDestroy vec) (fun vec)+{-# INLINE allocaVector #-}++allocaVectorN :: Int -> (Ptr Vector -> IO a) -> IO a+allocaVectorN n fun = allocaBytes {# sizeof igraph_vector_t #} $ \vec ->+ bracket_ (igraphVectorInit vec n) (igraphVectorDestroy vec) (fun vec)+{-# INLINE allocaVectorN #-}++{#fun igraph_vector_init as ^ { castPtr `Ptr Vector', `Int' } -> `CInt' void- #}+{#fun igraph_vector_destroy as ^ { castPtr `Ptr Vector' } -> `CInt' void- #}++withList :: Real a => [a] -> (Ptr Vector -> IO b) -> IO b+withList xs fun = withArrayLen (map realToFrac xs) $ \n ptr ->+ allocaBytes {# sizeof igraph_vector_t #} $ \vec ->+ bracket_ (igraphVectorInitCopy vec ptr n) (igraphVectorDestroy vec) (fun vec)+{-# INLINE withList #-} {#fun igraph_vector_init_copy as ^- { allocaVector- `Vector' addVectorFinalizer*+ { castPtr `Ptr Vector' , id `Ptr CDouble', `Int' } -> `CInt' void- #} -fromList :: [Double] -> IO Vector-fromList xs = withArrayLen (map realToFrac xs) $ \n ptr ->- igraphVectorInitCopy ptr n-{-# INLINE fromList #-}+-- | Allocate a nullPtr if Nothing+withListMaybe :: Real a => Maybe [a] -> (Ptr Vector -> IO b) -> IO b+withListMaybe (Just xs) fun = withList xs fun+withListMaybe Nothing fun = fun $ castPtr nullPtr+{-# INLINE withListMaybe #-} -toList :: Vector -> IO [Double]++toList :: Ptr Vector -> IO [Double] toList vec = do n <- igraphVectorSize vec allocaArray n $ \ptr -> do@@ -132,165 +175,153 @@ liftM (map realToFrac) $ peekArray n ptr {-# INLINE toList #-} +{#fun igraph_vector_copy_to as ^ { castPtr `Ptr Vector', id `Ptr CDouble' } -> `()' #}+ -- Initializing elements -{#fun igraph_vector_null as ^ { `Vector' } -> `()' #}+{#fun igraph_vector_null as ^ { castPtr `Ptr Vector' } -> `()' #} -{#fun igraph_vector_fill as ^ { `Vector', `Double' } -> `()' #}+{#fun igraph_vector_fill as ^ { castPtr `Ptr Vector', `Double' } -> `()' #} -- Accessing elements -{#fun pure igraph_vector_e as ^ { `Vector', `Int' } -> `Double' #}+{#fun igraph_vector_e as ^ { castPtr `Ptr Vector', `Int' } -> `Double' #} -{#fun igraph_vector_set as ^ { `Vector', `Int', `Double' } -> `()' #}+{#fun igraph_vector_set as ^ { castPtr `Ptr Vector', `Int', `Double' } -> `()' #} -{#fun pure igraph_vector_tail as ^ { `Vector' } -> `Double' #}+{#fun igraph_vector_tail as ^ { castPtr `Ptr Vector' } -> `Double' #} --- Copying vectors--{#fun igraph_vector_copy_to as ^ { `Vector', id `Ptr CDouble' } -> `()' #}- -- Vector properties-{#fun igraph_vector_size as ^ { `Vector' } -> `Int' #}+{#fun igraph_vector_size as ^ { castPtr `Ptr Vector' } -> `Int' #} -{#fun igraph_vector_ptr_init as igraphVectorPtrNew- { allocaVectorPtr- `VectorPtr' addVectorPtrFinalizer*- , `Int' } -> `CInt' void- #}--{#fun igraph_vector_ptr_e as ^ { `VectorPtr', `Int' } -> `Ptr ()' #}-{#fun igraph_vector_ptr_set as ^ { `VectorPtr', `Int', id `Ptr ()' } -> `()' #}-{#fun igraph_vector_ptr_size as ^ { `VectorPtr' } -> `Int' #}--fromPtrs :: [Ptr ()] -> IO VectorPtr-fromPtrs xs = do- vptr <- igraphVectorPtrNew n- forM_ (zip [0..] xs) $ \(i,x) -> igraphVectorPtrSet vptr i x- return vptr- where- n = length xs-{-# INLINE fromPtrs #-}--toLists :: VectorPtr -> IO [[Double]]-toLists vpptr = do- n <- igraphVectorPtrSize vpptr- forM [0..n-1] $ \i -> do- vptr <- igraphVectorPtrE vpptr i- vec <- newForeignPtr_ $ castPtr vptr- toList $ Vector vec-{-# INLINE toLists #-}- ----------------------------------------------------------------------------------- Igraph string vector+-- Pointer Vector -------------------------------------------------------------------------------- -{#fun igraph_strvector_init as igraphStrvectorNew- { allocaStrVector- `StrVector' addStrVectorFinalizer*- , `Int'- } -> `CInt' void-#}+data VectorPtr -{#fun igraph_strvector_get as ^- { `StrVector'- , `Int'- , alloca- `String' peekString*- } -> `CInt' void-#}+-- | Allocate and initialize a pointer vector.+allocaVectorPtr :: (Ptr VectorPtr -> IO a) -> IO a+allocaVectorPtr fun = allocaBytes {# sizeof igraph_vector_ptr_t #} $ \ptr ->+ bracket_ (igraphVectorPtrInit ptr 0) (igraphVectorPtrDestroy ptr) (fun ptr)+{-# INLINE allocaVectorPtr #-} -peekString :: Ptr CString -> IO String-peekString ptr = peek ptr >>= peekCString-{-# INLINE peekString #-}+allocaVectorPtrN :: Int -> (Ptr VectorPtr -> IO a) -> IO a+allocaVectorPtrN n fun = allocaBytes {# sizeof igraph_vector_ptr_t #} $ \ptr ->+ bracket_ (igraphVectorPtrInit ptr n) (igraphVectorPtrDestroy ptr) (fun ptr)+{-# INLINE allocaVectorPtrN #-} -{#fun igraph_strvector_set as ^ { `StrVector', `Int', id `CString'} -> `()' #}-{#fun igraph_strvector_set2 as ^ { `StrVector', `Int', id `CString', `Int'} -> `()' #}+{#fun igraph_vector_ptr_init as ^ { castPtr `Ptr VectorPtr', `Int' } -> `CInt' void- #}+{#fun igraph_vector_ptr_destroy as ^ { castPtr `Ptr VectorPtr' } -> `()' #} -toStrVector :: [B.ByteString] -> IO StrVector-toStrVector xs = do- vec <- igraphStrvectorNew n- forM_ (zip [0..] xs) $ \(i,x) -> B.useAsCString x (igraphStrvectorSet vec i)- return vec+withPtrs :: [Ptr a] -> (Ptr VectorPtr -> IO b) -> IO b+withPtrs xs fun = allocaVectorPtrN n $ \vptr -> do+ sequence_ $ zipWith (igraphVectorPtrSet vptr) [0..] $ map castPtr xs+ fun vptr where n = length xs+{-# INLINE withPtrs #-} +toLists :: Ptr VectorPtr -> IO [[Double]]+toLists vptr = do+ n <- igraphVectorPtrSize vptr+ forM [0..n-1] $ \i -> igraphVectorPtrE vptr i >>= toList . castPtr+{-# INLINE toLists #-} +{#fun igraph_vector_ptr_e as ^ { castPtr `Ptr VectorPtr', `Int' } -> `Ptr ()' #}+{#fun igraph_vector_ptr_set as ^ { castPtr `Ptr VectorPtr', `Int', id `Ptr ()' } -> `()' #}+{#fun igraph_vector_ptr_size as ^ { castPtr `Ptr VectorPtr' } -> `Int' #}++ -------------------------------------------------------------------------------- -- Customized string vector -------------------------------------------------------------------------------- -bsToByteString :: Ptr BSLen -> IO B.ByteString-bsToByteString ptr = do+data BSLen++toByteString :: Ptr BSLen -> IO B.ByteString+toByteString ptr = do n <- {#get bytestring_t->len #} ptr str <- {#get bytestring_t->value #} ptr packCStringLen (str, fromIntegral n)-{-# INLINE bsToByteString #-}+{-# INLINE toByteString #-} -asBS :: B.ByteString -> (Ptr BSLen -> IO a) -> IO a-asBS x f = unsafeUseAsCStringLen x $ \(str, n) -> do- fptr <- mallocForeignPtrBytes {#sizeof bytestring_t #}- withForeignPtr fptr $ \ptr -> do+withByteString :: B.ByteString -> (Ptr BSLen -> IO a) -> IO a+withByteString x f = unsafeUseAsCStringLen x $ \(str, n) ->+ allocaBytes {#sizeof bytestring_t #} $ \ptr -> do {#set bytestring_t.len #} ptr (fromIntegral n) {#set bytestring_t.value #} ptr str f ptr-{-# INLINE asBS #-}+{-# INLINE withByteString #-} -{#fun bsvector_init as bsvectorNew- { allocaBSVector- `BSVector' addBSVectorFinalizer*- , `Int'- } -> `CInt' void- #}+data BSVector -{#fun bsvector_set as bsvectorSet' { `BSVector', `Int', castPtr `Ptr BSLen' } -> `()' #}+allocaBSVectorN :: Int -> (Ptr BSVector -> IO a) -> IO a+allocaBSVectorN n fun = allocaBytes {# sizeof bsvector_t #} $ \ptr ->+ bracket_ (bsvectorInit ptr n) (bsvectorDestroy ptr) (fun ptr)+{-# INLINE allocaBSVectorN #-} -bsvectorSet :: BSVector -> Int -> B.ByteString -> IO ()-bsvectorSet vec i bs = asBS bs (bsvectorSet' vec i)-{-# INLINE bsvectorSet #-}+{#fun bsvector_init as ^ { castPtr `Ptr BSVector', `Int' } -> `CInt' void- #}+{#fun bsvector_destroy as ^ { castPtr `Ptr BSVector' } -> `()' #} -toBSVector :: [B.ByteString] -> IO BSVector-toBSVector xs = do- vec <- bsvectorNew n- foldM_ (\i x -> bsvectorSet vec i x >> return (i+1)) 0 xs- return vec+withByteStrings :: [B.ByteString] -> (Ptr BSVector -> IO a) -> IO a+withByteStrings xs fun = allocaBSVectorN n $ \bsvec -> do+ foldM_ (\i x -> bsvectorSet bsvec i x >> return (i+1)) 0 xs+ fun bsvec where n = length xs+{-# INLINE withByteStrings #-} +bsvectorSet :: Ptr BSVector -> Int -> B.ByteString -> IO ()+bsvectorSet vec i bs = withByteString bs (bsvectorSet' vec i)+{-# INLINE bsvectorSet #-}+{#fun bsvector_set as bsvectorSet'+ { castPtr `Ptr BSVector', `Int', castPtr `Ptr BSLen' } -> `()' #} -{#fun igraph_matrix_init as igraphMatrixNew- { allocaMatrix- `Matrix' addMatrixFinalizer*- , `Int', `Int'- } -> `CInt' void- #} -{#fun igraph_matrix_null as ^ { `Matrix' } -> `()' #}--{#fun igraph_matrix_fill as ^ { `Matrix', `Double' } -> `()' #}--{#fun igraph_matrix_e as ^ { `Matrix', `Int', `Int' } -> `Double' #}+--------------------------------------------------------------------------------+-- Matrix+-------------------------------------------------------------------------------- -{#fun igraph_matrix_set as ^ { `Matrix', `Int', `Int', `Double' } -> `()' #}+data Matrix -{#fun igraph_matrix_copy_to as ^ { `Matrix', id `Ptr CDouble' } -> `()' #}+allocaMatrix :: (Ptr Matrix -> IO a) -> IO a+allocaMatrix fun = allocaBytes {# sizeof igraph_matrix_t #} $ \mat ->+ bracket_ (igraphMatrixInit mat 0 0) (igraphMatrixDestroy mat) (fun mat)+{-# INLINE allocaMatrix #-} -{#fun igraph_matrix_nrow as ^ { `Matrix' } -> `Int' #}+allocaMatrixN :: Int -- ^ Number of rows+ -> Int -- ^ Number of columns+ -> (Ptr Matrix -> IO a) -> IO a+allocaMatrixN r c fun = allocaBytes {# sizeof igraph_matrix_t #} $ \mat ->+ bracket_ (igraphMatrixInit mat r c) (igraphMatrixDestroy mat) (fun mat)+{-# INLINE allocaMatrixN #-} -{#fun igraph_matrix_ncol as ^ { `Matrix' } -> `Int' #}+{#fun igraph_matrix_init as ^ { castPtr `Ptr Matrix', `Int', `Int' } -> `CInt' void- #}+{#fun igraph_matrix_destroy as ^ { castPtr `Ptr Matrix' } -> `()' #} -- row lists to matrix-fromRowLists :: [[Double]] -> IO Matrix-fromRowLists xs- | all (==c) $ map length xs = do- mptr <- igraphMatrixNew r c+withRowLists :: Real a => [[a]] -> (Ptr Matrix -> IO b) -> IO b+withRowLists xs fun+ | all (==c) $ map length xs = allocaMatrixN r c $ \mat -> do forM_ (zip [0..] xs) $ \(i, row) -> forM_ (zip [0..] row) $ \(j,v) ->- igraphMatrixSet mptr i j v- return mptr+ igraphMatrixSet mat i j $ realToFrac v+ fun mat | otherwise = error "Not a matrix." where r = length xs c = length $ head xs+{-# INLINE withRowLists #-} -- to row lists-toRowLists :: Matrix -> IO [[Double]]-toRowLists = liftM transpose . toColumnLists+toRowLists :: Ptr Matrix -> IO [[Double]]+toRowLists = fmap transpose . toColumnLists -toColumnLists :: Matrix -> IO [[Double]]+toColumnLists :: Ptr Matrix -> IO [[Double]] toColumnLists mptr = do r <- igraphMatrixNrow mptr c <- igraphMatrixNcol mptr@@ -299,132 +330,245 @@ peekArray (r*c) ptr return $ chunksOf r $ map realToFrac xs +{#fun igraph_matrix_null as ^ { castPtr `Ptr Matrix' } -> `()' #} -{#fun igraph_vs_all as ^- { allocaVs- `IGraphVs' addVsFinalizer*+{#fun igraph_matrix_fill as ^ { castPtr `Ptr Matrix', `Double' } -> `()' #}++{#fun igraph_matrix_e as ^ { castPtr `Ptr Matrix', `Int', `Int' } -> `Double' #}++{#fun igraph_matrix_set as ^ { castPtr `Ptr Matrix', `Int', `Int', `Double' } -> `()' #}++{#fun igraph_matrix_copy_to as ^ { castPtr `Ptr Matrix', id `Ptr CDouble' } -> `()' #}++{#fun igraph_matrix_nrow as ^ { castPtr `Ptr Matrix' } -> `Int' #}++{#fun igraph_matrix_ncol as ^ { castPtr `Ptr Matrix' } -> `Int' #}+++--------------------------------------------------------------------------------+-- Graph Constructors and Destructors+--------------------------------------------------------------------------------++{#pointer *igraph_t as IGraph foreign finalizer igraph_destroy newtype#}++allocaIGraph :: (Ptr IGraph -> IO a) -> IO a+allocaIGraph f = mallocBytes {# sizeof igraph_t #} >>= f+{-# INLINE allocaIGraph #-}++addIGraphFinalizer :: Ptr IGraph -> IO IGraph+addIGraphFinalizer ptr = do+ vec <- newForeignPtr igraph_destroy ptr+ return $ IGraph vec+{-# INLINE addIGraphFinalizer #-}++-- | Create a igraph object and attach a finalizer+igraphNew :: Int -> Bool -> HasInit -> IO IGraph+igraphNew n directed _ = igraphNew' n directed+{#fun igraph_empty as igraphNew'+ { allocaIGraph- `IGraph' addIGraphFinalizer*+ , `Int', `Bool' } -> `CInt' void- #} -{#fun igraph_vs_adj as ^- { allocaVs- `IGraphVs' addVsFinalizer*- , `Int', `Neimode'+{#fun igraph_copy as ^+ { allocaIGraph- `IGraph' addIGraphFinalizer*+ , `IGraph' } -> `CInt' void- #} -{#fun igraph_vs_vector as ^- { allocaVs- `IGraphVs' addVsFinalizer*- , `Vector'+{#fun igraph_create as ^+ { allocaIGraph- `IGraph' addIGraphFinalizer*+ , castPtr `Ptr Vector' -- ^ The edges to add, the first two elements are+ -- the first edge, etc.+ , `Int' -- ^ The number of vertices in the graph, if smaller or equal to+ -- the highest vertex id in the edges vector it will be+ -- increased automatically. So it is safe to give 0 here.+ , `Bool' -- ^ Whether to create a directed graph or not. If yes,+ -- then the first edge points from the first vertex id in edges+ -- to the second, etc. } -> `CInt' void- #} +{#fun igraph_to_directed as ^+ { `IGraph' -- ^ The graph object to convert.+ , `ToDirected' -- ^ Specifies the details of how exactly the conversion is+ -- done. Possible values: IGRAPH_TO_DIRECTED_ARBITRARY:+ -- the number of edges in the graph stays the same,+ -- an arbitrarily directed edge is created for each+ -- undirected edge; IGRAPH_TO_DIRECTED_MUTUAL: two directed+ -- edges are created for each undirected edge, one in each direction.+ } -> `CInt' void- #}+++--------------------------------------------------------------------------------+-- Vertex selector+--------------------------------------------------------------------------------++data VertexSelector++allocaVertexSelector :: (Ptr VertexSelector -> IO a) -> IO a+allocaVertexSelector fun = allocaBytes {# sizeof igraph_vs_t #} $ \vs -> do+ r <- fun vs+ igraphVsDestroy vs+ return r+{-# INLINE allocaVertexSelector #-}++{#fun igraph_vs_destroy as ^ { castPtr `Ptr VertexSelector' } -> `()' #}++withVerticesAll :: (Ptr VertexSelector -> IO a) -> IO a+withVerticesAll fun = allocaVertexSelector $ \vs -> igraphVsAll vs >> fun vs+{-# INLINE withVerticesAll #-}+{#fun igraph_vs_all as ^ { castPtr `Ptr VertexSelector' } -> `CInt' void- #}++withVerticesAdj :: Int -> Neimode -> (Ptr VertexSelector -> IO a) -> IO a+withVerticesAdj i mode fun = allocaVertexSelector $ \vs -> igraphVsAdj vs i mode >> fun vs+{-# INLINE withVerticesAdj #-}+{#fun igraph_vs_adj as ^+ { castPtr `Ptr VertexSelector', `Int', `Neimode' } -> `CInt' void- #}++withVerticesVector :: Ptr Vector -> (Ptr VertexSelector -> IO a) -> IO a+withVerticesVector vec fun = allocaVertexSelector $ \vs -> igraphVsVector vs vec >> fun vs+{-# INLINE withVerticesVector #-}+{#fun igraph_vs_vector as ^+ { castPtr `Ptr VertexSelector', castPtr `Ptr Vector' } -> `CInt' void- #}++withVerticesList :: Real a => [a] -> (Ptr VertexSelector -> IO b) -> IO b+withVerticesList xs fun = withList xs $ \vec -> withVerticesVector vec fun+{-# INLINE withVerticesList #-}+++-------------------------------------------------------------------------------- -- Vertex iterator+-------------------------------------------------------------------------------- +data VertexIterator++iterateVertices :: IGraph -> Ptr VertexSelector -> (Ptr VertexIterator -> IO a) -> IO a+iterateVertices gr vs fun = allocaBytes {# sizeof igraph_vit_t #} $ \vit ->+ bracket_ (igraphVitCreate gr vs vit) (igraphVitDestroy vit) (fun vit)+{-# INLINE iterateVertices #-}++iterateVerticesC :: IGraph+ -> Ptr VertexSelector+ -> (ConduitT i Int IO () -> IO a)+ -> IO a+iterateVerticesC gr vs fun = allocaBytes {# sizeof igraph_vit_t #} $ \vit ->+ bracket_ (igraphVitCreate gr vs vit) (igraphVitDestroy vit) (fun $ sourceVertexIterator vit)+{-# INLINE iterateVerticesC #-}++{#fun igraph_vit_create as ^+ { `IGraph'+ , castPtr %`Ptr VertexSelector'+ , castPtr `Ptr VertexIterator'+ } -> `CInt' void- #}+{#fun igraph_vit_destroy as ^ { castPtr `Ptr VertexIterator' } -> `()' #}+++sourceVertexIterator :: Ptr VertexIterator -> ConduitT i Int IO ()+sourceVertexIterator vit = do+ isEnd <- liftIO $ igraphVitEnd vit+ if isEnd+ then return ()+ else do+ liftIO (igraphVitGet vit) >>= yield+ liftIO $ igraphVitNext vit+ sourceVertexIterator vit+{-# INLINE sourceVertexIterator #-}+ #c igraph_bool_t igraph_vit_end(igraph_vit_t *vit) { return IGRAPH_VIT_END(*vit); }- void igraph_vit_next(igraph_vit_t *vit) { IGRAPH_VIT_NEXT(*vit); }- igraph_integer_t igraph_vit_get(igraph_vit_t *vit) { return IGRAPH_VIT_GET(*vit); } #endc -{#fun igraph_vit_create as igraphVitNew- { `IGraph'- , %`IGraphVs'- , allocaVit- `IGraphVit' addVitFinalizer*- } -> `CInt' void- #}+{#fun igraph_vit_end as ^ { castPtr `Ptr VertexIterator' } -> `Bool' #}+{#fun igraph_vit_next as ^ { castPtr `Ptr VertexIterator' } -> `()' #}+{#fun igraph_vit_get as ^ { castPtr `Ptr VertexIterator' } -> `Int' #} -{#fun igraph_vit_end as ^ { `IGraphVit' } -> `Bool' #} -{#fun igraph_vit_next as ^ { `IGraphVit' } -> `()' #}+--------------------------------------------------------------------------------+-- Edge Selector+-------------------------------------------------------------------------------- -{#fun igraph_vit_get as ^ { `IGraphVit' } -> `Int' #}+data EdgeSelector -vitToList :: IGraphVit -> IO [Int]-vitToList vit = do- isEnd <- igraphVitEnd vit- if isEnd- then return []- else do- cur <- igraphVitGet vit- igraphVitNext vit- acc <- vitToList vit- return $ cur : acc+allocaEdgeSelector :: (Ptr EdgeSelector -> IO a) -> IO a+allocaEdgeSelector fun = allocaBytes {# sizeof igraph_es_t #} $ \es -> do+ r <- fun es+ igraphEsDestroy es+ return r+{-# INLINE allocaEdgeSelector #-}+{#fun igraph_es_destroy as ^ { castPtr `Ptr EdgeSelector' } -> `()' #} +withEdgesAll :: EdgeOrderType -> (Ptr EdgeSelector -> IO a) -> IO a+withEdgesAll ord fun = allocaEdgeSelector $ \es -> igraphEsAll es ord >> fun es+{-# INLINE withEdgesAll #-}+{#fun igraph_es_all as ^ { castPtr `Ptr EdgeSelector', `EdgeOrderType'} -> `CInt' void- #} --- Edge Selector+withEdgeIdsVector :: Ptr Vector -> (Ptr EdgeSelector -> IO a) -> IO a+withEdgeIdsVector vec fun = allocaEdgeSelector $ \es ->+ igraphEsVector es vec >> fun es+{-# INLINE withEdgeIdsVector #-}+{# fun igraph_es_vector as ^+ { castPtr `Ptr EdgeSelector', castPtr `Ptr Vector' } -> `CInt' void- #} -{#fun igraph_es_all as ^- { allocaEs- `IGraphEs' addEsFinalizer*- , `EdgeOrderType'- } -> `CInt' void- #}+withEdgeIdsList :: [Int] -> (Ptr EdgeSelector -> IO b) -> IO b+withEdgeIdsList xs fun = withList xs $ \vec -> withEdgeIdsVector vec fun+{-# INLINE withEdgeIdsList #-} -{# fun igraph_es_vector as ^- { allocaEs- `IGraphEs' addEsFinalizer*- , `Vector'- } -> `CInt' void- #} +-------------------------------------------------------------------------------- -- Edge iterator+-------------------------------------------------------------------------------- +data EdgeIterator++iterateEdges :: IGraph -> Ptr EdgeSelector -> (Ptr EdgeIterator -> IO a) -> IO a+iterateEdges gr es fun = allocaBytes {# sizeof igraph_eit_t #} $ \eit ->+ bracket_ (igraphEitCreate gr es eit) (igraphEitDestroy eit) (fun eit)+{-# INLINE iterateEdges #-}+{#fun igraph_eit_create as ^ { `IGraph', castPtr %`Ptr EdgeSelector', castPtr `Ptr EdgeIterator' } -> `CInt' void- #}+{#fun igraph_eit_destroy as ^ { castPtr `Ptr EdgeIterator' } -> `()' #}++iterateEdgesC :: IGraph+ -> Ptr EdgeSelector+ -> (ConduitT i Int IO () -> IO a)+ -> IO a+iterateEdgesC gr es fun = allocaBytes {# sizeof igraph_eit_t #} $ \eit ->+ bracket_ (igraphEitCreate gr es eit) (igraphEitDestroy eit) (fun $ sourceEdgeIterator eit)+{-# INLINE iterateEdgesC #-}++sourceEdgeIterator :: Ptr EdgeIterator -> ConduitT i Int IO ()+sourceEdgeIterator eit = do+ isEnd <- liftIO $ igraphEitEnd eit+ if isEnd+ then return ()+ else do+ liftIO (igraphEitGet eit) >>= yield+ liftIO $ igraphEitNext eit+ sourceEdgeIterator eit+{-# INLINE sourceEdgeIterator #-}+ #c igraph_bool_t igraph_eit_end(igraph_eit_t *eit) { return IGRAPH_EIT_END(*eit); }- void igraph_eit_next(igraph_eit_t *eit) { IGRAPH_EIT_NEXT(*eit); }- igraph_integer_t igraph_eit_get(igraph_eit_t *eit) { return IGRAPH_EIT_GET(*eit); } #endc--{#fun igraph_eit_create as igraphEitNew- { `IGraph'- , %`IGraphEs'- , allocaEit- `IGraphEit' addEitFinalizer*- } -> `CInt' void- #}--{#fun igraph_eit_end as ^ { `IGraphEit' } -> `Bool' #}--{#fun igraph_eit_next as ^ { `IGraphEit' } -> `()' #}--{#fun igraph_eit_get as ^ { `IGraphEit' } -> `Int' #}--eitToList :: IGraphEit -> IO [Int]-eitToList eit = do- isEnd <- igraphEitEnd eit- if isEnd- then return []- else do- cur <- igraphEitGet eit- igraphEitNext eit- acc <- eitToList eit- return $ cur : acc+{#fun igraph_eit_end as ^ { castPtr `Ptr EdgeIterator' } -> `Bool' #}+{#fun igraph_eit_next as ^ { castPtr `Ptr EdgeIterator' } -> `()' #}+{#fun igraph_eit_get as ^ { castPtr `Ptr EdgeIterator' } -> `Int' #} ----------------------------------------------------------------------------------- Graph Constructors and Destructors-----------------------------------------------------------------------------------{#fun igraph_empty as igraphNew'- { allocaIGraph- `IGraph' addIGraphFinalizer*- , `Int', `Bool'- } -> `CInt' void- #}--{#fun igraph_copy as ^- { allocaIGraph- `IGraph' addIGraphFinalizer*- , `IGraph'- } -> `CInt' void- #}---- | Create a igraph object and attach a finalizer-igraphNew :: Int -> Bool -> HasInit -> IO IGraph-igraphNew n directed _ = igraphNew' n directed---------------------------------------------------------------------------------- -- Basic Query Operations -------------------------------------------------------------------------------- @@ -461,43 +605,103 @@ -- new vertices, call igraph_add_vertices() first. {# fun igraph_add_edges as ^ { `IGraph' -- ^ The graph to which the edges will be added.- , `Vector' -- ^ The edges themselves.+ , castPtr `Ptr Vector' -- ^ The edges themselves. , id `Ptr ()' -- ^ The attributes of the new edges. } -> `()' #} -- | delete vertices-{# fun igraph_delete_vertices as ^ { `IGraph', %`IGraphVs' } -> `Int' #}+{# fun igraph_delete_vertices as ^+ { `IGraph', castPtr %`Ptr VertexSelector' } -> `CInt' void- #} -- | delete edges-{# fun igraph_delete_edges as ^ { `IGraph', %`IGraphEs' } -> `Int' #}+{# fun igraph_delete_edges as ^+ { `IGraph', castPtr %`Ptr EdgeSelector' } -> `CInt' void- #} +data AttributeRecord +withAttr :: Serialize a+ => String -- ^ Attribute name+ -> [a] -- ^ Attributes+ -> (Ptr AttributeRecord -> IO b) -> IO b+withAttr name xs fun = withByteStrings (map encode xs) $ \bsvec ->+ withBSAttr name bsvec fun+{-# INLINE withAttr #-} -withAttr :: String- -> BSVector -> (Ptr AttributeRecord -> IO a) -> IO a-withAttr name bs f = withBSVector bs $ \ptr -> do- fptr <- mallocForeignPtrBytes {#sizeof igraph_attribute_record_t #}- withForeignPtr fptr $ \attr -> withCString name $ \name' -> do- {#set igraph_attribute_record_t.name #} attr name'+withBSAttr :: String -- ^ Attribute name+ -> Ptr BSVector -- ^ Attributes+ -> (Ptr AttributeRecord -> IO b) -> IO b+withBSAttr name bsvec fun = withCString name $ \name' ->+ allocaBytes {#sizeof igraph_attribute_record_t #} $ \attr ->+ setAttribute attr name' (castPtr bsvec) >> fun attr+ where+ setAttribute attr x y = do+ {#set igraph_attribute_record_t.name #} attr x {#set igraph_attribute_record_t.type #} attr 2- {#set igraph_attribute_record_t.value #} attr $ castPtr ptr- f attr-{-# INLINE withAttr #-}+ {#set igraph_attribute_record_t.value #} attr y+{-# INLINE withBSAttr #-} -{#fun igraph_haskell_attribute_has_attr as ^ { `IGraph', `AttributeElemtype', `String' } -> `Bool' #}+-- | Checks whether a (graph, vertex or edge) attribute exists+{#fun igraph_haskell_attribute_has_attr as ^+ { `IGraph'+ , `AttributeElemtype' -- ^ The type of the attribute+ , `String' -- ^ The name of the attribute+ } -> `Bool' #} -{#fun igraph_haskell_attribute_GAN_set as ^ { `IGraph', `String', `Double' } -> `Int' #}+-- | Query a string vertex attribute+{#fun igraph_haskell_attribute_VAS as ^+ { `IGraph'+ , `String' -- ^ The name of the attribute+ , `Int' -- ^ The id of the queried vertex+ } -> `Ptr BSLen' castPtr #} -{#fun igraph_haskell_attribute_GAN as ^ { `IGraph', `String' } -> `Double' #}+-- | Query a string edge attribute.+{#fun igraph_haskell_attribute_EAS as ^+ { `IGraph'+ , `String' -- ^ The name of the attribute+ , `Int' -- ^ The id of the queried edge+ } -> `Ptr BSLen' castPtr #} -{#fun igraph_haskell_attribute_VAS as ^ { `IGraph', `String', `Int' } -> `Ptr BSLen' castPtr #}+{#fun igraph_haskell_attribute_VAS_set as ^+ { `IGraph'+ , `String'+ , `Int'+ , castPtr `Ptr BSLen'+ } -> `CInt' void-#} -{#fun igraph_haskell_attribute_EAN as ^ { `IGraph', `String', `Int' } -> `Double' #}+{#fun igraph_haskell_attribute_VAS_setv as ^+ { `IGraph'+ , `String' -- ^ Name of the attribute+ , castPtr `Ptr BSVector' -- ^ String vector, the new attribute values.+ -- The length of this vector must match the+ -- number of vertices.+ } -> `CInt' void-#} -{#fun igraph_haskell_attribute_EAS as ^ { `IGraph', `String', `Int' } -> `Ptr BSLen' castPtr #}+-- | Set a string edge attribute.+{#fun igraph_haskell_attribute_EAS_set as ^+ { `IGraph'+ , `String' -- ^ The name of the attribute+ , `Int' -- ^ The id of the queried vertex+ , castPtr `Ptr BSLen' -- ^ The (new) value of the attribute.+ } -> `CInt' void-#} -{#fun igraph_haskell_attribute_EAS_setv as ^ { `IGraph', `String', `BSVector' } -> `Int' #}+-- | Set a string edge attribute for all edges.+{#fun igraph_haskell_attribute_EAS_setv as ^+ { `IGraph'+ , `String' -- ^ Name of the attribute+ , castPtr `Ptr BSVector' -- ^ String vector, the new attribute values.+ -- The length of this vector must match the+ -- number of edges.+ } -> `CInt' void-#} -{#fun igraph_haskell_attribute_VAS_set as ^ { `IGraph', `String', `Int', castPtr `Ptr BSLen' } -> `Int' #} -{#fun igraph_haskell_attribute_EAS_set as ^ { `IGraph', `String', `Int', castPtr `Ptr BSLen' } -> `Int' #}+--------------------------------------------------------------------------------+-- Arpack options+--------------------------------------------------------------------------------++data ArpackOpt++allocaArpackOpt :: (Ptr ArpackOpt -> IO a) -> IO a+allocaArpackOpt fun = allocaBytes {# sizeof igraph_arpack_options_t #} $ \opt -> do+ igraphArpackOptionsInit opt >> fun opt+{-# INLINE allocaArpackOpt #-}+{#fun igraph_arpack_options_init as ^ { castPtr `Ptr ArpackOpt' } -> `CInt' void- #}
src/IGraph/Internal/Constants.chs view
@@ -9,6 +9,9 @@ {#enum igraph_edgeorder_type_t as EdgeOrderType {underscoreToCase} deriving (Show, Eq) #} +{#enum igraph_to_directed_t as ToDirected {underscoreToCase}+ deriving (Eq) #}+ {#enum igraph_spincomm_update_t as SpincommUpdate {underscoreToCase} deriving (Show, Eq) #} @@ -28,6 +31,9 @@ deriving (Show, Read, Eq) #} {#enum igraph_rewiring_t as Rewiring {underscoreToCase}+ deriving (Show, Read, Eq) #}++{#enum igraph_star_mode_t as StarMode {underscoreToCase} deriving (Show, Read, Eq) #} {#enum igraph_degseq_t as Degseq {underscoreToCase}
− src/IGraph/Internal/Types.chs
@@ -1,231 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}-module IGraph.Internal.Types- ( -- * Vector type and basic operations- Vector(..)- , withVector- , allocaVector- , addVectorFinalizer-- -- * Pointer vector- , VectorPtr(..)- , withVectorPtr- , allocaVectorPtr- , addVectorPtrFinalizer-- -- * String vector- , StrVector(..)- , withStrVector- , allocaStrVector- , addStrVectorFinalizer-- -- * Bytestring- , BSLen(..)- , withBSLen-- -- * Bytestring vector- , BSVector(..)- , withBSVector- , allocaBSVector- , addBSVectorFinalizer-- -- * Igraph matrix type- , Matrix(..)- , withMatrix- , allocaMatrix- , addMatrixFinalizer-- -- * Igraph vertex selector- , IGraphVs(..)- , withIGraphVs- , allocaVs- , addVsFinalizer-- -- * Igraph vertex iterator- , IGraphVit(..)- , withIGraphVit- , allocaVit- , addVitFinalizer-- -- * Igraph edge Selector- , IGraphEs- , withIGraphEs- , allocaEs- , addEsFinalizer-- -- * Igraph edge iterator- , IGraphEit(..)- , withIGraphEit- , allocaEit- , addEitFinalizer-- -- * IGraph type and basic operations- , IGraph(..)- , withIGraph- , allocaIGraph- , addIGraphFinalizer-- -- * Igraph attribute record- , AttributeRecord(..)- , withAttributeRecord-- -- * Igraph arpack options type- , ArpackOpt(..)- , withArpackOpt- , igraphArpackNew- ) where--import Foreign--#include "haskell_attributes.h"-#include "haskell_igraph.h"------------------------------------------------------------------------------------- Igraph vector-----------------------------------------------------------------------------------{#pointer *igraph_vector_t as Vector foreign finalizer- igraph_vector_destroy newtype#}---- Construtors and destructors--allocaVector :: (Ptr Vector -> IO a) -> IO a-allocaVector f = mallocBytes {# sizeof igraph_vector_t #} >>= f-{-# INLINE allocaVector #-}--addVectorFinalizer :: Ptr Vector -> IO Vector-addVectorFinalizer ptr = do- vec <- newForeignPtr igraph_vector_destroy ptr- return $ Vector vec-{-# INLINE addVectorFinalizer #-}---{#pointer *igraph_vector_ptr_t as VectorPtr foreign finalizer- igraph_vector_ptr_destroy newtype#}--allocaVectorPtr :: (Ptr VectorPtr -> IO a) -> IO a-allocaVectorPtr f = mallocBytes {# sizeof igraph_vector_ptr_t #} >>= f-{-# INLINE allocaVectorPtr #-}--addVectorPtrFinalizer :: Ptr VectorPtr -> IO VectorPtr-addVectorPtrFinalizer ptr = do- vec <- newForeignPtr igraph_vector_ptr_destroy ptr- return $ VectorPtr vec-{-# INLINE addVectorPtrFinalizer #-}------------------------------------------------------------------------------------- Igraph string vector-----------------------------------------------------------------------------------{#pointer *igraph_strvector_t as StrVector foreign finalizer igraph_strvector_destroy newtype#}--allocaStrVector :: (Ptr StrVector -> IO a) -> IO a-allocaStrVector f = mallocBytes {# sizeof igraph_strvector_t #} >>= f-{-# INLINE allocaStrVector #-}--addStrVectorFinalizer :: Ptr StrVector -> IO StrVector-addStrVectorFinalizer ptr = do- vec <- newForeignPtr igraph_strvector_destroy ptr- return $ StrVector vec-{-# INLINE addStrVectorFinalizer #-}-------------------------------------------------------------------------------------- Customized string vector-----------------------------------------------------------------------------------{#pointer *bytestring_t as BSLen foreign newtype#}--{#pointer *bsvector_t as BSVector foreign finalizer bsvector_destroy newtype#}--allocaBSVector :: (Ptr BSVector -> IO a) -> IO a-allocaBSVector f = mallocBytes {# sizeof bsvector_t #} >>= f-{-# INLINE allocaBSVector #-}--addBSVectorFinalizer :: Ptr BSVector -> IO BSVector-addBSVectorFinalizer ptr = do- vec <- newForeignPtr bsvector_destroy ptr- return $ BSVector vec-{-# INLINE addBSVectorFinalizer #-}--{#pointer *igraph_matrix_t as Matrix foreign finalizer igraph_matrix_destroy newtype#}--allocaMatrix :: (Ptr Matrix -> IO a) -> IO a-allocaMatrix f = mallocBytes {# sizeof igraph_matrix_t #} >>= f-{-# INLINE allocaMatrix #-}--addMatrixFinalizer :: Ptr Matrix -> IO Matrix-addMatrixFinalizer ptr = do- vec <- newForeignPtr igraph_matrix_destroy ptr- return $ Matrix vec-{-# INLINE addMatrixFinalizer #-}---{#pointer *igraph_vs_t as IGraphVs foreign finalizer igraph_vs_destroy newtype #}--allocaVs :: (Ptr IGraphVs -> IO a) -> IO a-allocaVs f = mallocBytes {# sizeof igraph_vs_t #} >>= f-{-# INLINE allocaVs #-}--addVsFinalizer :: Ptr IGraphVs -> IO IGraphVs-addVsFinalizer ptr = newForeignPtr igraph_vs_destroy ptr >>= return . IGraphVs-{-# INLINE addVsFinalizer #-}----- Vertex iterator-{#pointer *igraph_vit_t as IGraphVit foreign finalizer igraph_vit_destroy newtype #}--allocaVit :: (Ptr IGraphVit -> IO a) -> IO a-allocaVit f = mallocBytes {# sizeof igraph_vit_t #} >>= f-{-# INLINE allocaVit #-}--addVitFinalizer :: Ptr IGraphVit -> IO IGraphVit-addVitFinalizer ptr = newForeignPtr igraph_vit_destroy ptr >>= return . IGraphVit-{-# INLINE addVitFinalizer #-}---- Edge Selector--{#pointer *igraph_es_t as IGraphEs foreign finalizer igraph_es_destroy newtype #}--allocaEs :: (Ptr IGraphEs -> IO a) -> IO a-allocaEs f = mallocBytes {# sizeof igraph_es_t #} >>= f-{-# INLINE allocaEs #-}--addEsFinalizer :: Ptr IGraphEs -> IO IGraphEs-addEsFinalizer ptr = newForeignPtr igraph_es_destroy ptr >>= return . IGraphEs-{-# INLINE addEsFinalizer #-}---- Edge iterator--{#pointer *igraph_eit_t as IGraphEit foreign finalizer igraph_eit_destroy newtype #}--allocaEit :: (Ptr IGraphEit -> IO a) -> IO a-allocaEit f = mallocBytes {# sizeof igraph_eit_t #} >>= f-{-# INLINE allocaEit #-}--addEitFinalizer :: Ptr IGraphEit -> IO IGraphEit-addEitFinalizer ptr = newForeignPtr igraph_eit_destroy ptr >>= return . IGraphEit-{-# INLINE addEitFinalizer #-}-------------------------------------------------------------------------------------- Graph Constructors and Destructors-----------------------------------------------------------------------------------{#pointer *igraph_t as IGraph foreign finalizer igraph_destroy newtype#}--allocaIGraph :: (Ptr IGraph -> IO a) -> IO a-allocaIGraph f = mallocBytes {# sizeof igraph_t #} >>= f-{-# INLINE allocaIGraph #-}--addIGraphFinalizer :: Ptr IGraph -> IO IGraph-addIGraphFinalizer ptr = do- vec <- newForeignPtr igraph_destroy ptr- return $ IGraph vec-{-# INLINE addIGraphFinalizer #-}--{#pointer *igraph_attribute_record_t as AttributeRecord foreign newtype#}--{#pointer *igraph_arpack_options_t as ArpackOpt foreign newtype#}--{#fun igraph_arpack_options_init as igraphArpackNew- { + } -> `ArpackOpt' #}
src/IGraph/Isomorphism.chs view
@@ -1,4 +1,5 @@ {-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE ScopedTypeVariables #-} module IGraph.Isomorphism ( getSubisomorphisms , isomorphic@@ -8,6 +9,7 @@ ) where import System.IO.Unsafe (unsafePerformIO)+import Data.Singletons (SingI, Sing, sing, fromSing) import Foreign import Foreign.C.Types@@ -19,12 +21,10 @@ #include "haskell_igraph.h" -getSubisomorphisms :: Graph d- => LGraph d v1 e1 -- ^ graph to be searched in- -> LGraph d v2 e2 -- ^ smaller graph+getSubisomorphisms :: Graph d v1 e1 -- ^ graph to be searched in+ -> Graph d v2 e2 -- ^ smaller graph -> [[Int]]-getSubisomorphisms g1 g2 = unsafePerformIO $ do- vpptr <- igraphVectorPtrNew 0+getSubisomorphisms g1 g2 = unsafePerformIO $ allocaVectorPtr $ \vpptr -> do igraphGetSubisomorphismsVf2 gptr1 gptr2 nullPtr nullPtr nullPtr nullPtr vpptr nullFunPtr nullFunPtr nullPtr (map.map) truncate <$> toLists vpptr@@ -39,16 +39,15 @@ , id `Ptr ()' , id `Ptr ()' , id `Ptr ()'- , `VectorPtr'+ , castPtr `Ptr VectorPtr' , id `FunPtr (Ptr IGraph -> Ptr IGraph -> CInt -> CInt -> Ptr () -> IO CInt)' , id `FunPtr (Ptr IGraph -> Ptr IGraph -> CInt -> CInt -> Ptr () -> IO CInt)' , id `Ptr ()' } -> `CInt' void- #} -- | Determine whether two graphs are isomorphic.-isomorphic :: Graph d- => LGraph d v1 e1- -> LGraph d v2 e2+isomorphic :: Graph d v1 e1+ -> Graph d v2 e2 -> Bool isomorphic g1 g2 = unsafePerformIO $ alloca $ \ptr -> do _ <- igraphIsomorphic (_graph g1) (_graph g2) ptr@@ -58,27 +57,32 @@ -- | Creates a graph from the given isomorphism class. -- This function is implemented only for graphs with three or four vertices.-isoclassCreate :: Graph d+isoclassCreate :: forall d. SingI d => Int -- ^ The number of vertices to add to the graph. -> Int -- ^ The isomorphism class- -> d- -> LGraph d () ()-isoclassCreate size idx d = unsafePerformIO $ do- gp <- igraphInit >> igraphIsoclassCreate size idx (isD d)- unsafeFreeze $ MLGraph gp+ -> Graph d () ()+isoclassCreate size idx = unsafePerformIO $ do+ gp <- igraphInit >> igraphIsoclassCreate size idx directed+ unsafeFreeze $ MGraph gp+ where+ directed = case fromSing (sing :: Sing d) of+ D -> True+ U -> False {#fun igraph_isoclass_create as ^ { allocaIGraph- `IGraph' addIGraphFinalizer* , `Int', `Int', `Bool' } -> `CInt' void- #} -isoclass3 :: Graph d => d -> [LGraph d () ()]-isoclass3 d = map (flip (isoclassCreate 3) d) n+isoclass3 :: forall d. SingI d => [Graph d () ()]+isoclass3 = map (isoclassCreate 3) (if directed then [0..15] else [0..3]) where- n | isD d = [0..15]- | otherwise = [0..3]+ directed = case fromSing (sing :: Sing d) of+ D -> True+ U -> False -isoclass4 :: Graph d => d -> [LGraph d () ()]-isoclass4 d = map (flip (isoclassCreate 4) d) n+isoclass4 :: forall d. SingI d => [Graph d () ()]+isoclass4 = map (isoclassCreate 4) (if directed then [0..217] else [0..10]) where- n | isD d = [0..217]- | otherwise = [0..10]+ directed = case fromSing (sing :: Sing d) of+ D -> True+ U -> False
src/IGraph/Layout.chs view
@@ -61,49 +61,49 @@ where area x = fromIntegral $ x^2 -getLayout :: Graph d => LGraph d v e -> LayoutMethod -> IO [(Double, Double)]-getLayout gr method = do- case method of- KamadaKawai seed niter sigma initemp coolexp kkconst -> do- mptr <- case seed of- Nothing -> igraphMatrixNew 0 0- Just xs -> if length xs /= nNodes gr- then error "Seed error: incorrect size"- else fromRowLists $ (\(x,y) -> [x,y]) $ unzip xs-- igraphLayoutKamadaKawai gptr mptr niter (sigma n) initemp coolexp+getLayout :: Graph d v e -> LayoutMethod -> IO [(Double, Double)]+getLayout gr method = case method of+ KamadaKawai seed niter sigma initemp coolexp kkconst -> case seed of+ Nothing -> allocaMatrix $ \mat -> do+ igraphLayoutKamadaKawai gptr mat niter (sigma n) initemp coolexp (kkconst n) (isJust seed) nullPtr nullPtr nullPtr nullPtr- [x, y] <- toColumnLists mptr+ [x, y] <- toColumnLists mat return $ zip x y+ Just xs -> if length xs /= nNodes gr+ then error "Seed error: incorrect size"+ else withRowLists ((\(x,y) -> [x,y]) (unzip xs)) $ \mat -> do+ igraphLayoutKamadaKawai gptr mat niter (sigma n) initemp coolexp+ (kkconst n) (isJust seed) nullPtr nullPtr nullPtr nullPtr+ [x, y] <- toColumnLists mat+ return $ zip x y - LGL niter delta area coolexp repulserad cellsize -> do- mptr <- igraphMatrixNew 0 0- igraphLayoutLgl gptr mptr niter (delta n) (area n) coolexp- (repulserad n) (cellsize n) (-1)- [x, y] <- toColumnLists mptr- return $ zip x y+ LGL niter delta area coolexp repulserad cellsize -> allocaMatrix $ \mat -> do+ igraphLayoutLgl gptr mat niter (delta n) (area n) coolexp+ (repulserad n) (cellsize n) (-1)+ [x, y] <- toColumnLists mat+ return $ zip x y where n = nNodes gr gptr = _graph gr {#fun igraph_layout_kamada_kawai as ^ { `IGraph'- , `Matrix'+ , castPtr `Ptr Matrix' , `Int' , `Double' , `Double' , `Double' , `Double' , `Bool'- , id `Ptr Vector'- , id `Ptr Vector'- , id `Ptr Vector'- , id `Ptr Vector'+ , castPtr `Ptr Vector'+ , castPtr `Ptr Vector'+ , castPtr `Ptr Vector'+ , castPtr `Ptr Vector' } -> `CInt' void- #} {# fun igraph_layout_lgl as ^ { `IGraph'- , `Matrix'+ , castPtr `Ptr Matrix' , `Int' , `Double' , `Double'
src/IGraph/Motif.chs view
@@ -1,4 +1,5 @@ {-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE DataKinds #-} module IGraph.Motif ( triad , triadCensus@@ -7,7 +8,7 @@ import Data.Hashable (Hashable) import System.IO.Unsafe (unsafePerformIO) -import qualified Foreign.Ptr as C2HSImp+import Foreign import IGraph {#import IGraph.Internal #}@@ -31,7 +32,7 @@ -- 120C: A->B->C, A<->C. -- 210: A->B<->C, A<->C. -- 300: A<->B<->C, A<->C, the complete graph.-triad :: [LGraph D () ()]+triad :: [Graph 'D () ()] triad = map make edgeList where edgeList =@@ -52,19 +53,18 @@ , [(0,1), (1,2), (2,1), (0,2), (2,0)] , [(0,1), (1,0), (1,2), (2,1), (0,2), (2,0)] ]- make :: [(Int, Int)] -> LGraph D () ()+ make :: [(Int, Int)] -> Graph 'D () () make xs = mkGraph (replicate 3 ()) $ zip xs $ repeat () -triadCensus :: (Hashable v, Eq v, Read v) => LGraph d v e -> [Int]-triadCensus gr = unsafePerformIO $ do- vptr <- igraphVectorNew 0- igraphTriadCensus (_graph gr) vptr- map truncate <$> toList vptr+triadCensus :: (Hashable v, Eq v, Read v) => Graph d v e -> [Int]+triadCensus gr = unsafePerformIO $ allocaVector $ \result -> do+ igraphTriadCensus (_graph gr) result+ map truncate <$> toList result -- motifsRandesu {#fun igraph_triad_census as ^ { `IGraph'- , `Vector' } -> `CInt' void- #}+ , castPtr `Ptr Vector' } -> `CInt' void- #} -{#fun igraph_motifs_randesu as ^ { `IGraph', `Vector', `Int'- , `Vector' } -> `CInt' void- #}+{#fun igraph_motifs_randesu as ^ { `IGraph', castPtr `Ptr Vector', `Int'+ , castPtr `Ptr Vector' } -> `CInt' void- #}
src/IGraph/Mutable.hs view
@@ -1,111 +1,129 @@-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE ScopedTypeVariables #-}+ module IGraph.Mutable ( MGraph(..)- , MLGraph(..)+ , new+ , nNodes+ , nEdges+ , addNodes+ , addLNodes+ , delNodes+ , addEdges+ , addLEdges+ , delEdges , setEdgeAttr , setNodeAttr+ , initializeNullAttribute )where -import Control.Monad (when, forM)+import Control.Monad (forM) import Control.Monad.Primitive import Data.Serialize (Serialize, encode)-import Foreign+import Data.Singletons.Prelude (Sing, SingI, fromSing, sing)+import Foreign hiding (new) import IGraph.Internal import IGraph.Internal.Initialization import IGraph.Types -- | Mutable labeled graph.-newtype MLGraph m d v e = MLGraph IGraph--class MGraph d where- -- | Create a new graph.- new :: PrimMonad m => Int -> m (MLGraph (PrimState m) d v e)-- -- | 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+newtype MGraph m (d :: EdgeType) v e = MGraph IGraph - -- | Add nodes with labels to the graph.- addLNodes :: (Serialize v, PrimMonad m)- => [v] -- ^ vertices' labels- -> MLGraph (PrimState m) d v e -> m ()- addLNodes labels (MLGraph g) = unsafePrimToPrim $ do- bsvec <- toBSVector $ map encode labels- withAttr vertexAttr bsvec $ \attr -> do- vptr <- fromPtrs [castPtr attr]- withVectorPtr vptr (igraphAddVertices g n . castPtr)- where- n = length labels+-- | Create a new graph.+new :: forall m d v e. (SingI d, PrimMonad m)+ => Int -> m (MGraph (PrimState m) d v e)+new n = unsafePrimToPrim $ igraphInit >>= igraphNew n directed >>= return . MGraph+ where+ directed = case fromSing (sing :: Sing d) of+ D -> True+ U -> False - -- | Delete nodes from the graph.- delNodes :: PrimMonad m => [Int] -> MLGraph (PrimState m) d v e -> m ()- delNodes ns (MLGraph g) = unsafePrimToPrim $ do- vptr <- fromList $ map fromIntegral ns- vsptr <- igraphVsVector vptr- _ <- igraphDeleteVertices g vsptr- return ()+-- | Return the number of nodes in a graph.+nNodes :: PrimMonad m => MGraph (PrimState m) d v e -> m Int+nNodes (MGraph gr) = unsafePrimToPrim $ igraphVcount gr+{-# INLINE nNodes #-} - -- | Add edges to the graph.- addEdges :: PrimMonad m => [(Int, Int)] -> MLGraph (PrimState m) d v e -> m ()- addEdges es (MLGraph g) = unsafePrimToPrim $ do- vec <- fromList xs- igraphAddEdges g vec nullPtr- where- xs = concatMap ( \(a,b) -> [fromIntegral a, fromIntegral b] ) es+-- | Return the number of edges in a graph.+nEdges :: PrimMonad m => MGraph (PrimState m) d v e -> m Int+nEdges (MGraph gr) = unsafePrimToPrim $ igraphEcount gr+{-# INLINE nEdges #-} - -- | Add edges with labels to the graph.- addLEdges :: (PrimMonad m, Serialize e) => [LEdge e] -> MLGraph (PrimState m) d v e -> m ()- addLEdges es (MLGraph g) = unsafePrimToPrim $ do- bsvec <- toBSVector $ map encode vs- withAttr edgeAttr bsvec $ \attr -> do- vec <- fromList $ concat xs- vptr <- fromPtrs [castPtr attr]- withVectorPtr vptr (igraphAddEdges g vec . castPtr)- where- (xs, vs) = unzip $ map ( \((a,b),v) -> ([fromIntegral a, fromIntegral b], v) ) es+-- | Add nodes to the graph.+addNodes :: PrimMonad m+ => Int -- ^ The number of new nodes.+ -> MGraph(PrimState m) d v e -> m ()+addNodes n (MGraph g) = unsafePrimToPrim $ igraphAddVertices g n nullPtr - -- | Delete edges from the graph.- delEdges :: PrimMonad m => [(Int, Int)] -> MLGraph (PrimState m) d v e -> m ()+-- | Add nodes with labels to the graph.+addLNodes :: (Serialize v, PrimMonad m)+ => [v] -- ^ vertices' labels+ -> MGraph (PrimState m) d v e -> m ()+addLNodes labels (MGraph g) = unsafePrimToPrim $+ withAttr vertexAttr labels $ \attr ->+ withPtrs [attr] (igraphAddVertices g n . castPtr)+ where+ n = length labels -instance MGraph U where- new n = unsafePrimToPrim $ igraphInit >>= igraphNew n False >>= return . MLGraph+-- | Delete nodes from the graph.+delNodes :: PrimMonad m => [Int] -> MGraph (PrimState m) d v e -> m ()+delNodes ns (MGraph g) = unsafePrimToPrim $ withVerticesList ns $ \vs ->+ igraphDeleteVertices g vs - delEdges es (MLGraph g) = unsafePrimToPrim $ do- eids <- forM es $ \(fr, to) -> igraphGetEid g fr to False True- vptr <- fromList $ map fromIntegral eids- esptr <- igraphEsVector vptr- _ <- igraphDeleteEdges g esptr- return ()+-- | Add edges to the graph.+addEdges :: PrimMonad m => [(Int, Int)] -> MGraph (PrimState m) d v e -> m ()+addEdges es (MGraph g) = unsafePrimToPrim $ withList xs $ \vec ->+ igraphAddEdges g vec nullPtr+ where+ xs = concatMap ( \(a,b) -> [a, b] ) es -instance MGraph D where- new n = unsafePrimToPrim $ igraphInit >>= igraphNew n True >>= return . MLGraph+-- | Add edges with labels to the graph.+addLEdges :: (PrimMonad m, Serialize e)+ => [LEdge e] -> MGraph (PrimState m) d v e -> m ()+addLEdges es (MGraph g) = unsafePrimToPrim $+ withAttr edgeAttr vs $ \attr -> withList (concat xs) $ \vec ->+ withPtrs [attr] (igraphAddEdges g vec . castPtr)+ where+ (xs, vs) = unzip $ map ( \((a,b),v) -> ([a, b], v) ) es - delEdges es (MLGraph g) = unsafePrimToPrim $ do- eids <- forM es $ \(fr, to) -> igraphGetEid g fr to True True- vptr <- fromList $ map fromIntegral eids- esptr <- igraphEsVector vptr- igraphDeleteEdges g esptr- return ()+-- | Delete edges from the graph.+delEdges :: forall m d v e. (SingI d, PrimMonad m)+ => [(Int, Int)] -> MGraph (PrimState m) d v e -> m ()+delEdges es (MGraph g) = unsafePrimToPrim $ do+ eids <- forM es $ \(fr, to) -> igraphGetEid g fr to directed True+ withEdgeIdsList eids (igraphDeleteEdges g)+ where+ directed = case fromSing (sing :: Sing d) of+ D -> True+ U -> False -- | Set node attribute. setNodeAttr :: (PrimMonad m, Serialize v) => Int -- ^ Node id -> v- -> MLGraph (PrimState m) d v e+ -> MGraph (PrimState m) d v e -> m ()-setNodeAttr nodeId x (MLGraph gr) = unsafePrimToPrim $ asBS (encode x) $ \bs -> do- err <- igraphHaskellAttributeVASSet gr vertexAttr nodeId bs- when (err /= 0) $ error "Fail to set node attribute!"+setNodeAttr nodeId x (MGraph gr) = unsafePrimToPrim $+ withByteString (encode x) $ igraphHaskellAttributeVASSet gr vertexAttr nodeId -- | Set edge attribute. setEdgeAttr :: (PrimMonad m, Serialize e) => Int -- ^ Edge id -> e- -> MLGraph (PrimState m) d v e+ -> MGraph (PrimState m) d v e -> m ()-setEdgeAttr edgeId x (MLGraph gr) = unsafePrimToPrim $ asBS (encode x) $ \bs -> do- err <- igraphHaskellAttributeEASSet gr edgeAttr edgeId bs- when (err /= 0) $ error "Fail to set edge attribute!"+setEdgeAttr edgeId x (MGraph gr) = unsafePrimToPrim $+ withByteString (encode x) $ igraphHaskellAttributeEASSet gr edgeAttr edgeId++initializeNullAttribute :: PrimMonad m+ => MGraph (PrimState m) d () ()+ -> m ()+initializeNullAttribute gr@(MGraph g) = do+ nn <- nNodes gr+ unsafePrimToPrim $ withByteStrings (map encode $ replicate nn ()) $+ igraphHaskellAttributeVASSetv g vertexAttr+ ne <- nEdges gr+ unsafePrimToPrim $ withByteStrings (map encode $ replicate ne ()) $+ igraphHaskellAttributeEASSetv g edgeAttr+{-# INLINE initializeNullAttribute #-}
src/IGraph/Read.hs view
@@ -4,20 +4,21 @@ , readAdjMatrixWeighted ) where -import qualified Data.ByteString.Char8 as B-import Data.ByteString.Lex.Fractional (readSigned, readExponential)-import Data.Maybe (fromJust)+import qualified Data.ByteString.Char8 as B+import Data.ByteString.Lex.Fractional (readExponential, readSigned)+import Data.Maybe (fromJust)+import Data.Singletons (SingI) -import IGraph+import IGraph readDouble :: B.ByteString -> Double readDouble = fst . fromJust . readSigned readExponential {-# INLINE readDouble #-} -readAdjMatrix :: Graph d => FilePath -> IO (LGraph d B.ByteString ())+readAdjMatrix :: SingI d => FilePath -> IO (Graph d B.ByteString ()) readAdjMatrix = fmap fromAdjMatrix . B.readFile -fromAdjMatrix :: Graph d => B.ByteString -> LGraph d B.ByteString ()+fromAdjMatrix :: SingI d => B.ByteString -> Graph d B.ByteString () fromAdjMatrix bs = let (header:xs) = B.lines bs mat = map (map readDouble . B.words) xs@@ -31,7 +32,7 @@ f ((i,j),v) = i < j && v /= 0 {-# INLINE fromAdjMatrix #-} -readAdjMatrixWeighted :: Graph d => FilePath -> IO (LGraph d B.ByteString Double)+readAdjMatrixWeighted :: SingI d => FilePath -> IO (Graph d B.ByteString Double) readAdjMatrixWeighted fl = do c <- B.readFile fl let (header:xs) = B.lines c
src/IGraph/Structure.chs view
@@ -5,7 +5,6 @@ , betweenness , eigenvectorCentrality , pagerank- , personalizedPagerank ) where import Control.Monad@@ -14,168 +13,132 @@ import qualified Data.HashMap.Strict as M import Data.Serialize (Serialize, decode) import System.IO.Unsafe (unsafePerformIO)+import Data.Maybe+import Data.Singletons (SingI) import Foreign import Foreign.C.Types import IGraph-import IGraph.Mutable+import IGraph.Mutable (MGraph(..)) {#import IGraph.Internal #} {#import IGraph.Internal.Constants #} #include "igraph/igraph.h" -inducedSubgraph :: (Hashable v, Eq v, Serialize v) => LGraph d v e -> [Int] -> LGraph d v e-inducedSubgraph gr vs = unsafePerformIO $ do- vs' <- fromList $ map fromIntegral vs- vsptr <- igraphVsVector vs'- igraphInducedSubgraph (_graph gr) vsptr IgraphSubgraphCreateFromScratch >>=- unsafeFreeze . MLGraph+inducedSubgraph :: (Hashable v, Eq v, Serialize v)+ => Graph d v e+ -> [Int]+ -> Graph d v e+inducedSubgraph gr nds = unsafePerformIO $ withVerticesList nds $ \vs ->+ igraphInducedSubgraph (_graph gr) vs IgraphSubgraphCreateFromScratch >>=+ unsafeFreeze . MGraph+{#fun igraph_induced_subgraph as ^+ { `IGraph'+ , allocaIGraph- `IGraph' addIGraphFinalizer*+ , castPtr %`Ptr VertexSelector'+ , `SubgraphImplementation'+ } -> `CInt' void- #} -- | Closeness centrality closeness :: [Int] -- ^ vertices- -> LGraph d v e+ -> Graph d v e -> Maybe [Double] -- ^ optional edge weights -> Neimode -> Bool -- ^ whether to normalize -> [Double]-closeness vs gr ws mode normal = unsafePerformIO $ do- vs' <- fromList $ map fromIntegral vs- vsptr <- igraphVsVector vs'- vptr <- igraphVectorNew 0- ws' <- case ws of- Just w -> fromList w- _ -> liftM Vector $ newForeignPtr_ $ castPtr nullPtr- igraphCloseness (_graph gr) vptr vsptr mode ws' normal- toList vptr+closeness nds gr ws mode normal = unsafePerformIO $ allocaVector $ \result ->+ withVerticesList nds $ \vs -> withListMaybe ws $ \ws' -> do+ igraphCloseness (_graph gr) result vs mode ws' normal+ toList result+{#fun igraph_closeness as ^+ { `IGraph'+ , castPtr `Ptr Vector'+ , castPtr %`Ptr VertexSelector'+ , `Neimode'+ , castPtr `Ptr Vector'+ , `Bool' } -> `CInt' void- #} + -- | Betweenness centrality betweenness :: [Int]- -> LGraph d v e+ -> Graph d v e -> Maybe [Double] -> [Double]-betweenness vs gr ws = unsafePerformIO $ do- vs' <- fromList $ map fromIntegral vs- vsptr <- igraphVsVector vs'- vptr <- igraphVectorNew 0- ws' <- case ws of- Just w -> fromList w- _ -> liftM Vector $ newForeignPtr_ $ castPtr nullPtr- igraphBetweenness (_graph gr) vptr vsptr True ws' False- toList vptr+betweenness nds gr ws = unsafePerformIO $ allocaVector $ \result ->+ withVerticesList nds $ \vs -> withListMaybe ws $ \ws' -> do+ igraphBetweenness (_graph gr) result vs True ws' False+ toList result+{#fun igraph_betweenness as ^+ { `IGraph'+ , castPtr `Ptr Vector'+ , castPtr %`Ptr VertexSelector'+ , `Bool'+ , castPtr `Ptr Vector'+ , `Bool' } -> `CInt' void- #} -- | Eigenvector centrality-eigenvectorCentrality :: LGraph d v e+eigenvectorCentrality :: Graph d v e -> Maybe [Double] -> [Double]-eigenvectorCentrality gr ws = unsafePerformIO $ do- vptr <- igraphVectorNew 0- ws' <- case ws of- Just w -> fromList w- _ -> liftM Vector $ newForeignPtr_ $ castPtr nullPtr- arparck <- igraphArpackNew- igraphEigenvectorCentrality (_graph gr) vptr nullPtr True True ws' arparck- toList vptr+eigenvectorCentrality gr ws = unsafePerformIO $ allocaArpackOpt $ \arparck ->+ allocaVector $ \result -> withListMaybe ws $ \ws' -> do+ igraphEigenvectorCentrality (_graph gr) result nullPtr True True ws' arparck+ toList result+{#fun igraph_eigenvector_centrality as ^+ { `IGraph'+ , castPtr `Ptr Vector'+ , id `Ptr CDouble'+ , `Bool'+ , `Bool'+ , castPtr `Ptr Vector'+ , castPtr `Ptr ArpackOpt' } -> `CInt' void- #} --- | Google's PageRank-pagerank :: Graph d- => LGraph d v e- -> Maybe [Double] -- ^ edge weights+-- | Google's PageRank algorithm, with option to+pagerank :: SingI d+ => Graph d v e+ -> Maybe [Double] -- ^ Node weights or reset probability. If provided,+ -- the personalized PageRank will be used+ -> Maybe [Double] -- ^ Edge weights -> Double -- ^ damping factor, usually around 0.85 -> [Double]-pagerank gr ws d- | n == 0 = []- | otherwise = unsafePerformIO $ alloca $ \p -> do- vptr <- igraphVectorNew 0- vsptr <- igraphVsAll- ws' <- case ws of- Just w -> if length w /= m- then error "pagerank: incorrect length of edge weight vector"- else fromList w- _ -> liftM Vector $ newForeignPtr_ $ castPtr nullPtr- igraphPagerank (_graph gr) IgraphPagerankAlgoPrpack vptr p vsptr- (isDirected gr) d ws' nullPtr- toList vptr- where- n = nNodes gr- m = nEdges gr---- | Personalized PageRank.-personalizedPagerank :: Graph d- => LGraph d v e- -> [Double] -- ^ reset probability- -> Maybe [Double]- -> Double- -> [Double]-personalizedPagerank gr reset ws d+pagerank gr reset ws d | n == 0 = []- | length reset /= n = error "personalizedPagerank: incorrect length of reset vector"- | otherwise = unsafePerformIO $ alloca $ \p -> do- vptr <- igraphVectorNew 0- vsptr <- igraphVsAll- ws' <- case ws of- Just w -> if length w /= m- then error "pagerank: incorrect length of edge weight vector"- else fromList w- _ -> liftM Vector $ newForeignPtr_ $ castPtr nullPtr- reset' <- fromList reset- igraphPersonalizedPagerank (_graph gr) IgraphPagerankAlgoPrpack vptr p vsptr- (isDirected gr) d reset' ws' nullPtr- toList vptr+ | isJust ws && length (fromJust ws) /= m = error "incorrect length of edge weight vector"+ | otherwise = unsafePerformIO $ alloca $ \p -> allocaVector $ \result ->+ withVerticesAll $ \vs -> withListMaybe ws $ \ws' -> do+ case reset of+ Nothing -> igraphPagerank (_graph gr) IgraphPagerankAlgoPrpack+ result p vs (isDirected gr) d ws' nullPtr+ Just reset' -> withList reset' $ \reset'' -> igraphPersonalizedPagerank+ (_graph gr) IgraphPagerankAlgoPrpack result p vs+ (isDirected gr) d reset'' ws' nullPtr+ toList result where n = nNodes gr m = nEdges gr -{#fun igraph_induced_subgraph as ^- { `IGraph'- , allocaIGraph- `IGraph' addIGraphFinalizer*- , %`IGraphVs'- , `SubgraphImplementation'- } -> `CInt' void- #}--{#fun igraph_closeness as ^ { `IGraph'- , `Vector'- , %`IGraphVs'- , `Neimode'- , `Vector'- , `Bool' } -> `CInt' void- #}--{#fun igraph_betweenness as ^ { `IGraph'- , `Vector'- , %`IGraphVs'- , `Bool'- , `Vector'- , `Bool' } -> `CInt' void- #}--{#fun igraph_eigenvector_centrality as ^ { `IGraph'- , `Vector'- , id `Ptr CDouble'- , `Bool'- , `Bool'- , `Vector'- , `ArpackOpt' } -> `CInt' void- #}- {#fun igraph_pagerank as ^ { `IGraph' , `PagerankAlgo'- , `Vector'+ , castPtr `Ptr Vector' , id `Ptr CDouble'- , %`IGraphVs'+ , castPtr %`Ptr VertexSelector' , `Bool' , `Double'- , `Vector'+ , castPtr `Ptr Vector' , id `Ptr ()' } -> `CInt' void- #} {#fun igraph_personalized_pagerank as ^ { `IGraph' , `PagerankAlgo'- , `Vector'+ , castPtr `Ptr Vector' , id `Ptr CDouble'- , %`IGraphVs'+ , castPtr %`Ptr VertexSelector' , `Bool' , `Double'- , `Vector'- , `Vector'+ , castPtr `Ptr Vector'+ , castPtr `Ptr Vector' , id `Ptr ()' } -> `CInt' void- #}
src/IGraph/Types.hs view
@@ -1,17 +1,39 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-} module IGraph.Types where +import Data.Serialize (Serialize)+import Data.Singletons.Prelude+import Data.Singletons.TH+import GHC.Generics (Generic)++$(singletons [d|+ data EdgeType = D+ | U+ deriving (Show, Read, Eq, Generic)+ |])++instance Serialize EdgeType+ type Node = Int type LNode a = (Node, a) type Edge = (Node, Node) type LEdge a = (Edge, a)---- | Undirected graph.-data U---- | Directed graph.-data D vertexAttr :: String vertexAttr = "vertex_attribute"
tests/Test/Attributes.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DataKinds #-} module Test.Attributes ( tests ) where@@ -31,14 +32,14 @@ nodeLabelTest :: TestTree nodeLabelTest = testCase "node label test" $ do let ns = sort $ map show [38..7000]- gr = mkGraph ns [] :: LGraph D String ()+ gr = mkGraph ns [] :: Graph 'D String () assertBool "" $ sort (map (nodeLab gr) $ nodes gr) == ns labelTest :: TestTree labelTest = testCase "edge label test" $ do dat <- randEdges 1000 10000 let es = sort $ zipWith (\a b -> (a,b)) dat $ map show [1..]- gr = fromLabeledEdges es :: LGraph D Int String+ gr = fromLabeledEdges es :: Graph 'D Int String es' = sort $ map (\(a,b) -> ((nodeLab gr a, nodeLab gr b), edgeLab gr (a,b))) $ edges gr assertBool "" $ es == es' @@ -48,13 +49,10 @@ let es = map ( \(a, b) -> ( ( defaultNodeAttributes{_nodeZindex=a} , defaultNodeAttributes{_nodeZindex=b}), defaultEdgeAttributes) ) dat- gr = fromLabeledEdges es :: LGraph D NodeAttr EdgeAttr- gr' :: LGraph D NodeAttr EdgeAttr+ gr = fromLabeledEdges es :: Graph 'D NodeAttr EdgeAttr+ gr' :: Graph 'D NodeAttr EdgeAttr gr' = case decode $ encode gr of Left msg -> error msg Right r -> r es' = map (\(a,b) -> ((nodeLab gr' a, nodeLab gr' b), edgeLab gr' (a,b))) $ edges gr'- gr'' <- runConduit $ (yield $ encode gr) .| decodeC :: IO (LGraph D NodeAttr EdgeAttr)- let es'' = map (\(a,b) -> ((nodeLab gr'' a, nodeLab gr'' b), edgeLab gr'' (a,b))) $ edges gr''- assertBool "" $ sort (map show es) == sort (map show es') &&- sort (map show es) == sort (map show es'')+ assertBool "" $ sort (map show es) == sort (map show es')
tests/Test/Basic.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DataKinds #-} module Test.Basic ( tests ) where@@ -13,7 +14,7 @@ import Conduit import IGraph-import IGraph.Mutable+import qualified IGraph.Mutable as GM import IGraph.Structure tests :: TestTree@@ -33,8 +34,8 @@ where edgeList = sort $ unsafePerformIO $ randEdges 1000 100 m = length edgeList- gr = mkGraph (replicate 100 ()) $ zip edgeList $ repeat () :: LGraph D () ()- simple = mkGraph (replicate 3 ()) $ zip [(0,1),(1,2),(2,0)] $ repeat () :: LGraph D () ()+ gr = mkGraph (replicate 100 ()) $ zip edgeList $ repeat () :: Graph 'D () ()+ simple = mkGraph (replicate 3 ()) $ zip [(0,1),(1,2),(2,0)] $ repeat () :: Graph 'D () () graphCreationLabeled :: TestTree graphCreationLabeled = testGroup "Graph creation -- with labels"@@ -49,15 +50,15 @@ randEdges 10000 1000) $ repeat 1 n = length $ nubSort $ concatMap (\((a,b),_) -> [a,b]) edgeList m = length edgeList- gr = fromLabeledEdges edgeList :: LGraph D String Int- gr' = runST $ fromLabeledEdges' edgeList yieldMany :: LGraph D String Int+ gr = fromLabeledEdges edgeList :: Graph 'D String Int+ gr' = unsafePerformIO $ fromLabeledEdges' edgeList yieldMany :: Graph 'D String Int graphEdit :: TestTree graphEdit = testGroup "Graph editing" [ testCase "" $ [(1,2)] @=? (sort $ edges simple') ] where- simple = mkGraph (replicate 3 ()) $ zip [(0,1),(1,2),(2,0)] $ repeat () :: LGraph U () ()+ simple = mkGraph (replicate 3 ()) $ zip [(0,1),(1,2),(2,0)] $ repeat () :: Graph 'U () () simple' = runST $ do g <- thaw simple- delEdges [(0,1),(0,2)] g+ GM.delEdges [(0,1),(0,2)] g freeze g
+ tests/Test/Clique.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE DataKinds #-}+module Test.Clique+ ( tests+ ) where++import Control.Monad.ST+import Data.List+import System.IO.Unsafe+import Test.Tasty+import Test.Tasty.HUnit+import Test.Utils++import IGraph+import IGraph.Clique+import IGraph.Generators+import IGraph.Mutable++tests :: TestTree+tests = testGroup "Clique"+ [ testCase "case 1" $ sort (map sort $ cliques gr (4,-1)) @=? c4+ , testCase "case 2" $ sort (map sort $ cliques gr (2,2)) @=? c2+ , testCase "case 3" $ sort (map sort $ largestCliques gr) @=? c4+ , testCase "case 4" $ sort (map sort $ cliques gr (-1,-1)) @=?+ sort (map sort $ c1 ++ c2 ++ c3 ++ c4)+ ]+ where+ gr = runST $ do+ g <- unsafeThaw (full 6 False :: Graph 'U () ())+ delEdges [(0,1), (0,2), (3,5)] g+ unsafeFreeze g+ c1 = [[0], [1], [2], [3], [4], [5]]+ c2 = [ [0,3], [0,4], [0,5], [1,2], [1,3], [1,4], [1,5], [2,3], [2,4]+ , [2,5], [3,4], [4,5] ]+ c3 = [ [0,3,4], [0,4,5], [1,2,3], [1,2,4], [1,2,5], [1,3,4], [1,4,5],+ [2,3,4], [2,4,5] ]+ c4 = [[1, 2, 3, 4], [1, 2, 4, 5]]
tests/Test/Structure.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DataKinds #-} module Test.Structure ( tests ) where@@ -13,10 +14,12 @@ import IGraph import IGraph.Mutable import IGraph.Structure+import IGraph.Generators tests :: TestTree tests = testGroup "Structure property tests" [ subGraphs+ , pagerankTest ] subGraphs :: TestTree@@ -27,7 +30,16 @@ , ["a","c"], [("a","c"), ("c","a")] ) test (ori,ns,expect) = sort expect @=? sort result where- gr = fromLabeledEdges $ zip ori $ repeat () :: LGraph D String ()+ gr = fromLabeledEdges $ zip ori $ repeat () :: Graph 'D String () ns' = map (head . getNodes gr) ns gr' = inducedSubgraph gr ns' result = map (nodeLab gr' *** nodeLab gr') $ edges gr'++pagerankTest :: TestTree+pagerankTest = testGroup "PageRank"+ [ testCase "case 1" $ ranks @=? ranks' ]+ where+ gr = star 11+ ranks = [0.47,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05]+ ranks' = map ((/100) . fromIntegral . round. (*100)) $+ pagerank gr Nothing Nothing 0.85
tests/test.hs view
@@ -1,8 +1,9 @@+import qualified Test.Attributes as Attributes import qualified Test.Basic as Basic+import qualified Test.Clique as Clique import qualified Test.Isomorphism as Isomorphism import qualified Test.Motif as Motif import qualified Test.Structure as Structure-import qualified Test.Attributes as Attributes import Test.Tasty main :: IO ()@@ -12,4 +13,5 @@ , Motif.tests , Isomorphism.tests , Attributes.tests+ , Clique.tests ]