Commit 69a1f831 authored by Kai Zhang's avatar Kai Zhang

add random generator

parent 5bbb7f57
Revision history for haskell-igraph Revision history for haskell-igraph
=================================== ===================================
v0.7.1 -- 2018-XX-XX v0.7.2 -- XXXX-XX-XX
--------------------
* Add random number generator.
v0.7.1 -- 2018-11-26
--------------------
* Add a few more functions. * Add a few more functions.
......
...@@ -30,6 +30,7 @@ library ...@@ -30,6 +30,7 @@ library
IGraph.Internal IGraph.Internal
IGraph IGraph
IGraph.Mutable IGraph.Mutable
IGraph.Random
IGraph.Types IGraph.Types
IGraph.Exporter.GEXF IGraph.Exporter.GEXF
IGraph.Algorithms IGraph.Algorithms
......
...@@ -22,6 +22,7 @@ import qualified Foreign.Ptr as C2HSImp ...@@ -22,6 +22,7 @@ import qualified Foreign.Ptr as C2HSImp
import Foreign import Foreign
import IGraph import IGraph
import IGraph.Random (Gen)
import IGraph.Mutable (MGraph(..)) import IGraph.Mutable (MGraph(..))
{#import IGraph.Internal #} {#import IGraph.Internal #}
{#import IGraph.Internal.Constants #} {#import IGraph.Internal.Constants #}
...@@ -86,8 +87,9 @@ data ErdosRenyiModel = GNP Int Double -- ^ G(n,p) graph, every possible edge is ...@@ -86,8 +87,9 @@ data ErdosRenyiModel = GNP Int Double -- ^ G(n,p) graph, every possible edge is
erdosRenyiGame :: forall d. SingI d erdosRenyiGame :: forall d. SingI d
=> ErdosRenyiModel => ErdosRenyiModel
-> Bool -- ^ self-loop -> Bool -- ^ self-loop
-> Gen
-> IO (Graph d () ()) -> IO (Graph d () ())
erdosRenyiGame model self = do erdosRenyiGame model self _ = do
igraphInit igraphInit
gr <- case model of gr <- case model of
GNP n p -> igraphErdosRenyiGame IgraphErdosRenyiGnp n p directed self GNP n p -> igraphErdosRenyiGame IgraphErdosRenyiGnp n p directed self
...@@ -107,8 +109,9 @@ erdosRenyiGame model self = do ...@@ -107,8 +109,9 @@ erdosRenyiGame model self = do
-- | Generates a random graph with a given degree sequence. -- | Generates a random graph with a given degree sequence.
degreeSequenceGame :: [Int] -- ^ Out degree degreeSequenceGame :: [Int] -- ^ Out degree
-> [Int] -- ^ In degree -> [Int] -- ^ In degree
-> Gen
-> IO (Graph 'D () ()) -> IO (Graph 'D () ())
degreeSequenceGame out_deg in_deg = do degreeSequenceGame out_deg in_deg _ = do
igraphInit igraphInit
withList out_deg $ \out_deg' -> withList out_deg $ \out_deg' ->
withList in_deg $ \in_deg' -> do withList in_deg $ \in_deg' -> do
...@@ -127,8 +130,9 @@ rewireEdges :: MGraph RealWorld d v e ...@@ -127,8 +130,9 @@ rewireEdges :: MGraph RealWorld d v e
-- one (inclusive). -- one (inclusive).
-> Bool -- ^ whether loop edges are allowed in the new graph, or not. -> Bool -- ^ whether loop edges are allowed in the new graph, or not.
-> Bool -- ^ whether multiple edges are allowed in the new graph. -> Bool -- ^ whether multiple edges are allowed in the new graph.
-> Gen
-> IO () -> IO ()
rewireEdges gr p loop multi = igraphRewireEdges (_mgraph gr) p loop multi rewireEdges gr p loop multi _ = igraphRewireEdges (_mgraph gr) p loop multi
{#fun igraph_rewire_edges as ^ {#fun igraph_rewire_edges as ^
{ `IGraph' { `IGraph'
, `Double' , `Double'
...@@ -140,8 +144,9 @@ rewireEdges gr p loop multi = igraphRewireEdges (_mgraph gr) p loop multi ...@@ -140,8 +144,9 @@ rewireEdges gr p loop multi = igraphRewireEdges (_mgraph gr) p loop multi
rewire :: (Serialize v, Ord v, Serialize e) rewire :: (Serialize v, Ord v, Serialize e)
=> Int -- ^ Number of rewiring trials to perform. => Int -- ^ Number of rewiring trials to perform.
-> Graph d v e -> Graph d v e
-> Gen
-> IO (Graph d v e) -> IO (Graph d v e)
rewire n gr = do rewire n gr _ = do
gr' <- thaw gr gr' <- thaw gr
igraphRewire (_mgraph gr') n IgraphRewiringSimple igraphRewire (_mgraph gr') n IgraphRewiringSimple
unsafeFreeze gr' unsafeFreeze gr'
......
...@@ -115,6 +115,12 @@ module IGraph.Internal ...@@ -115,6 +115,12 @@ module IGraph.Internal
-- * Igraph arpack options type -- * Igraph arpack options type
, ArpackOpt , ArpackOpt
, allocaArpackOpt , allocaArpackOpt
-- * Random numbers
, RNG
, igraphRngSetDefault
, allocaRng
, igraphRngSeed
) where ) where
import Control.Monad import Control.Monad
...@@ -749,3 +755,33 @@ allocaArpackOpt fun = allocaBytes {# sizeof igraph_arpack_options_t #} $ \opt -> ...@@ -749,3 +755,33 @@ allocaArpackOpt fun = allocaBytes {# sizeof igraph_arpack_options_t #} $ \opt ->
igraphArpackOptionsInit opt >> fun opt igraphArpackOptionsInit opt >> fun opt
{-# INLINE allocaArpackOpt #-} {-# INLINE allocaArpackOpt #-}
{#fun igraph_arpack_options_init as ^ { castPtr `Ptr ArpackOpt' } -> `CInt' void- #} {#fun igraph_arpack_options_init as ^ { castPtr `Ptr ArpackOpt' } -> `CInt' void- #}
--------------------------------------------------------------------------------
-- Random numbers
--------------------------------------------------------------------------------
data RNG
-- | Set the default igraph random number generator.
{#fun igraph_rng_set_default as ^ { castPtr `Ptr RNG' } -> `()' #}
-- | Allocate and initialize a RNG.
allocaRng :: (Ptr RNG -> IO a) -> IO a
allocaRng fun = allocaBytes {# sizeof igraph_rng_t #} $ \rng ->
bracket_ (igraphRngInit_ rng) (igraphRngDestroy rng) (fun rng)
{-# INLINE allocaRng #-}
{#fun igraph_rng_init_ as igraphRngInit_
{ castPtr `Ptr RNG' } -> `CInt' void- #}
{#fun igraph_rng_destroy as ^ { castPtr `Ptr RNG' } -> `()' #}
-- | Set the seed of a random number generator
{#fun igraph_rng_seed as ^
{ castPtr `Ptr RNG', `Int' } -> `CInt' void- #}
#c
int igraph_rng_init_(igraph_rng_t *rng) {
return(igraph_rng_init(rng, &igraph_rngtype_mt19937));
}
#endc
module IGraph.Random
( Gen
, withSystemRandom
, withSeed
) where
import IGraph.Internal
-- | Random number generator
data Gen = Gen
withSystemRandom :: (Gen -> IO a) -> IO a
withSystemRandom fun = fun Gen
{-# INLINE withSystemRandom #-}
withSeed :: Int -> (Gen -> IO a) -> IO a
withSeed seed fun = allocaRng $ \rng -> do
igraphRngSetDefault rng
igraphRngSeed rng seed
fun Gen
{-# INLINE withSeed #-}
\ No newline at end of file
...@@ -7,5 +7,5 @@ packages: ...@@ -7,5 +7,5 @@ packages:
extra-deps: [] extra-deps: []
resolver: nightly-2018-11-24 #resolver: nightly-2018-11-24
#resolver: lts-12.14 resolver: lts-12.14
...@@ -11,6 +11,7 @@ import Test.Tasty ...@@ -11,6 +11,7 @@ import Test.Tasty
import Test.Tasty.HUnit import Test.Tasty.HUnit
import IGraph import IGraph
import IGraph.Random
import IGraph.Algorithms import IGraph.Algorithms
import qualified IGraph.Mutable as GM import qualified IGraph.Mutable as GM
...@@ -72,7 +73,7 @@ decomposeTest = testGroup "Decompose" ...@@ -72,7 +73,7 @@ decomposeTest = testGroup "Decompose"
[ testCase "ring" $ edges (head $ decompose $ ring 10) @?= [ testCase "ring" $ edges (head $ decompose $ ring 10) @?=
[(0,1), (1,2), (2,3), (3,4), (4,5), (5,6), (6,7), (7,8), (8,9), (0,9)] [(0,1), (1,2), (2,3), (3,4), (4,5), (5,6), (6,7), (7,8), (8,9), (0,9)]
, testCase "1 component" $ do , testCase "1 component" $ do
gr <- erdosRenyiGame (GNP 100 (40/100)) False :: IO (Graph 'U () ()) gr <- (withSystemRandom $ erdosRenyiGame (GNP 100 (40/100)) False) :: IO (Graph 'U () ())
1 @?= length (decompose gr) 1 @?= length (decompose gr)
, testCase "toy example" $ map (sort . edges) (decompose gr) @?= , testCase "toy example" $ map (sort . edges) (decompose gr) @?=
[ [(0,1), (0,2), (1,2)] [ [(0,1), (0,2), (1,2)]
......
...@@ -13,7 +13,9 @@ import Test.Tasty.HUnit ...@@ -13,7 +13,9 @@ import Test.Tasty.HUnit
import Test.Utils import Test.Utils
import IGraph import IGraph
import IGraph.Random
import qualified IGraph.Mutable as GM import qualified IGraph.Mutable as GM
import IGraph.Algorithms.Generators
tests :: TestTree tests :: TestTree
tests = testGroup "Basic tests" tests = testGroup "Basic tests"
...@@ -21,6 +23,7 @@ tests = testGroup "Basic tests" ...@@ -21,6 +23,7 @@ tests = testGroup "Basic tests"
, graphCreationLabeled , graphCreationLabeled
, graphEdit , graphEdit
, nonSimpleGraphTest , nonSimpleGraphTest
, randomGeneratorTest
] ]
graphCreation :: TestTree graphCreation :: TestTree
...@@ -82,3 +85,14 @@ nonSimpleGraphTest = testGroup "loops, multiple edges" ...@@ -82,3 +85,14 @@ nonSimpleGraphTest = testGroup "loops, multiple edges"
, ((0,2), 'd') ] , ((0,2), 'd') ]
gr :: Graph 'U Int Char gr :: Graph 'U Int Char
gr = mkGraph [0,1,2] es gr = mkGraph [0,1,2] es
randomGeneratorTest :: TestTree
randomGeneratorTest = testGroup "random generator"
[ t1 ]
where
t1 = testCase "random graph" $ do
gr1 <- sort . edges <$> genGr 1244
gr2 <- sort . edges <$> genGr 1244
gr1 @=? gr2
genGr :: Int -> IO (Graph 'D () ())
genGr seed = withSeed seed $ erdosRenyiGame (GNP 1000 0.5) False
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