aivika-experiment 1.3.1 → 1.4
raw patch · 21 files changed
+558/−1295 lines, 21 filesdep +network-uridep −arraydep −networkdep −vectordep ~aivikaPVP ok
version bump matches the API change (PVP)
Dependencies added: network-uri
Dependencies removed: array, network, vector
Dependency ranges changed: aivika
API changes (from Hackage documentation)
- Simulation.Aivika.Experiment.ExperimentSpecsView: instance ExperimentView ExperimentSpecsView r
- Simulation.Aivika.Experiment.FileRenderer: HtmlRenderer :: HtmlRenderer
- Simulation.Aivika.Experiment.FileRenderer: class FileRenderer a
- Simulation.Aivika.Experiment.FileRenderer: data HtmlRenderer
- Simulation.Aivika.Experiment.FileRenderer: instance FileRenderer HtmlRenderer
- Simulation.Aivika.Experiment.FinalStatsView: instance ExperimentView FinalStatsView r
- Simulation.Aivika.Experiment.FinalTableView: instance FileRenderer r => ExperimentView FinalTableView r
- Simulation.Aivika.Experiment.LastValueView: instance ExperimentView LastValueView r
- Simulation.Aivika.Experiment.ListSource: addDataToListRef :: ListRef a -> ListData a -> IO ()
- Simulation.Aivika.Experiment.ListSource: data ListData a
- Simulation.Aivika.Experiment.ListSource: data ListRef a
- Simulation.Aivika.Experiment.ListSource: data ListSource a
- Simulation.Aivika.Experiment.ListSource: listDataList :: ListData a -> [a]
- Simulation.Aivika.Experiment.ListSource: listSourceData :: ListSource a -> Event (ListData a)
- Simulation.Aivika.Experiment.ListSource: newListRef :: IO (ListRef a)
- Simulation.Aivika.Experiment.ListSource: providerToDoubleListSource :: SeriesProvider -> Maybe (ListSource Double)
- Simulation.Aivika.Experiment.ListSource: providerToIntListSource :: SeriesProvider -> Maybe (ListSource Int)
- Simulation.Aivika.Experiment.ListSource: readListRef :: ListRef a -> IO [a]
- Simulation.Aivika.Experiment.SamplingStatsSource: addDataToSamplingStats :: SamplingData a => SamplingStatsData a -> SamplingStats a -> SamplingStats a
- Simulation.Aivika.Experiment.SamplingStatsSource: data SamplingStatsData a
- Simulation.Aivika.Experiment.SamplingStatsSource: data SamplingStatsSource a
- Simulation.Aivika.Experiment.SamplingStatsSource: providerToDoubleStatsSource :: SeriesProvider -> Maybe (SamplingStatsSource Double)
- Simulation.Aivika.Experiment.SamplingStatsSource: providerToIntStatsSource :: SeriesProvider -> Maybe (SamplingStatsSource Int)
- Simulation.Aivika.Experiment.SamplingStatsSource: samplingStatsSourceData :: SamplingStatsSource a -> Event (SamplingStatsData a)
- Simulation.Aivika.Experiment.TableView: instance FileRenderer r => ExperimentView TableView r
- Simulation.Aivika.Experiment.TimingStatsView: instance ExperimentView TimingStatsView r
- Simulation.Aivika.Experiment.Types: SeriesEntity :: [SeriesProvider] -> SeriesEntity
- Simulation.Aivika.Experiment.Types: SeriesProvider :: String -> Maybe (Event Double) -> Maybe (Event (SamplingStats Double)) -> Maybe (Event [Double]) -> Maybe (Event Int) -> Maybe (Event (SamplingStats Int)) -> Maybe (Event [Int]) -> Maybe (Event String) -> Maybe (Signal ()) -> SeriesProvider
- Simulation.Aivika.Experiment.Types: class Series s
- Simulation.Aivika.Experiment.Types: class SeriesContainer c
- Simulation.Aivika.Experiment.Types: containerData :: SeriesContainer c => c a -> Event a
- Simulation.Aivika.Experiment.Types: containerSignal :: SeriesContainer c => c a -> Maybe (Signal ())
- Simulation.Aivika.Experiment.Types: data SeriesArrayWithSubscript i s
- Simulation.Aivika.Experiment.Types: data SeriesEntity
- Simulation.Aivika.Experiment.Types: data SeriesListWithSubscript s
- Simulation.Aivika.Experiment.Types: data SeriesProvider
- Simulation.Aivika.Experiment.Types: data SeriesVectorWithSubscript s
- Simulation.Aivika.Experiment.Types: experimentDataInStartTime :: [(String, SeriesEntity)] -> Simulation ExperimentData
- Simulation.Aivika.Experiment.Types: experimentGenerators :: Experiment r -> [ExperimentGenerator r]
- Simulation.Aivika.Experiment.Types: experimentIndexHtml :: Experiment r -> Experiment r -> [ExperimentReporter] -> FilePath -> IO ()
- Simulation.Aivika.Experiment.Types: experimentMixedSignal :: ExperimentData -> [SeriesProvider] -> Signal ()
- Simulation.Aivika.Experiment.Types: experimentSeries :: ExperimentData -> Map String SeriesEntity
- Simulation.Aivika.Experiment.Types: experimentSeriesProviders :: ExperimentData -> [String] -> [SeriesProvider]
- Simulation.Aivika.Experiment.Types: experimentSignalInIntegTimes :: ExperimentData -> Signal Double
- Simulation.Aivika.Experiment.Types: experimentSignalInStartTime :: ExperimentData -> Signal Double
- Simulation.Aivika.Experiment.Types: experimentSignalInStopTime :: ExperimentData -> Signal Double
- Simulation.Aivika.Experiment.Types: instance (Ix i, Series s) => Series (SeriesArrayWithSubscript i s)
- Simulation.Aivika.Experiment.Types: instance (Ix i, SeriesContainer c) => Series (c (Array i Double))
- Simulation.Aivika.Experiment.Types: instance (Ix i, SeriesContainer c) => Series (c (Array i Int))
- Simulation.Aivika.Experiment.Types: instance (Ix i, SeriesContainer c) => Series (c (UArray i Double))
- Simulation.Aivika.Experiment.Types: instance (Ix i, SeriesContainer c) => Series (c (UArray i Int))
- Simulation.Aivika.Experiment.Types: instance (Show i, Ix i, Series s) => Series (Array i s)
- Simulation.Aivika.Experiment.Types: instance Series s => Series (SeriesListWithSubscript s)
- Simulation.Aivika.Experiment.Types: instance Series s => Series (SeriesVectorWithSubscript s)
- Simulation.Aivika.Experiment.Types: instance Series s => Series (Vector s)
- Simulation.Aivika.Experiment.Types: instance Series s => Series [s]
- Simulation.Aivika.Experiment.Types: instance SeriesContainer Dynamics
- Simulation.Aivika.Experiment.Types: instance SeriesContainer Event
- Simulation.Aivika.Experiment.Types: instance SeriesContainer Parameter
- Simulation.Aivika.Experiment.Types: instance SeriesContainer Ref
- Simulation.Aivika.Experiment.Types: instance SeriesContainer Signalable
- Simulation.Aivika.Experiment.Types: instance SeriesContainer Simulation
- Simulation.Aivika.Experiment.Types: instance SeriesContainer Var
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c (SamplingStats Double))
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c (SamplingStats Int))
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c (Vector Double))
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c (Vector Int))
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c Double)
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c Int)
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c String)
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c [Double])
- Simulation.Aivika.Experiment.Types: instance SeriesContainer c => Series (c [Int])
- Simulation.Aivika.Experiment.Types: providerName :: SeriesProvider -> String
- Simulation.Aivika.Experiment.Types: providerSignal :: SeriesProvider -> Maybe (Signal ())
- Simulation.Aivika.Experiment.Types: providerToDouble :: SeriesProvider -> Maybe (Event Double)
- Simulation.Aivika.Experiment.Types: providerToDoubleList :: SeriesProvider -> Maybe (Event [Double])
- Simulation.Aivika.Experiment.Types: providerToDoubleStats :: SeriesProvider -> Maybe (Event (SamplingStats Double))
- Simulation.Aivika.Experiment.Types: providerToInt :: SeriesProvider -> Maybe (Event Int)
- Simulation.Aivika.Experiment.Types: providerToIntList :: SeriesProvider -> Maybe (Event [Int])
- Simulation.Aivika.Experiment.Types: providerToIntStats :: SeriesProvider -> Maybe (Event (SamplingStats Int))
- Simulation.Aivika.Experiment.Types: providerToString :: SeriesProvider -> Maybe (Event String)
- Simulation.Aivika.Experiment.Types: reporterHtml :: ExperimentReporter -> Int -> HtmlWriter ()
- Simulation.Aivika.Experiment.Types: reporterTOCHtml :: ExperimentReporter -> Int -> HtmlWriter ()
- Simulation.Aivika.Experiment.Types: seriesArrayWithSubscript :: (Ix i, Series s) => Array i s -> Array i String -> SeriesArrayWithSubscript i s
- Simulation.Aivika.Experiment.Types: seriesEntity :: Series s => String -> s -> SeriesEntity
- Simulation.Aivika.Experiment.Types: seriesListWithSubscript :: Series s => [s] -> [String] -> SeriesListWithSubscript s
- Simulation.Aivika.Experiment.Types: seriesProviders :: SeriesEntity -> [SeriesProvider]
- Simulation.Aivika.Experiment.Types: seriesVectorWithSubscript :: Series s => Vector s -> Vector String -> SeriesVectorWithSubscript s
+ Simulation.Aivika.Experiment.ExperimentSpecsView: instance WebPageRendering r => ExperimentView ExperimentSpecsView r WebPageWriter
+ Simulation.Aivika.Experiment.FinalStatsView: finalStatsTransform :: FinalStatsView -> ResultTransform
+ Simulation.Aivika.Experiment.FinalStatsView: instance WebPageRendering r => ExperimentView FinalStatsView r WebPageWriter
+ Simulation.Aivika.Experiment.FinalTableView: finalTableTransform :: FinalTableView -> ResultTransform
+ Simulation.Aivika.Experiment.FinalTableView: instance WebPageRendering r => ExperimentView FinalTableView r WebPageWriter
+ Simulation.Aivika.Experiment.HtmlWriter: instance Applicative HtmlWriter
+ Simulation.Aivika.Experiment.HtmlWriter: instance Functor HtmlWriter
+ Simulation.Aivika.Experiment.LastValueView: instance WebPageRendering r => ExperimentView LastValueView r WebPageWriter
+ Simulation.Aivika.Experiment.LastValueView: lastValueTransform :: LastValueView -> ResultTransform
+ Simulation.Aivika.Experiment.MRef: data MRef a
+ Simulation.Aivika.Experiment.MRef: maybeReadMRef :: b -> (a -> b) -> MRef (Maybe a) -> IO b
+ Simulation.Aivika.Experiment.MRef: maybeWriteMRef :: MRef (Maybe a) -> IO a -> (a -> b) -> IO b
+ Simulation.Aivika.Experiment.MRef: modifyMRef :: MRef a -> (a -> a) -> IO ()
+ Simulation.Aivika.Experiment.MRef: newMRef :: a -> IO (MRef a)
+ Simulation.Aivika.Experiment.MRef: readMRef :: MRef a -> IO a
+ Simulation.Aivika.Experiment.MRef: writeMRef :: MRef a -> a -> IO ()
+ Simulation.Aivika.Experiment.TableView: instance WebPageRendering r => ExperimentView TableView r WebPageWriter
+ Simulation.Aivika.Experiment.TableView: tableTransform :: TableView -> ResultTransform
+ Simulation.Aivika.Experiment.TimingStatsView: instance WebPageRendering r => ExperimentView TimingStatsView r WebPageWriter
+ Simulation.Aivika.Experiment.TimingStatsView: timingStatsTransform :: TimingStatsView -> ResultTransform
+ Simulation.Aivika.Experiment.Types: WebPageRenderer :: WebPageRenderer
+ Simulation.Aivika.Experiment.Types: WebPageWriter :: (Int -> HtmlWriter ()) -> (Int -> HtmlWriter ()) -> WebPageWriter
+ Simulation.Aivika.Experiment.Types: class ExperimentRendering r a | r -> a
+ Simulation.Aivika.Experiment.Types: class ExperimentRendering r WebPageWriter => WebPageRendering r
+ Simulation.Aivika.Experiment.Types: data WebPageRenderer
+ Simulation.Aivika.Experiment.Types: data WebPageWriter
+ Simulation.Aivika.Experiment.Types: experimentLocalisation :: Experiment -> ResultLocalisation
+ Simulation.Aivika.Experiment.Types: experimentPredefinedSignals :: ExperimentData -> ResultPredefinedSignals
+ Simulation.Aivika.Experiment.Types: experimentResults :: ExperimentData -> Results
+ Simulation.Aivika.Experiment.Types: experimentTransform :: Experiment -> ResultTransform
+ Simulation.Aivika.Experiment.Types: instance ExperimentRendering WebPageRenderer WebPageWriter
+ Simulation.Aivika.Experiment.Types: instance WebPageRendering WebPageRenderer
+ Simulation.Aivika.Experiment.Types: renderExperiment :: ExperimentRendering r a => Experiment -> r -> [ExperimentReporter a] -> FilePath -> IO ()
+ Simulation.Aivika.Experiment.Types: reporterRequest :: ExperimentReporter a -> a
+ Simulation.Aivika.Experiment.Types: reporterWriteHtml :: WebPageWriter -> Int -> HtmlWriter ()
+ Simulation.Aivika.Experiment.Types: reporterWriteTOCHtml :: WebPageWriter -> Int -> HtmlWriter ()
+ Simulation.Aivika.Experiment.Types: type WebPageGenerator r = ExperimentGenerator r WebPageWriter
- Simulation.Aivika.Experiment.ExperimentSpecsWriter: ExperimentSpecsWriter :: Int -> String -> String -> String -> String -> String -> String -> String -> String -> String -> ShowS -> (forall r. ExperimentSpecsWriter -> Experiment r -> HtmlWriter ()) -> ExperimentSpecsWriter
+ Simulation.Aivika.Experiment.ExperimentSpecsWriter: ExperimentSpecsWriter :: Int -> String -> String -> String -> String -> String -> String -> String -> String -> String -> ShowS -> (ExperimentSpecsWriter -> Experiment -> HtmlWriter ()) -> ExperimentSpecsWriter
- Simulation.Aivika.Experiment.ExperimentSpecsWriter: experimentSpecsWrite :: ExperimentSpecsWriter -> forall r. ExperimentSpecsWriter -> Experiment r -> HtmlWriter ()
+ Simulation.Aivika.Experiment.ExperimentSpecsWriter: experimentSpecsWrite :: ExperimentSpecsWriter -> ExperimentSpecsWriter -> Experiment -> HtmlWriter ()
- Simulation.Aivika.Experiment.FinalStatsView: FinalStatsView :: String -> String -> SamplingStatsWriter Double -> Event Bool -> [String] -> FinalStatsView
+ Simulation.Aivika.Experiment.FinalStatsView: FinalStatsView :: String -> String -> SamplingStatsWriter Double -> Event Bool -> ResultTransform -> ResultTransform -> FinalStatsView
- Simulation.Aivika.Experiment.FinalStatsView: finalStatsSeries :: FinalStatsView -> [String]
+ Simulation.Aivika.Experiment.FinalStatsView: finalStatsSeries :: FinalStatsView -> ResultTransform
- Simulation.Aivika.Experiment.FinalTableView: FinalTableView :: String -> String -> String -> String -> ExperimentFilePath -> String -> ShowS -> Event Bool -> [String] -> FinalTableView
+ Simulation.Aivika.Experiment.FinalTableView: FinalTableView :: String -> String -> String -> String -> ExperimentFilePath -> String -> ShowS -> Event Bool -> ResultTransform -> ResultTransform -> FinalTableView
- Simulation.Aivika.Experiment.FinalTableView: finalTableSeries :: FinalTableView -> [String]
+ Simulation.Aivika.Experiment.FinalTableView: finalTableSeries :: FinalTableView -> ResultTransform
- Simulation.Aivika.Experiment.LastValueView: LastValueView :: String -> String -> String -> ShowS -> [String] -> LastValueView
+ Simulation.Aivika.Experiment.LastValueView: LastValueView :: String -> String -> String -> ShowS -> ResultTransform -> ResultTransform -> LastValueView
- Simulation.Aivika.Experiment.LastValueView: lastValueSeries :: LastValueView -> [String]
+ Simulation.Aivika.Experiment.LastValueView: lastValueSeries :: LastValueView -> ResultTransform
- Simulation.Aivika.Experiment.TableView: TableView :: String -> String -> String -> String -> ExperimentFilePath -> String -> ShowS -> Event Bool -> [String] -> TableView
+ Simulation.Aivika.Experiment.TableView: TableView :: String -> String -> String -> String -> ExperimentFilePath -> String -> ShowS -> Event Bool -> ResultTransform -> ResultTransform -> TableView
- Simulation.Aivika.Experiment.TableView: tableSeries :: TableView -> [String]
+ Simulation.Aivika.Experiment.TableView: tableSeries :: TableView -> ResultTransform
- Simulation.Aivika.Experiment.TimingStatsView: TimingStatsView :: String -> String -> String -> TimingStatsWriter Double -> Event Bool -> [String] -> TimingStatsView
+ Simulation.Aivika.Experiment.TimingStatsView: TimingStatsView :: String -> String -> String -> TimingStatsWriter Double -> Event Bool -> ResultTransform -> ResultTransform -> TimingStatsView
- Simulation.Aivika.Experiment.TimingStatsView: timingStatsSeries :: TimingStatsView -> [String]
+ Simulation.Aivika.Experiment.TimingStatsView: timingStatsSeries :: TimingStatsView -> ResultTransform
- Simulation.Aivika.Experiment.Types: Experiment :: Specs -> Int -> ExperimentFilePath -> String -> String -> Bool -> [ExperimentGenerator r] -> (Experiment r -> [ExperimentReporter] -> FilePath -> IO ()) -> IO Int -> Experiment r
+ Simulation.Aivika.Experiment.Types: Experiment :: Specs -> ResultTransform -> ResultLocalisation -> Int -> ExperimentFilePath -> String -> String -> Bool -> IO Int -> Experiment
- Simulation.Aivika.Experiment.Types: ExperimentData :: Signal Double -> Signal Double -> Signal Double -> Map String SeriesEntity -> ExperimentData
+ Simulation.Aivika.Experiment.Types: ExperimentData :: Results -> ResultPredefinedSignals -> ExperimentData
- Simulation.Aivika.Experiment.Types: ExperimentGenerator :: (Experiment r -> r -> FilePath -> IO ExperimentReporter) -> ExperimentGenerator r
+ Simulation.Aivika.Experiment.Types: ExperimentGenerator :: (Experiment -> r -> FilePath -> IO (ExperimentReporter a)) -> ExperimentGenerator r a
- Simulation.Aivika.Experiment.Types: ExperimentReporter :: IO () -> IO () -> (ExperimentData -> Event (Event ())) -> (Int -> HtmlWriter ()) -> (Int -> HtmlWriter ()) -> ExperimentReporter
+ Simulation.Aivika.Experiment.Types: ExperimentReporter :: IO () -> IO () -> (ExperimentData -> Event DisposableEvent) -> a -> ExperimentReporter a
- Simulation.Aivika.Experiment.Types: class ExperimentView v r
+ Simulation.Aivika.Experiment.Types: class ExperimentRendering r a => ExperimentView v r a | r -> a
- Simulation.Aivika.Experiment.Types: data Experiment r
+ Simulation.Aivika.Experiment.Types: data Experiment
- Simulation.Aivika.Experiment.Types: data ExperimentGenerator r
+ Simulation.Aivika.Experiment.Types: data ExperimentGenerator r a
- Simulation.Aivika.Experiment.Types: data ExperimentReporter
+ Simulation.Aivika.Experiment.Types: data ExperimentReporter a
- Simulation.Aivika.Experiment.Types: defaultExperiment :: Experiment r
+ Simulation.Aivika.Experiment.Types: defaultExperiment :: Experiment
- Simulation.Aivika.Experiment.Types: experimentDescription :: Experiment r -> String
+ Simulation.Aivika.Experiment.Types: experimentDescription :: Experiment -> String
- Simulation.Aivika.Experiment.Types: experimentDirectoryName :: Experiment r -> ExperimentFilePath
+ Simulation.Aivika.Experiment.Types: experimentDirectoryName :: Experiment -> ExperimentFilePath
- Simulation.Aivika.Experiment.Types: experimentNumCapabilities :: Experiment r -> IO Int
+ Simulation.Aivika.Experiment.Types: experimentNumCapabilities :: Experiment -> IO Int
- Simulation.Aivika.Experiment.Types: experimentRunCount :: Experiment r -> Int
+ Simulation.Aivika.Experiment.Types: experimentRunCount :: Experiment -> Int
- Simulation.Aivika.Experiment.Types: experimentSpecs :: Experiment r -> Specs
+ Simulation.Aivika.Experiment.Types: experimentSpecs :: Experiment -> Specs
- Simulation.Aivika.Experiment.Types: experimentTitle :: Experiment r -> String
+ Simulation.Aivika.Experiment.Types: experimentTitle :: Experiment -> String
- Simulation.Aivika.Experiment.Types: experimentVerbose :: Experiment r -> Bool
+ Simulation.Aivika.Experiment.Types: experimentVerbose :: Experiment -> Bool
- Simulation.Aivika.Experiment.Types: generateReporter :: ExperimentGenerator r -> Experiment r -> r -> FilePath -> IO ExperimentReporter
+ Simulation.Aivika.Experiment.Types: generateReporter :: ExperimentGenerator r a -> Experiment -> r -> FilePath -> IO (ExperimentReporter a)
- Simulation.Aivika.Experiment.Types: outputView :: ExperimentView v r => v -> ExperimentGenerator r
+ Simulation.Aivika.Experiment.Types: outputView :: ExperimentView v r a => v -> ExperimentGenerator r a
- Simulation.Aivika.Experiment.Types: reporterFinalise :: ExperimentReporter -> IO ()
+ Simulation.Aivika.Experiment.Types: reporterFinalise :: ExperimentReporter a -> IO ()
- Simulation.Aivika.Experiment.Types: reporterInitialise :: ExperimentReporter -> IO ()
+ Simulation.Aivika.Experiment.Types: reporterInitialise :: ExperimentReporter a -> IO ()
- Simulation.Aivika.Experiment.Types: reporterSimulate :: ExperimentReporter -> ExperimentData -> Event (Event ())
+ Simulation.Aivika.Experiment.Types: reporterSimulate :: ExperimentReporter a -> ExperimentData -> Event DisposableEvent
- Simulation.Aivika.Experiment.Types: runExperiment :: Experiment r -> r -> Simulation ExperimentData -> IO ()
+ Simulation.Aivika.Experiment.Types: runExperiment :: ExperimentRendering r a => Experiment -> [ExperimentGenerator r a] -> r -> Simulation Results -> IO ()
- Simulation.Aivika.Experiment.Types: runExperimentParallel :: Experiment r -> r -> Simulation ExperimentData -> IO ()
+ Simulation.Aivika.Experiment.Types: runExperimentParallel :: ExperimentRendering r a => Experiment -> [ExperimentGenerator r a] -> r -> Simulation Results -> IO ()
Files
- Simulation/Aivika/Experiment.hs +1/−7
- Simulation/Aivika/Experiment/ExperimentSpecsView.hs +16/−12
- Simulation/Aivika/Experiment/ExperimentSpecsWriter.hs +5/−9
- Simulation/Aivika/Experiment/FileRenderer.hs +0/−24
- Simulation/Aivika/Experiment/FinalStatsView.hs +56/−69
- Simulation/Aivika/Experiment/FinalTableView.hs +59/−70
- Simulation/Aivika/Experiment/Histogram.hs +8/−0
- Simulation/Aivika/Experiment/HtmlWriter.hs +12/−2
- Simulation/Aivika/Experiment/LastValueView.hs +36/−39
- Simulation/Aivika/Experiment/ListSource.hs +0/−88
- Simulation/Aivika/Experiment/MRef.hs +88/−0
- Simulation/Aivika/Experiment/SamplingStatsSource.hs +0/−68
- Simulation/Aivika/Experiment/SamplingStatsWriter.hs +2/−2
- Simulation/Aivika/Experiment/TableView.hs +47/−48
- Simulation/Aivika/Experiment/TimingStatsView.hs +46/−52
- Simulation/Aivika/Experiment/TimingStatsWriter.hs +2/−2
- Simulation/Aivika/Experiment/Types.hs +112/−751
- Simulation/Aivika/Experiment/Utils.hs +2/−2
- aivika-experiment.cabal +7/−10
- examples/LinearArray.hs +37/−20
- examples/MachRep3.hs +22/−20
Simulation/Aivika/Experiment.hs view
@@ -5,7 +5,7 @@ -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.6.3+-- Tested with: GHC 7.8.3 -- -- This module re-exports the library functionality. --@@ -13,35 +13,29 @@ module Simulation.Aivika.Experiment (-- * Modules module Simulation.Aivika.Experiment.Types,- module Simulation.Aivika.Experiment.FileRenderer, module Simulation.Aivika.Experiment.HtmlWriter, module Simulation.Aivika.Experiment.LastValueView, module Simulation.Aivika.Experiment.TableView, module Simulation.Aivika.Experiment.TimingStatsView, module Simulation.Aivika.Experiment.TimingStatsWriter, module Simulation.Aivika.Experiment.SamplingStatsWriter,- module Simulation.Aivika.Experiment.SamplingStatsSource, module Simulation.Aivika.Experiment.FinalStatsView, module Simulation.Aivika.Experiment.Histogram, module Simulation.Aivika.Experiment.ExperimentSpecsView, module Simulation.Aivika.Experiment.ExperimentSpecsWriter, module Simulation.Aivika.Experiment.FinalTableView,- module Simulation.Aivika.Experiment.ListSource, module Simulation.Aivika.Experiment.Utils) where import Simulation.Aivika.Experiment.Types-import Simulation.Aivika.Experiment.FileRenderer import Simulation.Aivika.Experiment.HtmlWriter import Simulation.Aivika.Experiment.LastValueView import Simulation.Aivika.Experiment.TableView import Simulation.Aivika.Experiment.TimingStatsView import Simulation.Aivika.Experiment.TimingStatsWriter import Simulation.Aivika.Experiment.SamplingStatsWriter-import Simulation.Aivika.Experiment.SamplingStatsSource import Simulation.Aivika.Experiment.FinalStatsView import Simulation.Aivika.Experiment.Histogram import Simulation.Aivika.Experiment.ExperimentSpecsView import Simulation.Aivika.Experiment.ExperimentSpecsWriter import Simulation.Aivika.Experiment.FinalTableView-import Simulation.Aivika.Experiment.ListSource import Simulation.Aivika.Experiment.Utils
Simulation/Aivika/Experiment/ExperimentSpecsView.hs view
@@ -3,11 +3,11 @@ -- | -- Module : Simulation.Aivika.Experiment.ExperimentSpecsView--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.6.3 -- -- The module defines 'ExperimentSpecsView' that shows the -- experiment specs.@@ -20,6 +20,8 @@ import Control.Monad import Control.Monad.Trans +import Data.Monoid+ import Simulation.Aivika.Experiment.Types import Simulation.Aivika.Experiment.HtmlWriter import Simulation.Aivika.Experiment.ExperimentSpecsWriter@@ -41,31 +43,33 @@ experimentSpecsDescription = "It shows the experiment specs.", experimentSpecsWriter = defaultExperimentSpecsWriter } -instance ExperimentView ExperimentSpecsView r where +instance WebPageRendering r => ExperimentView ExperimentSpecsView r WebPageWriter where outputView v = let reporter exp renderer dir = do st <- newExperimentSpecs v exp+ let writer =+ WebPageWriter { reporterWriteTOCHtml = experimentSpecsTOCHtml st,+ reporterWriteHtml = experimentSpecsHtml st } return ExperimentReporter { reporterInitialise = return (), reporterFinalise = return (),- reporterSimulate = const $ return $ return (),- reporterTOCHtml = experimentSpecsTOCHtml st,- reporterHtml = experimentSpecsHtml st }+ reporterSimulate = const $ return mempty,+ reporterRequest = writer } in ExperimentGenerator { generateReporter = reporter } -- | The state of the view.-data ExperimentSpecsViewState r =+data ExperimentSpecsViewState = ExperimentSpecsViewState { experimentSpecsView :: ExperimentSpecsView,- experimentSpecsExperiment :: Experiment r }+ experimentSpecsExperiment :: Experiment } -- | Create a new state of the view.-newExperimentSpecs :: ExperimentSpecsView -> Experiment r -> IO (ExperimentSpecsViewState r)+newExperimentSpecs :: ExperimentSpecsView -> Experiment -> IO ExperimentSpecsViewState newExperimentSpecs view exp = return ExperimentSpecsViewState { experimentSpecsView = view, experimentSpecsExperiment = exp } -- | Get the HTML code. -experimentSpecsHtml :: ExperimentSpecsViewState r -> Int -> HtmlWriter () +experimentSpecsHtml :: ExperimentSpecsViewState -> Int -> HtmlWriter () experimentSpecsHtml st index = do header st index let writer = experimentSpecsWriter (experimentSpecsView st)@@ -73,7 +77,7 @@ exp = experimentSpecsExperiment st write writer exp -header :: ExperimentSpecsViewState r -> Int -> HtmlWriter ()+header :: ExperimentSpecsViewState -> Int -> HtmlWriter () header st index = do writeHtmlHeader3WithId ("id" ++ show index) $ writeHtmlText (experimentSpecsTitle $ experimentSpecsView st)@@ -83,7 +87,7 @@ writeHtmlText description -- | Get the TOC item -experimentSpecsTOCHtml :: ExperimentSpecsViewState r -> Int -> HtmlWriter ()+experimentSpecsTOCHtml :: ExperimentSpecsViewState -> Int -> HtmlWriter () experimentSpecsTOCHtml st index = writeHtmlListItem $ writeHtmlLink ("#id" ++ show index) $
Simulation/Aivika/Experiment/ExperimentSpecsWriter.hs view
@@ -1,13 +1,11 @@ -{-# LANGUAGE RankNTypes #-}- -- | -- Module : Simulation.Aivika.Experiment.ExperimentSpecsWriter--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.6.3 -- -- The module defines 'ExperimentSpecsWriter' that knows how to write -- in HTML the experiment specs which include the simulation specs and @@ -18,11 +16,10 @@ (ExperimentSpecsWriter(..), defaultExperimentSpecsWriter) where +import Simulation.Aivika import Simulation.Aivika.Experiment.Types import Simulation.Aivika.Experiment.HtmlWriter -import Simulation.Aivika.Specs- -- | Defines a writer that knows how to represent the -- experiment specs as the HTML table. data ExperimentSpecsWriter =@@ -48,9 +45,8 @@ -- ^ Translated text \"the 4-th order Runge-Kutta\". experimentSpecsFormatter :: ShowS, -- ^ The formatter of numbers.- experimentSpecsWrite :: forall r.- ExperimentSpecsWriter- -> Experiment r+ experimentSpecsWrite :: ExperimentSpecsWriter+ -> Experiment -> HtmlWriter () -- ^ This function creates HTML. }
− Simulation/Aivika/Experiment/FileRenderer.hs
@@ -1,24 +0,0 @@---- |--- Module : Simulation.Aivika.Experiment.FileRenderer--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>--- License : BSD3--- Maintainer : David Sorokin <david.sorokin@gmail.com>--- Stability : experimental--- Tested with: GHC 7.4.1------ It defines a basic experiment renderer that allows saving the simulation results in files.-----module Simulation.Aivika.Experiment.FileRenderer- (FileRenderer(..),- HtmlRenderer(..)) where---- | The experiment renderer that allows saving the simulation results in files.-class FileRenderer a---- | The default renderer that creates an HTML page for the simulation experiment.-data HtmlRenderer = HtmlRenderer- -- ^ The default HTML renderer.--instance FileRenderer HtmlRenderer
Simulation/Aivika/Experiment/FinalStatsView.hs view
@@ -3,11 +3,11 @@ -- | -- Module : Simulation.Aivika.Experiment.FinalStatsView--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.8.3 -- -- The module defines 'FinalStatsView' gathers the statistics -- in the final time points for different simulation runs.@@ -24,16 +24,11 @@ import Data.IORef import Data.Maybe +import Simulation.Aivika import Simulation.Aivika.Experiment.Types import Simulation.Aivika.Experiment.HtmlWriter import Simulation.Aivika.Experiment.SamplingStatsWriter-import Simulation.Aivika.Experiment.SamplingStatsSource--import Simulation.Aivika.Specs-import Simulation.Aivika.Simulation-import Simulation.Aivika.Event-import Simulation.Aivika.Signal-import Simulation.Aivika.Statistics+import Simulation.Aivika.Experiment.MRef -- | Defines the 'View' that gathers the statistics -- in the final time points.@@ -47,38 +42,41 @@ finalStatsPredicate :: Event Bool, -- ^ It specifies the predicate that defines -- when we count data when gathering the statistics.- finalStatsSeries :: [String]- -- ^ It contains the labels of data for which- -- the statistics is collected.+ finalStatsTransform :: ResultTransform,+ -- ^ The transform applied to the results before receiving series.+ finalStatsSeries :: ResultTransform + -- ^ It defines the series for which the statistics to be collected. } -- | The default statistics view. defaultFinalStatsView :: FinalStatsView defaultFinalStatsView = FinalStatsView { finalStatsTitle = "Final Statistics",- finalStatsDescription = "The statistical data are gathered in the final time points for all runs.",+ finalStatsDescription = "Statistics is gathered in final time points for all runs.", finalStatsWriter = defaultSamplingStatsWriter, finalStatsPredicate = return True,- finalStatsSeries = [] }+ finalStatsTransform = id,+ finalStatsSeries = id } -instance ExperimentView FinalStatsView r where+instance WebPageRendering r => ExperimentView FinalStatsView r WebPageWriter where outputView v = let reporter exp renderer dir = do st <- newFinalStats v exp dir+ let writer =+ WebPageWriter { reporterWriteTOCHtml = finalStatsTOCHtml st,+ reporterWriteHtml = finalStatsHtml st } return ExperimentReporter { reporterInitialise = return (), reporterFinalise = return (), reporterSimulate = simulateFinalStats st,- reporterTOCHtml = finalStatsTOCHtml st,- reporterHtml = finalStatsHtml st }+ reporterRequest = writer } in ExperimentGenerator { generateReporter = reporter } -- | The state of the view.-data FinalStatsViewState r =+data FinalStatsViewState = FinalStatsViewState { finalStatsView :: FinalStatsView,- finalStatsExperiment :: Experiment r,- finalStatsLock :: MVar (),- finalStatsResults :: IORef (Maybe FinalStatsResults) }+ finalStatsExperiment :: Experiment,+ finalStatsResults :: MRef (Maybe FinalStatsResults) } -- | The statistics results. data FinalStatsResults =@@ -86,68 +84,57 @@ finalStatsValues :: [IORef (SamplingStats Double)] } -- | Create a new state of the view.-newFinalStats :: FinalStatsView -> Experiment r -> FilePath -> IO (FinalStatsViewState r)+newFinalStats :: FinalStatsView -> Experiment -> FilePath -> IO FinalStatsViewState newFinalStats view exp dir =- do l <- newMVar () - r <- newIORef Nothing+ do r <- newMRef Nothing return FinalStatsViewState { finalStatsView = view, finalStatsExperiment = exp,- finalStatsLock = l, finalStatsResults = r } -- | Create new statistics results.-newFinalStatsResults :: [String] -> Experiment r -> IO FinalStatsResults+newFinalStatsResults :: [String] -> Experiment -> IO FinalStatsResults newFinalStatsResults names exp = do values <- forM names $ \_ -> liftIO $ newIORef emptySamplingStats return FinalStatsResults { finalStatsNames = names, finalStatsValues = values }++-- | Require to return unique final statistics results associated with the specified state. +requireFinalStatsResults :: FinalStatsViewState -> [String] -> IO FinalStatsResults+requireFinalStatsResults st names =+ maybeWriteMRef (finalStatsResults st)+ (newFinalStatsResults names (finalStatsExperiment st)) $ \results ->+ if (names /= finalStatsNames results)+ then error "Series with different names are returned for different runs: requireFinalStatsResults"+ else results --- | Simulation the specified series.-simulateFinalStats :: FinalStatsViewState r -> ExperimentData -> Event (Event ())+-- | Simulate the specified series.+simulateFinalStats :: FinalStatsViewState -> ExperimentData -> Event DisposableEvent simulateFinalStats st expdata =- do let protolabels = finalStatsSeries $ finalStatsView st- protoproviders = flip map protolabels $ \protolabel ->- experimentSeriesProviders expdata [protolabel]- providers = concat protoproviders- input =- flip map providers $ \provider ->- case providerToDoubleStatsSource provider of- Nothing -> error $- "Cannot represent series " ++- providerName provider ++ - " as a source of double values: simulateFinalStats"- Just input -> samplingStatsSourceData input- names = map providerName providers- predicate = finalStatsPredicate $ finalStatsView st- exp = finalStatsExperiment st- lock = finalStatsLock st- results <- liftIO $ readIORef (finalStatsResults st)- case results of- Nothing ->- liftIO $- do results <- newFinalStatsResults names exp- writeIORef (finalStatsResults st) $ Just results- Just results ->- when (names /= finalStatsNames results) $- error "Series with different names are returned for different runs: simulateFinalStats"- results <- liftIO $ fmap fromJust $ readIORef (finalStatsResults st)- let values = finalStatsValues results- h = filterSignalM (const predicate) $- experimentSignalInStopTime expdata- handleSignal_ h $ \_ ->- do xs <- sequence input- liftIO $ withMVar lock $ \() ->- forM_ (zip xs values) $ \(x, values) ->- do y <- readIORef values- let y' = addDataToSamplingStats x y- y' `seq` writeIORef values y'- return $ return ()+ do let view = finalStatsView st+ rs = finalStatsSeries view $+ finalStatsTransform view $+ experimentResults expdata+ exts = extractDoubleStatsEitherResults rs+ signals = experimentPredefinedSignals expdata+ signal = filterSignalM (const predicate) $+ resultSignalInStopTime signals+ names = map resultExtractName exts+ predicate = finalStatsPredicate view+ results <- liftIO $ requireFinalStatsResults st names+ let values = finalStatsValues results + handleSignal signal $ \_ ->+ forM_ (zip exts values) $ \(ext, value) ->+ do x <- resultExtractData ext+ liftIO $+ do y <- readIORef value+ let y' = combineSamplingStatsEither x y+ y' `seq` writeIORef value y' -- | Get the HTML code. -finalStatsHtml :: FinalStatsViewState r -> Int -> HtmlWriter ()+finalStatsHtml :: FinalStatsViewState -> Int -> HtmlWriter () finalStatsHtml st index = do header st index- results <- liftIO $ readIORef (finalStatsResults st)+ results <- liftIO $ readMRef (finalStatsResults st) case results of Nothing -> return () Just results ->@@ -159,7 +146,7 @@ do stats <- liftIO $ readIORef value write writer name stats -header :: FinalStatsViewState r -> Int -> HtmlWriter ()+header :: FinalStatsViewState -> Int -> HtmlWriter () header st index = do writeHtmlHeader3WithId ("id" ++ show index) $ writeHtmlText (finalStatsTitle $ finalStatsView st)@@ -169,7 +156,7 @@ writeHtmlText description -- | Get the TOC item.-finalStatsTOCHtml :: FinalStatsViewState r -> Int -> HtmlWriter ()+finalStatsTOCHtml :: FinalStatsViewState -> Int -> HtmlWriter () finalStatsTOCHtml st index = writeHtmlListItem $ writeHtmlLink ("#id" ++ show index) $
Simulation/Aivika/Experiment/FinalTableView.hs view
@@ -3,11 +3,11 @@ -- | -- Module : Simulation.Aivika.Experiment.FinalTableView--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.8.3 -- -- The module defines 'FinalTableView' that saves the simulation -- results in the final time points for all simulation runs in@@ -29,15 +29,10 @@ import System.IO import System.FilePath +import Simulation.Aivika import Simulation.Aivika.Experiment.Types-import Simulation.Aivika.Experiment.FileRenderer import Simulation.Aivika.Experiment.HtmlWriter--import Simulation.Aivika.Specs-import Simulation.Aivika.Parameter-import Simulation.Aivika.Simulation-import Simulation.Aivika.Event-import Simulation.Aivika.Signal+import Simulation.Aivika.Experiment.MRef -- | Defines the 'View' that saves the simulation -- results in the final time points for all @@ -79,9 +74,10 @@ finalTablePredicate :: Event Bool, -- ^ It specifies the predicate that defines -- when we can save data in the table.- finalTableSeries :: [String] - -- ^ It contains the labels of data saved- -- in the CSV file.+ finalTableTransform :: ResultTransform,+ -- ^ The transform applied to the results before receiving series.+ finalTableSeries :: ResultTransform + -- ^ It defines the series to save in the CSV file. } -- | The default table view. @@ -95,105 +91,98 @@ finalTableSeparator = ",", finalTableFormatter = id, finalTablePredicate = return True,- finalTableSeries = [] }+ finalTableTransform = expandResults,+ finalTableSeries = id } -instance FileRenderer r => ExperimentView FinalTableView r where+instance WebPageRendering r => ExperimentView FinalTableView r WebPageWriter where outputView v = let reporter exp renderer dir = do st <- newFinalTable v exp dir+ let writer =+ WebPageWriter { reporterWriteTOCHtml = finalTableTOCHtml st,+ reporterWriteHtml = finalTableHtml st } return ExperimentReporter { reporterInitialise = return (), reporterFinalise = finaliseFinalTable st, reporterSimulate = simulateFinalTable st,- reporterTOCHtml = finalTableTOCHtml st,- reporterHtml = finalTableHtml st }+ reporterRequest = writer } in ExperimentGenerator { generateReporter = reporter } -- | The state of the view.-data FinalTableViewState r =+data FinalTableViewState = FinalTableViewState { finalTableView :: FinalTableView,- finalTableExperiment :: Experiment r,+ finalTableExperiment :: Experiment, finalTableDir :: FilePath, finalTableFile :: IORef (Maybe FilePath),- finalTableLock :: MVar (),- finalTableResults :: IORef (Maybe FinalTableResults) }+ finalTableResults :: MRef (Maybe FinalTableResults) } -- | The table results. data FinalTableResults = FinalTableResults { finalTableNames :: [String],- finalTableValues :: IORef (M.Map Int [String]) }+ finalTableValues :: MRef (M.Map Int [String]) } -- | Create a new state of the view.-newFinalTable :: FinalTableView -> Experiment r -> FilePath -> IO (FinalTableViewState r)+newFinalTable :: FinalTableView -> Experiment -> FilePath -> IO FinalTableViewState newFinalTable view exp dir = do f <- newIORef Nothing- l <- newMVar () - r <- newIORef Nothing+ r <- newMRef Nothing return FinalTableViewState { finalTableView = view, finalTableExperiment = exp, finalTableDir = dir, finalTableFile = f,- finalTableLock = l, finalTableResults = r } -- | Create new table results.-newFinalTableResults :: [String] -> Experiment r -> IO FinalTableResults+newFinalTableResults :: [String] -> Experiment -> IO FinalTableResults newFinalTableResults names exp =- do values <- newIORef M.empty + do values <- newMRef M.empty return FinalTableResults { finalTableNames = names, finalTableValues = values }++-- | Require to return unique final tables results associated with the specified state. +requireFinalTableResults :: FinalTableViewState -> [String] -> IO FinalTableResults+requireFinalTableResults st names =+ maybeWriteMRef (finalTableResults st)+ (newFinalTableResults names (finalTableExperiment st)) $ \results ->+ if (names /= finalTableNames results)+ then error "Series with different names are returned for different runs: requireFinalTableResults"+ else results -- | Simulation of the specified series.-simulateFinalTable :: FinalTableViewState r -> ExperimentData -> Event (Event ())+simulateFinalTable :: FinalTableViewState -> ExperimentData -> Event DisposableEvent simulateFinalTable st expdata =- do let labels = finalTableSeries $ finalTableView st- providers = experimentSeriesProviders expdata labels- input =- flip map providers $ \provider ->- case providerToString provider of- Nothing -> error $- "Cannot represent series " ++- providerName provider ++ - " as string values: simulateFinalTable"- Just input -> input- names = map providerName providers- predicate = finalTablePredicate $ finalTableView st- exp = finalTableExperiment st- lock = finalTableLock st- results <- liftIO $ readIORef (finalTableResults st)- case results of- Nothing ->- liftIO $- do results <- newFinalTableResults names exp- writeIORef (finalTableResults st) $ Just results- Just results ->- when (names /= finalTableNames results) $- error "Series with different names are returned for different runs: simulateFinalTable"- results <- liftIO $ fmap fromJust $ readIORef (finalTableResults st)- let values = finalTableValues results- h = filterSignalM (const predicate) $- experimentSignalInStopTime expdata- handleSignal_ h $ \_ ->- do xs <- sequence input+ do let view = finalTableView st+ rs = finalTableSeries view $+ finalTableTransform view $+ experimentResults expdata+ exts = extractStringResults rs+ signals = experimentPredefinedSignals expdata+ signal = filterSignalM (const predicate) $+ resultSignalInStopTime signals+ names = map resultExtractName exts+ predicate = finalTablePredicate view+ results <- liftIO $ requireFinalTableResults st names+ let values = finalTableValues results + handleSignal signal $ \_ ->+ do xs <- mapM resultExtractData exts i <- liftParameter simulationIndex- liftIO $ withMVar lock $ \() ->- modifyIORef values $ M.insert i xs- return $ return ()+ liftIO $ modifyMRef values $ M.insert i xs -- | Save the results in the CSV file after the simulation is complete.-finaliseFinalTable :: FinalTableViewState r -> IO ()+finaliseFinalTable :: FinalTableViewState -> IO () finaliseFinalTable st =- do let run = finalTableRunText $ finalTableView st- formatter = finalTableFormatter $ finalTableView st- title = finalTableTitle $ finalTableView st- separator = finalTableSeparator $ finalTableView st- results <- readIORef $ finalTableResults st+ do let view = finalTableView st+ run = finalTableRunText view+ formatter = finalTableFormatter view+ title = finalTableTitle view+ separator = finalTableSeparator view+ results <- readMRef $ finalTableResults st case results of Nothing -> return () Just results -> do let names = finalTableNames results values = finalTableValues results- m <- readIORef values + m <- readMRef values file <- resolveFilePath (finalTableDir st) $ mapFilePath (flip replaceExtension ".csv") $ expandFilePath (finalTableFileName $ finalTableView st) $@@ -220,7 +209,7 @@ writeIORef (finalTableFile st) $ Just file -- | Get the HTML code. -finalTableHtml :: FinalTableViewState r -> Int -> HtmlWriter ()+finalTableHtml :: FinalTableViewState -> Int -> HtmlWriter () finalTableHtml st index = do header st index file <- liftIO $ readIORef (finalTableFile st)@@ -231,7 +220,7 @@ writeHtmlLink (makeRelative (finalTableDir st) f) $ writeHtmlText (finalTableLinkText $ finalTableView st) -header :: FinalTableViewState r -> Int -> HtmlWriter ()+header :: FinalTableViewState -> Int -> HtmlWriter () header st index = do writeHtmlHeader3WithId ("id" ++ show index) $ writeHtmlText (finalTableTitle $ finalTableView st)@@ -241,7 +230,7 @@ writeHtmlText description -- | Get the TOC item.-finalTableTOCHtml :: FinalTableViewState r -> Int -> HtmlWriter ()+finalTableTOCHtml :: FinalTableViewState -> Int -> HtmlWriter () finalTableTOCHtml st index = writeHtmlListItem $ writeHtmlLink ("#id" ++ show index) $
Simulation/Aivika/Experiment/Histogram.hs view
@@ -1,4 +1,12 @@ +-- |+-- Module : Simulation.Aivika.Experiment.Histogram+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com>+-- License : BSD3+-- Maintainer : David Sorokin <david.sorokin@gmail.com>+-- Stability : experimental+-- Tested with: GHC 7.6.3+-- -- | This module computes the histogram by the -- specified data and strategy applied for such computing. --
Simulation/Aivika/Experiment/HtmlWriter.hs view
@@ -1,11 +1,11 @@ -- | -- Module : Simulation.Aivika.Experiment.HtmlWriter--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.8.3 -- -- This is an utility module that provides an HTML writer. --@@ -41,6 +41,7 @@ import Control.Monad import Control.Monad.Trans+import Control.Applicative import Network.URI @@ -64,6 +65,15 @@ liftIO m = HtmlWriter $ \f -> do x <- m return (x, f)++instance Functor HtmlWriter where++ fmap f m = m >>= \a -> return (f a)++instance Applicative HtmlWriter where++ pure = return+ (<*>) = ap -- | Write the HTML code. writeHtml :: String -> HtmlWriter ()
Simulation/Aivika/Experiment/LastValueView.hs view
@@ -3,11 +3,11 @@ -- | -- Module : Simulation.Aivika.Experiment.LastValueView--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.8.3 -- -- The module defines 'LastValueView' that shows the last values -- for the simulation variables.@@ -24,16 +24,11 @@ import Data.IORef import Data.Maybe +import Simulation.Aivika import Simulation.Aivika.Experiment.Types import Simulation.Aivika.Experiment.HtmlWriter import Simulation.Aivika.Experiment.Utils (replace) -import Simulation.Aivika.Specs-import Simulation.Aivika.Parameter-import Simulation.Aivika.Simulation-import Simulation.Aivika.Event-import Simulation.Aivika.Signal- -- | Defines the 'View' that shows the last values of the simulation -- variables. data LastValueView =@@ -53,8 +48,10 @@ -- ^ The description for the view. lastValueFormatter :: ShowS, -- ^ It transforms data before they will be shown.- lastValueSeries :: [String] - -- ^ It contains the labels of the observed series.+ lastValueTransform :: ResultTransform,+ -- ^ The transform applied to the results before receiving series.+ lastValueSeries :: ResultTransform + -- ^ It defines the series for which the last values to be shown. } -- | This is the default view.@@ -62,30 +59,33 @@ defaultLastValueView = LastValueView { lastValueTitle = "The Last Values", lastValueRunTitle = "$TITLE / Run $RUN_INDEX of $RUN_COUNT",- lastValueDescription = "It shows the values in the final time points.",+ lastValueDescription = "It shows the values in the final time point(s).", lastValueFormatter = id,- lastValueSeries = [] }+ lastValueTransform = id,+ lastValueSeries = id } -instance ExperimentView LastValueView r where +instance WebPageRendering r => ExperimentView LastValueView r WebPageWriter where outputView v = let reporter exp renderer dir = do st <- newLastValues v exp+ let writer =+ WebPageWriter { reporterWriteTOCHtml = lastValueTOCHtml st,+ reporterWriteHtml = lastValueHtml st } return ExperimentReporter { reporterInitialise = return (), reporterFinalise = return (), reporterSimulate = simulateLastValues st,- reporterTOCHtml = lastValueTOCHtml st,- reporterHtml = lastValueHtml st }+ reporterRequest = writer } in ExperimentGenerator { generateReporter = reporter }- + -- | The state of the view.-data LastValueViewState r =+data LastValueViewState = LastValueViewState { lastValueView :: LastValueView,- lastValueExperiment :: Experiment r,+ lastValueExperiment :: Experiment, lastValueMap :: M.Map Int (IORef [(String, String)]) } -- | Create a new state of the view.-newLastValues :: LastValueView -> Experiment r -> IO (LastValueViewState r)+newLastValues :: LastValueView -> Experiment -> IO LastValueViewState newLastValues view exp = do let n = experimentRunCount exp rs <- forM [0..(n - 1)] $ \i -> newIORef [] @@ -95,28 +95,25 @@ lastValueMap = m } -- | Get the last values during the simulation.-simulateLastValues :: LastValueViewState r -> ExperimentData -> Event (Event ())+simulateLastValues :: LastValueViewState -> ExperimentData -> Event DisposableEvent simulateLastValues st expdata =- do let labels = lastValueSeries $ lastValueView st- input =- flip map (experimentSeriesProviders expdata labels) $ \provider ->- case providerToString provider of- Nothing -> error $- "Cannot represent series " ++- providerName provider ++ - " as a string: simulateLastValues"- Just input -> (providerName provider, input)+ do let view = lastValueView st+ rs = lastValueSeries view $+ lastValueTransform view $+ experimentResults expdata+ exts = extractStringResults rs+ signals = experimentPredefinedSignals expdata+ signal = resultSignalInStopTime signals i <- liftParameter simulationIndex- handleSignal_ (experimentSignalInStopTime expdata) $ \t ->+ handleSignal signal $ \t -> do let r = fromJust $ M.lookup (i - 1) (lastValueMap st)- output <- forM input $ \(name, input) ->- do x <- input- return (name, x)+ output <- forM exts $ \ext ->+ do x <- resultExtractData ext+ return (resultExtractName ext, x) liftIO $ writeIORef r output- return $ return () -- | Get the HTML code. -lastValueHtml :: LastValueViewState r -> Int -> HtmlWriter () +lastValueHtml :: LastValueViewState -> Int -> HtmlWriter () lastValueHtml st index = let n = experimentRunCount $ lastValueExperiment st in if n == 1@@ -124,7 +121,7 @@ else lastValueHtmlMultiple st index -- | Get the HTML code for a single run.-lastValueHtmlSingle :: LastValueViewState r -> Int -> HtmlWriter ()+lastValueHtmlSingle :: LastValueViewState -> Int -> HtmlWriter () lastValueHtmlSingle st index = do header st index let r = fromJust $ M.lookup 0 (lastValueMap st)@@ -133,7 +130,7 @@ formatPair pair (lastValueFormatter $ lastValueView st) -- | Get the HTML code for multiple runs-lastValueHtmlMultiple :: LastValueViewState r -> Int -> HtmlWriter ()+lastValueHtmlMultiple :: LastValueViewState -> Int -> HtmlWriter () lastValueHtmlMultiple st index = do header st index let n = experimentRunCount $ lastValueExperiment st@@ -150,7 +147,7 @@ forM_ pairs $ \pair -> formatPair pair (lastValueFormatter $ lastValueView st) -header :: LastValueViewState r -> Int -> HtmlWriter ()+header :: LastValueViewState -> Int -> HtmlWriter () header st index = do writeHtmlHeader3WithId ("id" ++ show index) $ writeHtmlText (lastValueTitle $ lastValueView st)@@ -167,7 +164,7 @@ writeHtmlText $ formatter value -- | Get the TOC item -lastValueTOCHtml :: LastValueViewState r -> Int -> HtmlWriter ()+lastValueTOCHtml :: LastValueViewState -> Int -> HtmlWriter () lastValueTOCHtml st index = writeHtmlListItem $ writeHtmlLink ("#id" ++ show index) $
− Simulation/Aivika/Experiment/ListSource.hs
@@ -1,88 +0,0 @@---- |--- Module : Simulation.Aivika.Experiment.ListSource--- Copyright : Copyright (c) 2013, David Sorokin <david.sorokin@gmail.com>--- License : BSD3--- Maintainer : David Sorokin <david.sorokin@gmail.com>--- Stability : experimental--- Tested with: GHC 7.6.3------ It represents an optimized source of data to construct the list.-----module Simulation.Aivika.Experiment.ListSource- (ListSource,- providerToDoubleListSource,- providerToIntListSource,- ListData,- listSourceData,- listDataList,- ListRef,- newListRef,- addDataToListRef,- readListRef) where--import Data.IORef-import Control.Monad--import Simulation.Aivika.Event-import Simulation.Aivika.Statistics-import Simulation.Aivika.Experiment.Types---- | Represents the optimized source of data for constructing the list.-data ListSource a = SingleValueSource (Event a)- | MultipleValueSource (Event [a])---- | Represents the optimized data by which the list will be created.-data ListData a = SingleValueData !a- | MultipleValueData [a]---- | Try to return the source of list data by the specified provider.-providerToDoubleListSource :: SeriesProvider -> Maybe (ListSource Double)-providerToDoubleListSource provider =- case providerToDouble provider of- Just x -> Just $ SingleValueSource x- Nothing ->- case providerToDoubleList provider of- Just x -> Just $ MultipleValueSource x- Nothing -> Nothing- --- | Try to return the source of list data by the specified provider.-providerToIntListSource :: SeriesProvider -> Maybe (ListSource Int)-providerToIntListSource provider =- case providerToInt provider of- Just x -> Just $ SingleValueSource x- Nothing ->- case providerToIntList provider of- Just x -> Just $ MultipleValueSource x- Nothing -> Nothing---- | Get data from the source in the current time point.-listSourceData :: ListSource a -> Event (ListData a)-listSourceData (SingleValueSource x) = x >>= return . SingleValueData-listSourceData (MultipleValueSource xs) =- do ys <- xs- zs <- forM ys $ \y -> return $ y `seq` y- return $ MultipleValueData ys -- it contains strict data, which is important for big models ---- | Return the list of values contained in the specified data.-listDataList :: ListData a -> [a]-listDataList (SingleValueData x) = [x]-listDataList (MultipleValueData xs) = xs---- | Represents a reference to the list, optimized to work with the source of data.-newtype ListRef a = ListRef { listRef :: IORef [ListData a] } ---- | Create a new list reference.-newListRef :: IO (ListRef a)-newListRef = fmap ListRef $ newIORef []---- | Add data to the list reference.-addDataToListRef :: ListRef a -> ListData a -> IO ()-addDataToListRef (ListRef r) a = modifyIORef r (a :)---- | Read the list contained in the reference.-readListRef :: ListRef a -> IO [a]-readListRef (ListRef r) =- do x <- readIORef r- return $ concat $ map listDataList x
+ Simulation/Aivika/Experiment/MRef.hs view
@@ -0,0 +1,88 @@++-- |+-- Module : Simulation.Aivika.Experiment.MRef+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com>+-- License : BSD3+-- Maintainer : David Sorokin <david.sorokin@gmail.com>+-- Stability : experimental+-- Tested with: GHC 7.8.3+--+-- The module defines a shared mutable reference accessible from different threads.+--++module Simulation.Aivika.Experiment.MRef+ (MRef,+ newMRef,+ readMRef,+ maybeReadMRef,+ writeMRef,+ maybeWriteMRef,+ modifyMRef) where++import Control.Concurrent.MVar++import Data.Maybe+import Data.IORef++-- | This is a shared mutable reference accessible from different threads.+data MRef a =+ MRef { mrefLock :: MVar (),+ -- ^ A reference lock.+ mrefData :: IORef a+ -- ^ The reference itself.+ }++-- | Create a new shared reference with the specified initial value.+newMRef :: a -> IO (MRef a)+newMRef a =+ do v <- newMVar ()+ r <- newIORef a+ return MRef { mrefLock = v,+ mrefData = r }++-- | Read the contents of the shared reference.+readMRef :: MRef a -> IO a+readMRef = readIORef . mrefData++-- | Like 'maybe' but for the shared reference under assumption+-- that the reference is updated only once by its initial value.+maybeReadMRef :: b -> (a -> b) -> MRef (Maybe a) -> IO b+maybeReadMRef b0 f x =+ do a <- readIORef (mrefData x)+ case a of+ Just a -> return (f a)+ Nothing ->+ withMVar (mrefLock x) $ \() ->+ do a <- readIORef (mrefData x)+ case a of+ Just a -> return (f a)+ Nothing -> return b0++-- | Update the contents of the shared reference.+writeMRef :: MRef a -> a -> IO ()+writeMRef x a =+ withMVar (mrefLock x) $ \() ->+ writeIORef (mrefData x) a++-- | Update the contents if the reference was empty and then return a result of+-- applying the specified function to either the initial or current value.+maybeWriteMRef :: MRef (Maybe a) -> IO a -> (a -> b) -> IO b+maybeWriteMRef x m0 f =+ do a <- readIORef (mrefData x)+ case a of+ Just a -> return (f a)+ Nothing ->+ withMVar (mrefLock x) $ \() ->+ do a <- readIORef (mrefData x)+ case a of+ Just a -> return (f a)+ Nothing ->+ do a0 <- m0+ writeIORef (mrefData x) (Just a0)+ return (f a0)++-- | Modify the contents of the shared reference.+modifyMRef :: MRef a -> (a -> a) -> IO ()+modifyMRef x f =+ withMVar (mrefLock x) $ \() ->+ modifyIORef (mrefData x) f
− Simulation/Aivika/Experiment/SamplingStatsSource.hs
@@ -1,68 +0,0 @@---- |--- Module : Simulation.Aivika.Experiment.SamplingStatsSource--- Copyright : Copyright (c) 2013, David Sorokin <david.sorokin@gmail.com>--- License : BSD3--- Maintainer : David Sorokin <david.sorokin@gmail.com>--- Stability : experimental--- Tested with: GHC 7.6.3------ It represents an optimized source of statistical data.-----module Simulation.Aivika.Experiment.SamplingStatsSource- (SamplingStatsSource,- providerToDoubleStatsSource,- providerToIntStatsSource,- SamplingStatsData,- samplingStatsSourceData,- addDataToSamplingStats) where--import Simulation.Aivika.Event-import Simulation.Aivika.Statistics-import Simulation.Aivika.Experiment.Types---- | Represents the optimized source of data for the statistics.-data SamplingStatsSource a = SingleValueSource (Event a)- | MultipleValueSource (Event (SamplingStats a))---- | Represents the optimized data to be included in the statistics.-data SamplingStatsData a = SingleValueData !a- | MultipleValueData (SamplingStats a)---- | Try to return the source of statistical data by the specified provider.-providerToDoubleStatsSource :: SeriesProvider -> Maybe (SamplingStatsSource Double)-providerToDoubleStatsSource provider =- case providerToDouble provider of- Just x -> Just $ SingleValueSource x- Nothing ->- case providerToDoubleStats provider of- Just x -> Just $ MultipleValueSource x- Nothing -> Nothing- --- | Try to return the source of statistical data.-providerToIntStatsSource :: SeriesProvider -> Maybe (SamplingStatsSource Int)-providerToIntStatsSource provider =- case providerToInt provider of- Just x -> Just $ SingleValueSource x- Nothing ->- case providerToIntStats provider of- Just x -> Just $ MultipleValueSource x- Nothing -> Nothing---- | Get data from the source in the current time point.-samplingStatsSourceData :: SamplingStatsSource a -> Event (SamplingStatsData a)-samplingStatsSourceData source =- case source of- SingleValueSource x -> x >>= return . SingleValueData- MultipleValueSource x -> x >>= return . MultipleValueData---- | Add data from the source to the statistics.-addDataToSamplingStats :: SamplingData a- => SamplingStatsData a- -> SamplingStats a- -> SamplingStats a-addDataToSamplingStats d stats =- case d of- SingleValueData x -> addSamplingStats x stats- MultipleValueData x -> combineSamplingStats x stats
Simulation/Aivika/Experiment/SamplingStatsWriter.hs view
@@ -1,11 +1,11 @@ -- | -- Module : Simulation.Aivika.Experiment.SamplingStatsWriter--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.6.3 -- -- The module defines 'SamplingStatsWriter' that knows how to write -- the sampling statistics in HTML.
Simulation/Aivika/Experiment/TableView.hs view
@@ -3,11 +3,11 @@ -- | -- Module : Simulation.Aivika.Experiment.TableView--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.8.3 -- -- The module defines 'TableView' that saves the simulation -- results in the CSV file(s).@@ -23,21 +23,16 @@ import qualified Data.Map as M import Data.IORef import Data.Maybe+import Data.Monoid import System.IO import System.FilePath +import Simulation.Aivika import Simulation.Aivika.Experiment.Types-import Simulation.Aivika.Experiment.FileRenderer import Simulation.Aivika.Experiment.HtmlWriter import Simulation.Aivika.Experiment.Utils (replace) -import Simulation.Aivika.Specs-import Simulation.Aivika.Parameter-import Simulation.Aivika.Simulation-import Simulation.Aivika.Event-import Simulation.Aivika.Signal- -- | Defines the 'View' that saves the simulation results -- in the CSV file(s). data TableView =@@ -97,9 +92,10 @@ tablePredicate :: Event Bool, -- ^ It specifies the predicate that defines -- when we can save data in the table.- tableSeries :: [String] - -- ^ It contains the labels of data saved- -- in the CSV file(s).+ tableTransform :: ResultTransform,+ -- ^ The transform applied to the results before receiving series.+ tableSeries :: ResultTransform + -- ^ It defines the series to save in the CSV file(s). } -- | The default table view. @@ -113,29 +109,32 @@ tableSeparator = ",", tableFormatter = id, tablePredicate = return True,- tableSeries = [] }+ tableTransform = expandResults,+ tableSeries = id } -instance FileRenderer r => ExperimentView TableView r where+instance WebPageRendering r => ExperimentView TableView r WebPageWriter where outputView v = let reporter exp renderer dir = do st <- newTable v exp dir+ let writer =+ WebPageWriter { reporterWriteTOCHtml = tableTOCHtml st,+ reporterWriteHtml = tableHtml st } return ExperimentReporter { reporterInitialise = return (), reporterFinalise = return (), reporterSimulate = simulateTable st,- reporterTOCHtml = tableTOCHtml st,- reporterHtml = tableHtml st }+ reporterRequest = writer } in ExperimentGenerator { generateReporter = reporter } -- | The state of the view.-data TableViewState r =+data TableViewState = TableViewState { tableView :: TableView,- tableExperiment :: Experiment r,+ tableExperiment :: Experiment, tableDir :: FilePath, tableMap :: M.Map Int FilePath } -- | Create a new state of the view.-newTable :: TableView -> Experiment r -> FilePath -> IO (TableViewState r)+newTable :: TableView -> Experiment -> FilePath -> IO TableViewState newTable view exp dir = do let n = experimentRunCount exp fs <- forM [0..(n - 1)] $ \i ->@@ -153,50 +152,50 @@ tableMap = m } -- | Write the tables during the simulation.-simulateTable :: TableViewState r -> ExperimentData -> Event (Event ())+simulateTable :: TableViewState -> ExperimentData -> Event DisposableEvent simulateTable st expdata =- do let labels = tableSeries $ tableView st- providers = experimentSeriesProviders expdata labels- input =- flip map providers $ \provider ->- case providerToString provider of- Nothing -> error $- "Cannot represent series " ++- providerName provider ++ - " as a string: simulateTable"- Just input -> input- separator = tableSeparator $ tableView st- formatter = tableFormatter $ tableView st- predicate = tablePredicate $ tableView st+ do let view = tableView st+ rs = tableSeries view $+ tableTransform view $+ experimentResults expdata+ exts = extractStringResults rs+ signals = experimentPredefinedSignals expdata+ signal = pureResultSignal signals $+ resultSignal rs+ separator = tableSeparator view+ formatter = tableFormatter view+ predicate = tablePredicate view i <- liftParameter simulationIndex -- create a new file let f = fromJust $ M.lookup (i - 1) (tableMap st) h <- liftIO $ openFile f WriteMode -- write a header liftIO $- do forM_ (zip [0..] providers) $ \(column, provider) ->+ do forM_ (zip [0..] exts) $ \(column, ext) -> do when (column > 0) $ hPutStr h separator- hPutStr h $ show $ providerName provider+ hPutStr h $ show $ resultExtractName ext hPutStrLn h ""- handleSignal_ (experimentMixedSignal expdata providers) $ \t ->+ d1 <- handleSignal signal $ \t -> do p <- predicate when p $- do forM_ (zip [0..] input) $ \(column, input) -> -- write the row- do x <- input -- write the column+ do forM_ (zip [0..] exts) $ \(column, ext) -> -- write the row+ do x <- resultExtractData ext -- write the column liftIO $ do when (column > 0) $ hPutStr h separator hPutStr h $ formatter x liftIO $ hPutStrLn h ""- return $ - liftIO $- do when (experimentVerbose $ tableExperiment st) $- putStr "Generated file " >> putStrLn f- hClose h -- close the file+ let d2 = + DisposableEvent $+ liftIO $+ do when (experimentVerbose $ tableExperiment st) $+ putStr "Generated file " >> putStrLn f+ hClose h -- close the file+ return $ d1 <> d2 -- | Get the HTML code. -tableHtml :: TableViewState r -> Int -> HtmlWriter () +tableHtml :: TableViewState -> Int -> HtmlWriter () tableHtml st index = let n = experimentRunCount $ tableExperiment st in if n == 1@@ -204,7 +203,7 @@ else tableHtmlMultiple st index -- | Get the HTML code for a single run.-tableHtmlSingle :: TableViewState r -> Int -> HtmlWriter ()+tableHtmlSingle :: TableViewState -> Int -> HtmlWriter () tableHtmlSingle st index = do header st index let f = fromJust $ M.lookup 0 (tableMap st)@@ -213,7 +212,7 @@ writeHtmlText (tableLinkText $ tableView st) -- | Get the HTML code for multiple runs-tableHtmlMultiple :: TableViewState r -> Int -> HtmlWriter ()+tableHtmlMultiple :: TableViewState -> Int -> HtmlWriter () tableHtmlMultiple st index = do header st index let n = experimentRunCount $ tableExperiment st@@ -228,7 +227,7 @@ writeHtmlLink (makeRelative (tableDir st) f) $ writeHtmlText sublink -header :: TableViewState r -> Int -> HtmlWriter ()+header :: TableViewState -> Int -> HtmlWriter () header st index = do writeHtmlHeader3WithId ("id" ++ show index) $ writeHtmlText (tableTitle $ tableView st)@@ -238,7 +237,7 @@ writeHtmlText description -- | Get the TOC item -tableTOCHtml :: TableViewState r -> Int -> HtmlWriter ()+tableTOCHtml :: TableViewState -> Int -> HtmlWriter () tableTOCHtml st index = writeHtmlListItem $ writeHtmlLink ("#id" ++ show index) $
Simulation/Aivika/Experiment/TimingStatsView.hs view
@@ -3,11 +3,11 @@ -- | -- Module : Simulation.Aivika.Experiment.TimingStatsView--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.8.3 -- -- The module defines 'TimingStatsView' that shows the timing statistics -- for the variables for every simulation run separately.@@ -23,20 +23,14 @@ import qualified Data.Map as M import Data.IORef import Data.Maybe+import Data.Monoid +import Simulation.Aivika import Simulation.Aivika.Experiment.Types import Simulation.Aivika.Experiment.HtmlWriter import Simulation.Aivika.Experiment.TimingStatsWriter import Simulation.Aivika.Experiment.Utils (replace) -import Simulation.Aivika.Specs-import Simulation.Aivika.Parameter-import Simulation.Aivika.Simulation-import Simulation.Aivika.Dynamics-import Simulation.Aivika.Event-import Simulation.Aivika.Signal-import Simulation.Aivika.Statistics- -- | Defines the 'View' that shows the timing statistics -- for variables for every simulation run separately. data TimingStatsView =@@ -58,8 +52,10 @@ -- ^ It shows the timing statistics. timingStatsPredicate :: Event Bool, -- ^ Specifies when gathering the statistics.- timingStatsSeries :: [String] - -- ^ It contains the labels of the observed series.+ timingStatsTransform :: ResultTransform,+ -- ^ The transform applied to the results before receiving series.+ timingStatsSeries :: ResultTransform + -- ^ It defines the series for which the statistics to be collected. } -- | This is the default view.@@ -70,28 +66,31 @@ timingStatsDescription = "The statistical data are gathered in the time points.", timingStatsWriter = defaultTimingStatsWriter, timingStatsPredicate = return True,- timingStatsSeries = [] }+ timingStatsTransform = id,+ timingStatsSeries = id } -instance ExperimentView TimingStatsView r where +instance WebPageRendering r => ExperimentView TimingStatsView r WebPageWriter where outputView v = let reporter exp renderer dir = do st <- newTimingStats v exp+ let writer =+ WebPageWriter { reporterWriteTOCHtml = timingStatsTOCHtml st,+ reporterWriteHtml = timingStatsHtml st } return ExperimentReporter { reporterInitialise = return (), reporterFinalise = return (), reporterSimulate = simulateTimingStats st,- reporterTOCHtml = timingStatsTOCHtml st,- reporterHtml = timingStatsHtml st }+ reporterRequest = writer } in ExperimentGenerator { generateReporter = reporter } -- | The state of the view.-data TimingStatsViewState r =+data TimingStatsViewState = TimingStatsViewState { timingStatsView :: TimingStatsView,- timingStatsExperiment :: Experiment r,+ timingStatsExperiment :: Experiment, timingStatsMap :: M.Map Int (IORef [(String, IORef (TimingStats Double))]) } -- | Create a new state of the view.-newTimingStats :: TimingStatsView -> Experiment r -> IO (TimingStatsViewState r)+newTimingStats :: TimingStatsView -> Experiment -> IO TimingStatsViewState newTimingStats view exp = do let n = experimentRunCount exp rs <- forM [0..(n - 1)] $ \i -> newIORef [] @@ -101,40 +100,35 @@ timingStatsMap = m } -- | Get the timing statistics during the simulation.-simulateTimingStats :: TimingStatsViewState r -> ExperimentData -> Event (Event ())+simulateTimingStats :: TimingStatsViewState -> ExperimentData -> Event DisposableEvent simulateTimingStats st expdata =- do let labels = timingStatsSeries $ timingStatsView st- input providers =- flip map providers $ \provider ->- case providerToDouble provider of- Nothing -> error $- "Cannot represent series " ++- providerName provider ++ - " as double values: simulateTimingStats"- Just input -> (provider, input)- predicate = timingStatsPredicate $ timingStatsView st+ do let view = timingStatsView st+ rs = timingStatsSeries view $+ timingStatsTransform view $+ experimentResults expdata+ exts = extractDoubleResults rs+ signals = experimentPredefinedSignals expdata+ signal = filterSignalM (const predicate) $+ pureResultSignal signals $+ resultSignal rs+ predicate = timingStatsPredicate view i <- liftParameter simulationIndex let r = fromJust $ M.lookup (i - 1) $ timingStatsMap st- forM_ labels $ \label ->- do let providers = experimentSeriesProviders expdata [label]- pairs = input providers- forM_ pairs $ \(provider, input) ->- do stats <- liftIO $ newIORef emptyTimingStats- let name = providerName provider- liftIO $ modifyIORef r ((:) (name, stats))- let h = filterSignalM (const predicate) $- experimentMixedSignal expdata [provider]- handleSignal_ h $ \_ ->- do t <- liftDynamics time- x <- input- liftIO $- do y <- readIORef stats- let y' = addTimingStats t x y- y' `seq` writeIORef stats y'- return $ return ()+ ds <- forM exts $ \ext ->+ do stats <- liftIO $ newIORef emptyTimingStats+ let name = resultExtractName ext+ liftIO $ modifyIORef r ((:) (name, stats))+ handleSignal signal $ \_ ->+ do t <- liftDynamics time+ x <- resultExtractData ext+ liftIO $+ do y <- readIORef stats+ let y' = addTimingStats t x y+ y' `seq` writeIORef stats y'+ return $ mconcat ds -- | Get the HTML code. -timingStatsHtml :: TimingStatsViewState r -> Int -> HtmlWriter () +timingStatsHtml :: TimingStatsViewState -> Int -> HtmlWriter () timingStatsHtml st index = let n = experimentRunCount $ timingStatsExperiment st in if n == 1@@ -142,7 +136,7 @@ else timingStatsHtmlMultiple st index -- | Get the HTML code for a single run.-timingStatsHtmlSingle :: TimingStatsViewState r -> Int -> HtmlWriter ()+timingStatsHtmlSingle :: TimingStatsViewState -> Int -> HtmlWriter () timingStatsHtmlSingle st index = do header st index let r = fromJust $ M.lookup 0 (timingStatsMap st)@@ -154,7 +148,7 @@ write writer name stats -- | Get the HTML code for multiple runs-timingStatsHtmlMultiple :: TimingStatsViewState r -> Int -> HtmlWriter ()+timingStatsHtmlMultiple :: TimingStatsViewState -> Int -> HtmlWriter () timingStatsHtmlMultiple st index = do header st index let n = experimentRunCount $ timingStatsExperiment st@@ -174,7 +168,7 @@ write = timingStatsWrite writer write writer name stats -header :: TimingStatsViewState r -> Int -> HtmlWriter ()+header :: TimingStatsViewState -> Int -> HtmlWriter () header st index = do writeHtmlHeader3WithId ("id" ++ show index) $ writeHtmlText (timingStatsTitle $ timingStatsView st)@@ -184,7 +178,7 @@ writeHtmlText description -- | Get the TOC item -timingStatsTOCHtml :: TimingStatsViewState r -> Int -> HtmlWriter ()+timingStatsTOCHtml :: TimingStatsViewState -> Int -> HtmlWriter () timingStatsTOCHtml st index = writeHtmlListItem $ writeHtmlLink ("#id" ++ show index) $
Simulation/Aivika/Experiment/TimingStatsWriter.hs view
@@ -1,11 +1,11 @@ -- | -- Module : Simulation.Aivika.Experiment.TimingStatsWriter--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.6.3 -- -- The module defines 'TimingStatsWriter' that knows how to write -- the timing statistics in HTML.
Simulation/Aivika/Experiment/Types.hs view
@@ -1,13 +1,13 @@ -{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts #-} -- | -- Module : Simulation.Aivika.Experiment.Types--- Copyright : Copyright (c) 2012-2013, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.6.3+-- Tested with: GHC 7.8.3 -- -- The module defines the simulation experiments. They automate -- the process of generating and analyzing the results. Moreover,@@ -20,46 +20,32 @@ -- module Simulation.Aivika.Experiment.Types- (Experiment(..),+ (-- * General Definitions+ Experiment(..),+ ExperimentRendering(..), defaultExperiment, runExperiment, runExperimentParallel, ExperimentData(..),- experimentDataInStartTime,- experimentSeriesProviders,- experimentMixedSignal,- Series(..),- SeriesContainer(..),- SeriesEntity(..),- SeriesProvider(..),- SeriesListWithSubscript,- SeriesArrayWithSubscript,- SeriesVectorWithSubscript,- seriesListWithSubscript,- seriesArrayWithSubscript,- seriesVectorWithSubscript, ExperimentView(..), ExperimentGenerator(..), ExperimentReporter(..), ExperimentFilePath(..), resolveFilePath, expandFilePath,- mapFilePath) where+ mapFilePath,+ -- * Web Page Rendering+ WebPageRendering(..),+ WebPageRenderer(..),+ WebPageWriter(..),+ WebPageGenerator(..)) where import Control.Monad import Control.Monad.State import Control.Concurrent.ParallelIO.Local import qualified Data.Map as M-import qualified Data.Vector as V-import qualified Data.Vector.Unboxed as UV-import qualified Data.Array as A-import qualified Data.Array.Unboxed as UA -import Data.Array (Array)-import Data.Array.Unboxed (UArray)-import Data.Array.IO- import Data.Ix import Data.Maybe import Data.Monoid@@ -70,17 +56,18 @@ import GHC.Conc (getNumCapabilities) -import Simulation.Aivika hiding (Var, readVar, varChanged_)-import Simulation.Aivika.Var-import qualified Simulation.Aivika.Ref.Light as LR-+import Simulation.Aivika import Simulation.Aivika.Experiment.HtmlWriter import Simulation.Aivika.Experiment.Utils (replace) --- | It defines the simulation experiment with the specified rendering backend.-data Experiment r = +-- | It defines the simulation experiment with the specified rendering backend and its bound data.+data Experiment = Experiment { experimentSpecs :: Specs, -- ^ The simulation specs for the experiment.+ experimentTransform :: ResultTransform,+ -- ^ How the results must be transformed before rendering.+ experimentLocalisation :: ResultLocalisation,+ -- ^ Specifies a localisation applied when rendering the experiment. experimentRunCount :: Int, -- ^ How many simulation runs should be launched. experimentDirectoryName :: ExperimentFilePath,@@ -91,194 +78,81 @@ -- ^ The experiment description. experimentVerbose :: Bool, -- ^ Whether the process of generating the results is verbose.- experimentGenerators :: [ExperimentGenerator r], - -- ^ The experiment generators.- experimentIndexHtml :: Experiment r -> [ExperimentReporter] -> FilePath -> IO (),- -- ^ Create the @index.html@ file after the simulation is finished- -- in the specified directory. experimentNumCapabilities :: IO Int -- ^ The number of threads used for the Monte-Carlo simulation -- if the executable was compiled with the support of multi-threading. } -- | The default experiment.-defaultExperiment :: Experiment r+defaultExperiment :: Experiment defaultExperiment = Experiment { experimentSpecs = Specs 0 10 0.01 RungeKutta4 SimpleGenerator,+ experimentTransform = id,+ experimentLocalisation = englishResultLocalisation, experimentRunCount = 1, experimentDirectoryName = UniqueFilePath "experiment", experimentTitle = "Simulation Experiment", experimentDescription = "", experimentVerbose = True,- experimentGenerators = [], - experimentIndexHtml = createIndexHtml, experimentNumCapabilities = getNumCapabilities } +-- | It allows rendering the simulation results in an arbitrary way.+class ExperimentRendering r a | r -> a where++ -- | Render the experiment after the simulation is finished, for example,+ -- creating the @index.html@ file in the specified directory.+ renderExperiment :: Experiment -> r -> [ExperimentReporter a] -> FilePath -> IO ()+ -- | This is a generator of the reporter with the specified rendering backend. -data ExperimentGenerator r = - ExperimentGenerator { generateReporter :: Experiment r -> r -> FilePath -> IO ExperimentReporter - -- ^ Generate a reporter for the specified directory,- -- where the @index.html@ file will be saved for the - -- current simulation experiment.+data ExperimentGenerator r a = + ExperimentGenerator { generateReporter :: Experiment -> r -> FilePath -> IO (ExperimentReporter a)+ -- ^ Generate a reporter bound up with the specified directory. } -- | Defines a view in which the simulation results should be saved. -- You should extend this type class to define your own views such -- as the PDF document.-class ExperimentView v r where+class ExperimentRendering r a => ExperimentView v r a | r -> a where -- | Create a generator of the reporter.- outputView :: v -> ExperimentGenerator r- --- | Represents the series. It is usually something, or--- an array of something, or a list of such values which--- can be simulated.------ The array and list of series are treated as a sequence of--- separate sub-series that have a subscript which can be--- optionally specified explicitly. By default, the subscript--- is numeric but it may be any string.--- --- At the same time, if the array or list of numeric values--- is wrapped in monads 'Simulation', 'Dynamics' or 'Event' then the--- underlying numeric array and list are already treated as--- a sampling statistics or list of numbers in time point.------ Moreover, if the array or list of numbers is contained in--- reference 'Ref' or variable 'Var' then the array and list--- of such values are also treated as a sampling statistics--- or list of numbers in time point.-class Series s where- - -- | Return the simulatable entity with the specified name- -- for the given series.- seriesEntity :: String -> s -> SeriesEntity- --- | Defines the simulatable entity.-data SeriesEntity =- SeriesEntity { seriesProviders :: [SeriesProvider]- -- ^ Return the providers for the entity.- }- --- | This is provider of the simulatable data.-data SeriesProvider =- SeriesProvider { providerName :: String,- -- ^ Return the name.- providerToDouble :: Maybe (Event Double),- -- ^ Try to return the data as double values.- providerToDoubleStats :: Maybe (Event (SamplingStats Double)),- -- ^ Try to return the statistics data in time points.- providerToDoubleList :: Maybe (Event [Double]),- -- ^ Try to return the list of double values.- providerToInt :: Maybe (Event Int),- -- ^ Try to return the data as integers.- providerToIntStats :: Maybe (Event (SamplingStats Int)),- -- ^ Try to return the statistics data in time points.- providerToIntList :: Maybe (Event [Int]),- -- ^ Try to return the list of integer values.- providerToString :: Maybe (Event String),- -- ^ Try to return the data as strings.- providerSignal :: Maybe (Signal ())- -- ^ Try to get a signal for the data, which- -- is actual for the 'Ref' references and - -- the 'Var' variables. You should not provide- -- such a signal if the data are calculated- -- only in the integration time points, which- -- is true for the integrals, for example.- }+ outputView :: v -> ExperimentGenerator r a -- | It describes the source simulation data used in the experiment. data ExperimentData =- ExperimentData { experimentSignalInIntegTimes :: Signal Double,- -- ^ The signal triggered in the integration time points.- experimentSignalInStartTime :: Signal Double,- -- ^ The signal triggered in the start time.- experimentSignalInStopTime :: Signal Double,- -- ^ The signal triggered in the stop time.- experimentSeries :: M.Map String SeriesEntity- -- ^ The simulation entitities with labels as keys.+ ExperimentData { experimentResults :: Results,+ -- ^ The simulation results used in the experiment.+ experimentPredefinedSignals :: ResultPredefinedSignals+ -- ^ The predefined signals provided by every model. } --- | Prepare data for the simulation experiment in start time from the series --- with the specified labels.-experimentDataInStartTime :: [(String, SeriesEntity)] -> Simulation ExperimentData-experimentDataInStartTime m = runDynamicsInStartTime $ runEventWith EarlierEvents d where- d = do signalInIntegTimes <- newSignalInIntegTimes- signalInStartTime <- newSignalInStartTime- signalInStopTime <- newSignalInStopTime- let series = M.fromList m- return ExperimentData { experimentSignalInIntegTimes = signalInIntegTimes,- experimentSignalInStartTime = signalInStartTime,- experimentSignalInStopTime = signalInStopTime,- experimentSeries = series }---- | Get a mixed signal for the specified providers based on --- the experimental data. This signal is triggered when --- the provided signals are triggered. The mixed signal is --- also triggered in the integration time points if there is --- at least one provider without signal.-experimentMixedSignal :: ExperimentData -> [SeriesProvider] -> Signal ()-experimentMixedSignal expdata providers =- let xs0 = map providerSignal providers- xs1 = filter isJust xs0- xs2 = filter isNothing xs0- signal1 = mconcat $ map fromJust xs1- signal2 = if null xs2 - then signal3 <> signal4- else signal5- signal3 = void $ experimentSignalInStartTime expdata- signal4 = void $ experimentSignalInStopTime expdata- signal5 = void $ experimentSignalInIntegTimes expdata- in signal1 <> signal2---- | Return the 'SeriesProvider' values from the experiment data by the specified labels.-experimentSeriesProviders :: ExperimentData -> [String] -> [SeriesProvider]-experimentSeriesProviders expdata labels =- join $ flip map labels $ \label ->- case M.lookup label (experimentSeries expdata) of- Nothing -> - error $ - "There is no series with label " ++ label ++ - ": experimentSeriesProviders"- Just entity -> - seriesProviders entity---- | Defines what creates the simulation reports.-data ExperimentReporter =+-- | Defines what creates the simulation reports by the specified renderer.+data ExperimentReporter a = ExperimentReporter { reporterInitialise :: IO (), -- ^ Initialise the reporting before -- the simulation runs are started. reporterFinalise :: IO (), -- ^ Finalise the reporting after -- all simulation runs are finished.- reporterSimulate :: ExperimentData -> Event (Event ()),+ reporterSimulate :: ExperimentData -> Event DisposableEvent, -- ^ Start the simulation run in the start time -- and return a finalizer that will be called -- in the stop time after the last signal is -- triggered and processed.- reporterTOCHtml :: Int -> HtmlWriter (),- -- ^ Return a TOC (Table of Contents) item for - -- the HTML index file after the finalisation - -- function is called, i.e. in the very end. - -- The agument specifies the ordered number of - -- the item.- --- -- You should wrap your HTML in 'writeHtmlListItem'.- reporterHtml :: Int -> HtmlWriter ()- -- ^ Return an HTML code for the index file- -- after the finalisation function is called,- -- i.e. in the very end. The agument specifies- -- the ordered number of the item.+ reporterRequest :: a+ -- ^ Return data requested by the renderer. } -- | Run the simulation experiment sequentially. For example, -- it can be a Monte-Carlo simulation dependentent on the external -- 'Parameter' values.-runExperiment :: Experiment r+runExperiment :: ExperimentRendering r a+ => Experiment -- ^ the simulation experiment to run+ -> [ExperimentGenerator r a]+ -- ^ generators used for rendering -> r -- ^ the rendering backend- -> Simulation ExperimentData+ -> Simulation Results -- ^ the simulation results received from the model -> IO () runExperiment = runExperimentWithExecutor sequence_@@ -295,11 +169,14 @@ -- threads directly with help of 'experimentNumCapabilities', -- although the real number of parallel threads can depend on many -- factors.-runExperimentParallel :: Experiment r+runExperimentParallel :: ExperimentRendering r a+ => Experiment -- ^ the simulation experiment to run+ -> [ExperimentGenerator r a]+ -- ^ generators used for rendering -> r -- ^ the rendering backend- -> Simulation ExperimentData+ -> Simulation Results -- ^ the simulation results received from the model -> IO () runExperimentParallel e = runExperimentWithExecutor executor e @@ -309,23 +186,25 @@ parallel_ pool tasks -- | Run the simulation experiment with the specified executor.-runExperimentWithExecutor :: ([IO ()] -> IO ())+runExperimentWithExecutor :: ExperimentRendering r a + => ([IO ()] -> IO ()) -- ^ an executor that allows parallelizing the simulation if required- -> Experiment r+ -> Experiment -- ^ the simulation experiment to run+ -> [ExperimentGenerator r a]+ -- ^ generators used for rendering -> r -- ^ the rendering backend- -> Simulation ExperimentData+ -> Simulation Results -- ^ the simulation results received from the model -> IO ()-runExperimentWithExecutor executor e r simulation = +runExperimentWithExecutor executor e generators r simulation = do let specs = experimentSpecs e runCount = experimentRunCount e dirName = experimentDirectoryName e- generators = experimentGenerators e path <- resolveFilePath "" dirName when (experimentVerbose e) $- do putStr "Using directory " + do putStr "Updating directory " putStrLn path createDirectoryIfMissing True path reporters <- mapM (\x -> generateReporter x e r path)@@ -333,40 +212,72 @@ forM_ reporters reporterInitialise let simulate :: Simulation () simulate =- do d <- simulation+ do signals <- newResultPredefinedSignals+ results <- simulation+ let d = ExperimentData { experimentResults = experimentTransform e results,+ experimentPredefinedSignals = signals } fs <- runDynamicsInStartTime $ runEventWith EarlierEvents $ forM reporters $ \reporter -> reporterSimulate reporter d runEventInStopTime $- sequence_ fs+ disposeEvent $ mconcat fs executor $ runSimulations simulate specs runCount forM_ reporters reporterFinalise- experimentIndexHtml e e reporters path+ renderExperiment e r reporters path return ()- --- | Create an index HTML file. -createIndexHtml :: Experiment r -> [ExperimentReporter] -> FilePath -> IO ()-createIndexHtml e reporters path = - do let html :: HtmlWriter ()- html = - writeHtmlDocumentWithTitle (experimentTitle e) $++-- | It defines the web page renderer for simulation 'Experiment'. +data WebPageRenderer = WebPageRenderer++-- | It replies to the requests made by the web page renderer.+data WebPageWriter =+ WebPageWriter { reporterWriteTOCHtml :: Int -> HtmlWriter (),+ -- ^ Return a TOC (Table of Contents) item for + -- the HTML index file after the finalisation + -- function is called, i.e. in the very end. + -- The agument specifies the ordered number of + -- the item.+ --+ -- You should wrap your HTML in 'writeHtmlListItem'.+ reporterWriteHtml :: Int -> HtmlWriter ()+ -- ^ Return an HTML code for the index file+ -- after the finalisation function is called,+ -- i.e. in the very end. The agument specifies+ -- the ordered number of the item.+ }++-- | A subclass of renderers that know how to save the @index.html@ file+-- when rendering the simulation experiment.+class ExperimentRendering r WebPageWriter => WebPageRendering r++-- | A convenient type synonym for describing the web page generators.+type WebPageGenerator r = ExperimentGenerator r WebPageWriter++instance WebPageRendering WebPageRenderer++instance ExperimentRendering WebPageRenderer WebPageWriter where++ renderExperiment e r reporters path = + do let html :: HtmlWriter ()+ html = + writeHtmlDocumentWithTitle (experimentTitle e) $ do writeHtmlList $ forM_ (zip [1..] reporters) $ \(i, reporter) -> - reporterTOCHtml reporter i+ reporterWriteTOCHtml (reporterRequest reporter) i writeHtmlBreak unless (null $ experimentDescription e) $ writeHtmlParagraph $ writeHtmlText $ experimentDescription e forM_ (zip [1..] reporters) $ \(i, reporter) ->- reporterHtml reporter i- file = combine path "index.html"- ((), contents) <- runHtmlWriter html id- UTF8.writeFile file (contents [])- when (experimentVerbose e) $- do putStr "Generated file "- putStrLn file-+ reporterWriteHtml (reporterRequest reporter) i+ file = combine path "index.html"+ ((), contents) <- runHtmlWriter html id+ UTF8.writeFile file (contents [])+ when (experimentVerbose e) $+ do putStr "Generated file "+ putStrLn file+ -- | Specifies the file name, unique or writable, which can be appended with extension if required. data ExperimentFilePath = WritableFilePath FilePath -- ^ The file which is overwritten in @@ -409,553 +320,3 @@ mapFilePath :: (FilePath -> FilePath) -> ExperimentFilePath -> ExperimentFilePath mapFilePath f (WritableFilePath path) = WritableFilePath (f path) mapFilePath f (UniqueFilePath path) = UniqueFilePath (f path) ---- | Represent a container for simulation data.-class SeriesContainer c where-- -- | Extract data from the container.- containerData :: c a -> Event a-- -- | Get the signal for the container.- containerSignal :: c a -> Maybe (Signal ())--instance SeriesContainer Parameter where-- containerData = liftParameter-- containerSignal = const Nothing--instance SeriesContainer Simulation where-- containerData = liftSimulation-- containerSignal = const Nothing--instance SeriesContainer Dynamics where-- containerData = liftDynamics-- containerSignal = const Nothing--instance SeriesContainer Event where-- containerData = id-- containerSignal = const Nothing--instance SeriesContainer Ref where-- containerData = readRef-- containerSignal = Just . refChanged_--instance SeriesContainer LR.Ref where-- containerData = LR.readRef-- containerSignal = const Nothing--instance SeriesContainer Var where-- containerData = readVar-- containerSignal = Just . varChanged_--instance SeriesContainer Signalable where-- containerData = readSignalable-- containerSignal = Just . signalableChanged_--instance SeriesContainer c => Series (c Double) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble =- Just $- containerData s,- providerToDoubleStats =- Just $- fmap returnSamplingStats $- containerData s,- providerToDoubleList =- Just $- fmap return $- containerData s,- providerToInt = Nothing,- providerToIntStats = Nothing,- providerToIntList = Nothing,- providerToString =- Just $- fmap show $- containerData s,- providerSignal =- containerSignal s }] }--instance SeriesContainer c => Series (c Int) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble =- Just $- fmap fromIntegral $- containerData s,- providerToDoubleStats =- Just $- fmap returnSamplingStats $- fmap fromIntegral $- containerData s,- providerToDoubleList =- Just $- fmap return $- fmap fromIntegral $- containerData s,- providerToInt =- Just $- containerData s,- providerToIntStats =- Just $- fmap returnSamplingStats $- containerData s,- providerToIntList =- Just $- fmap return $- containerData s,- providerToString =- Just $- fmap show $- containerData s,- providerSignal =- containerSignal s }] }--instance SeriesContainer c => Series (c String) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats = Nothing,- providerToDoubleList = Nothing,- providerToInt = Nothing,- providerToIntStats = Nothing,- providerToIntList = Nothing,- providerToString =- Just $- containerData s,- providerSignal =- containerSignal s }] }--instance Series s => Series [s] where- - seriesEntity name s = - SeriesEntity { seriesProviders = - join $ forM (zip [0..] s) $ \(i, s) ->- let name' = name ++ "[" ++ show i ++ "]"- in seriesProviders $ seriesEntity name' s }- -instance (Show i, Ix i, Series s) => Series (Array i s) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- join $ forM (A.assocs s) $ \(i, s) ->- let name' = name ++ "[" ++ show i ++ "]"- in seriesProviders $ seriesEntity name' s }--instance Series s => Series (V.Vector s) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- join $ forM (zip [0..] (V.toList s)) $ \(i, s) ->- let name' = name ++ "[" ++ show i ++ "]"- in seriesProviders $ seriesEntity name' s }---- | Represents a list with the specified subscript.-data SeriesListWithSubscript s =- SeriesListWithSubscript { seriesList :: [s],- seriesListSubscript :: [String] }---- | Represents an array with the specified subscript.-data SeriesArrayWithSubscript i s =- SeriesArrayWithSubscript { seriesArray :: Array i s,- seriesArraySubscript :: Array i String }---- | Represents a vector with the specified subscript.-data SeriesVectorWithSubscript s =- SeriesVectorWithSubscript { seriesVector :: V.Vector s,- seriesVectorSubscript :: V.Vector String }---- | Add the specified subscript to the list.-seriesListWithSubscript :: Series s- => [s]- -- ^ the list to subscript- -> [String]- -- ^ the list of subscripts- -> SeriesListWithSubscript s- -- ^ the subscripted list-seriesListWithSubscript = SeriesListWithSubscript---- | Add the specified subscript to the array.-seriesArrayWithSubscript :: (Ix i, Series s)- => Array i s- -- ^ the array to subscript- -> Array i String- -- ^ the array of subscripts- -> SeriesArrayWithSubscript i s- -- ^ the subscripted array-seriesArrayWithSubscript = SeriesArrayWithSubscript---- | Add the specified subscript to the vector.-seriesVectorWithSubscript :: Series s- => V.Vector s- -- ^ the vector to subscript- -> V.Vector String- -- ^ the vector of subscripts- -> SeriesVectorWithSubscript s- -- ^ the subscripted vector-seriesVectorWithSubscript = SeriesVectorWithSubscript--instance Series s => Series (SeriesListWithSubscript s) where- - seriesEntity name s = - SeriesEntity { seriesProviders = do- let xs = seriesList s- ns = seriesListSubscript s- join $ forM (zip3 [1..] xs ns) $ \(i, s, n) ->- let name' = name ++ n- in seriesProviders $ seriesEntity name' s }- -instance (Ix i, Series s) => Series (SeriesArrayWithSubscript i s) where- - seriesEntity name s =- SeriesEntity { seriesProviders = do- let xs = seriesArray s- ns = seriesArraySubscript s- join $ forM (zip (A.assocs xs) (A.elems ns)) $ \((i, s), n) ->- let name' = name ++ n- in seriesProviders $ seriesEntity name' s }--instance Series s => Series (SeriesVectorWithSubscript s) where- - seriesEntity name s =- SeriesEntity { seriesProviders = do- let xs = seriesVector s- ns = seriesVectorSubscript s- join $ forM (zip (V.toList xs) (V.toList ns)) $ \(x, n) ->- let name' = name ++ n- in seriesProviders $ seriesEntity name' x }--instance SeriesContainer c => Series (c (SamplingStats Double)) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- containerData s,- providerToDoubleList = Nothing,- providerToInt = Nothing,- providerToIntStats = Nothing,- providerToIntList = Nothing,- providerToString = Nothing,- providerSignal =- containerSignal s } ] }--instance SeriesContainer c => Series (c (SamplingStats Int)) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap fromIntSamplingStats $- containerData s,- providerToDoubleList = Nothing,- providerToInt = Nothing,- providerToIntStats =- Just $- containerData s,- providerToIntList = Nothing,- providerToString = Nothing,- providerSignal =- containerSignal s } ] }--instance SeriesContainer c => Series (c [Double]) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap listSamplingStats $- containerData s,- providerToDoubleList =- Just $- containerData s,- providerToInt = Nothing,- providerToIntStats = Nothing,- providerToIntList = Nothing,- providerToString =- Just $- fmap show $- containerData s,- providerSignal =- containerSignal s } ] }--instance SeriesContainer c => Series (c [Int]) where- - seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap fromIntSamplingStats $- fmap listSamplingStats $- containerData s,- providerToDoubleList =- Just $- fmap (map fromIntegral) $- containerData s,- providerToInt = Nothing,- providerToIntStats =- Just $- fmap listSamplingStats $- containerData s,- providerToIntList =- Just $- containerData s,- providerToString =- Just $- fmap show $- containerData s,- providerSignal =- containerSignal s } ] }--instance (Ix i, SeriesContainer c) => Series (c (Array i Double)) where-- seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap listSamplingStats $- fmap A.elems $- containerData s,- providerToDoubleList =- Just $- fmap A.elems $- containerData s,- providerToInt = Nothing,- providerToIntStats = Nothing,- providerToIntList = Nothing,- providerToString = Nothing,- providerSignal =- containerSignal s } ] }--instance (Ix i, SeriesContainer c) => Series (c (Array i Int)) where-- seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap fromIntSamplingStats $- fmap listSamplingStats $- fmap A.elems $- containerData s,- providerToDoubleList =- Just $- fmap (map fromIntegral) $- fmap A.elems $- containerData s,- providerToInt = Nothing,- providerToIntStats =- Just $- fmap listSamplingStats $- fmap A.elems $- containerData s,- providerToIntList =- Just $- fmap A.elems $- containerData s,- providerToString = Nothing,- providerSignal =- containerSignal s } ] }--instance (Ix i, SeriesContainer c) => Series (c (UArray i Double)) where-- seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap listSamplingStats $- fmap UA.elems $- containerData s,- providerToDoubleList =- Just $- fmap UA.elems $- containerData s,- providerToInt = Nothing,- providerToIntStats = Nothing,- providerToIntList = Nothing,- providerToString = Nothing,- providerSignal =- containerSignal s } ] }--instance (Ix i, SeriesContainer c) => Series (c (UArray i Int)) where-- seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap fromIntSamplingStats $- fmap listSamplingStats $- fmap UA.elems $- containerData s,- providerToDoubleList =- Just $- fmap (map fromIntegral) $- fmap UA.elems $- containerData s,- providerToInt = Nothing,- providerToIntStats =- Just $- fmap listSamplingStats $- fmap UA.elems $- containerData s,- providerToIntList =- Just $- fmap UA.elems $- containerData s,- providerToString = Nothing,- providerSignal =- containerSignal s } ] }--instance SeriesContainer c => Series (c (V.Vector Double)) where-- seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap listSamplingStats $- fmap V.toList $- containerData s,- providerToDoubleList =- Just $- fmap V.toList $- containerData s,- providerToInt = Nothing,- providerToIntStats = Nothing,- providerToIntList = Nothing,- providerToString =- Just $- fmap show $- containerData s,- providerSignal =- containerSignal s } ] }--instance SeriesContainer c => Series (c (V.Vector Int)) where-- seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap fromIntSamplingStats $- fmap listSamplingStats $- fmap V.toList $- containerData s,- providerToDoubleList =- Just $- fmap (map fromIntegral) $- fmap V.toList $- containerData s,- providerToInt = Nothing,- providerToIntStats =- Just $- fmap listSamplingStats $- fmap V.toList $- containerData s,- providerToIntList =- Just $- fmap V.toList $- containerData s,- providerToString =- Just $- fmap show $- containerData s,- providerSignal =- containerSignal s }] }--instance SeriesContainer c => Series (c (UV.Vector Double)) where-- seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap listSamplingStats $- fmap UV.toList $- containerData s,- providerToDoubleList =- Just $- fmap UV.toList $- containerData s,- providerToInt = Nothing,- providerToIntStats = Nothing,- providerToIntList = Nothing,- providerToString =- Just $- fmap show $- containerData s,- providerSignal =- containerSignal s } ] }--instance SeriesContainer c => Series (c (UV.Vector Int)) where-- seriesEntity name s =- SeriesEntity { seriesProviders =- [SeriesProvider { providerName = name,- providerToDouble = Nothing,- providerToDoubleStats =- Just $- fmap fromIntSamplingStats $- fmap listSamplingStats $- fmap UV.toList $- containerData s,- providerToDoubleList =- Just $- fmap (map fromIntegral) $- fmap UV.toList $- containerData s,- providerToInt = Nothing,- providerToIntStats =- Just $- fmap listSamplingStats $- fmap UV.toList $- containerData s,- providerToIntList =- Just $- fmap UV.toList $- containerData s,- providerToString =- Just $- fmap show $- containerData s,- providerSignal =- containerSignal s } ] }
Simulation/Aivika/Experiment/Utils.hs view
@@ -1,11 +1,11 @@ -- | -- Module : Simulation.Aivika.Experiment.Utils--- Copyright : Copyright (c) 2012, David Sorokin <david.sorokin@gmail.com>+-- Copyright : Copyright (c) 2012-2014, David Sorokin <david.sorokin@gmail.com> -- License : BSD3 -- Maintainer : David Sorokin <david.sorokin@gmail.com> -- Stability : experimental--- Tested with: GHC 7.4.1+-- Tested with: GHC 7.6.3 -- -- It defines utility functions missed in the standard library. --
aivika-experiment.cabal view
@@ -1,5 +1,5 @@ name: aivika-experiment-version: 1.3.1+version: 1.4 synopsis: Simulation experiments for the Aivika library description: This package allows defining simulation experiments for the Aivika@@ -18,7 +18,7 @@ homepage: http://github.com/dsorokin/aivika-experiment cabal-version: >= 1.6 build-type: Simple-tested-with: GHC == 7.6.3+tested-with: GHC == 7.8.3 extra-source-files: examples/MachRep3.hs examples/LinearArray.hs@@ -27,38 +27,35 @@ exposed-modules: Simulation.Aivika.Experiment Simulation.Aivika.Experiment.Types- Simulation.Aivika.Experiment.FileRenderer Simulation.Aivika.Experiment.HtmlWriter Simulation.Aivika.Experiment.LastValueView Simulation.Aivika.Experiment.TableView Simulation.Aivika.Experiment.TimingStatsView Simulation.Aivika.Experiment.TimingStatsWriter Simulation.Aivika.Experiment.SamplingStatsWriter- Simulation.Aivika.Experiment.SamplingStatsSource Simulation.Aivika.Experiment.FinalStatsView Simulation.Aivika.Experiment.Histogram Simulation.Aivika.Experiment.ExperimentSpecsView Simulation.Aivika.Experiment.ExperimentSpecsWriter Simulation.Aivika.Experiment.FinalTableView- Simulation.Aivika.Experiment.ListSource Simulation.Aivika.Experiment.Utils+ Simulation.Aivika.Experiment.MRef build-depends: base >= 3 && < 6, mtl >= 1.1.0.2,- array >= 0.3.0.0,- vector >= 0.9, containers >= 0.4.0.0, directory >= 1.1.0.2, filepath >= 1.3.0.0, utf8-string >= 0.3.7, split >= 0.2.2,- network >= 2.3.0.13,+ network-uri >= 2.6, parallel-io >= 0.3.2.1,- aivika >= 1.3+ aivika >= 1.4 extensions: FlexibleInstances,+ FlexibleContexts, MultiParamTypeClasses,- RankNTypes+ FunctionalDependencies ghc-options: -O2
examples/LinearArray.hs view
@@ -9,6 +9,8 @@ {-# LANGUAGE RecursiveDo #-} import Data.Array+import Data.Monoid+ import Control.Monad import Control.Monad.Trans @@ -32,7 +34,7 @@ return (i, x) return $ array bnds ps -model :: Int -> Simulation ExperimentData+model :: Int -> Simulation Results model n = mdo m <- generateArray (1, n) $ \i -> integ (q + k * (c!(i - 1) - c!i) + k * (c!(i + 1) - c!i)) 0@@ -43,30 +45,45 @@ q = 1 k = 2 v = 0.75- experimentDataInStartTime- [("t", seriesEntity "time" time),- ("m", seriesEntity "M" m),- ("c", seriesEntity "C" c)]+ return $ results+ [resultSource "t" "time" time,+ resultSource "m" "M" m,+ resultSource "c" "C" c] -experiment :: FileRenderer r => Experiment r+experiment :: Experiment experiment = defaultExperiment { experimentSpecs = specs, experimentRunCount = 1, experimentTitle = "Linear Array", experimentDescription = "Model Linear Array as described in " ++- "the examples included in Berkeley-Madonna.",- experimentGenerators = - [outputView defaultExperimentSpecsView,- outputView $ defaultTableView {- tableSeries = ["t", "m", "c"] },- outputView $ defaultFinalTableView {- finalTableSeries = ["m", "c"] }, - outputView $ defaultLastValueView {- lastValueSeries = ["t", "m", "c"] },- outputView $ defaultTimingStatsView {- timingStatsSeries = ["t", "m", "c"] },- outputView $ defaultFinalStatsView {- finalStatsSeries = ["m", "c"] } ] } + "the examples included in Berkeley-Madonna." } -main = runExperiment experiment HtmlRenderer (model 51)+generators :: WebPageRendering r => [WebPageGenerator r]+generators =+ [outputView defaultExperimentSpecsView,+ outputView $ defaultTableView {+ tableSeries =+ resultByName "t" <>+ resultByName "m" <>+ resultByName "c" },+ outputView $ defaultFinalTableView {+ finalTableSeries =+ resultByName "m" <>+ resultByName "c" },+ outputView $ defaultLastValueView {+ lastValueSeries =+ resultByName "t" <>+ resultByName "m" <>+ resultByName "c" },+ outputView $ defaultTimingStatsView {+ timingStatsSeries =+ resultByName "t" <>+ resultByName "m" <>+ resultByName "c" },+ outputView $ defaultFinalStatsView {+ finalStatsSeries =+ resultByName "m" <>+ resultByName "c" } ]++main = runExperiment experiment generators WebPageRenderer (model 51)
examples/MachRep3.hs view
@@ -36,26 +36,28 @@ "until both machines are down. We find the proportion of up time. It " ++ "should come out to about 0.45." -experiment :: FileRenderer r => Experiment r+experiment :: Experiment experiment = defaultExperiment { experimentSpecs = specs, experimentRunCount = 3,- experimentDescription = description,- experimentGenerators =- [outputView defaultExperimentSpecsView,- outputView $ defaultLastValueView {- lastValueSeries = ["x"] },- outputView $ defaultTimingStatsView {- timingStatsSeries = ["x"] },- outputView $ defaultFinalStatsView {- finalStatsSeries = ["x"] },- outputView $ defaultTableView {- tableSeries = ["x"] }, - outputView $ defaultFinalTableView {- finalTableSeries = ["x"] } ] }+ experimentDescription = description } -model :: Simulation ExperimentData+generators :: WebPageRendering r => [WebPageGenerator r]+generators =+ [outputView defaultExperimentSpecsView,+ outputView $ defaultLastValueView {+ lastValueSeries = resultByName "x" },+ outputView $ defaultTimingStatsView {+ timingStatsSeries = resultByName "x" },+ outputView $ defaultFinalStatsView {+ finalStatsSeries = resultByName "x" },+ outputView $ defaultTableView {+ tableSeries = resultByName "x" }, + outputView $ defaultFinalTableView {+ finalTableSeries = resultByName "x" } ]++model :: Simulation Results model = do -- number of machines currently up nUp <- newRef 2@@ -104,13 +106,13 @@ runProcessInStartTimeUsingId pid2 (machine pid1) - let result = + let prop = do x <- readRef totalUpTime y <- liftDynamics time return $ x / (2 * y) - experimentDataInStartTime- [("x", seriesEntity "The proportion of up time" result),- ("t", seriesEntity "Simulation time" time)]+ return $ results+ [resultSource "x" "The proportion of up time" prop,+ resultSource "t" "Simulation time" time] -main = runExperiment experiment HtmlRenderer model+main = runExperiment experiment generators WebPageRenderer model