-- It corresponds to model MachRep3 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. -- -- Variation of models MachRep1, MachRep2. Two machines, but -- sometimes break down. Up time is exponentially distributed with mean -- 1.0, and repair time is exponentially distributed with mean 0.5. In -- this example, there is only one repairperson, and she is not summoned -- until both machines are down. We find the proportion of up time. It -- should come out to about 0.45. import System.Random import Control.Monad import Control.Monad.Trans import Simulation.Aivika import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.Chart meanUpTime = 1.0 meanRepairTime = 0.5 specs = Specs { spcStartTime = 0.0, spcStopTime = 1000.0, spcDT = 1.0, spcMethod = RungeKutta4, spcGeneratorType = SimpleGenerator } experiment :: Experiment experiment = defaultExperiment { experimentSpecs = specs, experimentRunCount = 200, experimentDescription = "Experiment Description", experimentGenerators = [outputView defaultExperimentSpecsView, outputView $ defaultDeviationChartView { deviationChartSeries = [Left "t", Right "x"] }, outputView $ defaultFinalXYChartView { finalXYChartPlotTitle = "The proportion up time for simulation runs < 50 and > 100", finalXYChartXSeries = Just "n", finalXYChartYSeries = [Right "x"], finalXYChartPredicate = do i <- liftParameter simulationIndex return $ (i < 50) || (i > 100) }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Default)", finalHistogramSeries = ["x", "x"] }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Default)", finalHistogramSeries = ["t", "t"] }, outputView $ defaultFinalStatsView { finalStatsSeries = ["x"] }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Default)", finalHistogramSeries = ["x"] }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Bin Size = 0.001)", finalHistogramBuild = histogramBinSize 0.001, finalHistogramSeries = ["x"] }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Bin Num = 10)", finalHistogramBuild = histogramNumBins 10, finalHistogramSeries = ["x"] }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Sturges)", finalHistogramBuild = histogram binSturges, finalHistogramSeries = ["x"] }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Doane)", finalHistogramBuild = histogram binDoane, finalHistogramSeries = ["x"] }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Sqrt)", finalHistogramBuild = histogram binSqrt, finalHistogramSeries = ["x"] }, outputView $ defaultFinalHistogramView { finalHistogramPlotTitle = "Final Histogram (Scott)", finalHistogramBuild = histogram binScott, finalHistogramSeries = ["x"] } ] } model :: Simulation ExperimentData model = do -- number of machines currently up nUp <- newRef 2 -- total up time for all machines totalUpTime <- newRef 0.0 repairPerson <- newResource FCFS 1 pid1 <- newProcessId pid2 <- newProcessId let machine :: ProcessId -> Process () machine pid = do upTime <- liftParameter $ randomExponential meanUpTime holdProcess upTime liftEvent $ modifyRef totalUpTime (+ upTime) liftEvent $ modifyRef nUp (+ (-1)) nUp' <- liftEvent $ readRef nUp if nUp' == 1 then passivateProcess else liftEvent $ do n <- resourceCount repairPerson when (n == 1) $ reactivateProcess pid requestResource repairPerson repairTime <- liftParameter $ randomExponential meanRepairTime holdProcess repairTime liftEvent $ modifyRef nUp (+ 1) releaseResource repairPerson machine pid runProcessInStartTimeUsingId IncludingCurrentEvents pid1 (machine pid2) runProcessInStartTimeUsingId IncludingCurrentEvents pid2 (machine pid1) let result = do x <- readRef totalUpTime y <- liftDynamics time return $ x / (2 * y) experimentDataInStartTime [("x", seriesEntity "The proportion of up time" result), ("t", seriesEntity "Total up time" totalUpTime), ("n", seriesEntity "Simulation run" simulationIndex)] main = runExperiment experiment model