-- It corresponds to model MachRep1 described in document
-- Introduction to Discrete-Event Simulation and the SimPy Language
-- [http://heather.cs.ucdavis.edu/~matloff/156/PLN/DESimIntro.pdf].
-- SimPy is available on [http://simpy.sourceforge.net/].
--
-- The model description is as follows.
--
-- Two machines, which sometimes break down.
-- Up time is exponentially distributed with mean 1.0, and repair time is
-- exponentially distributed with mean 0.5. There are two repairpersons,
-- so the two machines can be repaired simultaneously if they are down
-- at the same time.
--
-- Output is long-run proportion of up time. Should get value of about
-- 0.66.
import Control.Monad
import Control.Monad.Trans
import Control.Concurrent
import qualified Control.Distributed.Process as DP
import Control.Distributed.Process.Node (initRemoteTable)
import Control.Distributed.Process.Backend.SimpleLocalnet
import Simulation.Aivika.Trans
import Simulation.Aivika.Distributed
meanUpTime = 1.0
meanRepairTime = 0.5
specs = Specs { spcStartTime = 0.0,
spcStopTime = 10000.0,
spcDT = 1.0,
spcMethod = RungeKutta4,
spcGeneratorType = SimpleGenerator }
model :: Simulation DIO Double
model =
do totalUpTime <- newRef 0.0
let machine =
do upTime <-
liftParameter $
randomExponential meanUpTime
holdProcess upTime
liftEvent $
modifyRef totalUpTime (+ upTime)
repairTime <-
liftParameter $
randomExponential meanRepairTime
holdProcess repairTime
machine
runProcessInStartTime machine
runProcessInStartTime machine
let upTimeProp =
do x <- readRef totalUpTime
y <- liftDynamics time
return $ x / (2 * y)
runEventInStartTime $
enqueueEventIOWithStopTime $
liftIO $
putStrLn "Test IO"
runEventInStopTime upTimeProp
runModel :: DP.ProcessId -> DP.Process ()
runModel timeServerId =
do DP.say "Started simulating..."
let ps = defaultDIOParams { dioLoggingPriority = NOTICE }
m =
do registerDIO
a <- runSimulation model specs
terminateDIO
return a
(modelId, modelProcess) <- runDIO m ps timeServerId
a <- modelProcess
DP.say $ "The result is " ++ show a
master = \backend nodes ->
do liftIO . putStrLn $ "Slaves: " ++ show nodes
let timeServerParams = defaultTimeServerParams { tsLoggingPriority = DEBUG }
timeServerId <- DP.spawnLocal $ timeServer 1 timeServerParams
runModel timeServerId
main :: IO ()
main = do
backend <- initializeBackend "localhost" "8080" rtable
startMaster backend (master backend)
where
rtable :: DP.RemoteTable
-- rtable = __remoteTable initRemoteTable
rtable = initRemoteTable