packages feed

srtree-2.0.1.2: apps/symregg/Random.hs

module Random where 

import System.Random 
import Control.Monad.State.Strict
import Control.Monad
import Data.SRTree 
import Data.SRTree.Eval
import Data.Massiv.Array as MA

type Rng a = StateT StdGen IO a 

toss :: Rng Bool
toss = state random
{-# INLINE toss #-}

tossBiased :: Double -> Rng Bool
tossBiased p = do r <- state random 
                  pure (r < p)

randomVal :: Rng Double
randomVal = state random

randomRange :: (Ord val, Random val) => (val, val) -> Rng val
randomRange rng = state (randomR rng)
{-# INLINE randomRange #-}

randomFrom :: [a] -> Rng a
randomFrom funs = do n <- randomRange (0, length funs - 1)
                     pure $ funs !! n
{-# INLINE randomFrom #-}

randomVec :: Int -> Rng PVector
randomVec n = MA.fromList compMode <$> replicateM n (randomRange (-1, 1))

randomTree :: Int -> Int -> Int -> Rng (Fix SRTree) -> Rng (SRTree ()) -> Bool -> Rng (Fix SRTree)
randomTree minDepth maxDepth maxSize genTerm genNonTerm grow 
  | noSpaceLeft = genTerm
  | needNonTerm = genRecursion 
  | otherwise   = do r <- toss
                     if r 
                       then genTerm 
                       else genRecursion
  where 
    noSpaceLeft = maxDepth <= 1 || maxSize <= 2
    needNonTerm = (minDepth >= 0 || (maxDepth > 2 && not grow)) -- && maxSize > 2

    genRecursion = do 
        node <- genNonTerm
        case node of 
          Uni f _    -> Fix . Uni f <$> randomTree (minDepth - 1) (maxDepth - 1) (maxSize - 1) genTerm genNonTerm grow 
          Bin op _ _ -> do l <- randomTree (minDepth - 1) (maxDepth - 1) (if grow then maxSize - 2 else maxSize `div` 2) genTerm genNonTerm grow
                           r <- randomTree (minDepth - 1) (maxDepth - 1) (maxSize - 1 - countNodes l) genTerm genNonTerm grow 
                           pure . Fix  $ Bin op l r
{-# INLINE randomTree #-}