experimenter-0.1.0.0: src/Experimenter/Result/Query.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Strict #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Experimenter.Result.Query
( loadExperiments
, loadExperimentResults
, loadExperimentsResults
, loadPreparationInputWhere
, loadPreparationMeasuresWhere
, loadPreparationAggregateWhere
, loadReplicationWarmUpInputWhere
, loadReplicationWarmUpMeasuresWhere
, loadReplicationWarmUpAggregateWhere
, loadReplicationInputWhere
, loadReplicationMeasuresWhere
, loadReparationAggregateWhere
, loadResDataEndState
, loadResDataStartState
, loadParamSetup
, deserialise
, mDeserialise
, setParams
, fromRandGen
, toRandGen
, serialiseSeed
, deserialiseSeed
, StartStateType (..)
, EndStateType (..)
, setResDataStartState
, setResDataEndState
) where
import Conduit as C
import Control.DeepSeq
import Control.Lens (view)
import Control.Monad.Logger
import Control.Monad.Reader
import Control.Monad.Trans.Maybe
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.Conduit.List as CL
import Data.Either (isLeft)
import Data.Function (on)
import qualified Data.List as L
import Data.Maybe (fromMaybe)
import Data.Serialize as S (Serialize, get, put, runGet, runPut)
import qualified Data.Text as T
import Data.Time (getCurrentTime)
import Data.Vector.Serialize ()
import qualified Data.Vector.Unboxed as V
import Data.Word (Word32)
import qualified Database.Esqueleto as E
import Database.Persist as P
import Database.Persist.Postgresql (SqlBackend)
import Database.Persist.Sql (transactionSave)
import Prelude hiding (exp)
import System.Random.MWC
import Experimenter.Availability
import Experimenter.DB
import Experimenter.Experiment
import Experimenter.Input
import Experimenter.Measure
import Experimenter.Models
import Experimenter.Parameter
import Experimenter.Result.Type
import Experimenter.Setting
import Experimenter.StepResult
import Experimenter.Util
data EndStateType
= EndStatePrep !(Key PrepResultData)
| EndStateWarmUp !(Key WarmUpResultData)
| EndStateRep !(Key RepResultData)
data StartStateType
= StartStatePrep !(Key PrepResultData)
| StartStateWarmUp !(Key WarmUpResultData)
| StartStateRep !(Key RepResultData)
loadExperimentsResults :: (ExperimentDef a) => ExperimentSetting -> InputState a -> a -> Key Exps -> DB (ExpM a) (Maybe (Experiments a))
loadExperimentsResults setup initInpSt initSt key =
runMaybeT $ do
e <- MaybeT $ P.get key
exps <- lift (L.sortBy (compare `on` view experimentNumber) <$> loadExperimentList key)
expInfoParams <- lift (map entityVal <$> selectList [ExpsInfoParamExps ==. key] [])
eSetup <- lift (fromMaybe (error "Setup not found. Your DB is corrupted!") <$> getBy (UniqueExpsSetup key))
infoParms <- lift (mapM fromInfoParam expInfoParams)
return $
Experiments
key
(view expsName e)
(view expsStartTime e)
(view expsEndTime e)
(entityVal eSetup)
(parameters initSt)
(concat infoParms)
initSt
initInpSt
exps
where
infoParams = view experimentInfoParameters setup
fromInfoParam (ExpsInfoParam _ n bs) =
case L.find ((== n) . infoParameterName) infoParams of
Nothing -> do
$(logDebug) $ "Could not find parameter " <> n <> " in settings while loading values from the DB. It will not be reported therefore!"
return []
Just (ExperimentInfoParameter _ v) -> return [ExperimentInfoParameter n (fromEitherDef v $ S.runGet S.get bs)]
fromEitherDef _ (Right x) = x
fromEitherDef d (Left _) = d
loadExperiments :: (ExperimentDef a) => ExperimentSetting -> InputState a -> a -> DB (ExpM a) (Experiments a)
loadExperiments setup initInpSt initSt = do
eExp <- getOrCreateExps setup initInpSt initSt
let e = entityVal eExp
exps <- L.sortBy (compare `on` view experimentNumber) <$> loadExperimentList (entityKey eExp)
eSetup <- fromMaybe (error "Setup not found. Your DB is corrupted!") <$> getBy (UniqueExpsSetup (entityKey eExp))
return $!!
Experiments
(entityKey eExp)
(view expsName e)
(view expsStartTime e)
(view expsEndTime e)
(entityVal eSetup)
(parameters initSt)
(view experimentInfoParameters setup)
initSt
initInpSt
exps
loadExperimentList :: (ExperimentDef a) => Key Exps -> DB (ExpM a) [Experiment a]
loadExperimentList expsKey = selectList [ExpExps ==. expsKey] [] >>= mapM mkExperiment
where mkExperiment (Entity k exp) = do
paramSetting <- loadParamSetup k
Experiment k (view expNumber exp) (view expStartTime exp) (view expEndTime exp) paramSetting <$> loadExperimentResults k
mDeserialise :: (MonadIO m, MonadLogger m ,Serialize a) => T.Text -> Maybe ByteString -> m (Maybe (Maybe a))
mDeserialise n mBs = sequence (deserialise n <$> mBs)
deserialise :: (MonadIO m, MonadLogger m, Serialize a) => T.Text -> ByteString -> m (Maybe a)
deserialise n bs =
let !res = runGet S.get bs
in case res of
Left err -> do
$(logError) $ "Could not deserialise " <> n <> "! Discarding saved experiment result. Data length: " <> tshow (B.length bs) <> ". Error Message: " <> tshow err
return Nothing
Right r -> return $! Just r
loadExperimentResults :: (ExperimentDef a) => Key Exp -> DB (ExpM a) [ExperimentResult a]
loadExperimentResults kExp = do
xs <- selectList [ExpResultExp ==. kExp] [Asc ExpResultRepetition]
mapM loadExperimentResult xs
loadResDataEndState ::
forall a. (ExperimentDef a)
=> Key Exp
-> EndStateType
-> DB (ExpM a) (Maybe a)
loadResDataEndState expId endSt = do
!parts <-
fmap force $!
case endSt of
EndStatePrep k -> fmap (view prepEndStatePartData . entityVal) <$> selectList [PrepEndStatePartResultData ==. k] [Asc PrepEndStatePartNumber]
EndStateWarmUp k -> fmap (view warmUpEndStatePartData . entityVal) <$> selectList [WarmUpEndStatePartResultData ==. k] [Asc WarmUpEndStatePartNumber]
EndStateRep k -> fmap (view repEndStatePartData . entityVal) <$> selectList [RepEndStatePartResultData ==. k] [Asc RepEndStatePartNumber]
!res <-
if null parts
then return Nothing
else do
!mSer <- deserialise (T.pack "end state") (B.concat parts)
lift $! lift $! lift $! maybe (return Nothing) (fmap Just . deserialisable) mSer
force <$!> traverse (setParams expId) res
loadResDataStartState :: (ExperimentDef a) => Key Exp -> StartStateType -> DB (ExpM a) a
loadResDataStartState expId startSt = do
!parts <-
fmap force $!
case startSt of
StartStatePrep k -> fmap (view prepStartStatePartData . entityVal) <$> selectList [PrepStartStatePartResultData ==. k] [Asc PrepStartStatePartNumber]
StartStateWarmUp k -> fmap (view warmUpStartStatePartData . entityVal) <$> selectList [WarmUpStartStatePartResultData ==. k] [Asc WarmUpStartStatePartNumber]
StartStateRep k -> fmap (view repStartStatePartData . entityVal) <$> selectList [RepStartStatePartResultData ==. k] [Asc RepStartStatePartNumber]
!res <-
if null parts
then error "Could not get start state"
else do
!ser <- fromMaybe (error "Could not deserialise start state ") <$> deserialise "prep start state" (B.concat parts)
lift $! lift $! lift $! deserialisable ser
force <$!> setParams expId res
setResDataEndState :: (MonadIO m) => EndStateType -> Maybe ByteString -> ReaderT SqlBackend m ()
setResDataEndState (EndStatePrep k) (Just bs) = do
-- liftIO $ B.writeFile "/tmp/EndState" bs
let parts = splitState bs
mapM_ (\(nr, part) -> upsert (PrepEndStatePart k nr part) [PrepEndStatePartData =. part]) (zip [0..] parts)
deleteWhere [PrepEndStatePartResultData ==. k, PrepEndStatePartNumber >=. length parts]
setResDataEndState (EndStateWarmUp k) (Just bs) = do
let parts = splitState bs
mapM_ (\(nr, part) -> upsert (WarmUpEndStatePart k nr part) [WarmUpEndStatePartData =. part]) (zip [0..] parts)
deleteWhere [WarmUpEndStatePartResultData ==. k, WarmUpEndStatePartNumber >=. length parts]
setResDataEndState (EndStateRep k) (Just bs) = do
let parts = splitState bs
mapM_ (\(nr, part) -> upsert (RepEndStatePart k nr part) [RepEndStatePartData =. part]) (zip [0..] parts)
deleteWhere [RepEndStatePartResultData ==. k, RepEndStatePartNumber >=. length parts]
setResDataEndState (EndStatePrep k) Nothing = deleteWhere [PrepEndStatePartResultData ==. k]
setResDataEndState (EndStateWarmUp k) Nothing = deleteWhere [WarmUpEndStatePartResultData ==. k]
setResDataEndState (EndStateRep k) Nothing = deleteWhere [RepEndStatePartResultData ==. k]
setResDataStartState :: (MonadIO m) => StartStateType -> ByteString -> ReaderT SqlBackend m ()
setResDataStartState (StartStatePrep k) bs = do
let parts = splitState bs
mapM_ (\(nr, part) -> upsert (PrepStartStatePart k nr part) [PrepStartStatePartData =. part]) (zip [0..] parts)
deleteWhere [PrepStartStatePartResultData ==. k, PrepStartStatePartNumber >=. length parts]
setResDataStartState (StartStateWarmUp k) bs = do
let parts = splitState bs
mapM_ (\(nr, part) -> upsert (WarmUpStartStatePart k nr part) [WarmUpStartStatePartData =. part]) (zip [0..] parts)
deleteWhere [WarmUpStartStatePartResultData ==. k, WarmUpStartStatePartNumber >=. length parts]
setResDataStartState (StartStateRep k) bs = do
let parts = splitState bs
mapM_ (\(nr, part) -> upsert (RepStartStatePart k nr part) [RepStartStatePartData =. part]) (zip [0..] parts)
deleteWhere [RepStartStatePartResultData ==. k, RepStartStatePartNumber >=. length parts]
splitState :: ByteString -> [ByteString]
splitState bs
| B.null bs = []
| otherwise = B.take splitLength bs : splitState (B.drop splitLength bs)
where
splitLength = 128000000 -- 128MB as ByteString is composed of Word8 (8-bit unsigned integer = 1 byte) elements
setParams :: (MonadIO m, MonadLogger m, ExperimentDef a) => Key Exp -> a -> ReaderT SqlBackend m a
setParams expId st = do
paramSettings <- loadParamSetup expId
foldM setParams' st paramSettings
where setParams' !state !(ParameterSetting n bs _ _) =
case L.find (\(ParameterSetup name _ _ _ _ _ _) -> name == n) paramSetup of
Nothing -> do
$(logError) $ "Could not find parameter with name " <> n <> " in the current parameter setting. Thus it cannot be modified!"
return state
Just (ParameterSetup _ setter _ _ _ _ _) ->
case runGet S.get bs of
Left err -> error $ "Could not read value of parameter " <> T.unpack n <> ". Aborting! Serializtion error was: " ++ err
Right val -> do
$(logInfo) $ "Loaded parameter '" <> n <> "' value: " <> tshow val
return $ setter val state
paramSetup = parameters st
loadExperimentResult :: forall a . (ExperimentDef a) => Entity ExpResult -> DB (ExpM a) (ExperimentResult a)
loadExperimentResult (Entity k (ExpResult expId rep mPrepResDataId)) = do
!mEPrepResData <- fmap join $ sequence $ P.getEntity <$> mPrepResDataId
!prepRes <-
case mEPrepResData of
Nothing -> return Nothing
Just (Entity resDataKey (PrepResultData startT endT startRandGenBS endRandGenBS startInpStBS endInpStBS)) -> do
let !startSt = AvailableOnDemand (loadResDataStartState expId (StartStatePrep resDataKey))
let !endSt = AvailableOnDemand (loadResDataEndState expId (EndStatePrep resDataKey))
!mStartInpSt <- deserialise "prep start input state" startInpStBS
!mEndInpSt <- mDeserialise "prep end input state" endInpStBS
!inpCount <- loadPreparationInputCount resDataKey
!resultCount <- loadPrepartionMeasuresCount resDataKey
!startRandG <- toRandGen startRandGenBS
!endRandG <- maybe (return Nothing) (fmap Just . toRandGen) endRandGenBS
let !inputVals = AvailableListOnDemand (inpCount, loadPreparationInputWhere resDataKey)
let !res = AvailableListOnDemand (resultCount, loadPreparationMeasuresWhere resDataKey)
return $!! ResultData (ResultDataPrep resDataKey) startT endT startRandG endRandG inputVals res startSt endSt <$> mStartInpSt <*> mEndInpSt
!evalRes <- loadReplicationResults expId k
return $!! ExperimentResult k rep prepRes evalRes
serialiseSeed :: Seed -> ByteString
serialiseSeed seed = S.runPut $ S.put (fromSeed seed :: V.Vector Word32)
deserialiseSeed :: ByteString -> Seed
deserialiseSeed bs = toSeed (fromRight $ S.runGet S.get bs :: V.Vector Word32)
where fromRight (Right s) = s
fromRight (Left err) = error $ "Could not deserialise random generator. Error Message: " <> err
fromRandGen :: (MonadIO m) => GenIO -> m ByteString
fromRandGen ran = do
vec <- liftIO (fromSeed <$> save ran)
return $ S.runPut (S.put vec)
toRandGen :: (MonadIO m) => ByteString -> m GenIO
toRandGen bs =
case S.runGet S.get bs of
Left err -> error $ "Could not deserialise random generator. Error Message: " <> err
Right (vec :: V.Vector Word32) -> liftIO (restore $ toSeed vec)
loadParamSetup :: (MonadIO m) => Key Exp -> ReaderT SqlBackend m [ParameterSetting a1]
loadParamSetup kExp =
L.sortBy (compare `on` view parameterSettingName) . map (mkParameterSetting' . entityVal) <$>
E.select (E.from $ \pm -> E.where_ (pm E.^. ParamSettingExp E.==. E.val kExp) >> return pm)
where
mkParameterSetting' (ParamSetting _ n v b design) = ParameterSetting n v b (toEnum design)
-- fromCount :: [E.Value Int] -> Int
-- fromCount = fromMaybe 0 . listToMaybe . fmap (\(E.Value v) -> v)
loadPreparationInputCount :: (MonadIO m) => Key PrepResultData -> ReaderT SqlBackend m Int
loadPreparationInputCount kExpRes = count [PrepInputPrepResultData ==. kExpRes]
loadPreparationInputWhere :: (MonadIO m, ExperimentDef a) => Key PrepResultData -> AvailabilityListWhere -> ConduitM () (Input a) (DB m) ()
loadPreparationInputWhere kExpRes (PrepInputWhere where') = do
let src =
E.selectSource $
E.from $ \(prepI, prepIV) -> do
E.where_ (prepI E.^. PrepInputId E.==. prepIV E.^. PrepInputValuePrepInput)
E.where_ (prepI E.^. PrepInputPrepResultData E.==. E.val kExpRes)
where' prepI prepIV
return (prepI, prepIV)
src C..| C.mapMC mkInput C..| sequenceC []
-- sequence <$> mapM mkInput res
where
mkInput :: (MonadIO m, MonadLogger m, ExperimentDef a) => (Entity PrepInput, Entity PrepInputValue) -> m (Maybe (Input a))
mkInput (Entity _ (PrepInput _ p), Entity _ (PrepInputValue _ v)) = do
v' <- deserialise "prep input value" v
return $ Input p <$> v'
loadPreparationInputWhere kExpRes GetAll = loadPreparationInputWhere kExpRes (PrepInputWhere (\_ _ -> return ()))
loadPreparationInputWhere _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where PrepInputWhere was expected"
sequenceC :: Monad m => [Maybe o] -> ConduitT (Maybe o) o m ()
sequenceC xs = do
mx <- await
case mx of
Nothing -> CL.sourceList (fromMaybe [] $ sequence $ reverse xs)
Just x -> sequenceC (x:xs)
loadPrepartionMeasuresCount :: (MonadIO m) => Key PrepResultData -> DB m Int
loadPrepartionMeasuresCount kExpRes = count [PrepMeasurePrepResultData ==. kExpRes]
-- loadPrepartionMeasures :: (MonadIO m) => Key PrepResultData -> ConduitT () Measure (DB m) ()
-- loadPrepartionMeasures = loadPrepartionMeasuresWith (\_ _ -> return ())
loadPreparationMeasuresWhere :: (MonadIO m) => Key PrepResultData -> AvailabilityListWhere -> ConduitT () Measure (DB m) ()
loadPreparationMeasuresWhere kExpRes (PrepMeasureWhere where') = do
let src =
E.selectSource $
E.from $ \(prepM, prepRS) -> do
E.where_ (prepM E.^. PrepMeasureId E.==. prepRS E.^. PrepResultStepMeasure)
E.where_ (prepM E.^. PrepMeasurePrepResultData E.==. E.val kExpRes)
where' prepM prepRS
E.orderBy [E.asc (prepM E.^. PrepMeasurePeriod)]
return (prepM, prepRS)
src C..| C.mapC mkMeasure C..| CL.groupBy ((==) `on` view measurePeriod) C..| C.mapC combineMeasures
-- return $ map combineMeasures $ L.groupBy ((==) `on` view measurePeriod) $ map mkMeasure res
where
mkMeasure (Entity _ (PrepMeasure _ p), Entity _ (PrepResultStep _ n x y)) = Measure p [StepResult n x y]
combineMeasures xs@(Measure p _:_) = Measure p (concatMap (view measureResults) xs)
combineMeasures _ = error "not possible"
loadPreparationMeasuresWhere kExpRes GetAll = loadPreparationMeasuresWhere kExpRes (PrepMeasureWhere (\_ _ -> return ()))
loadPreparationMeasuresWhere _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where PrepMeasuresWhere was expected"
loadPreparationAggregateWhere :: (MonadIO m) => Key PrepResultData -> AggregateFunction -> AvailabilityListWhere -> DB m Double
loadPreparationAggregateWhere kExpRes agg (PrepMeasureWhere where') =
fmap (fromMaybe 0 . E.unValue . head) $
E.select $
E.from $ \(prepM, prepRS) -> do
E.where_ (prepM E.^. PrepMeasureId E.==. prepRS E.^. PrepResultStepMeasure)
E.where_ (prepM E.^. PrepMeasurePrepResultData E.==. E.val kExpRes)
where' prepM prepRS
return (agg $ prepRS E.^. PrepResultStepYValue)
loadPreparationAggregateWhere kExpRes agg GetAll = loadPreparationAggregateWhere kExpRes agg (PrepMeasureWhere (\_ _ -> return ()))
loadPreparationAggregateWhere _ _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where loadPreparationAggregateWhere was expected"
loadReplicationResults :: (ExperimentDef a) => Key Exp -> Key ExpResult -> DB (ExpM a) [ReplicationResult a]
loadReplicationResults expId kExpRes = do
xs <- selectList [RepResultExpResult ==. kExpRes] [Asc RepResultRepNr]
mapM (loadReplicationResult expId) xs
loadReplicationResult :: (ExperimentDef a) => Key Exp -> Entity RepResult -> DB (ExpM a) (ReplicationResult a)
loadReplicationResult expId (Entity k (RepResult _ repNr mWmUpResId mRepResId)) = do
!mWmUpRes <- fmap join $ sequence $ P.getEntity <$> mWmUpResId
!mRepRes <- fmap join $ sequence $ P.getEntity <$> mRepResId
!wmUp <-
case mWmUpRes of
Nothing -> return Nothing
Just eWmUp -> mkWmUp eWmUp
!rep <-
case mRepRes of
Nothing -> return Nothing
Just eRep -> mkRep eRep
return $!! ReplicationResult k repNr wmUp rep
where
mkWmUp (Entity wmUpResKey wmUpRes) = do
let wmUpStartTime = view warmUpResultDataStartTime wmUpRes
let wmUpEndTime = view warmUpResultDataEndTime wmUpRes
!wmUpStartRandGen <- toRandGen (view warmUpResultDataStartRandGen wmUpRes)
!wmUpEndRandGen <- maybe (return Nothing) (fmap Just . toRandGen) (view warmUpResultDataEndRandGen wmUpRes)
let !wmUpStartSt = AvailableOnDemand (loadResDataStartState expId (StartStateWarmUp wmUpResKey))
let !wmUpEndSt = AvailableOnDemand (loadResDataEndState expId (EndStateWarmUp wmUpResKey))
!mWmUpStartInpSt <- deserialise "warm up start input state" (view warmUpResultDataStartInputState wmUpRes)
!mWmUpEndInpSt <- mDeserialise "warm up end input state" (view warmUpResultDataEndInputState wmUpRes)
!wmUpInpValsCount <- loadReplicationWarmUpInputCount wmUpResKey
!wmUpMeasuresCount <- loadReplicationWarmUpMeasuresCount wmUpResKey
let !wmUpInpVals = AvailableListOnDemand (wmUpInpValsCount, loadReplicationWarmUpInputWhere wmUpResKey)
!wmUpMeasures = AvailableListOnDemand (wmUpMeasuresCount, loadReplicationWarmUpMeasuresWhere wmUpResKey)
return $!
ResultData (ResultDataWarmUp wmUpResKey) wmUpStartTime wmUpEndTime wmUpStartRandGen wmUpEndRandGen wmUpInpVals wmUpMeasures wmUpStartSt wmUpEndSt <$> mWmUpStartInpSt <*>
mWmUpEndInpSt
mkRep (Entity repResKey repRes) = do
let repStartTime = view repResultDataStartTime repRes
let repEndTime = view repResultDataEndTime repRes
!repStartRandGen <- toRandGen (view repResultDataStartRandGen repRes)
!repEndRandGen <- maybe (return Nothing) (fmap Just . toRandGen) (view repResultDataEndRandGen repRes)
!mRepStartInpSt <- deserialise "rep start input state" (view repResultDataStartInputState repRes)
!mRepEndInpSt <- mDeserialise "rep end input state" (view repResultDataEndInputState repRes)
!repInpValsCount <- loadReplicationInputCount repResKey
!repMeasuresCount <- loadReplicationMeasuresCount repResKey
let !repInpVals = AvailableListOnDemand (repInpValsCount, loadReplicationInputWhere repResKey)
!repMeasures = AvailableListOnDemand (repMeasuresCount, loadReplicationMeasuresWhere repResKey)
let !repStartSt = AvailableOnDemand (loadResDataStartState expId (StartStateRep repResKey))
let !repEndSt = AvailableOnDemand (loadResDataEndState expId (EndStateRep repResKey))
return $!
ResultData (ResultDataRep repResKey) repStartTime repEndTime repStartRandGen repEndRandGen repInpVals repMeasures repStartSt repEndSt <$> mRepStartInpSt <*> mRepEndInpSt
loadReplicationWarmUpInputCount :: (MonadIO m) => Key WarmUpResultData -> ReaderT SqlBackend m Int
loadReplicationWarmUpInputCount kExpRes = count [WarmUpInputRepResult ==. kExpRes]
loadReplicationWarmUpInputWhere :: (ExperimentDef a, MonadIO m) => Key WarmUpResultData -> AvailabilityListWhere -> ConduitT () (Input a) (DB m) ()
loadReplicationWarmUpInputWhere kExpRes (WarmUpInputWhere where') = do
let src =
E.selectSource $
E.from $ \(warmUpI, warmUpIV) -> do
E.where_ (warmUpI E.^. WarmUpInputId E.==. warmUpIV E.^. WarmUpInputValueWarmUpInput)
E.where_ (warmUpI E.^. WarmUpInputRepResult E.==. E.val kExpRes)
where' warmUpI warmUpIV
return (warmUpI, warmUpIV)
src C..| C.mapMC mkInput C..| sequenceC []
-- sequence <$> mapM mkInput res
where
mkInput (Entity _ (WarmUpInput _ p), Entity _ (WarmUpInputValue _ v)) = do
v' <- deserialise "warm up input value" v
return $ Input p <$> v'
loadReplicationWarmUpInputWhere kExpRes GetAll = loadReplicationWarmUpInputWhere kExpRes (WarmUpInputWhere (\_ _ -> return ()))
loadReplicationWarmUpInputWhere _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where PrepInputWhere was expected"
loadReplicationWarmUpMeasuresCount :: (MonadIO m) => Key WarmUpResultData -> ReaderT SqlBackend m Int
loadReplicationWarmUpMeasuresCount kExpRes = count [WarmUpMeasureRepResult ==. kExpRes]
loadReplicationWarmUpMeasuresWhere :: (MonadIO m) => Key WarmUpResultData -> AvailabilityListWhere -> ConduitM () Measure (DB m) ()
loadReplicationWarmUpMeasuresWhere kExpRes (WarmUpMeasureWhere where') = do
let src =
E.selectSource $
E.from $ \(warmUpM, warmUpRS) -> do
E.where_ (warmUpM E.^. WarmUpMeasureId E.==. warmUpRS E.^. WarmUpResultStepMeasure)
E.where_ (warmUpM E.^. WarmUpMeasureRepResult E.==. E.val kExpRes)
where' warmUpM warmUpRS
E.orderBy [E.asc (warmUpM E.^. WarmUpMeasurePeriod)]
return (warmUpM, warmUpRS)
src C..| C.mapC mkMeasure C..| CL.groupBy ((==) `on` view measurePeriod) C..| C.mapC combineMeasures
where
mkMeasure (Entity _ (WarmUpMeasure _ p), Entity _ (WarmUpResultStep _ n x y)) = Measure p [StepResult n x y]
combineMeasures xs@(Measure p _:_) = Measure p (concatMap (view measureResults) xs)
combineMeasures _ = error "not possible"
loadReplicationWarmUpMeasuresWhere kExpRes GetAll = loadReplicationWarmUpMeasuresWhere kExpRes (WarmUpMeasureWhere (\_ _ -> return ()))
loadReplicationWarmUpMeasuresWhere _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where PrepMeasuresWhere was expected"
loadReplicationWarmUpAggregateWhere :: (MonadIO m) => Key WarmUpResultData -> AggregateFunction -> AvailabilityListWhere -> DB m Double
loadReplicationWarmUpAggregateWhere kExpRes agg (WarmUpMeasureWhere where') =
fmap (fromMaybe 0 . E.unValue . head) $
E.select $
E.from $ \(warmUpM, warmUpRS) -> do
E.where_ (warmUpM E.^. WarmUpMeasureId E.==. warmUpRS E.^. WarmUpResultStepMeasure)
E.where_ (warmUpM E.^. WarmUpMeasureRepResult E.==. E.val kExpRes)
where' warmUpM warmUpRS
return (agg $ warmUpRS E.^. WarmUpResultStepYValue)
loadReplicationWarmUpAggregateWhere kExpRes agg GetAll = loadReplicationWarmUpAggregateWhere kExpRes agg (WarmUpMeasureWhere (\_ _ -> return ()))
loadReplicationWarmUpAggregateWhere _ _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where loadReplicationWarmUpAggregateWhere was expected"
loadReplicationInputCount :: (MonadIO m) => Key RepResultData -> ReaderT SqlBackend m Int
loadReplicationInputCount kExpRes = count [RepInputRepResult ==. kExpRes]
loadReplicationInputWhere :: (ExperimentDef a, MonadIO m) => Key RepResultData -> AvailabilityListWhere -> ConduitT () (Input a) (DB m) ()
loadReplicationInputWhere kExpRes (RepInputWhere where') = do
let src =
E.selectSource $
E.from $ \(repI, repIV) -> do
E.where_ (repI E.^. RepInputId E.==. repIV E.^. RepInputValueRepInput)
E.where_ (repI E.^. RepInputRepResult E.==. E.val kExpRes)
where' repI repIV
return (repI, repIV)
src C..| C.mapMC mkInput C..| sequenceC []
-- sequence <$> mapM mkInput res
where
mkInput (Entity _ (RepInput _ p), Entity _ (RepInputValue _ v)) = do
v' <- deserialise "eval input value" v
return $ Input p <$> v'
loadReplicationInputWhere kExpRes GetAll = loadReplicationInputWhere kExpRes (RepInputWhere (\_ _ -> return ()))
loadReplicationInputWhere _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where RepInputWhere was expected"
loadReplicationMeasuresCount :: (MonadIO m) => Key RepResultData -> ReaderT SqlBackend m Int
loadReplicationMeasuresCount kExpRes = count [RepMeasureRepResult ==. kExpRes]
loadReplicationMeasuresWhere :: (MonadIO m) => Key RepResultData -> AvailabilityListWhere -> ConduitT () Measure (DB m) ()
loadReplicationMeasuresWhere kExpRes (RepMeasureWhere where') = do
let src =
E.selectSource $
E.from $ \(repM, repRS) -> do
E.where_ (repM E.^. RepMeasureId E.==. repRS E.^. RepResultStepMeasure)
E.where_ (repM E.^. RepMeasureRepResult E.==. E.val kExpRes)
where' repM repRS
E.orderBy [E.asc (repM E.^. RepMeasurePeriod)]
return (repM, repRS)
src C..| C.mapC mkMeasure C..| CL.groupBy ((==) `on` view measurePeriod) C..| C.mapC combineMeasures
where
mkMeasure (Entity _ (RepMeasure _ p), Entity _ (RepResultStep _ n x y)) = Measure p [StepResult n x y]
combineMeasures xs@(Measure p _:_) = Measure p (concatMap (view measureResults) xs)
combineMeasures _ = error "not possible"
loadReplicationMeasuresWhere kExpRes GetAll = loadReplicationMeasuresWhere kExpRes (RepMeasureWhere (\_ _ -> return ()))
loadReplicationMeasuresWhere _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where RepMeasuresWhere was expected"
loadReparationAggregateWhere :: (MonadIO m) => Key RepResultData -> AggregateFunction -> AvailabilityListWhere -> DB m Double
loadReparationAggregateWhere kExpRes agg (RepMeasureWhere where') =
fmap (fromMaybe 0 . E.unValue . head) $
E.select $
E.from $ \(repM, repRS) -> do
E.where_ (repM E.^. RepMeasureId E.==. repRS E.^. RepResultStepMeasure)
E.where_ (repM E.^. RepMeasureRepResult E.==. E.val kExpRes)
where' repM repRS
return (agg $ repRS E.^. RepResultStepYValue)
loadReparationAggregateWhere kExpRes agg GetAll = loadReparationAggregateWhere kExpRes agg (RepMeasureWhere (\_ _ -> return ()))
loadReparationAggregateWhere _ _ where' = error $ "Wrong Where clause: " ++ show where' ++ " where RepAggregateWhere was expected"
getOrCreateExps :: forall a . (ExperimentDef a) => ExperimentSetting -> InputState a -> a -> DB (ExpM a) (Entity Exps)
getOrCreateExps setup initInpSt initSt = do
let name = view experimentBaseName setup
expsList <- selectList [ExpsName ==. name] []
expsInfoParams <- map (map entityVal) <$> mapM (\(Entity e _) -> selectList [ExpsInfoParamExps ==. e] []) expsList
let expsList' = map fst $ filter ((\xs -> length infoParams >= length xs && all matchesExpsInfoParam xs) . snd) (zip expsList expsInfoParams)
when (null expsList') $ $(logInfo) "No experiment with same Experiment Info Parameters found!"
exps <-
filterM
(\(Entity _ (Exps _ _ _ s iS)) -> do
serSt <- lift $ lift $ lift $ sequence $ deserialisable <$> runGet S.get s
let other = (,) <$> serSt <*> runGet S.get iS
when (isLeft other) $ $(logInfo) "Could not deserialise experiment with same name"
return $ fromEither False (equalExperiments (initSt, initInpSt) <$> other))
expsList'
when (not (null expsList') && null exps) $ $(logInfo) "Found experiments with same name, but the are different or not deserialisable!"
params <- mapM (\e -> selectList [ParamExps ==. entityKey e] [Asc ParamName]) exps
let mkParamTpl (Param _ n _ _) = n
let ~myParams = L.sort $ map (mkParamTpl . convertParameterSetup (entityKey (head exps))) (parameters initSt)
case L.find ((== myParams) . L.sort . map (mkParamTpl . entityVal) . snd) (zip exps params) of
Nothing -> do
$(logInfo) "Starting new experiment..."
time <- liftIO getCurrentTime
!serInitSt <- lift $ lift $ lift $ serialisable initSt
eExp <- insertEntity $ Exps name time Nothing (runPut $ put serInitSt) (runPut $ put initInpSt)
void transactionSave
void $ insert $ mkExpSetup eExp
mapM_ (insertInfoParam (entityKey eExp)) infoParams
mapM_ (insertParam (entityKey eExp)) (parameters initSt)
return eExp
Just (eExp, _) -> do
$(logInfo) "Found experiment with same name and parameter settings. Continuing experiment ..."
expInfoParams <- map entityVal <$> selectList [ExpsInfoParamExps ==. entityKey eExp] []
mapM_ (insertInfoParam (entityKey eExp)) (filter ((`notElem` map (view expsInfoParamName) expInfoParams) . infoParameterName) infoParams)
putMany [mkExpSetup eExp]
return eExp
where
mkExpSetup eExp =
ExpsSetup
(entityKey eExp)
(max 1 $ view experimentRepetitions setup)
(max 0 $ view preparationSteps setup)
(max 0 $ view evaluationWarmUpSteps setup)
(max 0 $ view evaluationSteps setup)
(max 1 $ view evaluationReplications setup)
(max 1 <$> view evaluationMaxStepsBetweenSaves setup)
insertInfoParam k (ExperimentInfoParameter n v) = insert $ ExpsInfoParam k n (S.runPut $ S.put v)
insertParam :: Key Exps -> ParameterSetup a -> DB (ExpM a) (Key Param)
insertParam eExp (ParameterSetup n _ _ _ (Just (minVal, maxVal)) _ _) = insert $ Param eExp n (Just $ runPut $ put minVal) (Just $ runPut $ put maxVal)
insertParam eExp (ParameterSetup n _ _ _ Nothing _ _) = insert $ Param eExp n Nothing Nothing
infoParams = view experimentInfoParameters setup
matchesExpsInfoParam (ExpsInfoParam _ n bs) =
case L.find ((== n) . infoParameterName) infoParams of
Nothing -> False
Just (ExperimentInfoParameter _ p) -> fromEither False ((p ==) <$> S.runGet S.get bs)