{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleContexts #-}

-- |
-- Module     : Simulation.Aivika.Trans.Experiment.Types
-- Copyright  : Copyright (c) 2012-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 8.0.1
--
-- The module defines the simulation experiments. They automate
-- the process of generating and analyzing the results. Moreover,
-- this module is open to extensions, allowing you to define
-- your own output views for the simulation results, for example,
-- such views that would allow saving the results in PDF or as
-- charts. To decrease the number of dependencies, such possible  
-- extenstions are not included in this package, although simple
-- views are provided.
--

module Simulation.Aivika.Trans.Experiment.Types where

import Control.Monad
import Control.Exception

import Data.Maybe
import Data.Monoid
import Data.Either

import GHC.Conc (getNumCapabilities)

import Simulation.Aivika.Trans

-- | It defines the simulation experiment with the specified rendering backend and its bound data.
data Experiment m = 
  Experiment { forall (m :: * -> *). Experiment m -> Specs m
experimentSpecs         :: Specs m,
               -- ^ The simulation specs for the experiment.
               forall (m :: * -> *). Experiment m -> ResultTransform m
experimentTransform     :: ResultTransform m,
               -- ^ How the results must be transformed before rendering.
               forall (m :: * -> *). Experiment m -> ResultLocalisation
experimentLocalisation  :: ResultLocalisation,
               -- ^ Specifies a localisation applied when rendering the experiment.
               forall (m :: * -> *). Experiment m -> Int
experimentRunCount      :: Int,
               -- ^ How many simulation runs should be launched.
               forall (m :: * -> *). Experiment m -> String
experimentTitle         :: String,
               -- ^ The experiment title.
               forall (m :: * -> *). Experiment m -> String
experimentDescription   :: String,
               -- ^ The experiment description.
               forall (m :: * -> *). Experiment m -> Bool
experimentVerbose       :: Bool,
               -- ^ Whether the process of generating the results is verbose.
               forall (m :: * -> *). Experiment m -> IO Int
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 m
defaultExperiment :: forall (m :: * -> *). Experiment m
defaultExperiment =
  Experiment { experimentSpecs :: Specs m
experimentSpecs         = forall (m :: * -> *).
Double -> Double -> Double -> Method -> GeneratorType m -> Specs m
Specs Double
0 Double
10 Double
0.01 Method
RungeKutta4 forall (m :: * -> *). GeneratorType m
SimpleGenerator,
               experimentTransform :: ResultTransform m
experimentTransform     = forall a. a -> a
id,
               experimentLocalisation :: ResultLocalisation
experimentLocalisation  = ResultLocalisation
englishResultLocalisation,
               experimentRunCount :: Int
experimentRunCount      = Int
1,
               experimentTitle :: String
experimentTitle         = String
"Simulation Experiment",
               experimentDescription :: String
experimentDescription   = String
"",
               experimentVerbose :: Bool
experimentVerbose       = Bool
True,
               experimentNumCapabilities :: IO Int
experimentNumCapabilities = IO Int
getNumCapabilities }

-- | Allows specifying the experiment monad.
class ExperimentMonadProviding r (m :: * -> *) where

  -- | Defines the experiment monad type.
  type ExperimentMonad r m :: * -> *

-- | Defines the experiment computation that tries to perform the calculation. 
type ExperimentMonadTry r m a = ExperimentMonad r m (Either SomeException a)

-- | It allows rendering the simulation results in an arbitrary way.
class ExperimentMonadProviding r m => ExperimentRendering r m where

  -- | Defines a context used when rendering the experiment.
  data ExperimentContext r m :: *

  -- | Defines the experiment environment.
  type ExperimentEnvironment r m :: *

  -- | Prepare before rendering the experiment.
  prepareExperiment :: Experiment m -> r -> ExperimentMonad r m (ExperimentEnvironment r m)

  -- | Render the experiment after the simulation is finished, for example,
  -- creating the @index.html@ file in the specified directory.
  renderExperiment :: Experiment m -> r -> [ExperimentReporter r m] -> ExperimentEnvironment r m -> ExperimentMonad r m ()

  -- | It is called when the experiment has been completed.
  onExperimentCompleted :: Experiment m -> r -> ExperimentEnvironment r m -> ExperimentMonad r m () 

  -- | It is called when the experiment rendering has failed.
  onExperimentFailed :: Exception e => Experiment m -> r -> ExperimentEnvironment r m -> e -> ExperimentMonad r m ()

-- | This is a generator of the reporter with the specified rendering backend.                     
data ExperimentGenerator r m = 
  ExperimentGenerator { forall r (m :: * -> *).
ExperimentGenerator r m
-> Experiment m
-> r
-> ExperimentEnvironment r m
-> ExperimentMonad r m (ExperimentReporter r m)
generateReporter :: Experiment m -> r -> ExperimentEnvironment r m -> ExperimentMonad r m (ExperimentReporter r m)
                        -- ^ Generate a reporter.
                      }

-- | 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 ExperimentRendering r m => ExperimentView v r m where
  
  -- | Create a generator of the reporter.
  outputView :: v m -> ExperimentGenerator r m

-- | It describes the source simulation data used in the experiment.
data ExperimentData m =
  ExperimentData { forall (m :: * -> *). ExperimentData m -> Results m
experimentResults :: Results m,
                   -- ^ The simulation results used in the experiment.
                   forall (m :: * -> *). ExperimentData m -> ResultPredefinedSignals m
experimentPredefinedSignals :: ResultPredefinedSignals m
                   -- ^ The predefined signals provided by every model.
                 }

-- | Defines what creates the simulation reports by the specified renderer.
data ExperimentReporter r m =
  ExperimentReporter { forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentMonad r m ()
reporterInitialise :: ExperimentMonad r m (),
                       -- ^ Initialise the reporting before 
                       -- the simulation runs are started.
                       forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentMonad r m ()
reporterFinalise   :: ExperimentMonad r m (),
                       -- ^ Finalise the reporting after
                       -- all simulation runs are finished.
                       forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentData m -> Composite m ()
reporterSimulate   :: ExperimentData m -> Composite m (),
                       -- ^ Start the simulation run in the start time.
                       forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentContext r m
reporterContext    :: ExperimentContext r m
                       -- ^ Return a context used by the renderer.
                     }

-- | Run the simulation experiment sequentially.
runExperiment_ :: (MonadDES m,
                   ExperimentRendering r m,
                   Monad (ExperimentMonad r m),
                   MonadException (ExperimentMonad r m))
                  => (m () -> ExperimentMonad r m a)
                  -- ^ the function that actually starts the simulation run
                  -> Experiment m
                  -- ^ the simulation experiment to run
                  -> [ExperimentGenerator r m]
                  -- ^ generators used for rendering
                  -> r
                  -- ^ the rendering backend
                  -> Simulation m (Results m)
                  -- ^ the simulation results received from the model
                  -> ExperimentMonadTry r m ()
{-# INLINABLE runExperiment_ #-}
runExperiment_ :: forall (m :: * -> *) r a.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
(m () -> ExperimentMonad r m a)
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> ExperimentMonadTry r m ()
runExperiment_ m () -> ExperimentMonad r m a
executor0 Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation =
  do Either SomeException ()
x <- forall (m :: * -> *) r a.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
([m ()] -> ExperimentMonad r m a)
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> ExperimentMonadTry r m a
runExperimentWithExecutor [m ()] -> ExperimentMonad r m ()
executor Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation
     forall (m :: * -> *) a. Monad m => a -> m a
return (Either SomeException ()
x forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return ())
       where executor :: [m ()] -> ExperimentMonad r m ()
executor = forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map m () -> ExperimentMonad r m a
executor0

-- | Run the simulation experiment sequentially.
runExperiment :: (MonadDES m,
                  ExperimentRendering r m,
                  Monad (ExperimentMonad r m),
                  MonadException (ExperimentMonad r m))
                 => (m () -> ExperimentMonad r m a)
                 -- ^ the function that actually starts the simulation run
                 -> Experiment m
                 -- ^ the simulation experiment to run
                 -> [ExperimentGenerator r m]
                 -- ^ generators used for rendering
                 -> r
                 -- ^ the rendering backend
                 -> Simulation m (Results m)
                 -- ^ the simulation results received from the model
                 -> ExperimentMonadTry r m [a]
{-# INLINABLE runExperiment #-}
runExperiment :: forall (m :: * -> *) r a.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
(m () -> ExperimentMonad r m a)
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> ExperimentMonadTry r m [a]
runExperiment m () -> ExperimentMonad r m a
executor0 = forall (m :: * -> *) r a.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
([m ()] -> ExperimentMonad r m a)
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> ExperimentMonadTry r m a
runExperimentWithExecutor [m ()] -> ExperimentMonad r m [a]
executor
  where executor :: [m ()] -> ExperimentMonad r m [a]
executor = forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map m () -> ExperimentMonad r m a
executor0

-- | Run the simulation experiment with the specified executor.
runExperimentWithExecutor :: (MonadDES m,
                              ExperimentRendering r m,
                              Monad (ExperimentMonad r m),
                              MonadException (ExperimentMonad r m))
                             => ([m ()] -> ExperimentMonad r m a)
                             -- ^ an executor that allows parallelizing the simulation if required
                             -> Experiment m
                             -- ^ the simulation experiment to run
                             -> [ExperimentGenerator r m]
                             -- ^ generators used for rendering
                             -> r
                             -- ^ the rendering backend
                             -> Simulation m (Results m)
                             -- ^ the simulation results received from the model
                             -> ExperimentMonadTry r m a
{-# INLINABLE runExperimentWithExecutor #-}
runExperimentWithExecutor :: forall (m :: * -> *) r a.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
([m ()] -> ExperimentMonad r m a)
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> ExperimentMonadTry r m a
runExperimentWithExecutor [m ()] -> ExperimentMonad r m a
executor Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation =
  do let specs :: Specs m
specs      = forall (m :: * -> *). Experiment m -> Specs m
experimentSpecs Experiment m
e
         runCount :: Int
runCount   = forall (m :: * -> *). Experiment m -> Int
experimentRunCount Experiment m
e
     ExperimentEnvironment r m
env <- forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r -> ExperimentMonad r m (ExperimentEnvironment r m)
prepareExperiment Experiment m
e r
r
     let c1 :: ExperimentMonadTry r m a
c1 =
           do [ExperimentReporter r m]
reporters <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\ExperimentGenerator r m
x -> forall r (m :: * -> *).
ExperimentGenerator r m
-> Experiment m
-> r
-> ExperimentEnvironment r m
-> ExperimentMonad r m (ExperimentReporter r m)
generateReporter ExperimentGenerator r m
x Experiment m
e r
r ExperimentEnvironment r m
env)
                           [ExperimentGenerator r m]
generators
              forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentMonad r m ()
reporterInitialise
              let simulate :: Simulation m ()
simulate =
                    do ResultPredefinedSignals m
signals <- forall (m :: * -> *).
MonadDES m =>
Simulation m (ResultPredefinedSignals m)
newResultPredefinedSignals
                       Results m
results <- Simulation m (Results m)
simulation
                       let d :: ExperimentData m
d = ExperimentData { experimentResults :: Results m
experimentResults = forall (m :: * -> *). Experiment m -> ResultTransform m
experimentTransform Experiment m
e Results m
results,
                                                experimentPredefinedSignals :: ResultPredefinedSignals m
experimentPredefinedSignals = ResultPredefinedSignals m
signals }
                       ((), DisposableEvent m
fs) <- forall (m :: * -> *) a. Dynamics m a -> Simulation m a
runDynamicsInStartTime forall a b. (a -> b) -> a -> b
$
                                   forall (m :: * -> *) a.
EventQueueing m =>
EventProcessing -> Event m a -> Dynamics m a
runEventWith EventProcessing
EarlierEvents forall a b. (a -> b) -> a -> b
$
                                   forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) a.
Composite m a
-> DisposableEvent m -> Event m (a, DisposableEvent m)
runComposite forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$
                                   forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall a b. (a -> b) -> a -> b
$ \ExperimentReporter r m
reporter ->
                                   forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentData m -> Composite m ()
reporterSimulate ExperimentReporter r m
reporter ExperimentData m
d
                       let m1 :: Simulation m ()
m1 =
                             forall (m :: * -> *) a. MonadDES m => Event m a -> Simulation m a
runEventInStopTime forall a b. (a -> b) -> a -> b
$
                             forall (m :: * -> *) a. Monad m => a -> m a
return ()
                           m2 :: Simulation m ()
m2 =
                             forall (m :: * -> *) a. MonadDES m => Event m a -> Simulation m a
runEventInStopTime forall a b. (a -> b) -> a -> b
$
                             forall (m :: * -> *). DisposableEvent m -> Event m ()
disposeEvent DisposableEvent m
fs
                           mh :: SimulationAbort -> m ()
mh (SimulationAbort String
e') =
                             forall (m :: * -> *) a. Monad m => a -> m a
return ()
                       forall (m :: * -> *) a b.
MonadException m =>
Simulation m a -> Simulation m b -> Simulation m a
finallySimulation (forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
Simulation m a -> (e -> Simulation m a) -> Simulation m a
catchSimulation Simulation m ()
m1 forall {m :: * -> *}. Monad m => SimulationAbort -> m ()
mh) Simulation m ()
m2
              a
a <- [m ()] -> ExperimentMonad r m a
executor forall a b. (a -> b) -> a -> b
$
                   forall (m :: * -> *) a.
MonadDES m =>
Simulation m a -> Specs m -> Int -> [m a]
runSimulations Simulation m ()
simulate Specs m
specs Int
runCount
              forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentMonad r m ()
reporterFinalise
              forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r
-> [ExperimentReporter r m]
-> ExperimentEnvironment r m
-> ExperimentMonad r m ()
renderExperiment Experiment m
e r
r [ExperimentReporter r m]
reporters ExperimentEnvironment r m
env
              forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r -> ExperimentEnvironment r m -> ExperimentMonad r m ()
onExperimentCompleted Experiment m
e r
r ExperimentEnvironment r m
env
              forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right a
a)
         ch :: SomeException -> ExperimentMonadTry r m a
ch z :: SomeException
z@(SomeException e
e') =
           do forall r (m :: * -> *) e.
(ExperimentRendering r m, Exception e) =>
Experiment m
-> r -> ExperimentEnvironment r m -> e -> ExperimentMonad r m ()
onExperimentFailed Experiment m
e r
r ExperimentEnvironment r m
env e
e'
              forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. a -> Either a b
Left SomeException
z)
     forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
m a -> (e -> m a) -> m a
catchComp ExperimentMonadTry r m a
c1 SomeException -> ExperimentMonadTry r m a
ch

-- | Run the simulation experiment by the specified run index in series.
runExperimentByIndex :: (MonadDES m,
                         ExperimentRendering r m,
                         Monad (ExperimentMonad r m),
                         MonadException (ExperimentMonad r m))
                        => (m () -> ExperimentMonad r m a)
                        -- ^ the function that actually starts the simulation run
                        -> Experiment m
                        -- ^ the simulation experiment to run
                        -> [ExperimentGenerator r m]
                        -- ^ generators used for rendering
                        -> r
                        -- ^ the rendering backend
                        -> Simulation m (Results m)
                        -- ^ the simulation results received from the model
                        -> Int
                        -- ^ the index of the current run (started from 1)
                        -> ExperimentMonadTry r m a
{-# INLINABLE runExperimentByIndex #-}
runExperimentByIndex :: forall (m :: * -> *) r a.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
(m () -> ExperimentMonad r m a)
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> Int
-> ExperimentMonadTry r m a
runExperimentByIndex m () -> ExperimentMonad r m a
executor Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation Int
runIndex =
  do let specs :: Specs m
specs      = forall (m :: * -> *). Experiment m -> Specs m
experimentSpecs Experiment m
e
         runCount :: Int
runCount   = forall (m :: * -> *). Experiment m -> Int
experimentRunCount Experiment m
e
     ExperimentEnvironment r m
env <- forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r -> ExperimentMonad r m (ExperimentEnvironment r m)
prepareExperiment Experiment m
e r
r
     let c1 :: ExperimentMonadTry r m a
c1 =
           do [ExperimentReporter r m]
reporters <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\ExperimentGenerator r m
x -> forall r (m :: * -> *).
ExperimentGenerator r m
-> Experiment m
-> r
-> ExperimentEnvironment r m
-> ExperimentMonad r m (ExperimentReporter r m)
generateReporter ExperimentGenerator r m
x Experiment m
e r
r ExperimentEnvironment r m
env)
                           [ExperimentGenerator r m]
generators
              forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentMonad r m ()
reporterInitialise
              let simulate :: Simulation m ()
simulate =
                    do ResultPredefinedSignals m
signals <- forall (m :: * -> *).
MonadDES m =>
Simulation m (ResultPredefinedSignals m)
newResultPredefinedSignals
                       Results m
results <- Simulation m (Results m)
simulation
                       let d :: ExperimentData m
d = ExperimentData { experimentResults :: Results m
experimentResults = forall (m :: * -> *). Experiment m -> ResultTransform m
experimentTransform Experiment m
e Results m
results,
                                                experimentPredefinedSignals :: ResultPredefinedSignals m
experimentPredefinedSignals = ResultPredefinedSignals m
signals }
                       ((), DisposableEvent m
fs) <- forall (m :: * -> *) a. Dynamics m a -> Simulation m a
runDynamicsInStartTime forall a b. (a -> b) -> a -> b
$
                                   forall (m :: * -> *) a.
EventQueueing m =>
EventProcessing -> Event m a -> Dynamics m a
runEventWith EventProcessing
EarlierEvents forall a b. (a -> b) -> a -> b
$
                                   forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) a.
Composite m a
-> DisposableEvent m -> Event m (a, DisposableEvent m)
runComposite forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$
                                   forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall a b. (a -> b) -> a -> b
$ \ExperimentReporter r m
reporter ->
                                   forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentData m -> Composite m ()
reporterSimulate ExperimentReporter r m
reporter ExperimentData m
d
                       let m1 :: Simulation m ()
m1 =
                             forall (m :: * -> *) a. MonadDES m => Event m a -> Simulation m a
runEventInStopTime forall a b. (a -> b) -> a -> b
$
                             forall (m :: * -> *) a. Monad m => a -> m a
return ()
                           m2 :: Simulation m ()
m2 =
                             forall (m :: * -> *) a. MonadDES m => Event m a -> Simulation m a
runEventInStopTime forall a b. (a -> b) -> a -> b
$
                             forall (m :: * -> *). DisposableEvent m -> Event m ()
disposeEvent DisposableEvent m
fs
                           mh :: SimulationAbort -> m ()
mh (SimulationAbort String
e') =
                             forall (m :: * -> *) a. Monad m => a -> m a
return ()
                       forall (m :: * -> *) a b.
MonadException m =>
Simulation m a -> Simulation m b -> Simulation m a
finallySimulation (forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
Simulation m a -> (e -> Simulation m a) -> Simulation m a
catchSimulation Simulation m ()
m1 forall {m :: * -> *}. Monad m => SimulationAbort -> m ()
mh) Simulation m ()
m2
              a
a <- m () -> ExperimentMonad r m a
executor forall a b. (a -> b) -> a -> b
$
                   forall (m :: * -> *) a.
MonadDES m =>
Simulation m a -> Specs m -> Int -> Int -> m a
runSimulationByIndex Simulation m ()
simulate Specs m
specs Int
runCount Int
runIndex
              forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentMonad r m ()
reporterFinalise
              forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r
-> [ExperimentReporter r m]
-> ExperimentEnvironment r m
-> ExperimentMonad r m ()
renderExperiment Experiment m
e r
r [ExperimentReporter r m]
reporters ExperimentEnvironment r m
env
              forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r -> ExperimentEnvironment r m -> ExperimentMonad r m ()
onExperimentCompleted Experiment m
e r
r ExperimentEnvironment r m
env
              forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right a
a)
         ch :: SomeException -> ExperimentMonadTry r m a
ch z :: SomeException
z@(SomeException e
e') =
           do forall r (m :: * -> *) e.
(ExperimentRendering r m, Exception e) =>
Experiment m
-> r -> ExperimentEnvironment r m -> e -> ExperimentMonad r m ()
onExperimentFailed Experiment m
e r
r ExperimentEnvironment r m
env e
e'
              forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. a -> Either a b
Left SomeException
z)
     forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
m a -> (e -> m a) -> m a
catchComp ExperimentMonadTry r m a
c1 SomeException -> ExperimentMonadTry r m a
ch

-- | Run the simulation experiment by the specified run index in series.
runExperimentByIndex_ :: (MonadDES m,
                          ExperimentRendering r m,
                          Monad (ExperimentMonad r m),
                          MonadException (ExperimentMonad r m))
                         => (m () -> ExperimentMonad r m a)
                         -- ^ the function that actually starts the simulation run
                         -> Experiment m
                         -- ^ the simulation experiment to run
                         -> [ExperimentGenerator r m]
                         -- ^ generators used for rendering
                         -> r
                         -- ^ the rendering backend
                         -> Simulation m (Results m)
                         -- ^ the simulation results received from the model
                         -> Int
                         -- ^ the index of the current run (started from 1)
                         -> ExperimentMonadTry r m ()
{-# INLINABLE runExperimentByIndex_ #-}
runExperimentByIndex_ :: forall (m :: * -> *) r a.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
(m () -> ExperimentMonad r m a)
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> Int
-> ExperimentMonadTry r m ()
runExperimentByIndex_ m () -> ExperimentMonad r m a
executor Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation Int
runIndex =
  do Either SomeException a
x <- forall (m :: * -> *) r a.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
(m () -> ExperimentMonad r m a)
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> Int
-> ExperimentMonadTry r m a
runExperimentByIndex m () -> ExperimentMonad r m a
executor Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation Int
runIndex
     forall (m :: * -> *) a. Monad m => a -> m a
return (Either SomeException a
x forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return ())

-- | Run the simulation experiment by the specified run index in series
-- returning the continuation of the actual computation.
runExperimentContByIndex :: (MonadDES m,
                             ExperimentRendering r m,
                             Monad (ExperimentMonad r m),
                             MonadException (ExperimentMonad r m))
                            => (m () -> ExperimentMonad r m (a, ExperimentMonad r m b))
                            -- ^ the function that actually starts the simulation run
                            -- and returns the corresponding continuation
                            -> Experiment m
                            -- ^ the simulation experiment to run
                            -> [ExperimentGenerator r m]
                            -- ^ generators used for rendering
                            -> r
                            -- ^ the rendering backend
                            -> Simulation m (Results m)
                            -- ^ the simulation results received from the model
                            -> Int
                            -- ^ the index of the current run (started from 1)
                            -> ExperimentMonadTry r m (a, ExperimentMonadTry r m b)
{-# INLINABLE runExperimentContByIndex #-}
runExperimentContByIndex :: forall (m :: * -> *) r a b.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
(m () -> ExperimentMonad r m (a, ExperimentMonad r m b))
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> Int
-> ExperimentMonadTry r m (a, ExperimentMonadTry r m b)
runExperimentContByIndex m () -> ExperimentMonad r m (a, ExperimentMonad r m b)
executor Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation Int
runIndex =
  do let specs :: Specs m
specs      = forall (m :: * -> *). Experiment m -> Specs m
experimentSpecs Experiment m
e
         runCount :: Int
runCount   = forall (m :: * -> *). Experiment m -> Int
experimentRunCount Experiment m
e
     ExperimentEnvironment r m
env <- forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r -> ExperimentMonad r m (ExperimentEnvironment r m)
prepareExperiment Experiment m
e r
r
     let c1 :: ExperimentMonadTry r m (a, ExperimentMonadTry r m b)
c1 =
           do [ExperimentReporter r m]
reporters <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\ExperimentGenerator r m
x -> forall r (m :: * -> *).
ExperimentGenerator r m
-> Experiment m
-> r
-> ExperimentEnvironment r m
-> ExperimentMonad r m (ExperimentReporter r m)
generateReporter ExperimentGenerator r m
x Experiment m
e r
r ExperimentEnvironment r m
env)
                           [ExperimentGenerator r m]
generators
              forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentMonad r m ()
reporterInitialise
              let simulate :: Simulation m ()
simulate =
                    do ResultPredefinedSignals m
signals <- forall (m :: * -> *).
MonadDES m =>
Simulation m (ResultPredefinedSignals m)
newResultPredefinedSignals
                       Results m
results <- Simulation m (Results m)
simulation
                       let d :: ExperimentData m
d = ExperimentData { experimentResults :: Results m
experimentResults = forall (m :: * -> *). Experiment m -> ResultTransform m
experimentTransform Experiment m
e Results m
results,
                                                experimentPredefinedSignals :: ResultPredefinedSignals m
experimentPredefinedSignals = ResultPredefinedSignals m
signals }
                       ((), DisposableEvent m
fs) <- forall (m :: * -> *) a. Dynamics m a -> Simulation m a
runDynamicsInStartTime forall a b. (a -> b) -> a -> b
$
                                   forall (m :: * -> *) a.
EventQueueing m =>
EventProcessing -> Event m a -> Dynamics m a
runEventWith EventProcessing
EarlierEvents forall a b. (a -> b) -> a -> b
$
                                   forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) a.
Composite m a
-> DisposableEvent m -> Event m (a, DisposableEvent m)
runComposite forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$
                                   forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall a b. (a -> b) -> a -> b
$ \ExperimentReporter r m
reporter ->
                                   forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentData m -> Composite m ()
reporterSimulate ExperimentReporter r m
reporter ExperimentData m
d
                       let m1 :: Simulation m ()
m1 =
                             forall (m :: * -> *) a. MonadDES m => Event m a -> Simulation m a
runEventInStopTime forall a b. (a -> b) -> a -> b
$
                             forall (m :: * -> *) a. Monad m => a -> m a
return ()
                           m2 :: Simulation m ()
m2 =
                             forall (m :: * -> *) a. MonadDES m => Event m a -> Simulation m a
runEventInStopTime forall a b. (a -> b) -> a -> b
$
                             forall (m :: * -> *). DisposableEvent m -> Event m ()
disposeEvent DisposableEvent m
fs
                           mh :: SimulationAbort -> m ()
mh (SimulationAbort String
e') =
                             forall (m :: * -> *) a. Monad m => a -> m a
return ()
                       forall (m :: * -> *) a b.
MonadException m =>
Simulation m a -> Simulation m b -> Simulation m a
finallySimulation (forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
Simulation m a -> (e -> Simulation m a) -> Simulation m a
catchSimulation Simulation m ()
m1 forall {m :: * -> *}. Monad m => SimulationAbort -> m ()
mh) Simulation m ()
m2
              (a
a, ExperimentMonad r m b
m) <- m () -> ExperimentMonad r m (a, ExperimentMonad r m b)
executor forall a b. (a -> b) -> a -> b
$
                        forall (m :: * -> *) a.
MonadDES m =>
Simulation m a -> Specs m -> Int -> Int -> m a
runSimulationByIndex Simulation m ()
simulate Specs m
specs Int
runCount Int
runIndex
              let m2 :: ExperimentMonadTry r m b
m2 =
                    do b
b <- ExperimentMonad r m b
m
                       forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExperimentReporter r m]
reporters forall r (m :: * -> *).
ExperimentReporter r m -> ExperimentMonad r m ()
reporterFinalise
                       forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r
-> [ExperimentReporter r m]
-> ExperimentEnvironment r m
-> ExperimentMonad r m ()
renderExperiment Experiment m
e r
r [ExperimentReporter r m]
reporters ExperimentEnvironment r m
env
                       forall r (m :: * -> *).
ExperimentRendering r m =>
Experiment m
-> r -> ExperimentEnvironment r m -> ExperimentMonad r m ()
onExperimentCompleted Experiment m
e r
r ExperimentEnvironment r m
env
                       forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right b
b)
                  mh :: SomeException -> ExperimentMonadTry r m b
mh z :: SomeException
z@(SomeException e
e') =
                    do forall r (m :: * -> *) e.
(ExperimentRendering r m, Exception e) =>
Experiment m
-> r -> ExperimentEnvironment r m -> e -> ExperimentMonad r m ()
onExperimentFailed Experiment m
e r
r ExperimentEnvironment r m
env e
e'
                       forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. a -> Either a b
Left SomeException
z)
              forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right (a
a, forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
m a -> (e -> m a) -> m a
catchComp ExperimentMonadTry r m b
m2 SomeException -> ExperimentMonadTry r m b
mh))
         ch :: SomeException
-> ExperimentMonadTry r m (a, ExperimentMonadTry r m b)
ch z :: SomeException
z@(SomeException e
e') =
           do forall r (m :: * -> *) e.
(ExperimentRendering r m, Exception e) =>
Experiment m
-> r -> ExperimentEnvironment r m -> e -> ExperimentMonad r m ()
onExperimentFailed Experiment m
e r
r ExperimentEnvironment r m
env e
e'
              forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. a -> Either a b
Left SomeException
z)
     forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
m a -> (e -> m a) -> m a
catchComp ExperimentMonadTry r m (a, ExperimentMonadTry r m b)
c1 SomeException
-> ExperimentMonadTry r m (a, ExperimentMonadTry r m b)
ch

-- | Run the simulation experiment by the specified run index in series
-- returning the continuation of the actual computation.
runExperimentContByIndex_ :: (MonadDES m,
                              ExperimentRendering r m,
                              Monad (ExperimentMonad r m),
                              MonadException (ExperimentMonad r m))
                             => (m () -> ExperimentMonad r m (a, ExperimentMonad r m b))
                             -- ^ the function that actually starts the simulation run
                             -- and returns the corresponding continuation
                             -> Experiment m
                             -- ^ the simulation experiment to run
                             -> [ExperimentGenerator r m]
                             -- ^ generators used for rendering
                             -> r
                             -- ^ the rendering backend
                             -> Simulation m (Results m)
                             -- ^ the simulation results received from the model
                             -> Int
                             -- ^ the index of the current run (started from 1)
                             -> ExperimentMonadTry r m (a, ExperimentMonadTry r m ())
{-# INLINABLE runExperimentContByIndex_ #-}
runExperimentContByIndex_ :: forall (m :: * -> *) r a b.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
(m () -> ExperimentMonad r m (a, ExperimentMonad r m b))
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> Int
-> ExperimentMonadTry r m (a, ExperimentMonadTry r m ())
runExperimentContByIndex_ m () -> ExperimentMonad r m (a, ExperimentMonad r m b)
executor Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation Int
runIndex =
  do Either
  SomeException (a, ExperimentMonad r m (Either SomeException b))
x <- forall (m :: * -> *) r a b.
(MonadDES m, ExperimentRendering r m, Monad (ExperimentMonad r m),
 MonadException (ExperimentMonad r m)) =>
(m () -> ExperimentMonad r m (a, ExperimentMonad r m b))
-> Experiment m
-> [ExperimentGenerator r m]
-> r
-> Simulation m (Results m)
-> Int
-> ExperimentMonadTry r m (a, ExperimentMonadTry r m b)
runExperimentContByIndex m () -> ExperimentMonad r m (a, ExperimentMonad r m b)
executor Experiment m
e [ExperimentGenerator r m]
generators r
r Simulation m (Results m)
simulation Int
runIndex
     case Either
  SomeException (a, ExperimentMonad r m (Either SomeException b))
x of
       Left SomeException
e -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. a -> Either a b
Left SomeException
e)
       Right (a
a, ExperimentMonad r m (Either SomeException b)
cont) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right (a
a, ExperimentMonad r m (Either SomeException b)
cont forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right ()))