module Simulation.Aivika.Trans.Signal
(
Signal(..),
handleSignal_,
handleSignalComposite,
SignalSource,
newSignalSource,
newSignalSource0,
publishSignal,
triggerSignal,
mapSignal,
mapSignalM,
apSignal,
filterSignal,
filterSignal_,
filterSignalM,
filterSignalM_,
emptySignal,
merge2Signals,
merge3Signals,
merge4Signals,
merge5Signals,
arrivalSignal,
delaySignal,
delaySignalM,
SignalHistory,
signalHistorySignal,
newSignalHistory,
newSignalHistoryStartingWith,
readSignalHistory,
newSignalInTimes,
newSignalInIntegTimes,
newSignalInStartTime,
newSignalInStopTime,
Signalable(..),
signalableChanged,
emptySignalable,
appendSignalable,
traceSignal) where
import Data.Monoid
import Data.List
import Data.Array
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Trans.Ref.Base
import Simulation.Aivika.Trans.DES
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Parameter
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Dynamics
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Composite
import Simulation.Aivika.Arrival (Arrival(..))
data SignalSource m a =
SignalSource { publishSignal :: Signal m a,
triggerSignal :: a -> Event m ()
}
data Signal m a =
Signal { handleSignal :: (a -> Event m ()) -> Event m (DisposableEvent m)
}
data SignalHandlerQueue m a =
SignalHandlerQueue { queueList :: Ref m [SignalHandler m a] }
data SignalHandler m a =
SignalHandler { handlerComp :: a -> Event m (),
handlerRef :: Ref m () }
instance MonadDES m => Eq (SignalHandler m a) where
x == y = (handlerRef x) == (handlerRef y)
handleSignal_ :: MonadDES m => Signal m a -> (a -> Event m ()) -> Event m ()
handleSignal_ signal h =
do x <- handleSignal signal h
return ()
handleSignalComposite :: MonadDES m => Signal m a -> (a -> Event m ()) -> Composite m ()
handleSignalComposite signal h =
do x <- liftEvent $ handleSignal signal h
disposableComposite x
newSignalSource :: MonadDES m => Simulation m (SignalSource m a)
newSignalSource =
do list <- newRef []
let queue = SignalHandlerQueue { queueList = list }
signal = Signal { handleSignal = handle }
source = SignalSource { publishSignal = signal,
triggerSignal = trigger }
handle h =
Event $ \p ->
do x <- invokeEvent p $ enqueueSignalHandler queue h
return $
DisposableEvent $
dequeueSignalHandler queue x
trigger a =
triggerSignalHandlers queue a
return source
newSignalSource0 :: (MonadDES m, MonadRef0 m) => m (SignalSource m a)
newSignalSource0 =
do list <- newRef0 []
let queue = SignalHandlerQueue { queueList = list }
signal = Signal { handleSignal = handle }
source = SignalSource { publishSignal = signal,
triggerSignal = trigger }
handle h =
Event $ \p ->
do x <- invokeEvent p $ enqueueSignalHandler queue h
return $
DisposableEvent $
dequeueSignalHandler queue x
trigger a =
triggerSignalHandlers queue a
return source
triggerSignalHandlers :: MonadDES m => SignalHandlerQueue m a -> a -> Event m ()
triggerSignalHandlers q a =
Event $ \p ->
do hs <- invokeEvent p $ readRef (queueList q)
forM_ hs $ \h ->
invokeEvent p $ handlerComp h a
enqueueSignalHandler :: MonadDES m => SignalHandlerQueue m a -> (a -> Event m ()) -> Event m (SignalHandler m a)
enqueueSignalHandler q h =
Event $ \p ->
do r <- invokeSimulation (pointRun p) $ newRef ()
let handler = SignalHandler { handlerComp = h,
handlerRef = r }
invokeEvent p $ modifyRef (queueList q) (handler :)
return handler
dequeueSignalHandler :: MonadDES m => SignalHandlerQueue m a -> SignalHandler m a -> Event m ()
dequeueSignalHandler q h =
modifyRef (queueList q) (delete h)
instance MonadDES m => Functor (Signal m) where
fmap = mapSignal
instance MonadDES m => Monoid (Signal m a) where
mempty = emptySignal
mappend = merge2Signals
mconcat [] = emptySignal
mconcat [x1] = x1
mconcat [x1, x2] = merge2Signals x1 x2
mconcat [x1, x2, x3] = merge3Signals x1 x2 x3
mconcat [x1, x2, x3, x4] = merge4Signals x1 x2 x3 x4
mconcat [x1, x2, x3, x4, x5] = merge5Signals x1 x2 x3 x4 x5
mconcat (x1 : x2 : x3 : x4 : x5 : xs) =
mconcat $ merge5Signals x1 x2 x3 x4 x5 : xs
mapSignal :: MonadDES m => (a -> b) -> Signal m a -> Signal m b
mapSignal f m =
Signal { handleSignal = \h ->
handleSignal m $ h . f }
filterSignal :: MonadDES m => (a -> Bool) -> Signal m a -> Signal m a
filterSignal p m =
Signal { handleSignal = \h ->
handleSignal m $ \a ->
when (p a) $ h a }
filterSignal_ :: MonadDES m => (a -> Bool) -> Signal m a -> Signal m ()
filterSignal_ p m =
Signal { handleSignal = \h ->
handleSignal m $ \a ->
when (p a) $ h () }
filterSignalM :: MonadDES m => (a -> Event m Bool) -> Signal m a -> Signal m a
filterSignalM p m =
Signal { handleSignal = \h ->
handleSignal m $ \a ->
do x <- p a
when x $ h a }
filterSignalM_ :: MonadDES m => (a -> Event m Bool) -> Signal m a -> Signal m ()
filterSignalM_ p m =
Signal { handleSignal = \h ->
handleSignal m $ \a ->
do x <- p a
when x $ h () }
merge2Signals :: MonadDES m => Signal m a -> Signal m a -> Signal m a
merge2Signals m1 m2 =
Signal { handleSignal = \h ->
do x1 <- handleSignal m1 h
x2 <- handleSignal m2 h
return $ x1 <> x2 }
merge3Signals :: MonadDES m => Signal m a -> Signal m a -> Signal m a -> Signal m a
merge3Signals m1 m2 m3 =
Signal { handleSignal = \h ->
do x1 <- handleSignal m1 h
x2 <- handleSignal m2 h
x3 <- handleSignal m3 h
return $ x1 <> x2 <> x3 }
merge4Signals :: MonadDES m
=> Signal m a -> Signal m a -> Signal m a
-> Signal m a -> Signal m a
merge4Signals m1 m2 m3 m4 =
Signal { handleSignal = \h ->
do x1 <- handleSignal m1 h
x2 <- handleSignal m2 h
x3 <- handleSignal m3 h
x4 <- handleSignal m4 h
return $ x1 <> x2 <> x3 <> x4 }
merge5Signals :: MonadDES m
=> Signal m a -> Signal m a -> Signal m a
-> Signal m a -> Signal m a -> Signal m a
merge5Signals m1 m2 m3 m4 m5 =
Signal { handleSignal = \h ->
do x1 <- handleSignal m1 h
x2 <- handleSignal m2 h
x3 <- handleSignal m3 h
x4 <- handleSignal m4 h
x5 <- handleSignal m5 h
return $ x1 <> x2 <> x3 <> x4 <> x5 }
mapSignalM :: MonadDES m => (a -> Event m b) -> Signal m a -> Signal m b
mapSignalM f m =
Signal { handleSignal = \h ->
handleSignal m (f >=> h) }
apSignal :: MonadDES m => Event m (a -> b) -> Signal m a -> Signal m b
apSignal f m =
Signal { handleSignal = \h ->
handleSignal m $ \a -> do { x <- f; h (x a) } }
emptySignal :: MonadDES m => Signal m a
emptySignal =
Signal { handleSignal = \h -> return mempty }
data SignalHistory m a =
SignalHistory { signalHistorySignal :: Signal m a,
signalHistoryTimes :: Ref m [Double],
signalHistoryValues :: Ref m [a] }
newSignalHistory :: MonadDES m => Signal m a -> Composite m (SignalHistory m a)
newSignalHistory =
newSignalHistoryStartingWith Nothing
newSignalHistoryStartingWith :: MonadDES m => Maybe a -> Signal m a -> Composite m (SignalHistory m a)
newSignalHistoryStartingWith init signal =
do ts <- liftSimulation $ newRef []
xs <- liftSimulation $ newRef []
case init of
Nothing -> return ()
Just a ->
liftEvent $
do t <- liftDynamics time
modifyRef ts (t :)
modifyRef xs (a :)
handleSignalComposite signal $ \a ->
do t <- liftDynamics time
modifyRef ts (t :)
modifyRef xs (a :)
return SignalHistory { signalHistorySignal = signal,
signalHistoryTimes = ts,
signalHistoryValues = xs }
readSignalHistory :: MonadDES m => SignalHistory m a -> Event m (Array Int Double, Array Int a)
readSignalHistory history =
do xs0 <- readRef (signalHistoryTimes history)
ys0 <- readRef (signalHistoryValues history)
let n = length xs0
xs = listArray (0, n 1) (reverse xs0)
ys = listArray (0, n 1) (reverse ys0)
return (xs, ys)
triggerSignalWithCurrentTime :: MonadDES m => SignalSource m Double -> Event m ()
triggerSignalWithCurrentTime s =
Event $ \p -> invokeEvent p $ triggerSignal s (pointTime p)
newSignalInTimes :: MonadDES m => [Double] -> Event m (Signal m Double)
newSignalInTimes xs =
do s <- liftSimulation newSignalSource
enqueueEventWithTimes xs $ triggerSignalWithCurrentTime s
return $ publishSignal s
newSignalInIntegTimes :: MonadDES m => Event m (Signal m Double)
newSignalInIntegTimes =
do s <- liftSimulation newSignalSource
enqueueEventWithIntegTimes $ triggerSignalWithCurrentTime s
return $ publishSignal s
newSignalInStartTime :: MonadDES m => Event m (Signal m Double)
newSignalInStartTime =
do s <- liftSimulation newSignalSource
t <- liftParameter starttime
enqueueEvent t $ triggerSignalWithCurrentTime s
return $ publishSignal s
newSignalInStopTime :: MonadDES m => Event m (Signal m Double)
newSignalInStopTime =
do s <- liftSimulation newSignalSource
t <- liftParameter stoptime
enqueueEvent t $ triggerSignalWithCurrentTime s
return $ publishSignal s
data Signalable m a =
Signalable { readSignalable :: Event m a,
signalableChanged_ :: Signal m ()
}
signalableChanged :: MonadDES m => Signalable m a -> Signal m a
signalableChanged x = mapSignalM (const $ readSignalable x) $ signalableChanged_ x
instance Functor m => Functor (Signalable m) where
fmap f x = x { readSignalable = fmap f (readSignalable x) }
instance (MonadDES m, Monoid a) => Monoid (Signalable m a) where
mempty = emptySignalable
mappend = appendSignalable
emptySignalable :: (MonadDES m, Monoid a) => Signalable m a
emptySignalable =
Signalable { readSignalable = return mempty,
signalableChanged_ = mempty }
appendSignalable :: (MonadDES m, Monoid a) => Signalable m a -> Signalable m a -> Signalable m a
appendSignalable m1 m2 =
Signalable { readSignalable = liftM2 (<>) (readSignalable m1) (readSignalable m2),
signalableChanged_ = (signalableChanged_ m1) <> (signalableChanged_ m2) }
arrivalSignal :: MonadDES m => Signal m a -> Signal m (Arrival a)
arrivalSignal m =
Signal { handleSignal = \h ->
do r <- liftSimulation $ newRef Nothing
handleSignal m $ \a ->
Event $ \p ->
do t0 <- invokeEvent p $ readRef r
let t = pointTime p
invokeEvent p $ writeRef r (Just t)
invokeEvent p $
h Arrival { arrivalValue = a,
arrivalTime = t,
arrivalDelay =
case t0 of
Nothing -> Nothing
Just t0 -> Just (t t0) } }
delaySignal :: MonadDES m => Double -> Signal m a -> Signal m a
delaySignal delta m =
Signal { handleSignal = \h ->
do r <- liftSimulation $ newRef False
h <- handleSignal m $ \a ->
Event $ \p ->
invokeEvent p $
enqueueEvent (pointTime p + delta) $
do x <- readRef r
unless x $ h a
return $ DisposableEvent $
disposeEvent h >>
writeRef r True
}
delaySignalM :: MonadDES m => Event m Double -> Signal m a -> Signal m a
delaySignalM delta m =
Signal { handleSignal = \h ->
do r <- liftSimulation $ newRef False
h <- handleSignal m $ \a ->
Event $ \p ->
do delta' <- invokeEvent p delta
invokeEvent p $
enqueueEvent (pointTime p + delta') $
do x <- readRef r
unless x $ h a
return $ DisposableEvent $
disposeEvent h >>
writeRef r True
}
traceSignal :: MonadDES m => String -> Signal m a -> Signal m a
traceSignal message m =
Signal { handleSignal = \h ->
handleSignal m $ traceEvent message . h }