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 +27/−2
- examples/BassDiffusion/Experiment.hs +5/−4
- examples/BouncingBall/Experiment.hs +7/−8
- examples/ChemicalReaction/Experiment.hs +16/−31
- examples/DifferenceEquations/Experiment.hs +13/−13
- examples/Financial/Experiment.hs +15/−28
- examples/Furnace/Experiment.hs +33/−38
- examples/InspectionAdjustmentStations/Experiment.hs +45/−32
- examples/InventorySystem/Experiment.hs +76/−0
- examples/InventorySystem/MainUsingCairo.hs +12/−0
- examples/InventorySystem/MainUsingDiagrams.hs +14/−0
- examples/InventorySystem/Model.hs +162/−0
- examples/InventorySystem/README +33/−0
- examples/LinearArray/Experiment.hs +16/−26
- examples/MachineBreakdowns/Experiment.hs +97/−0
- examples/MachineBreakdowns/MainUsingCairo.hs +12/−0
- examples/MachineBreakdowns/MainUsingDiagrams.hs +14/−0
- examples/MachineBreakdowns/Model.hs +146/−0
- examples/MachineBreakdowns/README +33/−0
- examples/PortOperations/Experiment.hs +70/−0
- examples/PortOperations/MainUsingCairo.hs +12/−0
- examples/PortOperations/MainUsingDiagrams.hs +14/−0
- examples/PortOperations/Model.hs +157/−0
- examples/PortOperations/README +43/−0
- examples/QuarryOperations/Experiment.hs +93/−0
- examples/QuarryOperations/MainUsingCairo.hs +12/−0
- examples/QuarryOperations/MainUsingDiagrams.hs +14/−0
- examples/QuarryOperations/Model.hs +209/−0
- examples/QuarryOperations/README +25/−0
- examples/SingleLaneTraffic/Experiment.hs +70/−0
- examples/SingleLaneTraffic/MainUsingCairo.hs +15/−0
- examples/SingleLaneTraffic/MainUsingDiagrams.hs +17/−0
- examples/SingleLaneTraffic/Model.hs +136/−0
- examples/SingleLaneTraffic/README +26/−0
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