module Simulation.Aivika.Stream.Random
(
randomStream,
randomUniformStream,
randomNormalStream,
randomExponentialStream,
randomErlangStream,
randomPoissonStream,
randomBinomialStream) where
import System.Random
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Parameter
import Simulation.Aivika.Parameter.Random
import Simulation.Aivika.Simulation
import Simulation.Aivika.Dynamics
import Simulation.Aivika.Event
import Simulation.Aivika.Process
import Simulation.Aivika.Processor
import Simulation.Aivika.Stream
import Simulation.Aivika.Statistics
import Simulation.Aivika.Ref
import Simulation.Aivika.Arrival
randomStream :: Parameter (Double, a)
-> Stream (Arrival a)
randomStream delay = Cons z0 where
z0 =
do t0 <- liftDynamics time
loop t0
loop t0 =
do t1 <- liftDynamics time
when (t1 /= t0) $
error $
"The time of requesting for a new random event is different from " ++
"the time when the previous event has arrived. Probably, your model " ++
"contains a logical error. The random events should be requested permanently. " ++
"At least, they can be lost, for example, when trying to enqueue them, but " ++
"the random stream itself must always work: randomStream."
(delay, a) <- liftParameter delay
holdProcess delay
t2 <- liftDynamics time
let arrival = Arrival { arrivalValue = a,
arrivalTime = t2,
arrivalDelay = delay }
return (arrival, Cons $ loop t2)
randomUniformStream :: Double
-> Double
-> Stream (Arrival Double)
randomUniformStream min max =
randomStream $
randomUniform min max >>= \x ->
return (x, x)
randomNormalStream :: Double
-> Double
-> Stream (Arrival Double)
randomNormalStream mu nu =
randomStream $
randomNormal mu nu >>= \x ->
return (x, x)
randomExponentialStream :: Double
-> Stream (Arrival Double)
randomExponentialStream mu =
randomStream $
randomExponential mu >>= \x ->
return (x, x)
randomErlangStream :: Double
-> Int
-> Stream (Arrival Double)
randomErlangStream beta m =
randomStream $
randomErlang beta m >>= \x ->
return (x, x)
randomPoissonStream :: Double
-> Stream (Arrival Int)
randomPoissonStream mu =
randomStream $
randomPoisson mu >>= \x ->
return (fromIntegral x, x)
randomBinomialStream :: Double
-> Int
-> Stream (Arrival Int)
randomBinomialStream prob trials =
randomStream $
randomBinomial prob trials >>= \x ->
return (fromIntegral x, x)