experimenter-0.1.0.14: src/Experimenter/Load.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Strict #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Experimenter.Load
( OnlyFinishedExperiments
, DatabaseSetting (..)
, loadExperimentsResultsM
, loadExperimentPrepEndStateIO
, loadExperimentPrepEndState
) where
import Control.Arrow (first, second, (&&&), (***))
import Control.Concurrent.MVar
import Control.DeepSeq
import Control.Lens
import Control.Monad.IO.Class
import Control.Monad.Logger (filterLogger, logDebug, logError, logInfo, runStdoutLoggingT)
import Control.Monad.Reader
import Control.Monad.Trans.Maybe
import qualified Data.ByteString as B
import Data.Function (on)
import Data.IORef
import Data.Int (Int64)
import Data.List (foldl')
import qualified Data.List as L
import Data.Maybe (catMaybes, fromJust, fromMaybe, isJust, isNothing)
import Data.Serialize hiding (get)
import qualified Data.Serialize as S
import qualified Data.Text as T
import Data.Time (addUTCTime, diffUTCTime, getCurrentTime)
import qualified Data.Vector as V
import Database.Persist.Postgresql
import GHC.Generics
import Network.HostName (getHostName)
import Prelude hiding (exp)
import System.IO
import System.IO.Unsafe (unsafePerformIO)
import System.Posix.Process
import System.Random.MWC
import Text.Read (readMaybe)
import Experimenter.Availability
import Experimenter.DB
import Experimenter.DatabaseSetting
import Experimenter.Experiment
import Experimenter.Input
import Experimenter.MasterSlave
import Experimenter.Measure
import Experimenter.Models
import Experimenter.Parameter
import Experimenter.Result
import Experimenter.Result.Query
import Experimenter.Setting
import Experimenter.StepResult
import Experimenter.Util
type OnlyFinishedExperiments = Bool
loadExperimentsResultsM ::
(ExperimentDef a)
=> OnlyFinishedExperiments
-> (ExpM a (Maybe (Experiments a)) -> IO (Maybe (Experiments a)))
-> DatabaseSetting
-> MkExperimentSetting a
-> InputState a
-> ExpM a a
-> Int64
-> IO (Maybe (Experiments a))
loadExperimentsResultsM filtFin runExpM dbSetup setup initInpSt mkInitSt key =
runExpM $ runDB dbSetup $ do
initSt <- lift $ lift $ lift mkInitSt
let sett = setup initSt
skipPrep exp' = any (^. parameterSettingSkipPreparationPhase) (exp' ^. parameterSetup)
isFinished exp' =
length (exp' ^. experimentResults) == sett ^. experimentRepetitions && -- repetitions
(skipPrep exp' || all (\expRes -> maybe 0 (lengthAvailabilityList . view results) (expRes ^. preparationResults) == sett ^. preparationSteps) (exp' ^. experimentResults)) && -- preparation length
all (\expRes -> length (expRes ^. evaluationResults) == sett ^. evaluationReplications) (exp' ^. experimentResults) && -- replications
all
(\expRes -> maybe 0 (lengthAvailabilityList . view results) (expRes ^. warmUpResults) == sett ^. evaluationWarmUpSteps)
(exp' ^. experimentResults . traversed . evaluationResults) && -- warm up length
all
(\expRes -> maybe 0 (lengthAvailabilityList . view results) (expRes ^. evalResults) == sett ^. evaluationSteps)
(exp' ^. experimentResults . traversed . evaluationResults) -- eval length
filterFinished =
over
experiments
(if filtFin
then filter isFinished
else id)
fmap filterFinished <$> loadExperimentsResults sett initInpSt initSt (toSqlKey key)
readValueSafe :: (Read a) => IO (Maybe a)
readValueSafe = do
liftIO $ putStr "Enter value: " >> hFlush stdout
readMaybe <$> getLine
readListValueSafeName :: [(a, T.Text)] -> IO (Maybe a)
readListValueSafeName xs = do
mapM_ (\(nr, (_, n)) -> putStrLn $ show nr <> ":\t " <> T.unpack n) $ zip [(0 :: Int) ..] xs
mNr <- readValueSafe
return $
case mNr of
Just nr
| nr >= 0 && nr < length xs -> Just $ fst $ xs !! nr
_ -> Nothing
-- | Convert a 'Maybe' computation to 'MaybeT'.
hoistMaybe :: (Applicative m) => Maybe b -> MaybeT m b
hoistMaybe = MaybeT . pure
loadExperimentPrepEndStateIO :: (ExpM a ~ IO, ExperimentDef a) => DatabaseSetting -> IO (Maybe a)
loadExperimentPrepEndStateIO = loadExperimentPrepEndState id
loadExperimentPrepEndState ::
forall a. (ExperimentDef a)
=> (ExpM a (Maybe a) -> IO (Maybe a))
-> DatabaseSetting
-> IO (Maybe a)
loadExperimentPrepEndState runExpM dbSetup =
runExpM $
runDB dbSetup $
runMaybeT $ do
liftIO $ putStrLn "From which experiment do you want to load the data? "
exps <- lift $ selectList [] []
let expsNames :: [(Key Exps, T.Text)]
expsNames = map (entityKey &&& (^. expsName) . entityVal) exps
(expsKey :: Key Exps) <- MaybeT $ liftIO $ readListValueSafeName expsNames
exp <- lift $ selectList [ExpExps ==. expsKey] []
(expKey :: Key Exp) <-
if length exp == 1
then return $ entityKey $ head exp
else do
liftIO $ putStrLn "Which experiment number?"
let expNrs = sortOnSnd $ map (entityKey &&& tshow . (^. expNumber) . entityVal) exp
MaybeT $ liftIO $ readListValueSafeName expNrs
reps <- lift $ selectList [ExpResultExp ==. expKey] []
liftIO $ putStrLn "And from which experiment repetition?"
let
repNames :: [(Key PrepResultData, T.Text)]
repNames = sortOnSnd $ map (first fromJust) $ filter (isJust . fst) $ map ((^. expResultPrepResultData) . entityVal &&& tshow . (^. expResultRepetition) . entityVal) reps
rep <- MaybeT $ liftIO $ readListValueSafeName repNames
let endStateType = EndStatePrep rep
ma <- lift (loadResDataEndState expKey endStateType :: DB (ExpM a) (Maybe a))
hoistMaybe ma
where sortOnSnd = L.sortBy (compare `on` snd)