Commit 59904c7f authored by Kai Zhang's avatar Kai Zhang

add Test for cliques

parent 5b8ed8af
Revision history for haskell-igraph Revision history for haskell-igraph
=================================== ===================================
v0.6.0 --
-------------------
* 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 v0.5.0 -- 2018-04-25
------------------- -------------------
......
...@@ -88,6 +88,7 @@ test-suite tests ...@@ -88,6 +88,7 @@ test-suite tests
Test.Structure Test.Structure
Test.Isomorphism Test.Isomorphism
Test.Motif Test.Motif
Test.Clique
Test.Utils Test.Utils
default-language: Haskell2010 default-language: Haskell2010
......
...@@ -59,7 +59,8 @@ import System.IO.Unsafe (unsafePerformIO) ...@@ -59,7 +59,8 @@ import System.IO.Unsafe (unsafePerformIO)
import IGraph.Internal import IGraph.Internal
import IGraph.Internal.Constants import IGraph.Internal.Constants
import IGraph.Mutable import IGraph.Mutable (MGraph(..))
import qualified IGraph.Mutable as GM
import IGraph.Types import IGraph.Types
-- | Graph with labeled nodes and edges. -- | Graph with labeled nodes and edges.
...@@ -89,6 +90,7 @@ instance (SingI d, Serialize v, Serialize e, Hashable v, Eq v) ...@@ -89,6 +90,7 @@ instance (SingI d, Serialize v, Serialize e, Hashable v, Eq v)
es <- replicateM ne get es <- replicateM ne get
return $ mkGraph nds es return $ mkGraph nds es
-- | Is the graph directed or not.
isDirected :: forall d v e. SingI d => Graph d v e -> Bool isDirected :: forall d v e. SingI d => Graph d v e -> Bool
isDirected _ = case fromSing (sing :: Sing d) of isDirected _ = case fromSing (sing :: Sing d) of
D -> True D -> True
...@@ -165,7 +167,7 @@ getEdgeLabByEid (Graph g _) i = unsafePerformIO $ ...@@ -165,7 +167,7 @@ getEdgeLabByEid (Graph g _) i = unsafePerformIO $
-- | Create a empty graph. -- | Create a empty graph.
empty :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e) empty :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e)
=> Graph d v e => Graph d v e
empty = runST $ new 0 >>= unsafeFreeze empty = runST $ GM.new 0 >>= unsafeFreeze
-- | Create a graph. -- | Create a graph.
mkGraph :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e) mkGraph :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e)
...@@ -173,9 +175,9 @@ mkGraph :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e) ...@@ -173,9 +175,9 @@ mkGraph :: (SingI d, Hashable v, Serialize v, Eq v, Serialize e)
-> [LEdge e] -- ^ Labeled edges. -> [LEdge e] -- ^ Labeled edges.
-> Graph d v e -> Graph d v e
mkGraph vattr es = runST $ do mkGraph vattr es = runST $ do
g <- new 0 g <- GM.new 0
addLNodes vattr g GM.addLNodes vattr g
addLEdges es g GM.addLEdges es g
unsafeFreeze g unsafeFreeze g
-- | Create a graph from labeled edges. -- | Create a graph from labeled edges.
...@@ -225,8 +227,8 @@ deserializeGraph nds evec bsvec = do ...@@ -225,8 +227,8 @@ deserializeGraph nds evec bsvec = do
return $ i + 1 return $ i + 1
_ <- foldMC f 0 _ <- foldMC f 0
liftIO $ do liftIO $ do
gr@(MGraph g) <- new 0 gr@(MGraph g) <- GM.new 0
addLNodes nds gr GM.addLNodes nds gr
withBSAttr edgeAttr bsvec $ \ptr -> withBSAttr edgeAttr bsvec $ \ptr ->
withPtrs [ptr] (igraphAddEdges g evec . castPtr) withPtrs [ptr] (igraphAddEdges g evec . castPtr)
unsafeFreeze gr unsafeFreeze gr
...@@ -280,7 +282,7 @@ nmap :: (Serialize v1, Serialize v2, Hashable v2, Eq v2) ...@@ -280,7 +282,7 @@ nmap :: (Serialize v1, Serialize v2, Hashable v2, Eq v2)
nmap f gr = runST $ do nmap f gr = runST $ do
(MGraph gptr) <- thaw gr (MGraph gptr) <- thaw gr
let gr' = MGraph gptr let gr' = MGraph gptr
forM_ (nodes gr) $ \x -> setNodeAttr x (f (x, nodeLab gr x)) gr' forM_ (nodes gr) $ \x -> GM.setNodeAttr x (f (x, nodeLab gr x)) gr'
unsafeFreeze gr' unsafeFreeze gr'
-- | Apply a function to change edges' labels. -- | Apply a function to change edges' labels.
...@@ -291,7 +293,7 @@ emap f gr = runST $ do ...@@ -291,7 +293,7 @@ emap f gr = runST $ do
let gr' = MGraph gptr let gr' = MGraph gptr
forM_ [0 .. nEdges gr - 1] $ \i -> do forM_ [0 .. nEdges gr - 1] $ \i -> do
let lab = f (getEdgeByEid gr i, getEdgeLabByEid gr i) let lab = f (getEdgeByEid gr i, getEdgeLabByEid gr i)
setEdgeAttr i lab gr' GM.setEdgeAttr i lab gr'
unsafeFreeze gr' unsafeFreeze gr'
-- | Keep nodes that satisfy the constraint. -- | Keep nodes that satisfy the constraint.
...@@ -300,7 +302,7 @@ nfilter :: (Hashable v, Eq v, Serialize v) ...@@ -300,7 +302,7 @@ nfilter :: (Hashable v, Eq v, Serialize v)
nfilter f gr = runST $ do nfilter f gr = runST $ do
let deleted = fst $ unzip $ filter (not . f) $ labNodes gr let deleted = fst $ unzip $ filter (not . f) $ labNodes gr
gr' <- thaw gr gr' <- thaw gr
delNodes deleted gr' GM.delNodes deleted gr'
unsafeFreeze gr' unsafeFreeze gr'
-- | Keep edges that satisfy the constraint. -- | Keep edges that satisfy the constraint.
...@@ -309,5 +311,5 @@ efilter :: (SingI d, Hashable v, Eq v, Serialize v, Serialize e) ...@@ -309,5 +311,5 @@ efilter :: (SingI d, Hashable v, Eq v, Serialize v, Serialize e)
efilter f gr = runST $ do efilter f gr = runST $ do
let deleted = fst $ unzip $ filter (not . f) $ labEdges gr let deleted = fst $ unzip $ filter (not . f) $ labEdges gr
gr' <- thaw gr gr' <- thaw gr
delEdges deleted gr' GM.delEdges deleted gr'
unsafeFreeze gr' unsafeFreeze gr'
...@@ -9,7 +9,7 @@ module IGraph.Generators ...@@ -9,7 +9,7 @@ module IGraph.Generators
, rewire , rewire
) where ) where
import Control.Monad (when) import Control.Monad (when, forM_)
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import Data.Serialize (Serialize) import Data.Serialize (Serialize)
import Data.Singletons (SingI, Sing, sing, fromSing) import Data.Singletons (SingI, Sing, sing, fromSing)
...@@ -19,7 +19,8 @@ import qualified Foreign.Ptr as C2HSImp ...@@ -19,7 +19,8 @@ import qualified Foreign.Ptr as C2HSImp
import Foreign import Foreign
import IGraph import IGraph
import IGraph.Mutable import IGraph.Mutable (MGraph(..))
import qualified IGraph.Mutable as M
{#import IGraph.Internal #} {#import IGraph.Internal #}
{#import IGraph.Internal.Constants #} {#import IGraph.Internal.Constants #}
{# import IGraph.Internal.Initialization #} {# import IGraph.Internal.Initialization #}
...@@ -31,8 +32,9 @@ full :: forall d. SingI d ...@@ -31,8 +32,9 @@ full :: forall d. SingI d
-> Bool -- ^ Whether to include self-edges (loops) -> Bool -- ^ Whether to include self-edges (loops)
-> Graph d () () -> Graph d () ()
full n hasLoop = unsafePerformIO $ do full n hasLoop = unsafePerformIO $ do
gr <- igraphFull n directed hasLoop gr <- MGraph <$> igraphFull n directed hasLoop
unsafeFreeze $ MGraph gr M.initializeNullAttribute gr
unsafeFreeze gr
where where
directed = case fromSing (sing :: Sing d) of directed = case fromSing (sing :: Sing d) of
D -> True D -> True
...@@ -51,11 +53,12 @@ erdosRenyiGame :: forall d. SingI d ...@@ -51,11 +53,12 @@ erdosRenyiGame :: forall d. SingI d
-> IO (Graph d () ()) -> IO (Graph d () ())
erdosRenyiGame model self = do erdosRenyiGame model self = do
igraphInit igraphInit
gr <- case model of gr <- fmap MGraph $ case model of
GNP n p -> igraphErdosRenyiGame IgraphErdosRenyiGnp n p directed self GNP n p -> igraphErdosRenyiGame IgraphErdosRenyiGnp n p directed self
GNM n m -> igraphErdosRenyiGame IgraphErdosRenyiGnm n (fromIntegral m) GNM n m -> igraphErdosRenyiGame IgraphErdosRenyiGnm n (fromIntegral m)
directed self directed self
unsafeFreeze $ MGraph gr M.initializeNullAttribute gr
unsafeFreeze gr
where where
directed = case fromSing (sing :: Sing d) of directed = case fromSing (sing :: Sing d) of
D -> True D -> True
...@@ -71,8 +74,9 @@ degreeSequenceGame :: [Int] -- ^ Out degree ...@@ -71,8 +74,9 @@ degreeSequenceGame :: [Int] -- ^ Out degree
-> IO (Graph 'D () ()) -> IO (Graph 'D () ())
degreeSequenceGame out_deg in_deg = withList out_deg $ \out_deg' -> degreeSequenceGame out_deg in_deg = withList out_deg $ \out_deg' ->
withList in_deg $ \in_deg' -> do withList in_deg $ \in_deg' -> do
gp <- igraphDegreeSequenceGame out_deg' in_deg' IgraphDegseqSimple gr <- MGraph <$> igraphDegreeSequenceGame out_deg' in_deg' IgraphDegseqSimple
unsafeFreeze $ MGraph gp M.initializeNullAttribute gr
unsafeFreeze gr
{#fun igraph_degree_sequence_game as ^ {#fun igraph_degree_sequence_game as ^
{ allocaIGraph- `IGraph' addIGraphFinalizer* { allocaIGraph- `IGraph' addIGraphFinalizer*
, castPtr `Ptr Vector', castPtr `Ptr Vector', `Degseq' , castPtr `Ptr Vector', castPtr `Ptr Vector', `Degseq'
...@@ -85,7 +89,6 @@ rewire :: (Hashable v, Serialize v, Eq v, Serialize e) ...@@ -85,7 +89,6 @@ rewire :: (Hashable v, Serialize v, Eq v, Serialize e)
-> IO (Graph d v e) -> IO (Graph d v e)
rewire n gr = do rewire n gr = do
(MGraph gptr) <- thaw gr (MGraph gptr) <- thaw gr
err <- igraphRewire gptr n IgraphRewiringSimple igraphRewire gptr n IgraphRewiringSimple
when (err /= 0) $ error "failed to rewire graph!"
unsafeFreeze $ MGraph gptr unsafeFreeze $ MGraph gptr
{#fun igraph_rewire as ^ { `IGraph', `Int', `Rewiring' } -> `Int' #} {#fun igraph_rewire as ^ { `IGraph', `Int', `Rewiring' } -> `CInt' void-#}
...@@ -97,14 +97,12 @@ module IGraph.Internal ...@@ -97,14 +97,12 @@ module IGraph.Internal
, withAttr , withAttr
, withBSAttr , withBSAttr
, igraphHaskellAttributeHasAttr , igraphHaskellAttributeHasAttr
, igraphHaskellAttributeGANSet
, igraphHaskellAttributeGAN
, igraphHaskellAttributeVAS , igraphHaskellAttributeVAS
, igraphHaskellAttributeEAN
, igraphHaskellAttributeEAS , igraphHaskellAttributeEAS
, igraphHaskellAttributeEASSetv
, igraphHaskellAttributeVASSet , igraphHaskellAttributeVASSet
, igraphHaskellAttributeVASSetv
, igraphHaskellAttributeEASSet , igraphHaskellAttributeEASSet
, igraphHaskellAttributeEASSetv
-- * Igraph arpack options type -- * Igraph arpack options type
, ArpackOpt , ArpackOpt
...@@ -620,31 +618,58 @@ withBSAttr name bsvec fun = withCString name $ \name' -> ...@@ -620,31 +618,58 @@ withBSAttr name bsvec fun = withCString name $ \name' ->
{#set igraph_attribute_record_t.value #} attr y {#set igraph_attribute_record_t.value #} attr y
{-# INLINE withBSAttr #-} {-# INLINE withBSAttr #-}
-- | Checks whether a (graph, vertex or edge) attribute exists
{#fun igraph_haskell_attribute_has_attr as ^ {#fun igraph_haskell_attribute_has_attr as ^
{ `IGraph', `AttributeElemtype', `String' } -> `Bool' #} { `IGraph'
, `AttributeElemtype' -- ^ The type of the attribute
{#fun igraph_haskell_attribute_GAN_set as ^ , `String' -- ^ The name of the attribute
{ `IGraph', `String', `Double' } -> `Int' #} } -> `Bool' #}
{#fun igraph_haskell_attribute_GAN as ^
{ `IGraph', `String' } -> `Double' #}
-- | Query a string vertex attribute
{#fun igraph_haskell_attribute_VAS as ^ {#fun igraph_haskell_attribute_VAS as ^
{ `IGraph', `String', `Int' } -> `Ptr BSLen' castPtr #} { `IGraph'
, `String' -- ^ The name of the attribute
, `Int' -- ^ The id of the queried vertex
} -> `Ptr BSLen' castPtr #}
{#fun igraph_haskell_attribute_EAN as ^ -- | Query a string edge attribute.
{ `IGraph', `String', `Int' } -> `Double' #}
{#fun igraph_haskell_attribute_EAS as ^ {#fun igraph_haskell_attribute_EAS as ^
{ `IGraph', `String', `Int' } -> `Ptr BSLen' castPtr #} { `IGraph'
, `String' -- ^ The name of the attribute
{#fun igraph_haskell_attribute_EAS_setv as ^ , `Int' -- ^ The id of the queried edge
{ `IGraph', `String', castPtr `Ptr BSVector' } -> `Int' #} } -> `Ptr BSLen' castPtr #}
{#fun igraph_haskell_attribute_VAS_set as ^ {#fun igraph_haskell_attribute_VAS_set as ^
{ `IGraph', `String', `Int', castPtr `Ptr BSLen' } -> `Int' #} { `IGraph'
, `String'
, `Int'
, castPtr `Ptr BSLen'
} -> `CInt' void-#}
{#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-#}
-- | Set a string edge attribute.
{#fun igraph_haskell_attribute_EAS_set as ^ {#fun igraph_haskell_attribute_EAS_set as ^
{ `IGraph', `String', `Int', castPtr `Ptr BSLen' } -> `Int' #} { `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-#}
-- | 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-#}
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
module IGraph.Mutable module IGraph.Mutable
( MGraph(..) ( MGraph(..)
, new , new
, nNodes
, nEdges
, addNodes , addNodes
, addLNodes , addLNodes
, delNodes , delNodes
...@@ -13,9 +15,10 @@ module IGraph.Mutable ...@@ -13,9 +15,10 @@ module IGraph.Mutable
, delEdges , delEdges
, setEdgeAttr , setEdgeAttr
, setNodeAttr , setNodeAttr
, initializeNullAttribute
)where )where
import Control.Monad (forM, when) import Control.Monad (forM)
import Control.Monad.Primitive import Control.Monad.Primitive
import Data.Serialize (Serialize, encode) import Data.Serialize (Serialize, encode)
import Data.Singletons.Prelude (Sing, SingI, fromSing, sing) import Data.Singletons.Prelude (Sing, SingI, fromSing, sing)
...@@ -37,6 +40,16 @@ new n = unsafePrimToPrim $ igraphInit >>= igraphNew n directed >>= return . MGra ...@@ -37,6 +40,16 @@ new n = unsafePrimToPrim $ igraphInit >>= igraphNew n directed >>= return . MGra
D -> True D -> True
U -> False U -> False
-- | 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 #-}
-- | 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 nodes to the graph. -- | Add nodes to the graph.
addNodes :: PrimMonad m addNodes :: PrimMonad m
=> Int -- ^ The number of new nodes. => Int -- ^ The number of new nodes.
...@@ -92,9 +105,7 @@ setNodeAttr :: (PrimMonad m, Serialize v) ...@@ -92,9 +105,7 @@ setNodeAttr :: (PrimMonad m, Serialize v)
-> MGraph (PrimState m) d v e -> MGraph (PrimState m) d v e
-> m () -> m ()
setNodeAttr nodeId x (MGraph gr) = unsafePrimToPrim $ setNodeAttr nodeId x (MGraph gr) = unsafePrimToPrim $
withByteString (encode x) $ \bs -> do withByteString (encode x) $ igraphHaskellAttributeVASSet gr vertexAttr nodeId
err <- igraphHaskellAttributeVASSet gr vertexAttr nodeId bs
when (err /= 0) $ error "Fail to set node attribute!"
-- | Set edge attribute. -- | Set edge attribute.
setEdgeAttr :: (PrimMonad m, Serialize e) setEdgeAttr :: (PrimMonad m, Serialize e)
...@@ -103,6 +114,16 @@ setEdgeAttr :: (PrimMonad m, Serialize e) ...@@ -103,6 +114,16 @@ setEdgeAttr :: (PrimMonad m, Serialize e)
-> MGraph (PrimState m) d v e -> MGraph (PrimState m) d v e
-> m () -> m ()
setEdgeAttr edgeId x (MGraph gr) = unsafePrimToPrim $ setEdgeAttr edgeId x (MGraph gr) = unsafePrimToPrim $
withByteString (encode x) $ \bs -> do withByteString (encode x) $ igraphHaskellAttributeEASSet gr edgeAttr edgeId
err <- igraphHaskellAttributeEASSet gr edgeAttr edgeId bs
when (err /= 0) $ error "Fail to set edge attribute!" 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 #-}
...@@ -21,13 +21,16 @@ import Foreign ...@@ -21,13 +21,16 @@ import Foreign
import Foreign.C.Types import Foreign.C.Types
import IGraph import IGraph
import IGraph.Mutable import IGraph.Mutable (MGraph(..))
{#import IGraph.Internal #} {#import IGraph.Internal #}
{#import IGraph.Internal.Constants #} {#import IGraph.Internal.Constants #}
#include "igraph/igraph.h" #include "igraph/igraph.h"
inducedSubgraph :: (Hashable v, Eq v, Serialize v) => Graph d v e -> [Int] -> 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 -> inducedSubgraph gr nds = unsafePerformIO $ withVerticesList nds $ \vs ->
igraphInducedSubgraph (_graph gr) vs IgraphSubgraphCreateFromScratch >>= igraphInducedSubgraph (_graph gr) vs IgraphSubgraphCreateFromScratch >>=
unsafeFreeze . MGraph unsafeFreeze . MGraph
......
...@@ -14,7 +14,7 @@ import Test.Utils ...@@ -14,7 +14,7 @@ import Test.Utils
import Conduit import Conduit
import IGraph import IGraph
import IGraph.Mutable import qualified IGraph.Mutable as GM
import IGraph.Structure import IGraph.Structure
tests :: TestTree tests :: TestTree
...@@ -60,5 +60,5 @@ graphEdit = testGroup "Graph editing" ...@@ -60,5 +60,5 @@ graphEdit = testGroup "Graph editing"
simple = mkGraph (replicate 3 ()) $ zip [(0,1),(1,2),(2,0)] $ repeat () :: Graph 'U () () simple = mkGraph (replicate 3 ()) $ zip [(0,1),(1,2),(2,0)] $ repeat () :: Graph 'U () ()
simple' = runST $ do simple' = runST $ do
g <- thaw simple g <- thaw simple
delEdges [(0,1),(0,2)] g GM.delEdges [(0,1),(0,2)] g
freeze g freeze g
{-# 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]]
import qualified Test.Attributes as Attributes
import qualified Test.Basic as Basic import qualified Test.Basic as Basic
import qualified Test.Clique as Clique
import qualified Test.Isomorphism as Isomorphism import qualified Test.Isomorphism as Isomorphism
import qualified Test.Motif as Motif import qualified Test.Motif as Motif
import qualified Test.Structure as Structure import qualified Test.Structure as Structure
import qualified Test.Attributes as Attributes
import Test.Tasty import Test.Tasty
main :: IO () main :: IO ()
...@@ -12,4 +13,5 @@ main = defaultMain $ testGroup "Haskell-igraph Tests" ...@@ -12,4 +13,5 @@ main = defaultMain $ testGroup "Haskell-igraph Tests"
, Motif.tests , Motif.tests
, Isomorphism.tests , Isomorphism.tests
, Attributes.tests , Attributes.tests
, Clique.tests
] ]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment