module Language.Passage.SliceSample where
import System.Random
genAll :: IO ()
genAll = mapM_ (genTest 100000) [0..3]
genTest :: Integer -> Int -> IO ()
genTest cnt i = do
putStr $ "Generating " ++ show nm ++ ". "
xs <- genPts cnt slicer 1 5 source
writeFile nm $ unlines (map show xs)
putStrLn "Done."
where gammaLL a b x = (a 1) * log x b * x
normLL = (* 0.5) . negate . (**2)
betaLL a b x = (a 1) * log x + (b1) * log (1 x)
(nm, slicer, source) =
[ ("data.gamma", slicePos, gammaLL 2 5)
, ("data.norm", slice, normLL)
, ("data.beta", sliceUnit, betaLL 2 5)
, ("data.truncNormal",sliceUnit, normLL)
] !! i
genPts :: Integer -> (StdGen -> Double -> Double -> (Double -> Double) -> (Double, Double, StdGen))
-> Double -> Double -> (Double -> Double) -> IO [Double]
genPts cnt slicer w initX ll = do
g <- newStdGen
return $ go g initX cnt
where go _ _ 0 = []
go g0 x0 c = let (x1, _, g1) = slicer g0 w x0 ll
in x1 : go g1 x1 (c1)
sliceUnit :: StdGen
-> Double
-> Double
-> (Double -> Double)
-> (Double, Double, StdGen)
sliceUnit g w x0 ll = genericSlice g w x0 ll (\_ _ -> 0) (\_ _ -> 1)
slicePos :: StdGen
-> Double
-> Double
-> (Double -> Double)
-> (Double, Double, StdGen)
slicePos g w x0 ll = genericSlice g w x0 ll (\_ _ -> 0) (\y lo -> search y (right_pts y lo))
where search y = head . dropWhile (\p -> ll p > y)
right_pts _ lo = [ right, right + w .. ]
where right = x0 + lo
slice :: StdGen
-> Double
-> Double
-> (Double -> Double)
-> (Double, Double, StdGen)
slice g w x0 ll = genericSlice g w x0 ll (\y lo -> search y (left_pts y lo)) (\y lo -> search y (right_pts y lo))
where search y = head . dropWhile (\p -> ll p > y)
left_pts _ lo = [ left, left w .. ]
where left = x0 lo
right_pts _ lo = [ right, right + w .. ]
where right = x0 lo + w
genericSlice :: StdGen
-> Double
-> Double
-> (Double -> Double)
-> (Double -> Double -> Double)
-> (Double -> Double -> Double)
-> (Double, Double, StdGen)
genericSlice g w x0 ll left right =
let (r, g1) = randomR (0, 1) g
y = log r + ll x0
(lo, g2) = randomR (0, w) g1
in pickRandom g2 x0 y ll (left y lo) (right y lo)
pickRandom :: StdGen -> Double -> Double -> (Double -> Double) -> Double -> Double -> (Double, Double, StdGen)
pickRandom g0 x0 y ll = go g0
where go g l r = if ll_x1 < y then if x1 < x0 then go g1 x1 r
else go g1 l x1
else (x1, ll_x1, g1)
where (x1, g1) = randomR (l, r) g
ll_x1 = ll x1