haskell-igraph-0.6.0: src/IGraph/Generators.chs
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
module IGraph.Generators
( full
, star
, ErdosRenyiModel(..)
, erdosRenyiGame
, degreeSequenceGame
, rewire
) where
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 (MGraph(..))
import qualified IGraph.Mutable as M
{#import IGraph.Internal #}
{#import IGraph.Internal.Constants #}
{# import IGraph.Internal.Initialization #}
#include "haskell_igraph.h"
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 :: forall d. SingI d
=> ErdosRenyiModel
-> Bool -- ^ self-loop
-> 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'
} -> `CInt' void- #}
-- | Generates a random graph with a given degree sequence.
degreeSequenceGame :: [Int] -- ^ Out degree
-> [Int] -- ^ In degree
-> 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*
, castPtr `Ptr Vector', castPtr `Ptr Vector', `Degseq'
} -> `CInt' void- #}
-- | Randomly rewires a graph while preserving the degree distribution.
rewire :: (Hashable v, Serialize v, Eq v, Serialize e)
=> Int -- ^ Number of rewiring trials to perform.
-> Graph d v e
-> IO (Graph d v e)
rewire n gr = do
(MGraph gptr) <- thaw gr
igraphRewire gptr n IgraphRewiringSimple
unsafeFreeze $ MGraph gptr
{#fun igraph_rewire as ^ { `IGraph', `Int', `Rewiring' } -> `CInt' void-#}