aivika-experiment-chart 0.3.1 → 0.4
raw patch · 14 files changed
+223/−236 lines, 14 filesdep ~aivikadep ~aivika-experimentPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aivika, aivika-experiment
API changes (from Hackage documentation)
- Simulation.Aivika.Experiment.FinalHistogramView: FinalHistogramView :: String -> String -> Int -> Int -> FileName -> Dynamics Bool -> ([[Double]] -> Histogram) -> [String] -> String -> (PlotBars Double Double -> PlotBars Double Double) -> (Layout1 Double Double -> Layout1 Double Double) -> FinalHistogramView
+ Simulation.Aivika.Experiment.FinalHistogramView: FinalHistogramView :: String -> String -> Int -> Int -> FileName -> Event Bool -> ([[Double]] -> Histogram) -> [String] -> String -> (PlotBars Double Double -> PlotBars Double Double) -> (Layout1 Double Double -> Layout1 Double Double) -> FinalHistogramView
- Simulation.Aivika.Experiment.FinalHistogramView: finalHistogramPredicate :: FinalHistogramView -> Dynamics Bool
+ Simulation.Aivika.Experiment.FinalHistogramView: finalHistogramPredicate :: FinalHistogramView -> Event Bool
- Simulation.Aivika.Experiment.FinalXYChartView: FinalXYChartView :: String -> String -> Int -> Int -> FileName -> Dynamics Bool -> Maybe String -> [Either String String] -> String -> [PlotLines Double Double -> PlotLines Double Double] -> (LayoutAxis Double -> LayoutAxis Double) -> (Layout1 Double Double -> Layout1 Double Double) -> FinalXYChartView
+ Simulation.Aivika.Experiment.FinalXYChartView: FinalXYChartView :: String -> String -> Int -> Int -> FileName -> Event Bool -> Maybe String -> [Either String String] -> String -> [PlotLines Double Double -> PlotLines Double Double] -> (LayoutAxis Double -> LayoutAxis Double) -> (Layout1 Double Double -> Layout1 Double Double) -> FinalXYChartView
- Simulation.Aivika.Experiment.FinalXYChartView: finalXYChartPredicate :: FinalXYChartView -> Dynamics Bool
+ Simulation.Aivika.Experiment.FinalXYChartView: finalXYChartPredicate :: FinalXYChartView -> Event Bool
- Simulation.Aivika.Experiment.HistogramView: HistogramView :: String -> String -> Int -> Int -> FileName -> Dynamics Bool -> ([[Double]] -> Histogram) -> [String] -> String -> String -> (PlotBars Double Double -> PlotBars Double Double) -> (Layout1 Double Double -> Layout1 Double Double) -> HistogramView
+ Simulation.Aivika.Experiment.HistogramView: HistogramView :: String -> String -> Int -> Int -> FileName -> Event Bool -> ([[Double]] -> Histogram) -> [String] -> String -> String -> (PlotBars Double Double -> PlotBars Double Double) -> (Layout1 Double Double -> Layout1 Double Double) -> HistogramView
- Simulation.Aivika.Experiment.HistogramView: histogramPredicate :: HistogramView -> Dynamics Bool
+ Simulation.Aivika.Experiment.HistogramView: histogramPredicate :: HistogramView -> Event Bool
- Simulation.Aivika.Experiment.TimeSeriesView: TimeSeriesView :: String -> String -> Int -> Int -> FileName -> Dynamics Bool -> [Either String String] -> String -> String -> [PlotLines Double Double -> PlotLines Double Double] -> (LayoutAxis Double -> LayoutAxis Double) -> (Layout1 Double Double -> Layout1 Double Double) -> TimeSeriesView
+ Simulation.Aivika.Experiment.TimeSeriesView: TimeSeriesView :: String -> String -> Int -> Int -> FileName -> Event Bool -> [Either String String] -> String -> String -> [PlotLines Double Double -> PlotLines Double Double] -> (LayoutAxis Double -> LayoutAxis Double) -> (Layout1 Double Double -> Layout1 Double Double) -> TimeSeriesView
- Simulation.Aivika.Experiment.TimeSeriesView: timeSeriesPredicate :: TimeSeriesView -> Dynamics Bool
+ Simulation.Aivika.Experiment.TimeSeriesView: timeSeriesPredicate :: TimeSeriesView -> Event Bool
- Simulation.Aivika.Experiment.XYChartView: XYChartView :: String -> String -> Int -> Int -> FileName -> Dynamics Bool -> Maybe String -> [Either String String] -> String -> String -> [PlotLines Double Double -> PlotLines Double Double] -> (LayoutAxis Double -> LayoutAxis Double) -> (Layout1 Double Double -> Layout1 Double Double) -> XYChartView
+ Simulation.Aivika.Experiment.XYChartView: XYChartView :: String -> String -> Int -> Int -> FileName -> Event Bool -> Maybe String -> [Either String String] -> String -> String -> [PlotLines Double Double -> PlotLines Double Double] -> (LayoutAxis Double -> LayoutAxis Double) -> (Layout1 Double Double -> Layout1 Double Double) -> XYChartView
- Simulation.Aivika.Experiment.XYChartView: xyChartPredicate :: XYChartView -> Dynamics Bool
+ Simulation.Aivika.Experiment.XYChartView: xyChartPredicate :: XYChartView -> Event Bool
Files
- Simulation/Aivika/Experiment/DeviationChartView.hs +6/−5
- Simulation/Aivika/Experiment/FinalHistogramView.hs +6/−5
- Simulation/Aivika/Experiment/FinalXYChartView.hs +6/−5
- Simulation/Aivika/Experiment/HistogramView.hs +6/−5
- Simulation/Aivika/Experiment/TimeSeriesView.hs +6/−5
- Simulation/Aivika/Experiment/XYChartView.hs +6/−5
- aivika-experiment-chart.cabal +3/−3
- examples/BassDiffusion.hs +18/−18
- examples/ChemicalReaction.hs +5/−7
- examples/DifferenceEquations.hs +5/−8
- examples/Financial.hs +5/−11
- examples/Furnace.hs +118/−124
- examples/LinearArray.hs +5/−7
- examples/MachRep3.hs +28/−28
Simulation/Aivika/Experiment/DeviationChartView.hs view
@@ -39,10 +39,11 @@ import Simulation.Aivika.Experiment.Chart (colourisePlotLines, colourisePlotFillBetween) import Simulation.Aivika.Experiment.SamplingStatsSource +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Signal-import Simulation.Aivika.Dynamics.Base (starttime, integIterationBnds, integTimes, integIteration)+import Simulation.Aivika.Event+import Simulation.Aivika.Signal import Simulation.Aivika.Statistics -- | Defines the 'View' that saves the deviation chart@@ -173,7 +174,7 @@ deviationChartStats = stats } -- | Simulate the specified series.-simulateDeviationChart :: DeviationChartViewState -> ExperimentData -> Dynamics (Dynamics ())+simulateDeviationChart :: DeviationChartViewState -> ExperimentData -> Event (Event ()) simulateDeviationChart st expdata = do let labels = deviationChartSeries $ deviationChartView st (leftLabels, rightLabels) = partitionEithers labels @@ -213,7 +214,7 @@ h = experimentSignalInIntegTimes expdata handleSignal_ h $ \_ -> do xs <- sequence source- i <- integIteration+ i <- liftDynamics integIteration liftIO $ withMVar lock $ \() -> forM_ (zip xs stats) $ \(x, stats) -> do y <- readArray stats i
Simulation/Aivika/Experiment/FinalHistogramView.hs view
@@ -41,10 +41,11 @@ import Simulation.Aivika.Experiment.Histogram import Simulation.Aivika.Experiment.ListSource +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Signal-import Simulation.Aivika.Dynamics.Base (starttime, integIterationBnds, integTimes, integIteration)+import Simulation.Aivika.Event+import Simulation.Aivika.Signal -- | Defines the 'View' that saves the histogram -- in the PNG file by the specified series in@@ -68,7 +69,7 @@ -- @ -- finalHistogramFileName = UniqueFileName \"$TITLE\" \".png\" -- @- finalHistogramPredicate :: Dynamics Bool,+ finalHistogramPredicate :: Event Bool, -- ^ It specifies the predicate that defines -- when we count data when plotting the histogram. finalHistogramBuild :: [[Double]] -> Histogram, @@ -161,7 +162,7 @@ finalHistogramValues = values } -- | Simulation of the specified series.-simulateFinalHistogram :: FinalHistogramViewState -> ExperimentData -> Dynamics (Dynamics ())+simulateFinalHistogram :: FinalHistogramViewState -> ExperimentData -> Event (Event ()) simulateFinalHistogram st expdata = do let labels = finalHistogramSeries $ finalHistogramView st providers = experimentSeriesProviders expdata labels
Simulation/Aivika/Experiment/FinalXYChartView.hs view
@@ -38,10 +38,11 @@ import Simulation.Aivika.Experiment.Utils (divideBy, replace) import Simulation.Aivika.Experiment.Chart (colourisePlotLines) +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Signal-import Simulation.Aivika.Dynamics.Base (time)+import Simulation.Aivika.Event+import Simulation.Aivika.Signal -- | Defines the 'View' that saves the XY chart -- in the PNG file by final time points for all@@ -64,7 +65,7 @@ -- @ -- finalXYChartFileName = UniqueFileName \"$TITLE\" \".png\" -- @- finalXYChartPredicate :: Dynamics Bool,+ finalXYChartPredicate :: Event Bool, -- ^ It specifies the predicate that defines -- when we count data when plotting the chart. finalXYChartXSeries :: Maybe String,@@ -172,7 +173,7 @@ finalXYChartXY = xy } -- | Simulation.-simulateFinalXYChart :: FinalXYChartViewState -> ExperimentData -> Dynamics (Dynamics ())+simulateFinalXYChart :: FinalXYChartViewState -> ExperimentData -> Event (Event ()) simulateFinalXYChart st expdata = do let ylabels = finalXYChartYSeries $ finalXYChartView st xlabels = finalXYChartXSeries $ finalXYChartView st
Simulation/Aivika/Experiment/HistogramView.hs view
@@ -39,9 +39,10 @@ import Simulation.Aivika.Experiment.Histogram import Simulation.Aivika.Experiment.ListSource -import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Signal+import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation+import Simulation.Aivika.Event+import Simulation.Aivika.Signal -- | Defines the 'View' that saves the histogram in -- the PNG files by all integration time points for @@ -65,7 +66,7 @@ -- @ -- histogramFileName = UniqueFileName \"$TITLE - $RUN_INDEX\" \".png\" -- @- histogramPredicate :: Dynamics Bool,+ histogramPredicate :: Event Bool, -- ^ It specifies the predicate that defines -- when we count data when plotting the histogram. histogramBuild :: [[Double]] -> Histogram, @@ -160,7 +161,7 @@ histogramMap = m } -- | Plot the histogram during the simulation.-simulateHistogram :: HistogramViewState -> ExperimentData -> Dynamics (Dynamics ())+simulateHistogram :: HistogramViewState -> ExperimentData -> Event (Event ()) simulateHistogram st expdata = do let labels = histogramSeries $ histogramView st providers = experimentSeriesProviders expdata labels
Simulation/Aivika/Experiment/TimeSeriesView.hs view
@@ -37,9 +37,10 @@ import Simulation.Aivika.Experiment.Utils (divideBy, replace) import Simulation.Aivika.Experiment.Chart (colourisePlotLines) -import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Signal+import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation+import Simulation.Aivika.Event+import Simulation.Aivika.Signal -- | Defines the 'View' that saves the time series charts -- in the PNG files.@@ -62,7 +63,7 @@ -- @ -- timeSeriesFileName = UniqueFileName \"$TITLE - $RUN_INDEX\" \".png\" -- @- timeSeriesPredicate :: Dynamics Bool,+ timeSeriesPredicate :: Event Bool, -- ^ It specifies the predicate that defines -- when we plot data in the chart. timeSeries :: [Either String String],@@ -162,7 +163,7 @@ timeSeriesMap = m } -- | Plot the time series chart during the simulation.-simulateTimeSeries :: TimeSeriesViewState -> ExperimentData -> Dynamics (Dynamics ())+simulateTimeSeries :: TimeSeriesViewState -> ExperimentData -> Event (Event ()) simulateTimeSeries st expdata = do let labels = timeSeries $ timeSeriesView st (leftLabels, rightLabels) = partitionEithers labels
Simulation/Aivika/Experiment/XYChartView.hs view
@@ -38,9 +38,10 @@ import Simulation.Aivika.Experiment.Utils (divideBy, replace) import Simulation.Aivika.Experiment.Chart (colourisePlotLines) -import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Signal+import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation+import Simulation.Aivika.Event+import Simulation.Aivika.Signal -- | Defines the 'View' that saves the XY charts -- in the PNG files.@@ -63,7 +64,7 @@ -- @ -- xyChartFileName = UniqueFileName \"$TITLE - $RUN_INDEX\" \".png\" -- @- xyChartPredicate :: Dynamics Bool,+ xyChartPredicate :: Event Bool, -- ^ It specifies the predicate that defines -- when we plot data in the chart. xyChartXSeries :: Maybe String,@@ -169,7 +170,7 @@ xyChartMap = m } -- | Plot the XY chart during the simulation.-simulateXYChart :: XYChartViewState -> ExperimentData -> Dynamics (Dynamics ())+simulateXYChart :: XYChartViewState -> ExperimentData -> Event (Event ()) simulateXYChart st expdata = do let ylabels = xyChartYSeries $ xyChartView st xlabels = xyChartXSeries $ xyChartView st
aivika-experiment-chart.cabal view
@@ -1,5 +1,5 @@ name: aivika-experiment-chart-version: 0.3.1+version: 0.4 synopsis: Simulation experiments with charting for the Aivika library description: This package complements the Aivika and Aivika Experiment packages with@@ -48,7 +48,7 @@ split >= 0.2.2, data-accessor >= 0.2.2.3, colour >= 2.3.3,- aivika >= 0.6.1,- aivika-experiment >= 0.3.1+ aivika >= 0.7,+ aivika-experiment >= 0.4 ghc-options: -O2
examples/BassDiffusion.hs view
@@ -4,11 +4,12 @@ import Control.Monad import Control.Monad.Trans +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation+import Simulation.Aivika.Event import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.EventQueue-import Simulation.Aivika.Dynamics.Agent-import Simulation.Aivika.Dynamics.Ref+import Simulation.Aivika.Agent+import Simulation.Aivika.Ref import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.DeviationChartView@@ -55,19 +56,19 @@ personPotentialAdopter :: AgentState, personAdopter :: AgentState } -createPerson :: EventQueue -> Simulation Person -createPerson q = - do agent <- newAgent q+createPerson :: Simulation Person +createPerson = + do agent <- newAgent potentialAdopter <- newState agent adopter <- newState agent return Person { personAgent = agent, personPotentialAdopter = potentialAdopter, personAdopter = adopter } -createPersons :: EventQueue -> Simulation (Array Int Person)-createPersons q =+createPersons :: Simulation (Array Int Person)+createPersons = do list <- forM [1 .. n] $ \i ->- do p <- createPerson q+ do p <- createPerson return (i, p) return $ array (1, n) list @@ -101,23 +102,22 @@ forM_ (elems ps) $ \p -> definePerson p ps potentialAdopters adopters -activatePerson :: Person -> Dynamics ()+activatePerson :: Person -> Event () activatePerson p = activateState (personPotentialAdopter p) -activatePersons :: Array Int Person -> Dynamics ()+activatePersons :: Array Int Person -> Event () activatePersons ps = forM_ (elems ps) $ \p -> activatePerson p model :: Simulation ExperimentData model =- do q <- newQueue- potentialAdopters <- newRef q 0- adopters <- newRef q 0- ps <- createPersons q+ do potentialAdopters <- newRef 0+ adopters <- newRef 0+ ps <- createPersons definePersons ps potentialAdopters adopters- runDynamicsInStartTime $+ runEventInStartTime IncludingCurrentEvents $ activatePersons ps- experimentDataInStartTime q+ experimentDataInStartTime [("potentialAdopters", seriesEntity "Potential Adopters" potentialAdopters),
examples/ChemicalReaction.hs view
@@ -1,11 +1,10 @@ {-# LANGUAGE RecursiveDo #-} +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.SystemDynamics-import Simulation.Aivika.Dynamics.EventQueue-import Simulation.Aivika.Dynamics.Base+import Simulation.Aivika.SystemDynamics import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.LastValueView@@ -67,13 +66,12 @@ model :: Simulation ExperimentData model =- mdo queue <- newQueue- a <- integ (- ka * a) 100+ mdo a <- integ (- ka * a) 100 b <- integ (ka * a - kb * b) 0 c <- integ (kb * b) 0 let ka = 1 kb = 1- experimentDataInStartTime queue+ experimentDataInStartTime [("t", seriesEntity "time" time), ("a", seriesEntity "a" a), ("b", seriesEntity "b" b),
examples/DifferenceEquations.hs view
@@ -1,12 +1,11 @@ {-# LANGUAGE RecursiveDo #-} +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.SystemDynamics-import Simulation.Aivika.Dynamics.EventQueue-import Simulation.Aivika.Dynamics.Base import Simulation.Aivika.Dynamics.Random+import Simulation.Aivika.SystemDynamics import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.TableView@@ -46,9 +45,7 @@ model :: Simulation ExperimentData model =- mdo queue <- newQueue- - x <- newNormal 3 0.8+ mdo x <- newNormalDynamics 3 0.8 sumX <- sumDynamics x 0 sumX2 <- sumDynamics (x * x) 0 @@ -59,7 +56,7 @@ let avg = ifDynamics (n .>. 0) (sumX / n) 0 let std = ifDynamics (n .>. 1) (sqrt ((sumX2 - sumX * avg) / (n - 1))) 0 - experimentDataInStartTime queue+ experimentDataInStartTime [("t", seriesEntity "time" time), ("n", seriesEntity "n" n), ("x", seriesEntity "x" x),
examples/Financial.hs view
@@ -20,12 +20,11 @@ import Control.Monad -- from package aivika+import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Base-import Simulation.Aivika.Dynamics.SystemDynamics-import Simulation.Aivika.Dynamics.Parameter-import Simulation.Aivika.Dynamics.EventQueue+import Simulation.Aivika.SystemDynamics+import Simulation.Aivika.Parameter.Random -- from package aivika-experiment import Simulation.Aivika.Experiment@@ -150,12 +149,7 @@ taxes = taxableIncome * taxRate variableProductionCost = liftParam paramsVariableProductionCost - -- we have to create an event queue to return the experimental data,- -- although it was not used in the model itself -- queue <- newQueue- - experimentDataInStartTime queue+ experimentDataInStartTime [(netIncomeName, seriesEntity "Net income" netIncome), (netCashFlowName, seriesEntity "Net cash flow" netCashFlow), (npvIncomeName, seriesEntity "NPV income" npvIncome),
examples/Furnace.hs view
@@ -37,28 +37,26 @@ import Control.Monad import Control.Monad.Trans +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Base-import Simulation.Aivika.Dynamics.EventQueue-import Simulation.Aivika.Dynamics.Ref-import Simulation.Aivika.Dynamics.UVar-import Simulation.Aivika.Dynamics.Process-import Simulation.Aivika.Dynamics.Random-import Simulation.Aivika.Statistics+import Simulation.Aivika.Event+import Simulation.Aivika.Ref+import Simulation.Aivika.Process+import Simulation.Aivika.Random +import qualified Simulation.Aivika.DoubleLinkedList as DLL+ import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.ExperimentSpecsView import Simulation.Aivika.Experiment.FinalStatsView import Simulation.Aivika.Experiment.DeviationChartView import Simulation.Aivika.Experiment.FinalHistogramView -import qualified Simulation.Aivika.Queue as Q- -- | The simulation specs. specs = Specs { spcStartTime = 0.0,- -- spcStopTime = 1000.0,- spcStopTime = 300.0,+ spcStopTime = 1000.0,+ -- spcStopTime = 300.0, spcDT = 0.1, spcMethod = RungeKutta4 } @@ -77,22 +75,16 @@ -- | Represents the furnace. data Furnace = - Furnace { furnaceQueue :: EventQueue,- -- ^ The event queue.- furnaceNormalGen :: IO Double,+ Furnace { furnaceNormalGen :: IO Double, -- ^ The normal random number generator. furnacePits :: [Pit], -- ^ The pits for ingots.- furnacePitCount :: UVar Int,+ furnacePitCount :: Ref Int, -- ^ The count of active pits with ingots.- furnacePitCountStats :: Ref (SamplingStats Int),- -- ^ The statistics about the active pits.- furnaceAwaitingIngots :: Q.Queue Ingot,+ furnaceAwaitingIngots :: DLL.DoubleLinkedList Ingot, -- ^ The awaiting ingots in the queue.- furnaceQueueCount :: UVar Int,+ furnaceQueueCount :: Ref Int, -- ^ The queue count.- furnaceQueueCountStats :: Ref (SamplingStats Int),- -- ^ The statistics about the queue count. furnaceWaitCount :: Ref Int, -- ^ The count of awaiting ingots. furnaceWaitTime :: Ref Double,@@ -113,9 +105,7 @@ -- | A pit in the furnace to place the ingots. data Pit = - Pit { pitQueue :: EventQueue,- -- ^ The bound dynamics queue.- pitIngot :: Ref (Maybe Ingot),+ Pit { pitIngot :: Ref (Maybe Ingot), -- ^ The ingot in the pit. pitTemp :: Ref Double -- ^ The ingot temperature in the pit.@@ -123,7 +113,7 @@ data Ingot = Ingot { ingotFurnace :: Furnace,- -- ^ Return the furnace.+ -- ^ The furnace. ingotReceiveTime :: Double, -- ^ The time at which the ingot was received. ingotReceiveTemp :: Double,@@ -137,31 +127,26 @@ } -- | Create a furnace.-newFurnace :: EventQueue -> Simulation Furnace-newFurnace queue =- do normalGen <- liftIO normalGen- pits <- sequence [newPit queue | i <- [1..10]]- pitCount <- newUVar queue 0- pitCountStats <- newRef queue emptySamplingStats- awaitingIngots <- liftIO Q.newQueue- queueCount <- newUVar queue 0- queueCountStats <- newRef queue emptySamplingStats- waitCount <- newRef queue 0- waitTime <- newRef queue 0.0- heatingTime <- newRef queue 0.0- h <- newRef queue 1650.0- totalCount <- newRef queue 0- loadCount <- newRef queue 0- unloadCount <- newRef queue 0- unloadTemps <- newRef queue []- return Furnace { furnaceQueue = queue,- furnaceNormalGen = normalGen,+newFurnace :: Simulation Furnace+newFurnace =+ do normalGen <- liftIO newNormalGen+ pits <- sequence [newPit | i <- [1..10]]+ pitCount <- newRef 0+ awaitingIngots <- liftIO DLL.newList+ queueCount <- newRef 0+ waitCount <- newRef 0+ waitTime <- newRef 0.0+ heatingTime <- newRef 0.0+ h <- newRef 1650.0+ totalCount <- newRef 0+ loadCount <- newRef 0+ unloadCount <- newRef 0+ unloadTemps <- newRef []+ return Furnace { furnaceNormalGen = normalGen, furnacePits = pits, furnacePitCount = pitCount,- furnacePitCountStats = pitCountStats, furnaceAwaitingIngots = awaitingIngots, furnaceQueueCount = queueCount,- furnaceQueueCountStats = queueCountStats, furnaceWaitCount = waitCount, furnaceWaitTime = waitTime, furnaceHeatingTime = heatingTime,@@ -172,18 +157,17 @@ furnaceUnloadTemps = unloadTemps } -- | Create a new pit.-newPit :: EventQueue -> Simulation Pit-newPit queue =- do ingot <- newRef queue Nothing- h' <- newRef queue 0.0- return Pit { pitQueue = queue,- pitIngot = ingot,+newPit :: Simulation Pit+newPit =+ do ingot <- newRef Nothing+ h' <- newRef 0.0+ return Pit { pitIngot = ingot, pitTemp = h' } -- | Create a new ingot.-newIngot :: Furnace -> Dynamics Ingot+newIngot :: Furnace -> Event Ingot newIngot furnace =- do t <- time+ do t <- liftDynamics time xi <- liftIO $ furnaceNormalGen furnace h' <- liftIO temprnd let c = 0.1 + (0.05 + xi * 0.01)@@ -195,7 +179,7 @@ ingotCoeff = c } -- | Heat the ingot up in the pit if there is such an ingot.-heatPitUp :: Pit -> Dynamics ()+heatPitUp :: Pit -> Event () heatPitUp pit = do ingot <- readRef (pitIngot pit) case ingot of@@ -205,21 +189,21 @@ -- update the temperature of the ingot. let furnace = ingotFurnace ingot- dt' <- dt+ dt' <- liftDynamics dt h' <- readRef (pitTemp pit) h <- readRef (furnaceTemp furnace) writeRef (pitTemp pit) $ h' + dt' * (h - h') * ingotCoeff ingot -- | Check whether there are ready ingots in the pits.-ingotsReady :: Furnace -> Dynamics Bool+ingotsReady :: Furnace -> Event Bool ingotsReady furnace = fmap (not . null) $ filterM (fmap (>= 2200.0) . readRef . pitTemp) $ furnacePits furnace -- | Try to unload the ready ingot from the specified pit.-tryUnloadPit :: Furnace -> Pit -> Dynamics ()+tryUnloadPit :: Furnace -> Pit -> Event () tryUnloadPit furnace pit = do h' <- readRef (pitTemp pit) when (h' >= 2000.0) $@@ -227,23 +211,20 @@ unloadIngot ingot pit -- | Try to load an awaiting ingot in the specified empty pit.-tryLoadPit :: Furnace -> Pit -> Dynamics () +tryLoadPit :: Furnace -> Pit -> Event () tryLoadPit furnace pit = do let ingots = furnaceAwaitingIngots furnace- flag <- liftIO $ Q.queueNull ingots+ flag <- liftIO $ DLL.listNull ingots unless flag $- do ingot <- liftIO $ Q.queueFront ingots- liftIO $ Q.dequeue ingots- t' <- time- modifyUVar (furnaceQueueCount furnace) (+ (-1))- c <- readUVar (furnaceQueueCount furnace)- modifyRef (furnaceQueueCountStats furnace) $- addSamplingStats c+ do ingot <- liftIO $ DLL.listFirst ingots+ liftIO $ DLL.listRemoveFirst ingots+ t' <- liftDynamics time+ modifyRef (furnaceQueueCount furnace) (+ (-1)) loadIngot (ingot { ingotLoadTime = t', ingotLoadTemp = 400.0 }) pit -- | Unload the ingot from the specified pit. -unloadIngot :: Ingot -> Pit -> Dynamics ()+unloadIngot :: Ingot -> Pit -> Event () unloadIngot ingot pit = do h' <- readRef (pitTemp pit) writeRef (pitIngot pit) Nothing@@ -251,13 +232,11 @@ -- count the active pits let furnace = ingotFurnace ingot- count <- readUVar (furnacePitCount furnace)- writeUVar (furnacePitCount furnace) (count - 1)- modifyRef (furnacePitCountStats furnace) $- addSamplingStats (count - 1)+ count <- readRef (furnacePitCount furnace)+ writeRef (furnacePitCount furnace) (count - 1) -- how long did we heat the ingot up?- t' <- time+ t' <- liftDynamics time modifyRef (furnaceHeatingTime furnace) (+ (t' - ingotLoadTime ingot)) @@ -268,17 +247,15 @@ modifyRef (furnaceUnloadCount furnace) (+ 1) -- | Load the ingot in the specified pit-loadIngot :: Ingot -> Pit -> Dynamics ()+loadIngot :: Ingot -> Pit -> Event () loadIngot ingot pit = do writeRef (pitIngot pit) $ Just ingot writeRef (pitTemp pit) $ ingotLoadTemp ingot -- count the active pits let furnace = ingotFurnace ingot- count <- readUVar (furnacePitCount furnace)- writeUVar (furnacePitCount furnace) (count + 1)- modifyRef (furnacePitCountStats furnace) $- addSamplingStats (count + 1)+ count <- readRef (furnacePitCount furnace)+ writeRef (furnacePitCount furnace) (count + 1) -- decrease the furnace temperature h <- readRef (furnaceTemp furnace)@@ -287,21 +264,19 @@ writeRef (furnaceTemp furnace) $ h + dh -- how long did we keep the ingot in the queue?- t' <- time- when (ingotReceiveTime ingot < t') $- do modifyRef (furnaceWaitCount furnace) (+ 1) - modifyRef (furnaceWaitTime furnace)- (+ (t' - ingotReceiveTime ingot))+ t' <- liftDynamics time+ modifyRef (furnaceWaitCount furnace) (+ 1) + modifyRef (furnaceWaitTime furnace)+ (+ (t' - ingotReceiveTime ingot)) -- count the loaded ingots modifyRef (furnaceLoadCount furnace) (+ 1) -- | Start iterating the furnace processing through the event queue.-startIteratingFurnace :: Furnace -> Dynamics ()+startIteratingFurnace :: Furnace -> Event () startIteratingFurnace furnace = - let queue = furnaceQueue furnace- pits = furnacePits furnace- in enqueueWithIntegTimes queue $+ let pits = furnacePits furnace+ in enqueueEventWithIntegTimes $ do ready <- ingotsReady furnace when ready $ do mapM_ (tryUnloadPit furnace) pits@@ -310,19 +285,19 @@ mapM_ heatPitUp pits -- update the temperature of the furnace- dt' <- dt+ dt' <- liftDynamics dt h <- readRef (furnaceTemp furnace) writeRef (furnaceTemp furnace) $ h + dt' * (2600.0 - h) * 0.2 -- | Return all empty pits.-emptyPits :: Furnace -> Dynamics [Pit]+emptyPits :: Furnace -> Event [Pit] emptyPits furnace = filterM (fmap isNothing . readRef . pitIngot) $ furnacePits furnace -- | Accept a new ingot.-acceptIngot :: Furnace -> Dynamics ()+acceptIngot :: Furnace -> Event () acceptIngot furnace = do ingot <- newIngot furnace @@ -330,14 +305,11 @@ modifyRef (furnaceTotalCount furnace) (+ 1) -- check what to do with the new ingot- count <- readUVar (furnacePitCount furnace)+ count <- readRef (furnacePitCount furnace) if count >= 10 then do let ingots = furnaceAwaitingIngots furnace- liftIO $ Q.enqueue ingots ingot- modifyUVar (furnaceQueueCount furnace) (+ 1)- c <- readUVar (furnaceQueueCount furnace)- modifyRef (furnaceQueueCountStats furnace) $- addSamplingStats c+ liftIO $ DLL.listAddLast ingots ingot+ modifyRef (furnaceQueueCount furnace) (+ 1) else do pit:_ <- emptyPits furnace loadIngot ingot pit @@ -347,12 +319,12 @@ do delay <- liftIO $ exprnd (1.0 / 2.5) holdProcess delay -- we have got a new ingot- liftDynamics $ acceptIngot furnace+ liftEvent $ acceptIngot furnace -- repeat it again processFurnace furnace -- | Initialize the furnace.-initializeFurnace :: Furnace -> Dynamics ()+initializeFurnace :: Furnace -> Event () initializeFurnace furnace = do x1 <- newIngot furnace x2 <- newIngot furnace@@ -374,21 +346,33 @@ -- | The simulation model that returns experimental data. model :: Simulation ExperimentData model =- do queue <- newQueue- furnace <- newFurnace queue- pid <- newProcessID queue+ do furnace <- newFurnace+ pid <- newProcessId -- initialize the furnace and start its iterating in start time- runDynamicsInStartTime $+ runEventInStartTime IncludingCurrentEvents $ do initializeFurnace furnace startIteratingFurnace furnace - -- start accepting input ingots by launching the process- runDynamicsInStartTime $- do t0 <- starttime- runProcess (processFurnace furnace) pid t0+ -- accept input ingots+ runProcessInStartTime IncludingCurrentEvents+ pid (processFurnace furnace)++ -- the mean wait time in the queue+ let meanWaitTime :: Event Double+ meanWaitTime =+ do waitTime <- readRef (furnaceWaitTime furnace)+ waitCount <- readRef (furnaceWaitCount furnace)+ return $ waitTime / fromIntegral waitCount+ + -- the mean heating time+ let meanHeatingTime :: Event Double+ meanHeatingTime =+ do heatingTime <- readRef (furnaceHeatingTime furnace)+ unloadCount <- readRef (furnaceUnloadCount furnace)+ return $ heatingTime / fromIntegral unloadCount - experimentDataInStartTime queue $+ experimentDataInStartTime [(totalIngotCountName, seriesEntity "total ingot count" $ furnaceTotalCount furnace),@@ -409,31 +393,29 @@ seriesEntity "the temperature of ready ingot" $ furnaceUnloadTemps furnace), - (pitCountStatsName,+ (pitCountName, seriesEntity "the used pit count" $- furnacePitCountStats furnace),+ furnacePitCount furnace), - (queueCountStatsName,+ (queueCountName, seriesEntity "the queue size" $- furnaceQueueCountStats furnace),+ furnaceQueueCount furnace), (meanWaitTimeName,- seriesEntity "the mean wait time" $- readRef (furnaceWaitTime furnace) /- fmap fromIntegral (readRef (furnaceWaitCount furnace))),+ seriesEntity "the mean wait time"+ meanWaitTime), (meanHeatingTimeName,- seriesEntity "the mean heating time" $- readRef (furnaceHeatingTime furnace) /- fmap fromIntegral (readRef (furnaceUnloadCount furnace))) ]+ seriesEntity "the mean heating time"+ meanHeatingTime) ] totalIngotCountName = "totalIngotCount" loadedIngotCountName = "loadedIngotCount" readyIngotCountName = "readyIngotCount" awaitedIngotCountName = "awaitedIngotCount" readyIngotTempsName = "readyIngotTemps"-pitCountStatsName = "pitCountStats"-queueCountStatsName = "queueCountStats"+pitCountName = "pitCount"+queueCountName = "queueCount" meanWaitTimeName = "the mean wait time in the queue" meanHeatingTimeName = "the mean heating time" @@ -486,22 +468,34 @@ outputView $ defaultDeviationChartView { deviationChartTitle = "Deviation Chart - 2", deviationChartPlotTitle = "The used pit count",- deviationChartSeries = [Right pitCountStatsName] },+ deviationChartSeries = [Right pitCountName] }, + outputView $ defaultFinalHistogramView {+ finalHistogramTitle = "Final Histogram - 2",+ finalHistogramPlotTitle = "The distribution of the used pit count " +++ "in the final simulation time point.",+ finalHistogramSeries = [pitCountName] },+ outputView $ defaultFinalStatsView { finalStatsTitle = "Final Statistics - 2", finalStatsDescription = "The summary of the used pit count in the final time point.",- finalStatsSeries = [pitCountStatsName] },+ finalStatsSeries = [pitCountName] }, outputView $ defaultDeviationChartView { deviationChartTitle = "Deviation Chart - 3", deviationChartPlotTitle = "The queue size",- deviationChartSeries = [Right queueCountStatsName] },+ deviationChartSeries = [Right queueCountName] }, + outputView $ defaultFinalHistogramView {+ finalHistogramTitle = "Final Histogram - 3",+ finalHistogramPlotTitle = "The distribution of the queue size " +++ "in the final simulation time point.",+ finalHistogramSeries = [queueCountName] },+ outputView $ defaultFinalStatsView { finalStatsTitle = "Final Statistics - 3", finalStatsDescription = "The summary of the queue size in the final time point.",- finalStatsSeries = [queueCountStatsName] },+ finalStatsSeries = [queueCountName] }, outputView $ defaultDeviationChartView { deviationChartTitle = "Deviation Chart - 4",
examples/LinearArray.hs view
@@ -14,11 +14,10 @@ import qualified Data.Vector as V +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.SystemDynamics-import Simulation.Aivika.Dynamics.EventQueue-import Simulation.Aivika.Dynamics.Base+import Simulation.Aivika.SystemDynamics import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.TableView@@ -46,8 +45,7 @@ model :: Int -> Simulation ExperimentData model n =- mdo queue <- newQueue- m <- generateArray (1, n) $ \i ->+ mdo m <- generateArray (1, n) $ \i -> integ (q + k * (c!(i - 1) - c!i) + k * (c!(i + 1) - c!i)) 0 let c = array (0, n + 1) [(i, if (i == 0) || (i == n + 1)@@ -56,7 +54,7 @@ q = 1 k = 2 v = 0.75- experimentDataInStartTime queue+ experimentDataInStartTime [("t", seriesEntity "time" time), ("m", seriesEntity "M" m), ("c", seriesEntity "C" c)]
examples/MachRep3.hs view
@@ -17,13 +17,14 @@ import Control.Monad import Control.Monad.Trans +import Simulation.Aivika.Specs+import Simulation.Aivika.Simulation import Simulation.Aivika.Dynamics-import Simulation.Aivika.Dynamics.Simulation-import Simulation.Aivika.Dynamics.Base-import Simulation.Aivika.Dynamics.EventQueue-import Simulation.Aivika.Dynamics.Ref-import Simulation.Aivika.Dynamics.Resource-import Simulation.Aivika.Dynamics.Process+import Simulation.Aivika.Event+import Simulation.Aivika.Ref+import Simulation.Aivika.QueueStrategy+import Simulation.Aivika.Resource+import Simulation.Aivika.Process import Simulation.Aivika.Experiment import Simulation.Aivika.Experiment.Histogram@@ -104,56 +105,55 @@ model :: Simulation ExperimentData model =- do queue <- newQueue- - -- number of machines currently up- nUp <- newRef queue 2+ do -- number of machines currently up+ nUp <- newRef 2 -- total up time for all machines- totalUpTime <- newRef queue 0.0+ totalUpTime <- newRef 0.0 - repairPerson <- newResource queue 1+ repairPerson <- newResource FCFS 1 - pid1 <- newProcessID queue- pid2 <- newProcessID queue+ pid1 <- newProcessId+ pid2 <- newProcessId - let machine :: ProcessID -> Process ()+ let machine :: ProcessId -> Process () machine pid = do startUpTime <- liftDynamics time upTime <- liftIO $ exprnd upRate holdProcess upTime finishUpTime <- liftDynamics time- liftDynamics $ modifyRef totalUpTime + liftEvent $ modifyRef totalUpTime (+ (finishUpTime - startUpTime)) - liftDynamics $ modifyRef nUp $ \a -> a - 1- nUp' <- liftDynamics $ readRef nUp+ liftEvent $ modifyRef nUp $ \a -> a - 1+ nUp' <- liftEvent $ readRef nUp if nUp' == 1 then passivateProcess- else do n <- liftDynamics $ - resourceCount repairPerson+ else liftEvent $+ do n <- resourceCount repairPerson when (n == 1) $ - liftDynamics $ reactivateProcess pid+ reactivateProcess pid requestResource repairPerson repairTime <- liftIO $ exprnd repairRate holdProcess repairTime- liftDynamics $ modifyRef nUp $ \a -> a + 1+ liftEvent $ modifyRef nUp $ \a -> a + 1 releaseResource repairPerson machine pid - runDynamicsInStartTime $- do t0 <- starttime- runProcess (machine pid2) pid1 t0- runProcess (machine pid1) pid2 t0+ runProcessInStartTime IncludingCurrentEvents+ pid1 (machine pid2)++ runProcessInStartTime IncludingCurrentEvents+ pid2 (machine pid1) let result = do x <- readRef totalUpTime- y <- time+ y <- liftDynamics time return $ x / (2 * y) - experimentDataInStartTime queue+ experimentDataInStartTime [("x", seriesEntity "The proportion of up time" result), ("t", seriesEntity "Total up time" totalUpTime), ("n", seriesEntity "Simulation run" simulationIndex)]