{-# LANGUAGE ScopedTypeVariables #-}
module Data.Graph.Generation
(
erdosRenyi
, erdosRenyiU
, erdosRenyiD
, rndGraph
, rndGraph'
, rndAdjacencyMatrix
) where
import Control.Monad (replicateM)
import Data.List (foldl')
import System.Random
import Data.Hashable
import Data.Graph.DGraph
import Data.Graph.Types
import Data.Graph.UGraph
erdosRenyi :: Graph g => Int -> Float -> IO (g Int ())
erdosRenyi n p = rndGraph' p [1..n]
erdosRenyiU :: Int -> Float -> IO (UGraph Int ())
erdosRenyiU = erdosRenyi
erdosRenyiD :: Int -> Float -> IO (DGraph Int ())
erdosRenyiD = erdosRenyi
rndGraph :: forall g v e . (Graph g, Hashable v, Eq v, Random e)
=> (e, e)
-> Float
-> [v]
-> IO (g v e)
rndGraph edgeBounds p verts = go verts (probability p) empty
where
go :: [v] -> Float -> g v e -> IO (g v e)
go [] _ g = return g
go (v:vs) pv g = do
rnds <- replicateM (length vs + 1) $ randomRIO (0.0, 1.0)
flipDir <- randomRIO (True, False)
edgeAttr <- randomRIO edgeBounds
let vs' = zip rnds vs
let g' = insertVertex v g
go vs pv $! foldl' (insertFlippedEdge pv v edgeAttr flipDir) g' vs'
rndGraph' :: forall g v . (Graph g, Hashable v, Eq v)
=> Float
-> [v]
-> IO (g v ())
rndGraph' p verts = go verts (probability p) empty
where
go :: [v] -> Float -> g v () -> IO (g v ())
go [] _ g = return g
go (v:vs) pv g = do
rnds <- replicateM (length vs + 1) $ randomRIO (0.0, 1.0)
flipDir <- randomRIO (True, False)
let vs' = zip rnds vs
let g' = insertVertex v g
go vs pv $! foldl' (insertFlippedEdge pv v () flipDir) g' vs'
rndAdjacencyMatrix :: Int -> IO [[Int]]
rndAdjacencyMatrix n = replicateM n randRow
where randRow = replicateM n (randomRIO (0,1)) :: IO [Int]
insertFlippedEdge :: (Graph g, Hashable v, Eq v)
=> Float
-> v
-> e
-> Bool
-> g v e
-> (Float, v)
-> g v e
insertFlippedEdge pv v edgeAttr flipDir g (p', v')
| p' < pv = insertEdgeTriple triple g
| otherwise = g
where triple = if flipDir then (v', v, edgeAttr) else (v, v', edgeAttr)
probability :: Float -> Float
probability v | v >= 1 = 1 | v <= 0 = 0 | otherwise = v