packages feed

hgraph-1.2.0.0: src/HGraph/Undirected/Generator.hs

module HGraph.Undirected.Generator
       ( grid
       , cycleGraph
       , completeTree
       , completeGraph
       , randomGraph
       )
where

import HGraph.Undirected
import Data.List
import Control.Monad.State
import System.Random

cycleGraph g0 n = foldr (flip addEdge) (foldr (flip addVertex) g0 [0..n-1]) [(x, (x + 1) `mod` n) | x <- [0..n-1]]

grid g0 w h = foldr (flip addEdge) (foldr (flip addVertex) g0 vs) es
  where
    vs = [(x,y) | x <- [1..w], y <- [1..h]]
    es = concat [[(v,(x+1,y)), (v, (x,y+1))] | x <- [1..w-1], y <- [1..h-1], let v = (x,y)]
      ++ [((x, h), (x+1, h)) | x <- [1..w-1]]
      ++ [((w, y), (w, y+1)) | y <- [1..h-1]]

completeTree g0 depth arity = completeTree' (addVertex (empty g0) 0) 0 1
  where
    completeTree' g root d
      | d > depth = g
      | otherwise = head $ drop arity $
                    iterate' (\h -> let r1 = numVertices h
                                   in addEdge (completeTree' (addVertex h r1) r1 (d+1) ) (root,r1)) g

completeGraph g0 k = foldr (flip addEdge) (foldr (flip addVertex) (empty g0) [0..k-1]) [(u,v) | u <- [0..k-1], v <- [u+1..k-1] ]

randomGraph g0 n m
  | m > (n * (n - 1)) `div` 4 = do -- dense graph
    let g1 = foldr (flip addEdge) (foldr (flip addVertex) (empty g0) [1..n]) [(v,u) | v <- [1..n], u <- [v+1..n]]
    removeRandomEdges g1 m
  | otherwise = do -- spare graph
    let g1 = foldr (flip addVertex) (empty g0) [0..n-1]
    addRandomEdges g1 m

addRandomEdges g m
  | numEdges g == m = return g
  | otherwise = do
    v <- randomN 0 (numVertices g - 1)
    u <- randomN 0 (numVertices g - 1)
    if u /= v then
      addRandomEdges (addEdge g (v,u)) m
    else
      addRandomEdges g m

removeRandomEdges g m
  | numEdges g == m = return g
  | otherwise = do
    v <- randomN 0 (numVertices g - 1)
    u <- randomN 0 (numVertices g - 1)
    if u /= v && edgeExists g (v,u) then
      removeRandomEdges (removeEdge g (v,u)) m
    else
      removeRandomEdges g m

randomN :: (Random a, RandomGen g) => a -> a -> State g a
randomN n0 n1 = do
  gen <- get
  let (r,gen') = randomR (n0,n1) gen
  put gen'
  return r