Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
H
haskell-igraph
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
haskell-igraph
Commits
6ce9fdfd
Commit
6ce9fdfd
authored
Apr 30, 2018
by
Kai Zhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use dependent types
parent
9877beeb
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
340 additions
and
285 deletions
+340
-285
haskell-igraph.cabal
haskell-igraph.cabal
+1
-0
IGraph.hs
src/IGraph.hs
+133
-127
Clique.chs
src/IGraph/Clique.chs
+4
-4
Community.chs
src/IGraph/Community.chs
+3
-3
GEXF.hs
src/IGraph/Exporter/GEXF.hs
+7
-6
Generators.chs
src/IGraph/Generators.chs
+32
-23
Isomorphism.chs
src/IGraph/Isomorphism.chs
+25
-20
Layout.chs
src/IGraph/Layout.chs
+1
-1
Motif.chs
src/IGraph/Motif.chs
+4
-3
Mutable.hs
src/IGraph/Mutable.hs
+76
-66
Read.hs
src/IGraph/Read.hs
+8
-7
Structure.chs
src/IGraph/Structure.chs
+10
-9
Types.hs
src/IGraph/Types.hs
+23
-6
Attributes.hs
tests/Test/Attributes.hs
+5
-4
Basic.hs
tests/Test/Basic.hs
+6
-5
Structure.hs
tests/Test/Structure.hs
+2
-1
No files found.
haskell-igraph.cabal
View file @
6ce9fdfd
...
...
@@ -65,6 +65,7 @@ library
, hashable
, hxt
, split
, singletons
extra-libraries: igraph
hs-source-dirs: src
...
...
src/IGraph.hs
View file @
6ce9fdfd
This diff is collapsed.
Click to expand it.
src/IGraph/Clique.chs
View file @
6ce9fdfd
...
...
@@ -18,7 +18,7 @@ import IGraph.Internal.C2HS
#include "haskell_igraph.h"
cliques ::
L
Graph 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
...
...
@@ -27,13 +27,13 @@ cliques gr (lo, hi) = unsafePerformIO $ allocaVectorPtr $ \vptr -> do
(map.map) truncate <$> toLists vptr
{#fun igraph_cliques as ^ { `IGraph', castPtr `Ptr VectorPtr', `Int', `Int' } -> `CInt' void- #}
largestCliques ::
L
Graph d v e -> [[Int]]
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 ::
L
Graph d v e
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
...
...
@@ -42,7 +42,7 @@ maximalCliques gr (lo, hi) = unsafePerformIO $ allocaVectorPtr $ \vpptr -> do
(map.map) truncate <$> toLists vpptr
{#fun igraph_maximal_cliques as ^ { `IGraph', castPtr `Ptr VectorPtr', `Int', `Int' } -> `CInt' void- #}
cliqueNumber ::
L
Graph d v e -> Int
cliqueNumber :: Graph d v e -> Int
cliqueNumber gr = unsafePerformIO $ igraphCliqueNumber $ _graph gr
{#fun igraph_clique_number as ^
{ `IGraph'
...
...
src/IGraph/Community.chs
View file @
6ce9fdfd
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE DataKinds #-}
module IGraph.Community
( modularity
, findCommunity
...
...
@@ -25,8 +26,7 @@ import IGraph.Internal.C2HS
#include "haskell_igraph.h"
modularity :: Graph d
=> LGraph d v e
modularity :: Graph d v e
-> [[Int]] -- ^ Communities.
-> Maybe [Double] -- ^ Weights
-> Double
...
...
@@ -70,7 +70,7 @@ defaultSpinglass = Spinglass
, _coolFact = 0.99
, _gamma = 1.0 }
findCommunity ::
LGraph
U v e
findCommunity ::
Graph '
U v e
-> Maybe [Double] -- ^ node weights
-> CommunityMethod -- ^ Community finding algorithms
-> [[Int]]
...
...
src/IGraph/Exporter/GEXF.hs
View file @
6ce9fdfd
...
...
@@ -9,12 +9,13 @@ module IGraph.Exporter.GEXF
,
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 @@ defaultEdgeAttributes = EdgeAttr
,
_edgeZindex
=
2
}
genXMLTree
::
(
ArrowXml
a
,
Graph
d
)
=>
L
Graph
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 @@ genXMLTree gr = root [] [gexf]
a
=
show
$
alphaChannel
$
_edgeColour
at
{-# INLINE genXMLTree #-}
writeGEXF
::
Graph
d
=>
FilePath
->
L
Graph
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 file @
6ce9fdfd
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
module IGraph.Generators
( full
, ErdosRenyiModel(..)
...
...
@@ -10,6 +12,7 @@ module IGraph.Generators
import Control.Monad (when)
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
...
...
@@ -23,14 +26,17 @@ import IGraph.Mutable
#include "haskell_igraph.h"
full ::
Graph
d
full ::
forall d. SingI
d
=> Int -- ^ The number of vertices in the graph.
-> Bool -- ^ Whether to include self-edges (loops)
-> d -- ^ U or D
-> LGraph d () ()
full n hasLoop d = unsafePerformIO $ do
gr <- igraphFull n (isD d) hasLoop
unsafeFreeze $ MLGraph gr
-> Graph d () ()
full n hasLoop = unsafePerformIO $ do
gr <- igraphFull n directed hasLoop
unsafeFreeze $ MGraph gr
where
directed = case fromSing (sing :: Sing d) of
D -> True
U -> False
{#fun igraph_full as ^
{ allocaIGraph- `IGraph' addIGraphFinalizer*
, `Int', `Bool', `Bool'
...
...
@@ -39,18 +45,21 @@ full n hasLoop d = unsafePerformIO $ do
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 <- case model of
GNP n p -> igraphErdosRenyiGame IgraphErdosRenyiGnp n p directed self
GNM n m -> igraphErdosRenyiGame IgraphErdosRenyiGnm n (fromIntegral m)
directed self
unsafeFreeze $ MGraph 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'
...
...
@@ -59,24 +68,24 @@ erdosRenyiGame (GNM n m) d self = do
-- | Generates a random graph with a given degree sequence.
degreeSequenceGame :: [Int] -- ^ Out degree
-> [Int] -- ^ In degree
-> IO (
LGraph
D () ())
-> IO (
Graph '
D () ())
degreeSequenceGame out_deg in_deg = withList out_deg $ \out_deg' ->
withList in_deg $ \in_deg' -> do
gp <- igraphDegreeSequenceGame out_deg' in_deg' IgraphDegseqSimple
unsafeFreeze $ M
L
Graph gp
unsafeFreeze $ MGraph gp
{#fun igraph_degree_sequence_game as ^
{ allocaIGraph- `IGraph' addIGraphFinalizer*
, 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.
->
L
Graph d v e
-> IO (
L
Graph d v e)
-> Graph d v e
-> IO (Graph d v e)
rewire n gr = do
(M
L
Graph gptr) <- thaw gr
(MGraph gptr) <- thaw gr
err <- igraphRewire gptr n IgraphRewiringSimple
when (err /= 0) $ error "failed to rewire graph!"
unsafeFreeze $ M
L
Graph gptr
unsafeFreeze $ MGraph gptr
{#fun igraph_rewire as ^ { `IGraph', `Int', `Rewiring' } -> `Int' #}
src/IGraph/Isomorphism.chs
View file @
6ce9fdfd
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE ScopedTypeVariables #-}
module IGraph.Isomorphism
( getSubisomorphisms
, isomorphic
...
...
@@ -8,6 +9,7 @@ module IGraph.Isomorphism
) where
import System.IO.Unsafe (unsafePerformIO)
import Data.Singletons (SingI, Sing, sing, fromSing)
import Foreign
import Foreign.C.Types
...
...
@@ -19,9 +21,8 @@ import IGraph.Mutable
#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 $ allocaVectorPtr $ \vpptr -> do
igraphGetSubisomorphismsVf2 gptr1 gptr2 nullPtr nullPtr nullPtr nullPtr vpptr
...
...
@@ -45,9 +46,8 @@ getSubisomorphisms g1 g2 = unsafePerformIO $ allocaVectorPtr $ \vpptr -> do
} -> `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
...
...
@@ -57,27 +57,32 @@ isomorphic g1 g2 = unsafePerformIO $ alloca $ \ptr -> do
-- | 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 -> [L
Graph 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 -> [L
Graph 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 file @
6ce9fdfd
...
...
@@ -61,7 +61,7 @@ defaultLGL = LGL
where
area x = fromIntegral $ x^2
getLayout :: Graph d
=> LGraph d
v e -> LayoutMethod -> IO [(Double, Double)]
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
...
...
src/IGraph/Motif.chs
View file @
6ce9fdfd
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE DataKinds #-}
module IGraph.Motif
( triad
, triadCensus
...
...
@@ -32,7 +33,7 @@ import IGraph
-- 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 =
...
...
@@ -53,10 +54,10 @@ triad = map make edgeList
, [(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) =>
L
Graph d v e -> [Int]
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
...
...
src/IGraph/Mutable.hs
View file @
6ce9fdfd
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
module
IGraph.Mutable
(
MGraph
(
..
)
,
MLGraph
(
..
)
,
new
,
addNodes
,
addLNodes
,
delNodes
,
addEdges
,
addLEdges
,
delEdges
,
setEdgeAttr
,
setNodeAttr
)
where
import
Control.Monad
(
when
,
forM
)
import
Control.Monad
(
forM
,
when
)
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
M
LGraph
m
d
v
e
=
ML
Graph
IGraph
class
MGraph
d
where
-- | Create a new graph.
new
::
PrimMonad
m
=>
Int
->
m
(
ML
Graph
(
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
-- | 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
$
withAttr
vertexAttr
labels
$
\
attr
->
withPtrs
[
attr
]
(
igraphAddVertices
g
n
.
castPtr
)
where
n
=
length
labels
-- | Delete nodes from the graph.
delNodes
::
PrimMonad
m
=>
[
Int
]
->
MLGraph
(
PrimState
m
)
d
v
e
->
m
(
)
delNodes
ns
(
MLGraph
g
)
=
unsafePrimToPrim
$
withVerticesList
ns
$
\
vs
->
igraphDeleteVertices
g
v
s
-- | Add edges to
the graph.
addEdges
::
PrimMonad
m
=>
[(
Int
,
Int
)]
->
ML
Graph
(
PrimState
m
)
d
v
e
->
m
()
addEdges
es
(
MLGraph
g
)
=
unsafePrimToPrim
$
withList
xs
$
\
vec
->
igraphAddEdges
g
vec
nullPtr
where
xs
=
concatMap
(
\
(
a
,
b
)
->
[
a
,
b
]
)
es
-- | 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
$
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
-- | Delete edges from the graph.
delEdges
::
PrimMonad
m
=>
[(
Int
,
Int
)]
->
MLGraph
(
PrimState
m
)
d
v
e
->
m
()
instance
MGraph
U
where
new
n
=
unsafePrimToPrim
$
igraphInit
>>=
igraphNew
n
False
>>=
return
.
MLGraph
delEdges
es
(
MLGraph
g
)
=
unsafePrimToPrim
$
do
eids
<-
forM
es
$
\
(
fr
,
to
)
->
igraphGetEid
g
fr
to
False
True
withEdgeIdsList
eids
(
igraphDeleteEdges
g
)
instance
MGraph
D
wher
e
new
n
=
unsafePrimToPrim
$
igraphInit
>>=
igraphNew
n
True
>>=
return
.
MLGraph
d
elEdges
es
(
MLGraph
g
)
=
unsafePrimToPrim
$
do
eids
<-
forM
es
$
\
(
fr
,
to
)
->
igraphGetEid
g
fr
to
True
True
withEdgeIdsList
eids
(
igraphDeleteEdges
g
)
newtype
M
Graph
m
(
d
::
EdgeType
)
v
e
=
M
Graph
IGraph
-- | Create a new graph.
new
::
forall
m
d
v
e
.
(
SingI
d
,
PrimMonad
m
)
=>
Int
->
m
(
M
Graph
(
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
-- | 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
-- | 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
label
s
-- | Delete nodes from
the graph.
delNodes
::
PrimMonad
m
=>
[
Int
]
->
M
Graph
(
PrimState
m
)
d
v
e
->
m
()
delNodes
ns
(
MGraph
g
)
=
unsafePrimToPrim
$
withVerticesList
ns
$
\
vs
->
igraphDeleteVertices
g
vs
-- | 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
-- | 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
-- | 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
Tru
e
withEdgeIdsList
eids
(
igraphDeleteEdges
g
)
where
d
irected
=
case
fromSing
(
sing
::
Sing
d
)
of
D
->
True
U
->
False
-- | Set node attribute.
setNodeAttr
::
(
PrimMonad
m
,
Serialize
v
)
=>
Int
-- ^ Node id
->
v
->
M
L
Graph
(
PrimState
m
)
d
v
e
->
MGraph
(
PrimState
m
)
d
v
e
->
m
()
setNodeAttr
nodeId
x
(
M
L
Graph
gr
)
=
unsafePrimToPrim
$
setNodeAttr
nodeId
x
(
MGraph
gr
)
=
unsafePrimToPrim
$
withByteString
(
encode
x
)
$
\
bs
->
do
err
<-
igraphHaskellAttributeVASSet
gr
vertexAttr
nodeId
bs
when
(
err
/=
0
)
$
error
"Fail to set node attribute!"
...
...
@@ -90,9 +100,9 @@ setNodeAttr nodeId x (MLGraph gr) = unsafePrimToPrim $
setEdgeAttr
::
(
PrimMonad
m
,
Serialize
e
)
=>
Int
-- ^ Edge id
->
e
->
M
L
Graph
(
PrimState
m
)
d
v
e
->
MGraph
(
PrimState
m
)
d
v
e
->
m
()
setEdgeAttr
edgeId
x
(
M
L
Graph
gr
)
=
unsafePrimToPrim
$
setEdgeAttr
edgeId
x
(
MGraph
gr
)
=
unsafePrimToPrim
$
withByteString
(
encode
x
)
$
\
bs
->
do
err
<-
igraphHaskellAttributeEASSet
gr
edgeAttr
edgeId
bs
when
(
err
/=
0
)
$
error
"Fail to set edge attribute!"
src/IGraph/Read.hs
View file @
6ce9fdfd
...
...
@@ -4,20 +4,21 @@ module IGraph.Read
,
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
(
L
Graph
d
B
.
ByteString
()
)
readAdjMatrix
::
SingI
d
=>
FilePath
->
IO
(
Graph
d
B
.
ByteString
()
)
readAdjMatrix
=
fmap
fromAdjMatrix
.
B
.
readFile
fromAdjMatrix
::
Graph
d
=>
B
.
ByteString
->
L
Graph
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 @@ fromAdjMatrix bs =
f
((
i
,
j
),
v
)
=
i
<
j
&&
v
/=
0
{-# INLINE fromAdjMatrix #-}
readAdjMatrixWeighted
::
Graph
d
=>
FilePath
->
IO
(
L
Graph
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 file @
6ce9fdfd
...
...
@@ -15,6 +15,7 @@ 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
...
...
@@ -26,14 +27,14 @@ import IGraph.Mutable
#include "igraph/igraph.h"
inducedSubgraph :: (Hashable v, Eq v, Serialize v) =>
LGraph d v e -> [Int] -> L
Graph d v e
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 . M
L
Graph
unsafeFreeze . MGraph
-- | Closeness centrality
closeness :: [Int] -- ^ vertices
->
L
Graph d v e
-> Graph d v e
-> Maybe [Double] -- ^ optional edge weights
-> Neimode
-> Bool -- ^ whether to normalize
...
...
@@ -45,7 +46,7 @@ closeness nds gr ws mode normal = unsafePerformIO $ allocaVector $ \result ->
-- | Betweenness centrality
betweenness :: [Int]
->
L
Graph d v e
-> Graph d v e
-> Maybe [Double]
-> [Double]
betweenness nds gr ws = unsafePerformIO $ allocaVector $ \result ->
...
...
@@ -54,7 +55,7 @@ betweenness nds gr ws = unsafePerformIO $ allocaVector $ \result ->
toList result
-- | Eigenvector centrality
eigenvectorCentrality ::
L
Graph d v e
eigenvectorCentrality :: Graph d v e
-> Maybe [Double]
-> [Double]
eigenvectorCentrality gr ws = unsafePerformIO $ allocaArpackOpt $ \arparck ->
...
...
@@ -63,8 +64,8 @@ eigenvectorCentrality gr ws = unsafePerformIO $ allocaArpackOpt $ \arparck ->
toList result
-- | Google's PageRank
pagerank ::
Graph
d
=>
L
Graph d v e
pagerank ::
SingI
d
=> Graph d v e
-> Maybe [Double] -- ^ edge weights
-> Double -- ^ damping factor, usually around 0.85
-> [Double]
...
...
@@ -81,8 +82,8 @@ pagerank gr ws d
m = nEdges gr
-- | Personalized PageRank.
personalizedPagerank ::
Graph
d
=>
L
Graph d v e
personalizedPagerank ::
SingI
d
=> Graph d v e
-> [Double] -- ^ reset probability
-> Maybe [Double]
-> Double
...
...
src/IGraph/Types.hs
View file @
6ce9fdfd
{-# LANGUAGE DataKinds #-}
{-# 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.Singletons.Prelude
import
Data.Singletons.TH
$
(
singletons
[
d
|
data EdgeType = D
| U
deriving (Show, Read, Eq)
|]
)
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 file @
6ce9fdfd
{-# LANGUAGE DataKinds #-}
module
Test.Attributes
(
tests
)
where
...
...
@@ -31,14 +32,14 @@ tests = testGroup "Attribute tests"
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,8 +49,8 @@ serializeTest = testCase "serialize test" $ do
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
...
...
tests/Test/Basic.hs
View file @
6ce9fdfd
{-# LANGUAGE DataKinds #-}
module
Test.Basic
(
tests
)
where
...
...
@@ -33,8 +34,8 @@ graphCreation = testGroup "Graph creation"
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,14 +50,14 @@ graphCreationLabeled = testGroup "Graph creation -- with labels"
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'
=
unsafePerformIO
$
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
...
...
tests/Test/Structure.hs
View file @
6ce9fdfd
{-# LANGUAGE DataKinds #-}
module
Test.Structure
(
tests
)
where
...
...
@@ -27,7 +28,7 @@ subGraphs = testGroup "generate induced subgraphs"
,
[
"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'
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment