module Numeric.Probability.Example.Queuing where
import qualified Numeric.Probability.Distribution as Dist
import qualified Numeric.Probability.Random as Rnd
import Numeric.Probability.Percentage
(Dist, RDist, Trans, )
import Data.List (nub,sort)
type Time = Int
type Profile = (Time, Time)
type Event a = (a,Profile)
type Queue a = [(a,Time)]
type State a = (Queue a,Time)
type System a = [([a],Time)]
type Events a = [Event a]
event :: Time -> Events a -> Queue a -> [State a]
event = mEvent 1
system :: Events a -> System a
system = mSystem 1
mEvent :: Int -> Time -> Events a -> Queue a -> [State a]
mEvent _ _ [] [] = []
mEvent n 0 ((c,(s,a)):es) q = mEvent n a es (q++[(c,s)])
mEvent n a es [] = ([],a):mEvent n 0 es []
mEvent n _ [] q = (q,s):mEvent n 0 [] (mServe n s q)
where s = mTimeStep n q
mEvent n a es q =
if a < s
then (q,a) : mEvent n 0 es (mServe n a q)
else (q,s) : mEvent n (a-s) es (mServe n s q)
where s = mTimeStep n q
mServe :: Int -> Int -> Queue a -> Queue a
mServe _ _ [] = []
mServe 0 _ x = x
mServe n c ((a,t):es) =
if t > c
then (a,t-c) : mServe (n-1) c es
else mServe (n-1) c es
mTimeStep :: Int -> Queue a -> Int
mTimeStep _ ((_,t):[]) = t
mTimeStep 1 ((_,t):_) = t
mTimeStep n ((_,t):es) = min t (mTimeStep (n-1) es)
mTimeStep _ _ = error "Queuing.mTimeStep: queue must be non-empty"
mSystem :: Int -> Events a -> System a
mSystem n es = map (\(q,t)->(map fst q,t)) $ mEvent n 0 es []
type RProfile = (Dist Time, Trans Time)
type REvent a = (a, RProfile)
type REvents a = [REvent a]
rSystem :: Int -> REvents a -> Rnd.T (System a)
rSystem n re = do
e <- rBuildEvents re
return (mSystem n e)
rBuildEvents :: REvents a -> Rnd.T (Events a)
rBuildEvents ((a,(dt,tt)):ex) = do
rest <- rBuildEvents ex
t <- Rnd.pick dt
nt <- Rnd.pick $ tt t
return ((a,(t,nt)):rest)
rBuildEvents [] = return []
rmSystem :: Ord a => Int -> Int -> REvents a -> RDist (System a)
rmSystem c n re = Rnd.dist $ replicate c (rSystem n re)
evalSystem :: (Ord a, Ord b) =>
Int -> Int -> REvents a -> (System a -> b) -> RDist b
evalSystem c n re ef =
do
rds <- rmSystem c n re
return (Dist.map ef rds)
unit :: b -> ((), b)
unit = (\p->((),p))
maxQueue :: Ord a => System a -> Int
maxQueue s = maximum [length q | (q,_) <- s]
allWaiting :: Ord a => Int -> System a -> [a]
allWaiting n s = nub $ sort $ concat [ drop n q | (q,_) <- s]
countWaiting :: Ord a => Int -> System a -> Int
countWaiting n = length . allWaiting n
waiting :: Int -> System a -> Time
waiting n s = sum [ t*length (drop n q) | (q,t) <- s]
inSystem :: System a -> Time
inSystem s = sum [ t*length q | (q,t) <- s]
total :: System a -> Time
total = sum . map snd
server :: Int -> System a -> Time
server n s = sum [ t*length (take n q) | (q,t) <- s]
idle :: Int -> System a -> Time
idle n s = sum [ t*(n - length q) | (q,t) <- s, length q <= n]
idleAvgP :: Int -> System a -> Float
idleAvgP n s = (fromIntegral $ idle n s) / (fromIntegral $ server n s)