-- Example: Reneging from a Queue
--
-- It is described in [1]. This is section 7.8.
--
-- This example models customers arriving to a queue and leaving a queue
-- after a prescribed period of time. The time between arrivals is
-- exponentially distributed with a mean of 20 minutes. The service time
-- for customers is uniformly distributed between 15 and 25 minutes.
-- Customers will only wait for service if the waiting time is less than
-- a renege time which is lognormally distributed with a mean of 10 minutes
-- and a standard deviation of 2 minutes. It is desired to estimate the time
-- in the system for those customers served, the percent of customers that
-- renege and the length of the waiting time.
--
-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.
import Control.Monad
import Control.Monad.Trans
import Data.Array
import Simulation.Aivika.Trans
import qualified Simulation.Aivika.Trans.Queue.Infinite as IQ
import Simulation.Aivika.IO
type DES = IO
-- | The simulation specs.
specs = Specs { spcStartTime = 0.0,
spcStopTime = 10000.0,
spcDT = 0.1,
spcMethod = RungeKutta4,
spcGeneratorType = SimpleGenerator }
mu = 10
nu = 2
logMu = log mu - logNu * logNu / 2
logNu = sqrt $ log ((nu * nu) / (mu * mu) + 1)
model :: Simulation DES (Results DES)
model = do
let customers = randomExponentialStream 20
timeInSystem <- newRef emptySamplingStats
renegeEvents <- newRef (0 :: Int)
queue <- runEventInStartTime $ IQ.newFCFSQueue
let queueProcess =
do x <- IQ.dequeue queue
randomUniformProcess_ 15 25
t <- liftDynamics time
liftEvent $
modifyRef timeInSystem $
addSamplingStats (t - arrivalTime x)
queueProcess
renegingProcess x =
do randomLogNormalProcess_ logMu logNu
liftEvent $
do f <- IQ.queueDelete queue x
when f $ modifyRef renegeEvents ((+) 1)
runProcessInStartTime queueProcess
runProcessInStartTime $
flip consumeStream customers $ \x ->
liftEvent $
do IQ.enqueue queue x
runProcess $ renegingProcess x
return $
results
[resultSource
"queue" "the queue"
queue,
--
resultSource
"timeInSystem" "time in system"
timeInSystem,
--
resultSource
"renegeEvents" "renege events"
renegeEvents]
modelSummary :: Simulation DES (Results DES)
modelSummary =
fmap resultSummary model
main =
do printSimulationResultsInStopTime
printResultSourceInEnglish
modelSummary specs