module Simulation.Aivika.Lattice.Estimate
(
Estimate,
EstimateLift(..),
runEstimateInStartTime,
estimateTime,
foldEstimate,
memoEstimate,
estimateUpSide,
estimateDownSide,
estimateFuture,
shiftEstimate,
estimateAt,
catchEstimate,
finallyEstimate,
throwEstimate,
traceEstimate) where
import Simulation.Aivika.Trans.Internal.Types
import Simulation.Aivika.Trans.Simulation
import Simulation.Aivika.Trans.Parameter
import Simulation.Aivika.Trans.Ref
import Simulation.Aivika.Trans.Observable
import Simulation.Aivika.Lattice.Internal.Estimate
import Simulation.Aivika.Lattice.Internal.LIO
import qualified Simulation.Aivika.Lattice.Internal.Ref as R
memoEstimate :: (Estimate LIO a -> Estimate LIO a)
-> Estimate LIO a
-> Simulation LIO (Estimate LIO a)
memoEstimate :: (Estimate LIO a -> Estimate LIO a)
-> Estimate LIO a -> Simulation LIO (Estimate LIO a)
memoEstimate Estimate LIO a -> Estimate LIO a
f Estimate LIO a
m =
do Ref (Maybe a)
r <- Maybe a -> Simulation LIO (Ref (Maybe a))
forall a. a -> Simulation LIO (Ref a)
R.newRef Maybe a
forall a. Maybe a
Nothing
Double
t2 <- Parameter LIO Double -> Simulation LIO Double
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
ParameterLift t m =>
Parameter m a -> t m a
liftParameter Parameter LIO Double
forall (m :: * -> *). Monad m => Parameter m Double
stoptime
let loop :: Estimate LIO a
loop =
(Point LIO -> LIO a) -> Estimate LIO a
forall (m :: * -> *) a. (Point m -> m a) -> Estimate m a
Estimate ((Point LIO -> LIO a) -> Estimate LIO a)
-> (Point LIO -> LIO a) -> Estimate LIO a
forall a b. (a -> b) -> a -> b
$ \Point LIO
p ->
do Maybe a
b <- Ref (Maybe a) -> LIO (Maybe a)
forall a. Ref a -> LIO a
R.readRef0 Ref (Maybe a)
r
case Maybe a
b of
Just a
a -> a -> LIO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
Maybe a
Nothing ->
if Point LIO -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point LIO
p Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
t2
then do a
a <- Point LIO -> Estimate LIO a -> LIO a
forall (m :: * -> *) a. Point m -> Estimate m a -> m a
invokeEstimate Point LIO
p Estimate LIO a
m
Ref (Maybe a) -> Maybe a -> LIO ()
forall a. Ref a -> a -> LIO ()
R.writeRef0 Ref (Maybe a)
r (a -> Maybe a
forall a. a -> Maybe a
Just a
a)
a -> LIO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
else do a
a <- Point LIO -> Estimate LIO a -> LIO a
forall (m :: * -> *) a. Point m -> Estimate m a -> m a
invokeEstimate Point LIO
p (Estimate LIO a -> Estimate LIO a
f Estimate LIO a
loop)
Ref (Maybe a) -> Maybe a -> LIO ()
forall a. Ref a -> a -> LIO ()
R.writeRef0 Ref (Maybe a)
r (a -> Maybe a
forall a. a -> Maybe a
Just a
a)
a -> LIO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
Estimate LIO a -> Simulation LIO (Estimate LIO a)
forall (m :: * -> *) a. Monad m => a -> m a
return Estimate LIO a
loop
estimateUpSide :: Estimate LIO a -> Estimate LIO a
estimateUpSide :: Estimate LIO a -> Estimate LIO a
estimateUpSide Estimate LIO a
m =
(Point LIO -> LIO a) -> Estimate LIO a
forall (m :: * -> *) a. (Point m -> m a) -> Estimate m a
Estimate ((Point LIO -> LIO a) -> Estimate LIO a)
-> (Point LIO -> LIO a) -> Estimate LIO a
forall a b. (a -> b) -> a -> b
$ \Point LIO
p ->
(LIOParams -> IO a) -> LIO a
forall a. (LIOParams -> IO a) -> LIO a
LIO ((LIOParams -> IO a) -> LIO a) -> (LIOParams -> IO a) -> LIO a
forall a b. (a -> b) -> a -> b
$ \LIOParams
ps ->
do let ps' :: LIOParams
ps' = LIOParams -> LIOParams
upSideLIOParams LIOParams
ps
r :: Run LIO
r = Point LIO -> Run LIO
forall (m :: * -> *). Point m -> Run m
pointRun Point LIO
p
Point LIO
p' <- LIOParams -> LIO (Point LIO) -> IO (Point LIO)
forall a. LIOParams -> LIO a -> IO a
invokeLIO LIOParams
ps' (LIO (Point LIO) -> IO (Point LIO))
-> LIO (Point LIO) -> IO (Point LIO)
forall a b. (a -> b) -> a -> b
$
Run LIO -> Parameter LIO (Point LIO) -> LIO (Point LIO)
forall (m :: * -> *) a. Run m -> Parameter m a -> m a
invokeParameter Run LIO
r
Parameter LIO (Point LIO)
latticePoint
LIOParams -> LIO a -> IO a
forall a. LIOParams -> LIO a -> IO a
invokeLIO LIOParams
ps' (LIO a -> IO a) -> LIO a -> IO a
forall a b. (a -> b) -> a -> b
$
Point LIO -> Estimate LIO a -> LIO a
forall (m :: * -> *) a. Point m -> Estimate m a -> m a
invokeEstimate Point LIO
p' Estimate LIO a
m
estimateDownSide :: Estimate LIO a -> Estimate LIO a
estimateDownSide :: Estimate LIO a -> Estimate LIO a
estimateDownSide Estimate LIO a
m =
(Point LIO -> LIO a) -> Estimate LIO a
forall (m :: * -> *) a. (Point m -> m a) -> Estimate m a
Estimate ((Point LIO -> LIO a) -> Estimate LIO a)
-> (Point LIO -> LIO a) -> Estimate LIO a
forall a b. (a -> b) -> a -> b
$ \Point LIO
p ->
(LIOParams -> IO a) -> LIO a
forall a. (LIOParams -> IO a) -> LIO a
LIO ((LIOParams -> IO a) -> LIO a) -> (LIOParams -> IO a) -> LIO a
forall a b. (a -> b) -> a -> b
$ \LIOParams
ps ->
do let ps' :: LIOParams
ps' = LIOParams -> LIOParams
downSideLIOParams LIOParams
ps
r :: Run LIO
r = Point LIO -> Run LIO
forall (m :: * -> *). Point m -> Run m
pointRun Point LIO
p
Point LIO
p' <- LIOParams -> LIO (Point LIO) -> IO (Point LIO)
forall a. LIOParams -> LIO a -> IO a
invokeLIO LIOParams
ps' (LIO (Point LIO) -> IO (Point LIO))
-> LIO (Point LIO) -> IO (Point LIO)
forall a b. (a -> b) -> a -> b
$
Run LIO -> Parameter LIO (Point LIO) -> LIO (Point LIO)
forall (m :: * -> *) a. Run m -> Parameter m a -> m a
invokeParameter Run LIO
r
Parameter LIO (Point LIO)
latticePoint
LIOParams -> LIO a -> IO a
forall a. LIOParams -> LIO a -> IO a
invokeLIO LIOParams
ps' (LIO a -> IO a) -> LIO a -> IO a
forall a b. (a -> b) -> a -> b
$
Point LIO -> Estimate LIO a -> LIO a
forall (m :: * -> *) a. Point m -> Estimate m a -> m a
invokeEstimate Point LIO
p' Estimate LIO a
m
shiftEstimate :: Int
-> Int
-> Estimate LIO a
-> Estimate LIO a
shiftEstimate :: Int -> Int -> Estimate LIO a -> Estimate LIO a
shiftEstimate Int
di Int
dk Estimate LIO a
m =
(Point LIO -> LIO a) -> Estimate LIO a
forall (m :: * -> *) a. (Point m -> m a) -> Estimate m a
Estimate ((Point LIO -> LIO a) -> Estimate LIO a)
-> (Point LIO -> LIO a) -> Estimate LIO a
forall a b. (a -> b) -> a -> b
$ \Point LIO
p ->
(LIOParams -> IO a) -> LIO a
forall a. (LIOParams -> IO a) -> LIO a
LIO ((LIOParams -> IO a) -> LIO a) -> (LIOParams -> IO a) -> LIO a
forall a b. (a -> b) -> a -> b
$ \LIOParams
ps ->
do let ps' :: LIOParams
ps' = Int -> Int -> LIOParams -> LIOParams
shiftLIOParams Int
di Int
dk LIOParams
ps
r :: Run LIO
r = Point LIO -> Run LIO
forall (m :: * -> *). Point m -> Run m
pointRun Point LIO
p
Point LIO
p' <- LIOParams -> LIO (Point LIO) -> IO (Point LIO)
forall a. LIOParams -> LIO a -> IO a
invokeLIO LIOParams
ps' (LIO (Point LIO) -> IO (Point LIO))
-> LIO (Point LIO) -> IO (Point LIO)
forall a b. (a -> b) -> a -> b
$
Run LIO -> Parameter LIO (Point LIO) -> LIO (Point LIO)
forall (m :: * -> *) a. Run m -> Parameter m a -> m a
invokeParameter Run LIO
r
Parameter LIO (Point LIO)
latticePoint
LIOParams -> LIO a -> IO a
forall a. LIOParams -> LIO a -> IO a
invokeLIO LIOParams
ps' (LIO a -> IO a) -> LIO a -> IO a
forall a b. (a -> b) -> a -> b
$
Point LIO -> Estimate LIO a -> LIO a
forall (m :: * -> *) a. Point m -> Estimate m a -> m a
invokeEstimate Point LIO
p' Estimate LIO a
m
estimateFuture :: Int
-> Int
-> Estimate LIO a
-> Estimate LIO a
estimateFuture :: Int -> Int -> Estimate LIO a -> Estimate LIO a
estimateFuture Int
di Int
dk Estimate LIO a
m
| Int
di Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = [Char] -> Estimate LIO a
forall a. HasCallStack => [Char] -> a
error [Char]
"Expected to see a positive time index shift: estimateFuture"
| Bool
otherwise = Int -> Int -> Estimate LIO a -> Estimate LIO a
forall a. Int -> Int -> Estimate LIO a -> Estimate LIO a
shiftEstimate Int
di Int
dk Estimate LIO a
m
estimateAt :: Int
-> Int
-> Estimate LIO a
-> Estimate LIO a
estimateAt :: Int -> Int -> Estimate LIO a -> Estimate LIO a
estimateAt Int
i Int
k Estimate LIO a
m =
(Point LIO -> LIO a) -> Estimate LIO a
forall (m :: * -> *) a. (Point m -> m a) -> Estimate m a
Estimate ((Point LIO -> LIO a) -> Estimate LIO a)
-> (Point LIO -> LIO a) -> Estimate LIO a
forall a b. (a -> b) -> a -> b
$ \Point LIO
p ->
(LIOParams -> IO a) -> LIO a
forall a. (LIOParams -> IO a) -> LIO a
LIO ((LIOParams -> IO a) -> LIO a) -> (LIOParams -> IO a) -> LIO a
forall a b. (a -> b) -> a -> b
$ \LIOParams
ps ->
do let ps' :: LIOParams
ps' = Int -> Int -> LIOParams -> LIOParams
lioParamsAt Int
i Int
k LIOParams
ps
r :: Run LIO
r = Point LIO -> Run LIO
forall (m :: * -> *). Point m -> Run m
pointRun Point LIO
p
Point LIO
p' <- LIOParams -> LIO (Point LIO) -> IO (Point LIO)
forall a. LIOParams -> LIO a -> IO a
invokeLIO LIOParams
ps' (LIO (Point LIO) -> IO (Point LIO))
-> LIO (Point LIO) -> IO (Point LIO)
forall a b. (a -> b) -> a -> b
$
Run LIO -> Parameter LIO (Point LIO) -> LIO (Point LIO)
forall (m :: * -> *) a. Run m -> Parameter m a -> m a
invokeParameter Run LIO
r
Parameter LIO (Point LIO)
latticePoint
LIOParams -> LIO a -> IO a
forall a. LIOParams -> LIO a -> IO a
invokeLIO LIOParams
ps' (LIO a -> IO a) -> LIO a -> IO a
forall a b. (a -> b) -> a -> b
$
Point LIO -> Estimate LIO a -> LIO a
forall (m :: * -> *) a. Point m -> Estimate m a -> m a
invokeEstimate Point LIO
p' Estimate LIO a
m
foldEstimate :: (a -> a -> Estimate LIO a)
-> Estimate LIO a
-> Simulation LIO (Estimate LIO a)
foldEstimate :: (a -> a -> Estimate LIO a)
-> Estimate LIO a -> Simulation LIO (Estimate LIO a)
foldEstimate a -> a -> Estimate LIO a
f = (Estimate LIO a -> Estimate LIO a)
-> Estimate LIO a -> Simulation LIO (Estimate LIO a)
forall a.
(Estimate LIO a -> Estimate LIO a)
-> Estimate LIO a -> Simulation LIO (Estimate LIO a)
memoEstimate Estimate LIO a -> Estimate LIO a
g
where g :: Estimate LIO a -> Estimate LIO a
g Estimate LIO a
m =
do a
a1 <- Estimate LIO a -> Estimate LIO a
forall a. Estimate LIO a -> Estimate LIO a
estimateUpSide Estimate LIO a
m
a
a2 <- Estimate LIO a -> Estimate LIO a
forall a. Estimate LIO a -> Estimate LIO a
estimateDownSide Estimate LIO a
m
a -> a -> Estimate LIO a
f a
a1 a
a2