packages feed

aivika-experiment-chart 4.0.3 → 4.2

raw patch · 34 files changed

+1689/−182 lines, 34 filesdep ~aivikaPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: aivika

API changes (from Hackage documentation)

Files

aivika-experiment-chart.cabal view
@@ -1,5 +1,5 @@ name:            aivika-experiment-chart-version:         4.0.3+version:         4.2 synopsis:        Simulation experiments with charting for the Aivika library description:     This package complements the Aivika and Aivika Experiment packages with@@ -58,6 +58,11 @@                      examples/InspectionAdjustmentStations/MainUsingCairo.hs                      examples/InspectionAdjustmentStations/MainUsingDiagrams.hs                      examples/InspectionAdjustmentStations/README+                     examples/InventorySystem/Model.hs+                     examples/InventorySystem/Experiment.hs+                     examples/InventorySystem/MainUsingCairo.hs+                     examples/InventorySystem/MainUsingDiagrams.hs+                     examples/InventorySystem/README                      examples/LinearArray/Model.hs                      examples/LinearArray/Experiment.hs                      examples/LinearArray/MainUsingCairo.hs@@ -68,6 +73,26 @@                      examples/MachRep3/MainUsingCairo.hs                      examples/MachRep3/MainUsingDiagrams.hs                      examples/MachRep3/README+                     examples/MachineBreakdowns/Model.hs+                     examples/MachineBreakdowns/Experiment.hs+                     examples/MachineBreakdowns/MainUsingCairo.hs+                     examples/MachineBreakdowns/MainUsingDiagrams.hs+                     examples/MachineBreakdowns/README+                     examples/QuarryOperations/Model.hs+                     examples/QuarryOperations/Experiment.hs+                     examples/QuarryOperations/MainUsingCairo.hs+                     examples/QuarryOperations/MainUsingDiagrams.hs+                     examples/QuarryOperations/README+                     examples/PortOperations/Model.hs+                     examples/PortOperations/Experiment.hs+                     examples/PortOperations/MainUsingCairo.hs+                     examples/PortOperations/MainUsingDiagrams.hs+                     examples/PortOperations/README+                     examples/SingleLaneTraffic/Model.hs+                     examples/SingleLaneTraffic/Experiment.hs+                     examples/SingleLaneTraffic/MainUsingCairo.hs+                     examples/SingleLaneTraffic/MainUsingDiagrams.hs+                     examples/SingleLaneTraffic/README  library @@ -91,7 +116,7 @@                      lens >= 3.9,                      data-default-class < 0.1,                      colour >= 2.3.3,-                     aivika >= 4.0.3,+                     aivika >= 4.2,                      aivika-experiment >= 4.0.3      extensions:      MultiParamTypeClasses
examples/BassDiffusion/Experiment.hs view
@@ -20,15 +20,16 @@     experimentRunCount = 20,     experimentDescription = "This is the famous Bass Diffusion model solved with help of the agent-based modelling." } +potentialAdopters = resultByName "potentialAdopters"+adopters = resultByName "adopters"+ generators :: ChartRendering r => [WebPageGenerator r] generators =   [outputView defaultExperimentSpecsView,    outputView defaultInfoView,    outputView $ defaultDeviationChartView {      deviationChartLeftYSeries = -        resultByName "potentialAdopters" <>-        resultByName "adopters" },+        potentialAdopters <> adopters },     outputView $ defaultTimeSeriesView {       timeSeriesLeftYSeries =-         resultByName "potentialAdopters" <>-         resultByName "adopters" } ]+         potentialAdopters <> adopters } ]
examples/BouncingBall/Experiment.hs view
@@ -22,22 +22,21 @@     experimentDescription = "Simulation of a Bouncing Ball as described in " ++                             "the corresponded MATLAB & Simulink example" } +t = resultByName "t"+x = resultByName "x"+v = resultByName "v"+ generators :: ChartRendering r => [WebPageGenerator r] generators =   [outputView defaultExperimentSpecsView,    outputView defaultInfoView,    outputView $ defaultTableView {-     tableSeries =-        resultByName "t" <>-        resultByName "x" <>-        resultByName "v" },+     tableSeries = t <> x <> v },    outputView $ defaultTimeSeriesView {      timeSeriesDescription = "The chart shows the position of the ball",      timeSeriesTitle = "Position",-     timeSeriesLeftYSeries =-        resultByName "x" },+     timeSeriesLeftYSeries = x },    outputView $ defaultTimeSeriesView {      timeSeriesDescription = "The chart shows the velocity of the ball",      timeSeriesTitle = "Velocity",-     timeSeriesLeftYSeries =-        resultByName "v" } ]+     timeSeriesLeftYSeries = v } ]
examples/ChemicalReaction/Experiment.hs view
@@ -22,50 +22,35 @@     experimentDescription = "Chemical Reaction as described in " ++                             "the 5-minute tutorial of Berkeley-Madonna" } +t = resultByName "t"+a = resultByName "a"+b = resultByName "b"+c = resultByName "c"+ generators :: ChartRendering r => [WebPageGenerator r] generators =   [outputView defaultExperimentSpecsView,    outputView $ defaultLastValueView {-     lastValueSeries =-        resultByName "t" <>-        resultByName "a" <>-        resultByName "b" <>-        resultByName "c" },+     lastValueSeries = t <> a <> b <> c },    outputView $ defaultTableView {-     tableSeries =-        resultByName "t" <>-        resultByName "a" <>-        resultByName "b" <>-        resultByName "c" },+     tableSeries = t <> a <> b <> c },    outputView $ defaultTimeSeriesView {      timeSeriesTitle = "Time Series",-     timeSeriesLeftYSeries =-        resultByName "a" <>-        resultByName "b" <>-        resultByName "c" },+     timeSeriesLeftYSeries = a <> b <> c },    outputView $ defaultXYChartView {      xyChartTitle = "XYChart - 1",      xyChartPlotTitle = "b=b(a), c=c(a)",-     xyChartXSeries =-       resultByName "a",-     xyChartLeftYSeries =-       resultByName "b",-     xyChartRightYSeries =-       resultByName "c" },+     xyChartXSeries = a,+     xyChartLeftYSeries = b,+     xyChartRightYSeries = c },    outputView $ defaultXYChartView {      xyChartTitle = "XYChart - 2",      xyChartPlotTitle = "a=a(b), c=c(b)",-     xyChartXSeries =-       resultByName "b",-     xyChartRightYSeries =-       resultByName "a" <>-       resultByName "c" },+     xyChartXSeries = b,+     xyChartRightYSeries = a <> c },    outputView $ defaultXYChartView {      xyChartTitle = "XYChart - 3",      xyChartPlotTitle = "a=a(c), b=b(c)",-     xyChartXSeries =-       resultByName "c",-     xyChartLeftYSeries =-       resultByName "b",-     xyChartRightYSeries =-       resultByName "a" } ]+     xyChartXSeries = c,+     xyChartLeftYSeries = b,+     xyChartRightYSeries = a } ]
examples/DifferenceEquations/Experiment.hs view
@@ -23,29 +23,29 @@                             "the corresponded tutorial of Berkeley-Madonna " ++                             "with small modification for calculating std." } +t     = resultByName "t"+x     = resultByName "x"+sumX  = resultByName "sumX"+sumX2 = resultByName "sumX2"+avg   = resultByName "avg"+std   = resultByName "std"+ generators :: ChartRendering r => [WebPageGenerator r] generators =   [outputView defaultExperimentSpecsView,    outputView defaultInfoView,    outputView $ defaultTableView {      tableSeries =-        mconcat $ map resultByName $-        ["t", "x", "sumX", "sumX2", "avg", "std"] }, +        t <> x <> sumX <> sumX2 <> avg <> std },    outputView $ defaultTimeSeriesView {      timeSeriesTitle = "Time Series",-     timeSeriesLeftYSeries =-       resultByName "x" <>-       resultByName "avg" },+     timeSeriesLeftYSeries = x <> avg },    outputView $ defaultTimingStatsView {-     timingStatsSeries =-        resultByName "x" },+     timingStatsSeries = x },    outputView $ defaultTimeSeriesView {      timeSeriesTitle = "Sums",-     timeSeriesLeftYSeries =-       resultByName "sumX",-     timeSeriesRightYSeries =-       resultByName "sumX2" },+     timeSeriesLeftYSeries = sumX,+     timeSeriesRightYSeries = sumX2 },    outputView $ defaultTimeSeriesView {      timeSeriesTitle = "Standard Deviation",-     timeSeriesLeftYSeries =-       resultByName "std" } ]+     timeSeriesLeftYSeries = std } ]
examples/Financial/Experiment.hs view
@@ -25,6 +25,12 @@     experimentDescription = "Financial Model (the Monte-Carlo simulation) as described in " ++                             "Vensim 5 Modeling Guide, Chapter Financial Modeling and Risk." } +netIncome = resultByName netIncomeName+npvIncome = resultByName npvIncomeName+  +netCashFlow = resultByName netCashFlowName+npvCashFlow = resultByName npvCashFlowName+ monteCarloGenerators :: ChartRendering r => [WebPageGenerator r] monteCarloGenerators =   [outputView defaultExperimentSpecsView,@@ -32,37 +38,25 @@    outputView $ defaultDeviationChartView {      deviationChartTitle = "Chart 1",      deviationChartPlotTitle = "The deviation chart for Net Income and Cash Flow",-     deviationChartLeftYSeries =-       resultByName netIncomeName <>-       resultByName netCashFlowName },+     deviationChartLeftYSeries = netIncome <> netCashFlow },    outputView $ defaultDeviationChartView {      deviationChartTitle = "Chart 2",      deviationChartPlotTitle = "The deviation chart for Net Present Value of Income and Cash Flow",-     deviationChartLeftYSeries =-       resultByName npvIncomeName <>-       resultByName npvCashFlowName },+     deviationChartLeftYSeries = npvIncome <> npvCashFlow },    outputView $ defaultFinalHistogramView {      finalHistogramTitle = "Histogram 1",      finalHistogramPlotTitle = "Histogram for Net Income and Cash Flow",-     finalHistogramSeries =-       resultByName netIncomeName <>-       resultByName netCashFlowName },+     finalHistogramSeries = netIncome <> netCashFlow },    outputView $ defaultFinalHistogramView {      finalHistogramTitle = "Histogram 2",      finalHistogramPlotTitle = "Histogram for Net Present Value of Income and Cash Flow",-     finalHistogramSeries =-       resultByName npvIncomeName <>-       resultByName npvCashFlowName },+     finalHistogramSeries = npvIncome <> npvCashFlow },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Summary 1",-     finalStatsSeries =-       resultByName netIncomeName <>-       resultByName netCashFlowName },+     finalStatsSeries = netIncome <> netCashFlow },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Summary 2",-     finalStatsSeries =-       resultByName npvIncomeName <>-       resultByName npvCashFlowName } ]+     finalStatsSeries = npvIncome <> npvCashFlow } ]    -- | The experiment with single simulation run. singleExperiment :: Experiment@@ -80,18 +74,11 @@    outputView $ defaultTimeSeriesView {      timeSeriesTitle = "Time Series 1",      timeSeriesPlotTitle = "Time series of Net Income and Cash Flow",-     timeSeriesLeftYSeries =-       resultByName netIncomeName <>-       resultByName netCashFlowName },+     timeSeriesLeftYSeries = netIncome <> netCashFlow },    outputView $ defaultTimeSeriesView {      timeSeriesTitle = "Time Series 2",      timeSeriesPlotTitle = "Time series of Net Present Value for Income and Cash Flow",-     timeSeriesLeftYSeries =-       resultByName npvIncomeName <>-       resultByName npvCashFlowName },+     timeSeriesLeftYSeries = npvIncome <> npvCashFlow },    outputView $ defaultTableView {      tableTitle = "Table",-     tableSeries =-       mconcat $ map resultByName $ -       [netIncomeName, netCashFlowName,-                    npvIncomeName, npvCashFlowName] } ]+     tableSeries = netIncome <> netCashFlow <> npvIncome <> npvCashFlow } ]
examples/Furnace/Experiment.hs view
@@ -8,6 +8,8 @@ import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.Chart +import qualified Simulation.Aivika.Results.Transform as T+ import Model  -- | The simulation specs.@@ -27,6 +29,19 @@     experimentRunCount = 100,     experimentTitle = "The Furnace model (the Monte-Carlo simulation)" } +inputIngotCount  = resultByName inputIngotCountName+loadedIngotCount = resultByName loadedIngotCountName+outputIngotCount = resultByName outputIngotCountName+pitCount         = resultByName pitCountName+heatingTime      = resultByName heatingTimeName+outputIngotTemp  = resultByName outputIngotTempName++furnaceQueue     = T.Queue $ resultByName furnaceQueueName+furnaceQueueCount      = T.tr $ T.queueCount furnaceQueue+furnaceQueueCountStats = T.tr $ T.queueCountStats furnaceQueue+furnaceQueueWaitTime   = T.tr $ T.queueWaitTime furnaceQueue+furnaceQueueRate       = T.tr $ T.queueRate furnaceQueue+ generators :: ChartRendering r => [WebPageGenerator r] generators =   [outputView defaultExperimentSpecsView,@@ -35,97 +50,77 @@      deviationChartTitle = "Deviation Chart - 1",      deviationChartPlotTitle = "The input, loaded and output ingot counts",      deviationChartRightYSeries =-       resultByName inputIngotCountName <>-       resultByName loadedIngotCountName <>-       resultByName outputIngotCountName },+       inputIngotCount <> loadedIngotCount <> outputIngotCount },    outputView $ defaultFinalHistogramView {      finalHistogramTitle = "Final Histogram - 1",      finalHistogramPlotTitle = "The distribution of input, loaded and output " ++                                "ingot counts in the final time point.",      finalHistogramSeries =-       resultByName inputIngotCountName <>-       resultByName loadedIngotCountName <>-       resultByName outputIngotCountName },+       inputIngotCount <> loadedIngotCount <> outputIngotCount },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Final Statistics - 1",      finalStatsDescription = "The summary of input, loaded and output " ++                              "ingot counts in the final time point.",      finalStatsSeries =-       resultByName inputIngotCountName <>-       resultByName loadedIngotCountName <>-       resultByName outputIngotCountName },+       inputIngotCount <> loadedIngotCount <> outputIngotCount },    outputView $ defaultDeviationChartView {      deviationChartTitle = "Deviation Chart - 2",      deviationChartPlotTitle = "The used pit count",-     deviationChartRightYSeries =-       resultByName pitCountName },+     deviationChartRightYSeries = pitCount },    outputView $ defaultFinalHistogramView {      finalHistogramTitle = "Final Histogram - 2",      finalHistogramPlotTitle = "The used pit count in the final time point.",-     finalHistogramSeries =-       resultByName pitCountName },+     finalHistogramSeries = pitCount },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Final Statistics - 2",      finalStatsDescription = "The summary of the used pit count in the final time point.",-     finalStatsSeries =-       resultByName pitCountName },+     finalStatsSeries = pitCount },    outputView $ defaultDeviationChartView {      deviationChartTitle = "Deviation Chart - 3",-     deviationChartPlotTitle = "The average queue size",-     deviationChartRightYSeries =-       resultByName furnaceQueueName >>> resultById QueueCountStatsId },+     deviationChartPlotTitle = "The queue size",+     deviationChartRightYSeries = furnaceQueueCount <> furnaceQueueCountStats },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Final Statistics - 3",      finalStatsDescription = "The summary of the average queue size in the final time point.",-     finalStatsSeries =-       resultByName furnaceQueueName >>> resultById QueueCountStatsId },+     finalStatsSeries = furnaceQueueCountStats },    outputView $ defaultDeviationChartView {      deviationChartTitle = "Deviation Chart - 4",      deviationChartPlotTitle = "The mean wait time",-     deviationChartRightYSeries =-       resultByName furnaceQueueName >>> resultById QueueWaitTimeId },+     deviationChartRightYSeries = furnaceQueueWaitTime },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Final Statistics - 4",      finalStatsDescription = "The summary of the mean wait time in " ++                              "the final time point.",-     finalStatsSeries =-       resultByName furnaceQueueName >>> resultById QueueWaitTimeId },+     finalStatsSeries = furnaceQueueWaitTime },    outputView $ defaultDeviationChartView {      deviationChartTitle = "Deviation Chart - 5",      deviationChartPlotTitle = "The queue rate",-     deviationChartRightYSeries =-       resultByName furnaceQueueName >>> resultById QueueRateId },+     deviationChartRightYSeries = furnaceQueueRate },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Final Statistics - 5",      finalStatsDescription = "The summary of the queue rate in " ++                              "the final time point.",-     finalStatsSeries =-       resultByName furnaceQueueName >>> resultById QueueRateId },+     finalStatsSeries = furnaceQueueRate },    outputView $ defaultDeviationChartView {      deviationChartTitle = "Deviation Chart - 6",      deviationChartPlotTitle = "The mean heating time",-     deviationChartRightYSeries =-       resultByName heatingTimeName },+     deviationChartRightYSeries = heatingTime },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Final Statistics - 6",      finalStatsDescription = "The summary of the mean heating time in " ++                              "the final time point.",-     finalStatsSeries =-       resultByName heatingTimeName },+     finalStatsSeries = heatingTime },    outputView $ defaultDeviationChartView {      deviationChartTitle = "Deviation Chart - 7",      deviationChartPlotTitle = "The output ingot temperature",-     deviationChartRightYSeries =-       resultByName outputIngotTempName },+     deviationChartRightYSeries = outputIngotTemp },    outputView $ defaultFinalHistogramView {      finalHistogramTitle = "Final Histogram - 7",      finalHistogramPlotTitle = "The output ingot temperature in " ++                                "the final time point.",-     finalHistogramSeries =-       resultByName outputIngotTempName },+     finalHistogramSeries = outputIngotTemp },    outputView $ defaultFinalStatsView {      finalStatsTitle = "Final Statistics - 7",      finalStatsDescription = "The summary of the output ingot temperature in " ++                              "the final time point.",-     finalStatsSeries =-       resultByName outputIngotTempName } ]+     finalStatsSeries = outputIngotTemp } ]
examples/InspectionAdjustmentStations/Experiment.hs view
@@ -9,6 +9,8 @@ import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.Chart +import qualified Simulation.Aivika.Results.Transform as T+ -- | The simulation specs. specs = Specs { spcStartTime = 0.0,                 spcStopTime = 480.0,@@ -25,37 +27,32 @@     -- experimentRunCount = 10,     experimentTitle = "Inspection and Adjustment Stations on a Production Line (the Monte-Carlo simulation)" } +inputArrivalTimer  = T.ArrivalTimer $ resultByName "inputArrivalTimer"+outputArrivalTimer = T.ArrivalTimer $ resultByName "outputArrivalTimer"++inspectionStations = T.Server $ resultByName "inspectionStations"+adjustmentStations = T.Server $ resultByName "adjustmentStations"++inspectionQueue = T.Queue $ resultByName "inspectionQueue"+adjustmentQueue = T.Queue $ resultByName "adjustmentQueue"+ resultProcessingTime :: ResultTransform resultProcessingTime =-  (resultByName "inputArrivalTimer" >>>-   resultById ArrivalProcessingTimeId)-  <>-  (resultByName "outputArrivalTimer" >>>-   resultById ArrivalProcessingTimeId)+  (T.tr $ T.arrivalProcessingTime inputArrivalTimer) <>+  (T.tr $ T.arrivalProcessingTime outputArrivalTimer)  resultProcessingFactor :: ResultTransform resultProcessingFactor =-  (resultByName "inspectionStations" >>>-   resultById ServerProcessingFactorId)-  <>-  (resultByName "adjustmentStations" >>>-   resultById ServerProcessingFactorId)+  (T.tr $ T.serverProcessingFactor inspectionStations) <>+  (T.tr $ T.serverProcessingFactor adjustmentStations) -resultQueueSize :: ResultTransform-resultQueueSize =-  (resultByName "inspectionQueue" >>>-   resultById QueueCountStatsId)-  <>-  (resultByName "adjustmentQueue" >>>-   resultById QueueCountStatsId)+inspectionQueueCount      = T.tr $ T.queueCount inspectionQueue+inspectionQueueCountStats = T.tr $ T.queueCountStats inspectionQueue+inspectionWaitTime        = T.tr $ T.queueWaitTime inspectionQueue -resultWaitTime :: ResultTransform-resultWaitTime =-  (resultByName "inspectionQueue" >>>-   resultById QueueWaitTimeId)-  <>-  (resultByName "adjustmentQueue" >>>-   resultById QueueWaitTimeId)+adjustmentQueueCount      = T.tr $ T.queueCount adjustmentQueue+adjustmentQueueCountStats = T.tr $ T.queueCountStats adjustmentQueue+adjustmentWaitTime        = T.tr $ T.queueWaitTime adjustmentQueue  generators :: ChartRendering r => [WebPageGenerator r] generators =@@ -76,16 +73,32 @@      finalStatsTitle = "The processing factor (statistics)",      finalStatsSeries = resultProcessingFactor },    outputView $ defaultDeviationChartView {-     deviationChartTitle = "The queue size (chart)",+     deviationChartTitle = "The inspection queue size (chart)",      deviationChartWidth = 1000,-     deviationChartRightYSeries = resultQueueSize },+     deviationChartRightYSeries = +       inspectionQueueCount <> inspectionQueueCountStats },    outputView $ defaultFinalStatsView {-     finalStatsTitle = "The queue size (statistics)",-     finalStatsSeries = resultQueueSize },+     finalStatsTitle = "The inspection queue size (statistics)",+     finalStatsSeries = inspectionQueueCountStats },    outputView $ defaultDeviationChartView {-     deviationChartTitle = "The queue wait time (chart)",+     deviationChartTitle = "The inspection queue wait time (chart)",      deviationChartWidth = 1000,-     deviationChartRightYSeries = resultWaitTime },+     deviationChartRightYSeries = inspectionWaitTime },    outputView $ defaultFinalStatsView {-     finalStatsTitle = "The queue wait time (statistics)",-     finalStatsSeries = resultWaitTime } ]+     finalStatsTitle = "The inspection queue wait time (statistics)",+     finalStatsSeries = inspectionWaitTime },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The adjustment queue size (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = +       adjustmentQueueCount <> adjustmentQueueCountStats },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The adjustment queue size (statistics)",+     finalStatsSeries = adjustmentQueueCountStats },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The adjustment queue wait time (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = adjustmentWaitTime },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The adjustment queue wait time (statistics)",+     finalStatsSeries = adjustmentWaitTime } ]
+ examples/InventorySystem/Experiment.hs view
@@ -0,0 +1,76 @@++module Experiment (experiment, generators) where++import Data.Monoid++import Control.Arrow++import Simulation.Aivika+import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart++import qualified Simulation.Aivika.Results.Transform as T++-- | The simulation specs.+specs = Specs { spcStartTime = 0.0,+                spcStopTime = 312.0,+                spcDT = 0.1,+                spcMethod = RungeKutta4,+                spcGeneratorType = SimpleGenerator }++-- | The experiment.+experiment :: Experiment+experiment =+  defaultExperiment {+    experimentSpecs = specs,+    experimentRunCount = 1000,+    -- experimentRunCount = 10,+    experimentTitle = "Inventory System with Lost Sales and Backorders" }++radio = T.Resource $ resultByName "radio"+radioCount      = T.tr $ T.resourceCount radio+radioCountStats = T.tr $ T.resourceCountStats radio++invPos = T.TimingCounter $ resultByName "invPos"+invPosValue = T.tr $ T.timingCounterValue invPos+invPosStats = T.tr $ T.timingCounterStats invPos++tbLostSales = resultByName "tbLostSales"+tbLostSalesCount = +  T.tr $+  T.samplingStatsCount $+  T.SamplingStats tbLostSales++safetyStock :: ResultTransform+safetyStock = resultByName "safetyStock"++generators :: ChartRendering r => [WebPageGenerator r]+generators =+  [outputView defaultExperimentSpecsView,+   outputView defaultInfoView,+   outputView $ defaultFinalStatsView {+     finalStatsTitle  = "Inventory Position and Time Between Lost Sales",+     finalStatsSeries = invPosStats <> tbLostSales },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "Radios and Inventory Position",+     -- deviationChartWidth = 1000,+     deviationChartRightYSeries = +       radioCount <> invPosValue },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "Radios",+     -- deviationChartWidth = 1000,+     deviationChartRightYSeries = +       radioCount <> radioCountStats },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "Inventory Position",+     -- deviationChartWidth = 1000,+     deviationChartRightYSeries = +       invPosValue <> invPosStats },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "Safety Stock",+     -- deviationChartWidth = 1000,+     deviationChartRightYSeries = +       safetyStock },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "Safety Stock",+     finalStatsSeries = safetyStock } ]
+ examples/InventorySystem/MainUsingCairo.hs view
@@ -0,0 +1,12 @@++-- To run, package aivika-experiment-cairo must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Cairo++import Graphics.Rendering.Chart.Backend.Cairo++import Model+import Experiment++main = runExperiment experiment generators (WebPageRenderer $ CairoRenderer PNG) model
+ examples/InventorySystem/MainUsingDiagrams.hs view
@@ -0,0 +1,14 @@++-- To run, package aivika-experiment-diagrams must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Diagrams++import Graphics.Rendering.Chart.Backend.Diagrams++import qualified Data.Map as M++import Model+import Experiment++main = runExperiment experiment generators (WebPageRenderer $ DiagramsRenderer SVG M.empty) model
+ examples/InventorySystem/Model.hs view
@@ -0,0 +1,162 @@++-- Example: Inventory System with Lost Sales and Backorders +--+-- It is described in different sources [1, 2]. So, this is chapter 11 of [2] and section 6.7 of [1].+--+-- A large discount house is planning to install a system to control the inventory of+-- a particular radio. The time between demands for a radio is exponentially distributed+-- with a mean time of 0.2 weeks. In the case where customers demand the radio when it+-- is not in stock, 80 percent will go to another nearby discount house to find it, thereby+-- representing lost sales, while the other 20 percent will backorder the radio and wait+-- for the next shipment arrival. The store employs a periodic review-reorder point+-- inventory system where the inventory status is reviewed every four weeks to decide if+-- an order should be placed. The company policy is to order up to the stock control level+-- of 72 radios whenever the inventory position, consisting of the radios in stock plus+-- the radios on order minus the radios on backorder, is found to be less than or equal to+-- the reorder point of 18 radios. The procurement lead time (the time from the placement+-- of an order to its receipt) is constant and requires three weeks.+--+-- The objective of this example is to simulate the inventory system for a period of six+-- years (312 weeks) to obtain statistics on the following quantities:+--+--   1) number of radios in stock;+--   2) inventory position;+--   3) safety stock (radios in stock at order receipt times); and+--   4) time between lost sales.+--+-- The initial conditions for the simulation are an inventory position of 72 and no+-- initial backorders. In order to reduce the bias in the statistics due to the initial+-- starting conditions, all the statistics are to be cleared at the end of the first year+-- of the six year simulation period.+--+-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+-- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006++module Model (model) where++import Control.Monad+import Control.Monad.Trans++import Simulation.Aivika+import qualified Simulation.Aivika.Resource as R++-- | The time between demands for a radio.+avgRadioDemand = 0.2++-- | The percent of customers who will backorder the radio.+backorderPercent = 0.2++-- | The stock control level to be ordered up.+stockControlLevel = 72++-- | The inventory position for reordering radio.+reorderPositionThreshold = 18++-- | The initial radios in stock.+radio0 = 72 :: Int++-- | The time from the placement of an order to its receipt+leadTime = 3++-- | How often to order the radios?+reviewPeriod = 4++-- | Clear the statistics at the end of the first year+clearingTime = 52++model :: Simulation Results+model = do+  -- the start time+  t0 <- liftParameter starttime+  -- the inventory position+  invPos <- newRef $ returnTimingCounter t0 radio0+  -- the radios in stock+  radio <- runEventInStartTime $ R.newFCFSResource radio0+  -- the time between lost sales+  tbLostSales <- newRef emptySamplingStats+  -- the last arrive time for the lost sale+  lostSaleArrive <- newRef Nothing+  -- a customer order+  let customerOrder :: Event ()+      customerOrder = do+        do t <- liftDynamics time+           modifyRef invPos $+             decTimingCounter t 1+           runProcess $+             R.requestResource radio+  -- a customer has been lost+  let customerLost :: Event ()+      customerLost = do+        t0 <- readRef lostSaleArrive+        t  <- liftDynamics time+        case t0 of+          Nothing -> return ()+          Just t0 ->+            modifyRef tbLostSales $+            addSamplingStats (t - t0)+        writeRef lostSaleArrive (Just t)+  -- a customer arrival process+  let customerArrival :: Process ()+      customerArrival = do+        randomExponentialProcess_ avgRadioDemand+        liftEvent $ do+          r <- R.resourceCount radio+          if r > 0+            then customerOrder+            else do b <- liftParameter $+                         randomTrue backorderPercent+                    if b+                      then customerOrder+                      else customerLost+        customerArrival+  -- start the customer arrival process+  runProcessInStartTime customerArrival+  -- the safety stock+  safetyStock <- newRef emptySamplingStats+  -- an inventory review process+  let invReview :: Process ()+      invReview = do+        x <- liftEvent $ readRef invPos+        let n = timingCounterValue x+        when (n <= reorderPositionThreshold) $+          do let orderQty = stockControlLevel - n+             liftEvent $+               do t <- liftDynamics time+                  modifyRef invPos $+                    setTimingCounter t stockControlLevel+             holdProcess leadTime+             liftEvent $+               do r <- R.resourceCount radio+                  modifyRef safetyStock $+                    addSamplingStats r+                  R.incResourceCount radio orderQty+  -- start the inventory review process+  runEventInStartTime $+    enqueueEventWithTimes [t0, t0 + reviewPeriod ..] $+    runProcess invReview+  -- clear the statistics at the end of the first year+  runEventInStartTime $+    enqueueEvent clearingTime $+    do t <- liftDynamics time+       modifyRef invPos $ \x ->+         returnTimingCounter t (timingCounterValue x)+       writeRef tbLostSales emptySamplingStats+       writeRef safetyStock emptySamplingStats+  -- return the simulation results+  return $+    results+    [resultSource+     "radio" "the number of radios in stock"+     radio,+     --+     resultSource+     "invPos" "the inventory position"+     invPos,+     --+     resultSource+     "tbLostSales" "the time between lost sales"+     tbLostSales,+     --+     resultSource+     "safetyStock" "the safety stock"+     safetyStock]
+ examples/InventorySystem/README view
@@ -0,0 +1,33 @@++Example: Inventory System with Lost Sales and Backorders++It is described in different sources [1, 2]. So, this is chapter 11 of [2] and section 6.7 of [1].++A large discount house is planning to install a system to control the inventory of+a particular radio. The time between demands for a radio is exponentially distributed+with a mean time of 0.2 weeks. In the case where customers demand the radio when it+is not in stock, 80 percent will go to another nearby discount house to find it, thereby+representing lost sales, while the other 20 percent will backorder the radio and wait+for the next shipment arrival. The store employs a periodic review-reorder point+inventory system where the inventory status is reviewed every four weeks to decide if+an order should be placed. The company policy is to order up to the stock control level+of 72 radios whenever the inventory position, consisting of the radios in stock plus+the radios on order minus the radios on backorder, is found to be less than or equal to+the reorder point of 18 radios. The procurement lead time (the time from the placement+of an order to its receipt) is constant and requires three weeks.++The objective of this example is to simulate the inventory system for a period of six+years (312 weeks) to obtain statistics on the following quantities:++  1) number of radios in stock;+  2) inventory position;+  3) safety stock (radios in stock at order receipt times); and+  4) time between lost sales.++The initial conditions for the simulation are an inventory position of 72 and no+initial backorders. In order to reduce the bias in the statistics due to the initial+starting conditions, all the statistics are to be cleared at the end of the first year+of the six year simulation period.++[1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+[2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006
examples/LinearArray/Experiment.hs view
@@ -22,51 +22,41 @@     experimentDescription = "Model Linear Array as described in " ++                             "the examples included in Berkeley-Madonna." } +t = resultByName "t"+m = resultByName "m"+c = resultByName "c"+         generators :: ChartRendering r => [WebPageGenerator r] generators =    [outputView defaultExperimentSpecsView,    outputView $ defaultTableView {-     tableSeries =-        resultByName "t" <>-        resultByName "m" <>-        resultByName "c" },+     tableSeries = t <> m <> c },    outputView $ defaultTimeSeriesView {-     timeSeriesLeftYSeries =-        resultByName "m",+     timeSeriesLeftYSeries = m,      timeSeriesWidth = 800,      timeSeriesHeight = 800 },    outputView $ defaultTimeSeriesView {-     timeSeriesRightYSeries =-        resultByName "c",+     timeSeriesRightYSeries = c,      timeSeriesWidth = 800,      timeSeriesHeight = 800 },    outputView $ defaultTimeSeriesView {-     timeSeriesLeftYSeries =-        resultByName "m",-     timeSeriesRightYSeries =-       resultByName "c",+     timeSeriesLeftYSeries = m,+     timeSeriesRightYSeries = c,      timeSeriesWidth = 800,      timeSeriesHeight = 800 },    outputView $ defaultXYChartView {-     xyChartXSeries =-        resultByName "t",-     xyChartLeftYSeries =-       resultByName "m",+     xyChartXSeries = t,+     xyChartLeftYSeries = m,      xyChartWidth = 800,      xyChartHeight = 800 },    outputView $ defaultXYChartView {-     xyChartXSeries =-        resultByName "t",-     xyChartRightYSeries =-       resultByName "c",+     xyChartXSeries = t,+     xyChartRightYSeries = c,      xyChartWidth = 800,      xyChartHeight = 800 },    outputView $ defaultXYChartView {-     xyChartXSeries =-        resultByName "t",-     xyChartLeftYSeries =-       resultByName "m",-     xyChartRightYSeries =-       resultByName "c",+     xyChartXSeries = t,+     xyChartLeftYSeries = m,+     xyChartRightYSeries = c,      xyChartWidth = 800,      xyChartHeight = 800 } ]
+ examples/MachineBreakdowns/Experiment.hs view
@@ -0,0 +1,97 @@++module Experiment (experiment, generators) where++import Data.Monoid++import Control.Arrow++import Simulation.Aivika+import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart++import qualified Simulation.Aivika.Results.Transform as T++-- | The simulation specs.+specs = Specs { spcStartTime = 0.0,+                spcStopTime = 500.0,+                spcDT = 0.1,+                spcMethod = RungeKutta4,+                spcGeneratorType = SimpleGenerator }++-- | The experiment.+experiment :: Experiment+experiment =+  defaultExperiment {+    experimentSpecs = specs,+    experimentRunCount = 1000,+    -- experimentRunCount = 10,+    experimentTitle = "Machine Tool with Breakdowns" }++jobsCompleted     = T.ArrivalTimer $ resultByName "jobsCompleted"+jobsInterrupted   = resultByName "jobsInterrupted"+inputQueue        = T.Queue $ resultByName "inputQueue"+machineProcessing = T.Server $ resultByName "machineProcessing"++jobsCompletedCount =+  T.tr $ T.samplingStatsCount $+  T.arrivalProcessingTime jobsCompleted+  +processingTime :: ResultTransform+processingTime =+  T.tr $ T.arrivalProcessingTime jobsCompleted++waitTime :: ResultTransform+waitTime =+  T.tr $ T.queueWaitTime inputQueue++queueCount :: ResultTransform+queueCount =+  T.tr $ T.queueCount inputQueue++queueCountStats :: ResultTransform+queueCountStats =+  T.tr $ T.queueCountStats inputQueue++processingFactor :: ResultTransform+processingFactor =+  T.tr $ T.serverProcessingFactor machineProcessing++generators :: ChartRendering r => [WebPageGenerator r]+generators =+  [outputView defaultExperimentSpecsView,+   outputView defaultInfoView,+   outputView $ defaultFinalStatsView {+     finalStatsTitle  = "Machine Tool With Breakdowns",+     finalStatsSeries = jobsCompletedCount <> jobsInterrupted },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The Wait Time (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = waitTime },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Wait Time (statistics)",+     finalStatsSeries = waitTime },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The Queue Size (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = queueCount <> queueCountStats },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Queue Size (statistics)",+     finalStatsSeries = queueCountStats },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The Processing Time (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = processingTime },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Processing Time (statistics)",+     finalStatsSeries = processingTime },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The Machine Load (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = processingFactor },+   outputView $ defaultFinalHistogramView {+     finalHistogramTitle = "The Machine Load (histogram)",+     finalHistogramWidth = 1000,+     finalHistogramSeries = processingFactor },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Machine Load (statistics)",+     finalStatsSeries = processingFactor } ]
+ examples/MachineBreakdowns/MainUsingCairo.hs view
@@ -0,0 +1,12 @@++-- To run, package aivika-experiment-cairo must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Cairo++import Graphics.Rendering.Chart.Backend.Cairo++import Model+import Experiment++main = runExperimentParallel experiment generators (WebPageRenderer $ CairoRenderer PNG) model
+ examples/MachineBreakdowns/MainUsingDiagrams.hs view
@@ -0,0 +1,14 @@++-- To run, package aivika-experiment-diagrams must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Diagrams++import Graphics.Rendering.Chart.Backend.Diagrams++import qualified Data.Map as M++import Model+import Experiment++main = runExperimentParallel experiment generators (WebPageRenderer $ DiagramsRenderer SVG M.empty) model
+ examples/MachineBreakdowns/Model.hs view
@@ -0,0 +1,146 @@++-- Example: Machine Tool with Breakdowns +--+-- It is described in different sources [1, 2]. So, this is chapter 13 of [2] and section 6.12 of [1].+--+-- Jobs arrive to a machine tool on the average of one per hour. The distribution of +-- these interarrival times is exponential. During normal operation, the jobs are +-- processed on a first-in, first-out basis. The time to process a job in hours is +-- normally distributed with a mean of 0.5 and a standard deviation of 0.1. In addition +-- to the processing time, there is a set up time that is uniformly distributed between +-- 0.2 and 0.5 of an hour. Jobs that have been processed by the machine tool are routed +-- to a different section of the shop and are considered to have left the machine tool +-- area.+-- +-- The machine tool experiences breakdowns during which time it can no longer process +-- jobs. The time between breakdowns is normally distributed with a mean of 20 hours +-- and a standard deviation of 2 hours. When a breakdown occurs, the job being processed +-- is removed from the machine tool and is placed at the head of the queue of jobs +-- waiting to be processed. Jobs preempted restart from the point at which they were +-- interrupted.+-- +-- When the machine tool breaks down, a repair process is initiated which is +-- accomplished in three phases. Each phase is exponentially distributed with a mean of +-- 3/4 of an hour. Since the repair time is the sum of independent and identically +-- distributed exponential random variables, the repair time is Erlang distributed. +-- The machine tool is to be analyzed for 500 hours to obtain information on +-- the utilization of the machine tool and the time required to process a job. +-- Statistics are to be collected for thousand simulation runs.+--+-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+-- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006++module Model (model) where++import Control.Monad+import Control.Monad.Trans+import Control.Category++import Data.Monoid+import Data.List++import Simulation.Aivika+import qualified Simulation.Aivika.Queue.Infinite as IQ+import qualified Simulation.Aivika.Resource.Preemption as PR++-- | How often do jobs arrive to a machine tool (exponential)?+jobArrivingMu = 1++-- | A mean of time to process a job (normal). +jobProcessingMu = 0.5++-- | The standard deviation of time to process a job (normal).+jobProcessingSigma = 0.1++-- | The minimum set-up time (uniform).+minSetUpTime = 0.2++-- | The maximum set-up time (uniform).+maxSetUpTime = 0.5++-- | A mean of time between breakdowns (normal).+breakdownMu = 20++-- | The standard deviation of time between breakdowns (normal).+breakdownSigma = 2++-- | A mean of each of the three repair phases (Erlang).+repairMu = 3/4++-- | A priority of the job (less is higher)+jobPriority = 1++-- | A priority of the breakdown (less is higher)+breakdownPriority = 0++-- | The simulation model.+model :: Simulation Results+model = do+  -- create an input queue+  inputQueue <- runEventInStartTime IQ.newFCFSQueue+  -- a counter of jobs completed+  jobsCompleted <- newArrivalTimer+  -- a counter of interrupted jobs+  jobsInterrupted <- newRef (0 :: Int)+  -- create an input stream+  let inputStream =+        randomExponentialStream jobArrivingMu+  -- create a preemptible resource+  tool <- runEventInStartTime $ PR.newResource 1+  -- the machine setting up+  machineSettingUp <-+    newPreemptibleRandomUniformServer True minSetUpTime maxSetUpTime+  -- the machine processing+  machineProcessing <-+    newPreemptibleRandomNormalServer True jobProcessingMu jobProcessingSigma+  -- the machine breakdown+  let machineBreakdown =+        do randomNormalProcess_ breakdownMu breakdownSigma+           PR.usingResourceWithPriority tool breakdownPriority $+             randomErlangProcess_ repairMu 3+           machineBreakdown+  -- start the process of breakdowns+  runProcessInStartTime machineBreakdown+  -- update a counter of job interruptions+  runEventInStartTime $+    handleSignal_ (serverTaskPreemptionBeginning machineProcessing) $ \a ->+    modifyRef jobsInterrupted (+ 1)+  -- define the queue network+  let network = +        queueProcessor+        (\a -> liftEvent $ IQ.enqueue inputQueue a)+        (IQ.dequeue inputQueue) >>>+        (withinProcessor $ PR.requestResourceWithPriority tool jobPriority) >>>+        serverProcessor machineSettingUp >>>+        serverProcessor machineProcessing >>>+        (withinProcessor $ PR.releaseResource tool) >>>+        arrivalTimerProcessor jobsCompleted+  -- start the machine tool+  runProcessInStartTime $+    sinkStream $ runProcessor network inputStream+  -- return the simulation results in start time+  return $+    results+    [resultSource+     "inputQueue" "the queue of jobs"+     inputQueue,+     --+     resultSource+     "machineSettingUp" "the machine setting up"+     machineSettingUp,+     --+     resultSource+     "machineProcessing" "the machine processing"+     machineProcessing,+     --+     resultSource+     "jobsInterrupted" "a counter of the interrupted jobs"+     jobsInterrupted,+     --+     resultSource+     "jobsCompleted" "a counter of the completed jobs"+     jobsCompleted,+     --+     resultSource+     "tool" "the machine tool"+     tool]
+ examples/MachineBreakdowns/README view
@@ -0,0 +1,33 @@++CAUTION: THE MODEL IS NOT COMPLETE YET!++Example: Machine Tool with Breakdowns++It is described in different sources [1, 2]. So, this is chapter 13 of [2] and section 6.12 of [1].++Jobs arrive to a machine tool on the average of one per hour. The distribution of +these interarrival times is exponential. During normal operation, the jobs are +processed on a first-in, first-out basis. The time to process a job in hours is +normally distributed with a mean of 0.5 and a standard deviation of 0.1. In addition +to the processing time, there is a set up time that is uniformly distributed between +0.2 and 0.5 of an hour. Jobs that have been processed by the machine tool are routed +to a different section of the shop and are considered to have left the machine tool +area.++The machine tool experiences breakdowns during which time it can no longer process +jobs. The time between breakdowns is normally distributed with a mean of 20 hours +and a standard deviation of 2 hours. When a breakdown occurs, the job being processed +is removed from the machine tool and is placed at the head of the queue of jobs +waiting to be processed. Jobs preempted restart from the point at which they were +interrupted.++When the machine tool breaks down, a repair process is initiated which is +accomplished in three phases. Each phase is exponentially distributed with a mean of +3/4 of an hour. Since the repair time is the sum of independent and identically +distributed exponential random variables, the repair time is Erlang distributed. +The machine tool is to be analyzed for 500 hours to obtain information on +the utilization of the machine tool and the time required to process a job. +Statistics are to be collected for thousand simulation runs.++[1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+[2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006
+ examples/PortOperations/Experiment.hs view
@@ -0,0 +1,70 @@++module Experiment (experiment, generators) where++import Data.Monoid++import Control.Arrow++import Simulation.Aivika+import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart++import qualified Simulation.Aivika.Results.Transform as T++-- | The simulation specs.+specs = Specs { spcStartTime = 0.0,+                spcStopTime = 8760.0,+                spcDT = 0.1,+                spcMethod = RungeKutta4,+                spcGeneratorType = SimpleGenerator }++-- | The experiment.+experiment :: Experiment+experiment =+  defaultExperiment {+    experimentSpecs = specs,+    experimentRunCount = 500,+    -- experimentRunCount = 10,+    experimentTitle = "Port Operations" }++portTime = resultByName "portTime"++berth                 = T.Resource $ resultByName "berth"+berthCountStats       = T.tr $ T.resourceCountStats berth+berthUtilisationCount = T.tr $ T.resourceUtilisationCountStats berth+berthQueueCount       = T.tr $ T.resourceQueueCount berth+berthQueueCountStats  = T.tr $ T.resourceQueueCountStats berth+berthWaitTime         = T.tr $ T.resourceWaitTime berth++tug                 = T.Resource $ resultByName "tug"+tugCountStats       = T.tr $ T.resourceCountStats tug+tugUtilisationCount = T.tr $ T.resourceUtilisationCountStats tug+tugQueueCount       = T.tr $ T.resourceQueueCount tug+tugQueueCountStats  = T.tr $ T.resourceQueueCountStats tug+tugWaitTime         = T.tr $ T.resourceWaitTime tug++generators :: ChartRendering r => [WebPageGenerator r]+generators =+  [outputView defaultExperimentSpecsView,+   outputView defaultInfoView,+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Port Time Summary",+     finalStatsSeries = portTime },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Resource Queue Length",+     finalStatsSeries = berthQueueCountStats <> tugQueueCountStats },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Resource Wait Time",+     finalStatsSeries = berthWaitTime <> tugWaitTime },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Resource Utilisation Summary",+     finalStatsSeries = berthUtilisationCount <> tugUtilisationCount },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Resource Availability Summary",+     finalStatsSeries = berthCountStats <> tugCountStats },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The Berth Resource Queue Length",+     deviationChartRightYSeries = berthQueueCount <> berthQueueCountStats },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The Tug Resource Queue Length",+     deviationChartRightYSeries = tugQueueCount <> tugQueueCountStats }]
+ examples/PortOperations/MainUsingCairo.hs view
@@ -0,0 +1,12 @@++-- To run, package aivika-experiment-cairo must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Cairo++import Graphics.Rendering.Chart.Backend.Cairo++import Model+import Experiment++main = runExperiment experiment generators (WebPageRenderer $ CairoRenderer PNG) model
+ examples/PortOperations/MainUsingDiagrams.hs view
@@ -0,0 +1,14 @@++-- To run, package aivika-experiment-diagrams must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Diagrams++import Graphics.Rendering.Chart.Backend.Diagrams++import qualified Data.Map as M++import Model+import Experiment++main = runExperiment experiment generators (WebPageRenderer $ DiagramsRenderer SVG M.empty) model
+ examples/PortOperations/Model.hs view
@@ -0,0 +1,157 @@++{-# LANGUAGE RecursiveDo #-}++-- Example: Port Operations+--+-- It is described in different sources [1, 2]. So, this is chapter 12 of [2] and section 6.13 of [1].+--+-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+-- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006+-- +-- A port in Africa is used to load tankers with crude oil for overwater shipment.+-- The port has facilities for loading as many as three tankers simultaneously.+-- The  tankers, which arrive at the port every 11 +/- 7 hours, are of three different+-- types. The relative frequency of the various types, and their loading time+-- requirements, are as follows:+-- +-- Type      Relative Frequency      Loading Time, Hours+--   1              0.25                   18 +/- 2+--   2              0.55                   24 +/- 3+--   3              0.20                   36 +/- 4+-- +-- There is one tug at the port. Tankers of all types require the services of this tug+-- to move into a berth, and later to move out of a berth. When the tug is available,+-- any berthing or de-berthing activity takes about one hour. Top priority is given to+-- the berthing activity.+-- +-- A shipper is considering bidding on a contract to transport oil from the port to+-- the United Kingdom. He has determined that 5 tankers of a particular type would+-- have to be committed to this task to meet contract specifications. These tankers+-- would require 21 +/- 3 hours to load oil at the port. After loading and de-berthing,+-- they would travel to the United Kingdom, offload the oil, and return to the port for+-- reloading. Their round-trip travel time, including offloading, is estimated to be+-- 240 +/- hours.+-- +-- A complicated factor is that the port experiences storms. The time between+-- the onset of storms is exponentially distributed with a mean of 48 hours and a +-- storm lasts 4 +/- 2 hours. No tug can start an operation until a storm is over.+-- +-- Before the port authorities can commit themselves to accommodating the+-- proposed 5 tankers, the effect of the additional port traffic on the in-port residence+-- time of the current port users must be determined. It is desired to simulate the+-- operation of the port for a one-year period (= 8640 hours) under the proposed new+-- commitment to measure in-port residence time of the proposed additional tankers,+-- as well as the three types of tankers which already use the port. All durations+-- given as ranges are uniformly distributed.        ++module Model (model) where++import Control.Monad+import Control.Monad.Trans++import Data.Array++import Simulation.Aivika+import qualified Simulation.Aivika.Resource as R++data Tunker =+  Tunker { tunkerLoadingTime :: Double,+           tunkerType :: Int }++model :: Simulation Results+model = mdo+  portTime' <- forM [1..4] $ \i ->+    newRef emptySamplingStats+  let portTime =+        array (1, 4) $ zip [1..] portTime'+  berth <-+    runEventInStartTime $+    R.newFCFSResource 3+  tug   <-+    runEventInStartTime $+    R.newFCFSResource 1+  let tunkers13 = randomUniformStream 4 18+      tunkers4  = takeStream 5 $+                  randomUniformStream 48 48+  runProcessInStartTime $+    flip consumeStream tunkers13 $ \x ->+    do p <- liftParameter $+            randomUniform 0 1+       let tp | p <= 0.25 = 1+              | p <= 0.25 + 0.55 = 2+              | otherwise = 3+       case tp of+         1 -> liftEvent arv1+         2 -> liftEvent arv2+         3 -> liftEvent arv3+  runProcessInStartTime $+    flip consumeStream tunkers4 $ \x ->+    liftEvent arv4+  let arv1 :: Event ()+      arv1 = do+        loadingTime <- liftParameter $+                       randomUniform 16 20+        let t = Tunker loadingTime 1+        runProcess (port t)+      arv2 :: Event ()+      arv2 = do+        loadingTime <- liftParameter $+                       randomUniform 21 27+        let t = Tunker loadingTime 2+        runProcess (port t)+      arv3 :: Event ()+      arv3 = do+        loadingTime <- liftParameter $+                       randomUniform 32 40+        let t = Tunker loadingTime 3+        runProcess (port t)+      arv4 :: Event ()+      arv4 = do+        loadingTime <- liftParameter $+                       randomUniform 18 24+        let t = Tunker loadingTime 4+        runProcess (port t)+  let port :: Tunker -> Process ()+      port t = do+        t0 <- liftDynamics time+        R.requestResource berth+        R.requestResource tug+        holdProcess 1+        R.releaseResource tug+        holdProcess (tunkerLoadingTime t)+        R.requestResource tug+        holdProcess 1+        R.releaseResource tug+        R.releaseResource berth+        t1 <- liftDynamics time+        let tp = tunkerType t +        liftEvent $+          modifyRef (portTime ! tp) $+          addSamplingStats (t1 - t0)+        when (tp == 4) $+          liftEvent $+          runProcess $+          do randomUniformProcess_  216 264+             liftEvent arv4+      storm :: Process ()+      storm = do+        randomExponentialProcess_ 48+        R.decResourceCount tug 1+        randomUniformProcess_ 2 6+        liftEvent $+          R.incResourceCount tug 1+        storm+  runProcessInStartTime storm+  return $+    results+    [resultSource+     "portTime" "Port Time"+     portTime,+     --+     resultSource+     "berth" "Berth"+     berth,+     --+     resultSource+     "tug" "Tug"+     tug ]
+ examples/PortOperations/README view
@@ -0,0 +1,43 @@++Example: Port Operations++It is described in different sources [1, 2]. So, this is chapter 12 of [2] and section 6.13 of [1].++A port in Africa is used to load tankers with crude oil for overwater shipment.+The port has facilities for loading as many as three tankers simultaneously.+The  tankers, which arrive at the port every 11 +/- 7 hours, are of three different+types. The relative frequency of the various types, and their loading time+requirements, are as follows:++Type      Relative Frequency      Loading Time, Hours+  1              0.25                   18 +/- 2+  2              0.55                   24 +/- 3+  3              0.20                   36 +/- 4++There is one tug at the port. Tankers of all types require the services of this tug+to move into a berth, and later to move out of a berth. When the tug is available,+any berthing or de-berthing activity takes about one hour. Top priority is given to+the berthing activity.++A shipper is considering bidding on a contract to transport oil from the port to+the United Kingdom. He has determined that 5 tankers of a particular type would+have to be committed to this task to meet contract specifications. These tankers+would require 21 +/- 3 hours to load oil at the port. After loading and de-berthing,+they would travel to the United Kingdom, offload the oil, and return to the port for+reloading. Their round-trip travel time, including offloading, is estimated to be+240 +/- hours.++A complicated factor is that the port experiences storms. The time between+the onset of storms is exponentially distributed with a mean of 48 hours and a.+storm lasts 4 +/- 2 hours. No tug can start an operation until a storm is over.++Before the port authorities can commit themselves to accommodating the+proposed 5 tankers, the effect of the additional port traffic on the in-port residence+time of the current port users must be determined. It is desired to simulate the+operation of the port for a one-year period (= 8640 hours) under the proposed new+commitment to measure in-port residence time of the proposed additional tankers,+as well as the three types of tankers which already use the port. All durations+given as ranges are uniformly distributed.++[1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+[2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006
+ examples/QuarryOperations/Experiment.hs view
@@ -0,0 +1,93 @@++module Experiment(experiment, generators) where++import Control.Category+import Data.Monoid++import Simulation.Aivika+import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart++import qualified Simulation.Aivika.Results.Transform as T++-- | The simulation specs.+specs = Specs { spcStartTime = 0.0,+                spcStopTime = 480.0,+                spcDT = 0.1,+                spcMethod = RungeKutta4,+                spcGeneratorType = SimpleGenerator }++-- | The experiment.+experiment :: Experiment+experiment =+  defaultExperiment {+    experimentSpecs = specs,+    experimentRunCount = 1000,+    -- experimentRunCount = 10,+    experimentTitle = "Quarry Operations" }++shovelQueue  = T.Queue $ resultByName "shovelQueue"+crusherQueue = T.Queue $ resultByName "crusherQueue"++shovelActvty  = T.Activity $ resultByName "shovelActvty"+crusherActvty = T.Activity $ resultByName "crusherActvty"++shovelQueueCount      = T.tr $ T.queueCount shovelQueue+shovelQueueCountStats = T.tr $ T.queueCountStats shovelQueue+shovelQueueWaitTime   = T.tr $ T.queueWaitTime shovelQueue+shovelQueueRate       = T.tr $ T.queueRate shovelQueue++crusherQueueCount      = T.tr $ T.queueCount crusherQueue+crusherQueueCountStats = T.tr $ T.queueCountStats crusherQueue+crusherQueueWaitTime   = T.tr $ T.queueWaitTime crusherQueue+crusherQueueRate       = T.tr $ T.queueRate crusherQueue++shovelUtilisationFactor  = T.tr $ T.activityUtilisationFactor shovelActvty+crusherUtilisationFactor = T.tr $ T.activityUtilisationFactor crusherActvty++subgenerators1 :: ChartRendering r => String -> ResultTransform -> [WebPageGenerator r]+subgenerators1 title series =+  [outputView $ defaultDeviationChartView {+     deviationChartTitle = title ++ " (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = series },+   outputView $ defaultFinalHistogramView {+     finalHistogramTitle = title ++ " (histogram)",+     finalHistogramWidth = 1000,+     finalHistogramSeries = series },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = title ++ " (statistics)",+     finalStatsSeries = series } ]++subgenerators2 :: ChartRendering r => String -> ResultTransform -> [WebPageGenerator r]+subgenerators2 title series =+  [outputView $ defaultDeviationChartView {+     deviationChartTitle = title ++ " (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = series },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = title ++ " (statistics)",+     finalStatsSeries = series } ]++subgenerators3 :: ChartRendering r => String -> ResultTransform -> ResultTransform -> [WebPageGenerator r]+subgenerators3 title series1 series2 =+  [outputView $ defaultDeviationChartView {+     deviationChartTitle = title ++ " (chart)",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = series1 <> series2 },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = title ++ " (statistics)",+     finalStatsSeries = series2 } ]++generators :: ChartRendering r => [WebPageGenerator r]+generators =+  [outputView defaultExperimentSpecsView,+   outputView defaultInfoView] <>+  subgenerators3 "The shovel queue size" shovelQueueCount shovelQueueCountStats <>+  subgenerators2 "The shovel queue wait time" shovelQueueWaitTime <>+  subgenerators1 "The shovel queue rate" shovelQueueRate <>+  subgenerators3 "The crusher queue size" crusherQueueCount crusherQueueCountStats <>+  subgenerators2 "The crusher queue wait time" crusherQueueWaitTime <>+  subgenerators1 "The crusher queue rate" crusherQueueRate <>+  subgenerators1 "The shovel utilisation factor" shovelUtilisationFactor <>+  subgenerators1 "The crusher utilisation factor" crusherUtilisationFactor
+ examples/QuarryOperations/MainUsingCairo.hs view
@@ -0,0 +1,12 @@++-- To run, package aivika-experiment-cairo must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Cairo++import Graphics.Rendering.Chart.Backend.Cairo++import Model+import Experiment++main = runExperiment experiment generators (WebPageRenderer $ CairoRenderer PNG) model
+ examples/QuarryOperations/MainUsingDiagrams.hs view
@@ -0,0 +1,14 @@++-- To run, package aivika-experiment-diagrams must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Diagrams++import Graphics.Rendering.Chart.Backend.Diagrams++import qualified Data.Map as M++import Model+import Experiment++main = runExperiment experiment generators (WebPageRenderer $ DiagramsRenderer SVG M.empty) model
+ examples/QuarryOperations/Model.hs view
@@ -0,0 +1,209 @@++{-# LANGUAGE Arrows #-}++-- Example: In this example, the operations of a quarry are modeled.+--+-- It is described in different sources [1, 2]. So, this is chapter 10 of [2] and section 5.16 of [1].+--+-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+-- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006+-- +-- In this example, the operations of a quarry are modeled. In the quarry,+-- trucks deliver ore from three shovels to a crusher. A truck always+-- returns to its assigned shovel after dumping a load at the crusher.+-- There are two different truck sizes in use, twenty-ton and fifty-ton.+-- The size of the truck affects its loading time at the shovel, travel+-- time to the crusher, dumping time at the crusher and return trip time+-- from the crusher back to the appropriate shovel. For the twenty-ton+-- trucks, there loading, travel, dumping and return trip times are:+-- exponentially distributed with a mean 5; a constant 2.5; exponentially+-- distributed with mean 2; and a constant 1.5. The corresponding times+-- for the fifty-ton trucks are: exponentially distributed with mean 10;+-- a constant 3; exponentially distributed with mean 4; and a constant 2.+-- To each shovel is assigned two twenty-ton trucks are one fifty-ton truck.+-- The shovel queues are all ranked on a first-in, first-out basis.+-- The crusher queue is ranked on truck size, largest trucks first.+-- It is desired to analyze this system over 480 time units to determine+-- the utilization and queue lengths associated with the shovels and crusher.++module Model(model) where++import Control.Monad+import Control.Monad.Trans+import Control.Category++import Simulation.Aivika+import qualified Simulation.Aivika.Queue.Infinite as IQ++-- | The average loading time for twenty-ton truck+avgLoadingTime20 = 5++-- | A constant travel time for twenty-ton truck+travelTime20 = 2.5++-- | The average dumping time for twenty-ton truck+avgDumpingTime20 = 2++-- | A constant return trip time for twenty-ton truck+returnTripTime20 = 1.5++-- | A priority of the twenty-ton truck (less is higher)+crushingPriority20 = 2++-- | The average loading time for fifty-ton truck+avgLoadingTime50 = 10++-- | A constant travel time for fifty-ton truck+travelTime50 = 3++-- | The average dumping time for fifty-ton truck+avgDumpingTime50 = 4++-- | A constant return trip time for fifty-ton truck+returnTripTime50 = 2++-- | A priority of the fifty-ton truck (less is higher)+crushingPriority50 = 1++-- | It models a truck assigned to some queue.+data Truck =+  Truck { truckQueue :: TruckQueue,+          -- ^ a queue to which the truck is assigned+          truckTonSize :: TruckTonSize,+          -- ^ the truck ton size+          truckAvgLoadingTime :: Double,+          -- ^ the average loading time+          truckTravelTime :: Double,+          -- ^ a constant travel time+          truckCrushingPriority :: Double,+          -- ^ a priority for crushing (less is higher)+          truckAvgDumpingTime :: Double,+          -- ^ the average dumping time+          truckReturnTripTime :: Double+          -- ^ a constant return trip time+        }++-- | It defines the truck ton size+data TruckTonSize = TwentyTonSize | FiftyTonSize++-- | Specifies a queue to which the truck is assigned+data TruckQueue = TruckQueue1 | TruckQueue2 | TruckQueue3++-- | Return a truck assigned to the specified queue with the given ton size.+truck :: TruckQueue -> TruckTonSize -> Truck+truck tq TwentyTonSize =+  Truck { truckQueue = tq,+          truckTonSize = TwentyTonSize,+          truckAvgLoadingTime = avgLoadingTime20,+          truckTravelTime = travelTime20,+          truckCrushingPriority = crushingPriority20,+          truckAvgDumpingTime = avgDumpingTime20,+          truckReturnTripTime = returnTripTime20 }+truck tq FiftyTonSize =+  Truck { truckQueue = tq,+          truckTonSize = FiftyTonSize,+          truckAvgLoadingTime = avgLoadingTime50,+          truckTravelTime = travelTime50,+          truckCrushingPriority = crushingPriority50,+          truckAvgDumpingTime = avgDumpingTime50,+          truckReturnTripTime = returnTripTime50 }+  +model :: Simulation Results+model = do+  -- create a queue for the first shovel+  shovelQueue1 <-+    runEventInStartTime IQ.newFCFSQueue+  -- create another queue for the second shovel+  shovelQueue2 <-+    runEventInStartTime IQ.newFCFSQueue+  -- create a queue for the thrid shovel+  shovelQueue3 <-+    runEventInStartTime IQ.newFCFSQueue+  -- add initial trucks to the queue+  let initShovelQueue q tq =+        do IQ.enqueue q $ truck tq TwentyTonSize+           IQ.enqueue q $ truck tq TwentyTonSize+           IQ.enqueue q $ truck tq FiftyTonSize+  -- initiate the three shovel queues+  runEventInStartTime $+    do initShovelQueue shovelQueue1 TruckQueue1+       initShovelQueue shovelQueue2 TruckQueue2+       initShovelQueue shovelQueue3 TruckQueue3+  -- create a priority queue for the crusher+  crusherQueue <-+    runEventInStartTime IQ.newPriorityQueue+  -- define how the specified truck travels from the shovel to the crusher+  let truckTravel t =+        spawnProcess $+        do holdProcess (truckTravelTime t)+           liftEvent $+             IQ.enqueueWithStoringPriority crusherQueue (truckCrushingPriority t) t+  -- define how the specified truck returns to the queue+  let truckReturnTrip t =+        spawnProcess $+        do holdProcess (truckReturnTripTime t)+           let q = case truckQueue t of+                 TruckQueue1 -> shovelQueue1+                 TruckQueue2 -> shovelQueue2+                 TruckQueue3 -> shovelQueue3+           liftEvent $+             IQ.enqueue q t+  -- utilise the crusher's activity+  let utiliseCrusher q t =+        do randomExponentialProcess_ $+             truckAvgDumpingTime t+           return t+  -- utilise the shovel's activity+  let utiliseShovel q t =+        do randomExponentialProcess_ $+             truckAvgLoadingTime t+           return t+  -- create shovel activities+  shovelAct1 <-+    newActivity $ utiliseShovel shovelQueue1+  shovelAct2 <-+    newActivity $ utiliseShovel shovelQueue2+  shovelAct3 <-+    newActivity $ utiliseShovel shovelQueue3+  -- create the crusher's activity+  crusherAct <-+    newActivity $ utiliseCrusher crusherQueue+  -- define how we should iterate the crusher+  let crusherNet act q =+        proc () ->+        do t  <- arrNet (const $ IQ.dequeue q) -< ()+           t' <- activityNet act  -< t+           arrNet truckReturnTrip -< t'+  let shovelNet act q =+        proc () ->+        do t  <- arrNet (const $ IQ.dequeue q) -< ()+           t' <- activityNet act -< t+           arrNet truckTravel    -< t'+  -- start processing the cursher's queue+  runProcessInStartTime $+    iterateNet (crusherNet crusherAct crusherQueue) ()+  -- start processing the shovel queues+  runProcessInStartTime $+    iterateNet (shovelNet shovelAct1 shovelQueue1) ()+  runProcessInStartTime $+    iterateNet (shovelNet shovelAct2 shovelQueue2) ()+  runProcessInStartTime $+    iterateNet (shovelNet shovelAct3 shovelQueue3) ()+  -- return the simulation results in start time+  return $+    results+    [resultSource+     "shovelQueue" "the shovel's queue"+     [shovelQueue1, shovelQueue2, shovelQueue3],+     --+     resultSource+     "crusherQueue" "the crusher's queue"+     crusherQueue,+     --+     resultSource+     "shovelActvty" "the shovel's activity"+     [shovelAct1, shovelAct2, shovelAct3],+     --+     resultSource+     "crusherActvty" "the crusher's activity"+     crusherAct]
+ examples/QuarryOperations/README view
@@ -0,0 +1,25 @@++Example: In this example, the operations of a quarry are modeled.++It is described in different sources [1, 2]. So, this is chapter 10 of [2] and section 5.16 of [1].++[1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+[2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006++In this example, the operations of a quarry are modeled. In the quarry,+trucks deliver ore from three shovels to a crusher. A truck always+returns to its assigned shovel after dumping a load at the crusher.+There are two different truck sizes in use, twenty-ton and fifty-ton.+The size of the truck affects its loading time at the shovel, travel+time to the crusher, dumping time at the crusher and return trip time+from the crusher back to the appropriate shovel. For the twenty-ton+trucks, there loading, travel, dumping and return trip times are:+exponentially distributed with a mean 5; a constant 2.5; exponentially+distributed with mean 2; and a constant 1.5. The corresponding times+for the fifty-ton trucks are: exponentially distributed with mean 10;+a constant 3; exponentially distributed with mean 4; and a constant 2.+To each shovel is assigned two twenty-ton trucks are one fifty-ton truck.+The shovel queues are all ranked on a first-in, first-out basis.+The crusher queue is ranked on truck size, largest trucks first.+It is desired to analyze this system over 480 time units to determine+the utilization and queue lengths associated with the shovels and crusher.
+ examples/SingleLaneTraffic/Experiment.hs view
@@ -0,0 +1,70 @@++module Experiment (experiment, generators) where++import Data.Monoid++import Control.Arrow++import Simulation.Aivika+import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart++import qualified Simulation.Aivika.Results.Transform as T++-- | The simulation specs.+specs = Specs { spcStartTime = 0.0,+                spcStopTime = 3600.0,+                spcDT = 0.1,+                spcMethod = RungeKutta4,+                spcGeneratorType = SimpleGenerator }++-- | The experiment.+experiment :: Experiment+experiment =+  defaultExperiment {+    experimentSpecs = specs,+    experimentRunCount = 1000,+    -- experimentRunCount = 10,+    experimentTitle = "Single-Lane Traffic Analysis" }++waitTime       = resultByName "waitTime"+greenLightTime = resultByName "greenLightTime"++start                      = T.Resource $ resultByName "start"+startQueueCount            = T.tr $ T.resourceQueueCount start+startQueueCountStats       = T.tr $ T.resourceQueueCountStats start+startWaitTime              = T.tr $ T.resourceWaitTime start+startCountStats            = T.tr $ T.resourceCountStats start+startUtilisationCountStats = T.tr $ T.resourceUtilisationCountStats start++generators :: ChartRendering r => [WebPageGenerator r]+generators =+  [outputView defaultExperimentSpecsView,+   outputView defaultInfoView,+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "Green Light Time (Initial Conditions)",+     finalStatsSeries = greenLightTime },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Average Waiting Time",+     finalStatsSeries = waitTime },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The Average Waiting Time Chart",+     deviationChartWidth = 1000,+     deviationChartRightYSeries = waitTime },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Resource Queue Count",+     finalStatsSeries = startQueueCountStats },+   outputView $ defaultDeviationChartView {+     deviationChartTitle = "The Resource Queue Count Chart",+     deviationChartWidth = 1000,+     deviationChartRightYSeries =+       startQueueCount <> startQueueCountStats },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Resource Wait Time",+     finalStatsSeries = startWaitTime },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Resource Utilisation Summary",+     finalStatsSeries = startUtilisationCountStats },+   outputView $ defaultFinalStatsView {+     finalStatsTitle = "The Resource Availability Summary",+     finalStatsSeries = startCountStats } ]
+ examples/SingleLaneTraffic/MainUsingCairo.hs view
@@ -0,0 +1,15 @@++-- To run, package aivika-experiment-cairo must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Cairo++import Graphics.Rendering.Chart.Backend.Cairo++import Model+import Experiment++main = do+  runExperiment experiment generators (WebPageRenderer $ CairoRenderer PNG) model1+  runExperiment experiment generators (WebPageRenderer $ CairoRenderer PNG) model2+  runExperiment experiment generators (WebPageRenderer $ CairoRenderer PNG) model3
+ examples/SingleLaneTraffic/MainUsingDiagrams.hs view
@@ -0,0 +1,17 @@++-- To run, package aivika-experiment-diagrams must be installed.++import Simulation.Aivika.Experiment+import Simulation.Aivika.Experiment.Chart.Backend.Diagrams++import Graphics.Rendering.Chart.Backend.Diagrams++import qualified Data.Map as M++import Model+import Experiment++main = do+  runExperiment experiment generators (WebPageRenderer $ DiagramsRenderer SVG M.empty) model1+  runExperiment experiment generators (WebPageRenderer $ DiagramsRenderer SVG M.empty) model2+  runExperiment experiment generators (WebPageRenderer $ DiagramsRenderer SVG M.empty) model3
+ examples/SingleLaneTraffic/Model.hs view
@@ -0,0 +1,136 @@++-- Example: Single-Lane Traffic Analysis +--+-- It is described in different sources [1, 2]. So, this is chapter 15 of [2] and section 6.18 of [1].+--+-- The system to be modeled in this example consists of the traffic flow from+-- two directions along a two-lane road, one lane of which has been closed for+-- 500 meters for repairs. Traffic lights have been placed at each end of+-- the closed lane to control the flow of traffic through the repair section.+-- The lights allow traffic to flow for a specified time interval from only+-- one direction. When a light turns green, the waiting cars start and pass+-- the light every two seconds. If a car arrives at a green light when there+-- are no waiting cars, the car passes through the light without delay. The car+-- arrival pattern is exponentially distributed, with an average of 9 seconds+-- between cars from direction 1 and 12 seconds between cars from direction 2.+-- A light cycle consists of green in direction 1, both red, green in direction 2,+-- both red, and then the cycle is repeated. Both lights remain red for 55 seconds+-- to allow the cars in transit to leave the repair section before traffic from+-- the other direction can be initiated.+-- +-- The objective is to simulate the above system to determine values for+-- the green time for direction 1 and the green time for direction 2 which+-- yield a low average waiting time for all cars.+-- +-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+-- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006++module Model (model1, model2, model3) where++import Control.Monad+import Control.Monad.Trans+import Control.Arrow++import Data.Array++import Simulation.Aivika+import qualified Simulation.Aivika.Resource as R++data LightTime =+  LightTime { greenLightTime1 :: Double,+              greenLightTime2 :: Double }++model :: LightTime -> Simulation Results+model lightTime = do+  let greenLightTime =+        array (1, 2)+        [(1, return $ greenLightTime1 lightTime :: Event Double),+         (2, return $ greenLightTime2 lightTime :: Event Double)]+  waitTime1 <- newRef emptySamplingStats+  waitTime2 <- newRef emptySamplingStats+  let waitTime =+        array (1, 2) [(1, waitTime1), (2, waitTime2)]+  start1 <-+    runEventInStartTime $+    R.newFCFSResource 1+  start2 <-+    runEventInStartTime $+    R.newFCFSResource 1+  let start =+        array (1, 2) [(1, start1), (2, start2)]+  light1 <- newGateClosed+  light2 <- newGateClosed+  let stream1 = randomExponentialStream 9+      stream2 = randomExponentialStream 12+  runProcessInStartTime $+    flip consumeStream stream1 $ \x ->+    liftEvent $+    runProcess $+    do R.requestResource start1+       awaitGateOpened light1+       t <- liftDynamics time+       liftEvent $+         modifyRef waitTime1 $+         addSamplingStats (t - arrivalTime x)+       when (t > arrivalTime x) $+         holdProcess 2+       R.releaseResource start1+  runProcessInStartTime $+    flip consumeStream stream2 $ \x ->+    liftEvent $+    runProcess $+    do R.requestResource start2+       awaitGateOpened light2+       t <- liftDynamics time+       liftEvent $+         modifyRef waitTime2 $+         addSamplingStats (t - arrivalTime x)+       when (t > arrivalTime x) $+         holdProcess 2+       R.releaseResource start2+  let lighting =+        do holdProcess 55+           liftEvent $+             openGate light1+           holdProcess $+             greenLightTime1 lightTime+           liftEvent $+             closeGate light1+           holdProcess 55+           liftEvent $+             openGate light2+           holdProcess $+             greenLightTime2 lightTime+           liftEvent $+             closeGate light2+           lighting+  runProcessInStartTime lighting+  return $+    results+    [resultSource+     "start" "Start Resource"+     start,+     --+     resultSource+     "waitTime" "Wait Time"+     waitTime,+     --+     resultSource+     "greenLightTime" "Green Light Time"+     greenLightTime]++modelSummary :: LightTime -> Simulation Results+modelSummary lightTime =+  fmap resultSummary $ model lightTime++lightTime1 = LightTime 60 45+lightTime2 = LightTime 80 60+lightTime3 = LightTime 40 30++model1 = model lightTime1+model2 = model lightTime2+model3 = model lightTime3++modelSummary1 = fmap resultSummary model1+modelSummary2 = fmap resultSummary model2+modelSummary3 = fmap resultSummary model3
+ examples/SingleLaneTraffic/README view
@@ -0,0 +1,26 @@++Example: Single-Lane Traffic Analysis++It is described in different sources [1, 2]. So, this is chapter 15 of [2] and section 6.18 of [1].++The system to be modeled in this example consists of the traffic flow from+two directions along a two-lane road, one lane of which has been closed for+500 meters for repairs. Traffic lights have been placed at each end of+the closed lane to control the flow of traffic through the repair section.+The lights allow traffic to flow for a specified time interval from only+one direction. When a light turns green, the waiting cars start and pass+the light every two seconds. If a car arrives at a green light when there+are no waiting cars, the car passes through the light without delay. The car+arrival pattern is exponentially distributed, with an average of 9 seconds+between cars from direction 1 and 12 seconds between cars from direction 2.+A light cycle consists of green in direction 1, both red, green in direction 2,+both red, and then the cycle is repeated. Both lights remain red for 55 seconds+to allow the cars in transit to leave the repair section before traffic from+the other direction can be initiated.++The objective is to simulate the above system to determine values for+the green time for direction 1 and the green time for direction 2 which+yield a low average waiting time for all cars.++[1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+[2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006