packages feed

aivika 0.5 → 0.5.1

raw patch · 7 files changed

+241/−63 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Simulation.Aivika.Dynamics.Buffer: bufferDequeue :: Buffer -> Signal ()
+ Simulation.Aivika.Dynamics.Buffer: bufferEnqueue :: Buffer -> Signal ()
+ Simulation.Aivika.Dynamics.Buffer: bufferEnqueueLost :: Buffer -> Signal ()
+ Simulation.Aivika.Dynamics.EventQueue: enqueueWithCurrentTime :: EventQueue -> Dynamics () -> Dynamics ()
+ Simulation.Aivika.Dynamics.EventQueue: enqueueWithIntegTimes :: EventQueue -> Dynamics () -> Dynamics ()
+ Simulation.Aivika.Dynamics.EventQueue: enqueueWithStartTime :: EventQueue -> Dynamics () -> Dynamics ()
+ Simulation.Aivika.Dynamics.EventQueue: enqueueWithStopTime :: EventQueue -> Dynamics () -> Dynamics ()
+ Simulation.Aivika.Dynamics.EventQueue: enqueueWithTimes :: EventQueue -> [Double] -> Dynamics () -> Dynamics ()
+ Simulation.Aivika.Dynamics.EventQueue: queueCount :: EventQueue -> Dynamics Int
+ Simulation.Aivika.Dynamics.FIFO: fifoDequeue :: FIFO a -> Signal a
+ Simulation.Aivika.Dynamics.FIFO: fifoEnqueue :: FIFO a -> Signal a
+ Simulation.Aivika.Dynamics.FIFO: fifoEnqueueLost :: FIFO a -> Signal a
+ Simulation.Aivika.Dynamics.LIFO: lifoDequeue :: LIFO a -> Signal a
+ Simulation.Aivika.Dynamics.LIFO: lifoEnqueue :: LIFO a -> Signal a
+ Simulation.Aivika.Dynamics.LIFO: lifoEnqueueLost :: LIFO a -> Signal a

Files

Simulation/Aivika/Dynamics/Buffer.hs view
@@ -19,6 +19,9 @@         bufferMaxCount,         bufferCount,         bufferLostCount,+        bufferEnqueue,+        bufferDequeue,+        bufferEnqueueLost,         newBuffer,         dequeueBuffer,         tryDequeueBuffer,@@ -36,6 +39,7 @@ import Simulation.Aivika.Dynamics.EventQueue import Simulation.Aivika.Dynamics.Process import Simulation.Aivika.Dynamics.Resource+import Simulation.Aivika.Dynamics.Internal.Signal  import Simulation.Aivika.Dynamics.LIFO import Simulation.Aivika.Dynamics.FIFO@@ -48,7 +52,11 @@            bufferReadRes  :: Resource,            bufferWriteRes :: Resource,            bufferCountRef :: IORef Int,-           bufferLostCountRef :: IORef Int }+           bufferLostCountRef :: IORef Int, +           bufferEnqueueSource :: SignalSource (),+           bufferEnqueueLostSource :: SignalSource (),+           bufferDequeueSource :: SignalSource (),+           bufferUpdatedSource :: SignalSource () }    -- | Create a new queue with the specified maximum available number of items.   newBuffer :: EventQueue -> Int -> Simulation Buffer  @@ -57,12 +65,20 @@      l <- liftIO $ newIORef 0      r <- newResourceWithCount q count 0      w <- newResourceWithCount q count count+     s1 <- newSignalSourceUnsafe+     s2 <- newSignalSourceUnsafe+     s3 <- newSignalSourceUnsafe+     s4 <- newSignalSourceWithUpdate (runQueue q)      return Buffer { bufferQueue = q,                      bufferMaxCount = count,                      bufferReadRes  = r,                      bufferWriteRes = w,                      bufferCountRef = i,-                     bufferLostCountRef = l }+                     bufferLostCountRef = l, +                     bufferEnqueueSource = s1,+                     bufferEnqueueLostSource = s2,+                     bufferDequeueSource = s3,+                     bufferUpdatedSource = s4 }    -- | Test whether the queue is empty. bufferNull :: Buffer -> Dynamics Bool@@ -92,6 +108,7 @@   do requestResource (bufferReadRes q)      liftIO $ dequeueImpl q      releaseResource (bufferWriteRes q)+     liftDynamics $ triggerSignal (bufferDequeueSource q) ()    -- | Try to dequeue immediately.   tryDequeueBuffer :: Buffer -> Dynamics Bool@@ -100,6 +117,7 @@      if x         then do liftIO $ dequeueImpl q                releaseResourceInDynamics (bufferWriteRes q)+               triggerSignal (bufferDequeueSource q) ()                return True        else return False @@ -110,6 +128,7 @@   do requestResource (bufferWriteRes q)      liftIO $ enqueueImpl q      releaseResource (bufferReadRes q)+     liftDynamics $ triggerSignal (bufferEnqueueSource q) ()       -- | Try to enqueue the item immediately.   tryEnqueueBuffer :: Buffer -> Dynamics Bool@@ -118,6 +137,7 @@      if x         then do liftIO $ enqueueImpl q                releaseResourceInDynamics (bufferReadRes q)+               triggerSignal (bufferEnqueueSource q) ()                return True        else return False @@ -129,7 +149,29 @@      if x        then do liftIO $ enqueueImpl q                releaseResourceInDynamics (bufferReadRes q)-       else liftIO $ modifyIORef (bufferLostCountRef q) $ (+) 1+               triggerSignal (bufferEnqueueSource q) ()+       else do liftIO $ modifyIORef (bufferLostCountRef q) $ (+) 1+               triggerSignal (bufferEnqueueLostSource q) ()++-- | Return a signal that notifies when any item is enqueued.+bufferEnqueue :: Buffer -> Signal ()+bufferEnqueue q = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (bufferUpdatedSource q)+        m2 = publishSignal (bufferEnqueueSource q)++-- | Return a signal which notifies that the item was lost when+-- attempting to add it to the full queue with help of +-- 'enqueueBufferOrLost'.+bufferEnqueueLost :: Buffer -> Signal ()+bufferEnqueueLost q = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (bufferUpdatedSource q)+        m2 = publishSignal (bufferEnqueueLostSource q)++-- | Return a signal that notifies when any item is dequeued.+bufferDequeue :: Buffer -> Signal ()+bufferDequeue q = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (bufferUpdatedSource q)+        m2 = publishSignal (bufferDequeueSource q)  -- | An implementation method. dequeueImpl :: Buffer -> IO ()
Simulation/Aivika/Dynamics/EventQueue.hs view
@@ -16,8 +16,14 @@        (EventQueue,         newQueue,         enqueue,+        enqueueWithTimes,+        enqueueWithIntegTimes,+        enqueueWithStartTime,+        enqueueWithStopTime,+        enqueueWithCurrentTime,         runQueue,-        runQueueSync) where+        runQueueSync,+        queueCount) where  import Data.IORef import Control.Monad@@ -103,3 +109,80 @@          else let Dynamics m = runQueue q               in m p   +-- | Return the number of pending events that should+-- be yet actuated.+queueCount :: EventQueue -> Dynamics Int+queueCount q = Dynamics r where+  r p = +    do let Dynamics m = runQueueSync q+       m p+       PQ.queueCount $ queuePQ q+       +-- | Actuate the event handler in the specified time points.+enqueueWithTimes :: EventQueue -> [Double] -> Dynamics () -> Dynamics ()+enqueueWithTimes q ts m = loop ts+  where loop []       = return ()+        loop (t : ts) = enqueue q t $ m >> loop ts+       +-- | Actuate the event handler in the specified time points.+enqueueWithPoints :: EventQueue -> [Point] -> Dynamics () -> Dynamics ()+enqueueWithPoints q xs (Dynamics m) = loop xs+  where loop []       = return ()+        loop (x : xs) = enqueue q (pointTime x) $ +                        Dynamics $ \p ->+                        do m x    -- N.B. we substitute the time point!+                           let Dynamics m' = loop xs+                           m' p++-- | Actuate the event handler in the integration time points.+enqueueWithIntegTimes :: EventQueue -> Dynamics () -> Dynamics ()+enqueueWithIntegTimes q m =+  Dynamics $ \p ->+  do let sc  = pointSpecs p+         (nl, nu) = integIterationBnds sc+         points  = map point [nl .. nu]+         point n = Point { pointSpecs = sc,+                           pointRun = pointRun p,+                           pointTime = basicTime sc n 0,+                           pointIteration = n,+                           pointPhase = 0 }+         Dynamics m' = enqueueWithPoints q points m+     m' p++-- | Actuate the event handler in the start time.+enqueueWithStartTime :: EventQueue -> Dynamics () -> Dynamics ()+enqueueWithStartTime q m =+  Dynamics $ \p ->+  do let sc  = pointSpecs p+         (nl, nu) = integIterationBnds sc+         point n = Point { pointSpecs = sc,+                           pointRun = pointRun p,+                           pointTime = basicTime sc n 0,+                           pointIteration = n,+                           pointPhase = 0 }+         Dynamics m' = enqueueWithPoints q [point nl] m+     m' p++-- | Actuate the event handler in the stop time.+enqueueWithStopTime :: EventQueue -> Dynamics () -> Dynamics ()+enqueueWithStopTime q m =+  Dynamics $ \p ->+  do let sc  = pointSpecs p+         (nl, nu) = integIterationBnds sc+         point n = Point { pointSpecs = sc,+                           pointRun = pointRun p,+                           pointTime = basicTime sc n 0,+                           pointIteration = n,+                           pointPhase = 0 }+         Dynamics m' = enqueueWithPoints q [point nu] m+     m' p++-- | Actuate the event handler in the current time but +-- through the event queue, which allows continuing the +-- current tasks and then calling the handler after the +-- tasks are finished. The simulation time will be the same.+enqueueWithCurrentTime :: EventQueue -> Dynamics () -> Dynamics ()+enqueueWithCurrentTime q m =+  Dynamics $ \p ->+  do let Dynamics m' = enqueue q (pointTime p) m+     m' p
Simulation/Aivika/Dynamics/FIFO.hs view
@@ -17,6 +17,9 @@         fifoMaxCount,         fifoCount,         fifoLostCount,+        fifoEnqueue,+        fifoDequeue,+        fifoEnqueueLost,         newFIFO,         dequeueFIFO,         tryDequeueFIFO,@@ -36,6 +39,7 @@ import Simulation.Aivika.Dynamics.EventQueue import Simulation.Aivika.Dynamics.Process import Simulation.Aivika.Dynamics.Resource+import Simulation.Aivika.Dynamics.Internal.Signal  -- | Represents the FIFO queue with rule: first input - first output. data FIFO a =@@ -47,7 +51,11 @@          fifoLostCountRef :: IORef Int,          fifoStartRef :: IORef Int,          fifoEndRef   :: IORef Int,-         fifoArray :: IOArray Int a }+         fifoArray :: IOArray Int a, +         fifoEnqueueSource :: SignalSource a,+         fifoEnqueueLostSource :: SignalSource a,+         fifoDequeueSource :: SignalSource a,+         fifoUpdatedSource :: SignalSource a }    -- | Create a new FIFO queue with the specified maximum available number of items.   newFIFO :: EventQueue -> Int -> Simulation (FIFO a)  @@ -59,6 +67,10 @@      a <- liftIO $ newArray_ (0, count - 1)      r <- newResourceWithCount q count 0      w <- newResourceWithCount q count count+     s1 <- newSignalSourceUnsafe+     s2 <- newSignalSourceUnsafe+     s3 <- newSignalSourceUnsafe+     s4 <- newSignalSourceWithUpdate (runQueue q)      return FIFO { fifoQueue = q,                    fifoMaxCount = count,                    fifoReadRes  = r,@@ -67,7 +79,11 @@                    fifoLostCountRef = l,                    fifoStartRef = s,                    fifoEndRef   = e,-                   fifoArray = a }+                   fifoArray = a, +                   fifoEnqueueSource = s1,+                   fifoEnqueueLostSource = s2,+                   fifoDequeueSource = s3,+                   fifoUpdatedSource = s4 }    -- | Test whether the FIFO queue is empty. fifoNull :: FIFO a -> Dynamics Bool@@ -98,6 +114,7 @@   do requestResource (fifoReadRes fifo)      a <- liftIO $ dequeueImpl fifo      releaseResource (fifoWriteRes fifo)+     liftDynamics $ triggerSignal (fifoDequeueSource fifo) a      return a    -- | Try to dequeue from the FIFO queue immediately.  @@ -107,6 +124,7 @@      if x         then do a <- liftIO $ dequeueImpl fifo                releaseResourceInDynamics (fifoWriteRes fifo)+               triggerSignal (fifoDequeueSource fifo) a                return $ Just a        else return Nothing @@ -117,6 +135,7 @@   do requestResource (fifoWriteRes fifo)      liftIO $ enqueueImpl fifo a      releaseResource (fifoReadRes fifo)+     liftDynamics $ triggerSignal (fifoEnqueueSource fifo) a       -- | Try to enqueue the item in the FIFO queue. Return 'False' in -- the monad if the queue is full.@@ -126,6 +145,7 @@      if x         then do liftIO $ enqueueImpl fifo a                releaseResourceInDynamics (fifoReadRes fifo)+               triggerSignal (fifoEnqueueSource fifo) a                return True        else return False @@ -137,7 +157,29 @@      if x        then do liftIO $ enqueueImpl fifo a                releaseResourceInDynamics (fifoReadRes fifo)-       else liftIO $ modifyIORef (fifoLostCountRef fifo) $ (+) 1+               triggerSignal (fifoEnqueueSource fifo) a+       else do liftIO $ modifyIORef (fifoLostCountRef fifo) $ (+) 1+               triggerSignal (fifoEnqueueLostSource fifo) a++-- | Return a signal that notifies when any item is enqueued.+fifoEnqueue :: FIFO a -> Signal a+fifoEnqueue fifo = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (fifoUpdatedSource fifo)+        m2 = publishSignal (fifoEnqueueSource fifo)++-- | Return a signal which notifies that the item was lost when +-- attempting to add it to the full queue with help of+-- 'enqueueFIFOOrLost'.+fifoEnqueueLost :: FIFO a -> Signal a+fifoEnqueueLost fifo = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (fifoUpdatedSource fifo)+        m2 = publishSignal (fifoEnqueueLostSource fifo)++-- | Return a signal that notifies when any item is dequeued.+fifoDequeue :: FIFO a -> Signal a+fifoDequeue fifo = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (fifoUpdatedSource fifo)+        m2 = publishSignal (fifoDequeueSource fifo)  -- | An implementation method. dequeueImpl :: FIFO a -> IO a
Simulation/Aivika/Dynamics/LIFO.hs view
@@ -17,6 +17,9 @@         lifoMaxCount,         lifoCount,         lifoLostCount,+        lifoEnqueue,+        lifoDequeue,+        lifoEnqueueLost,         newLIFO,         dequeueLIFO,         tryDequeueLIFO,@@ -36,6 +39,7 @@ import Simulation.Aivika.Dynamics.EventQueue import Simulation.Aivika.Dynamics.Process import Simulation.Aivika.Dynamics.Resource+import Simulation.Aivika.Dynamics.Internal.Signal  -- | Represents the LIFO queue with rule: last input - first output. data LIFO a =@@ -45,7 +49,11 @@          lifoWriteRes :: Resource,          lifoCountRef :: IORef Int,          lifoLostCountRef :: IORef Int,-         lifoArray :: IOArray Int a }+         lifoArray :: IOArray Int a, +         lifoEnqueueSource :: SignalSource a,+         lifoEnqueueLostSource :: SignalSource a,+         lifoDequeueSource :: SignalSource a,+         lifoUpdatedSource :: SignalSource a }    -- | Create a new LIFO queue with the specified maximum available number of items.   newLIFO :: EventQueue -> Int -> Simulation (LIFO a)  @@ -55,13 +63,21 @@      a <- liftIO $ newArray_ (0, count - 1)      r <- newResourceWithCount q count 0      w <- newResourceWithCount q count count+     s1 <- newSignalSourceUnsafe+     s2 <- newSignalSourceUnsafe+     s3 <- newSignalSourceUnsafe+     s4 <- newSignalSourceWithUpdate (runQueue q)      return LIFO { lifoQueue = q,                    lifoMaxCount = count,                    lifoReadRes  = r,                    lifoWriteRes = w,                    lifoCountRef = i,                    lifoLostCountRef = l,-                   lifoArray = a }+                   lifoArray = a,+                   lifoEnqueueSource = s1,+                   lifoEnqueueLostSource = s2,+                   lifoDequeueSource = s3,+                   lifoUpdatedSource = s4 }    -- | Test whether the LIFO queue is empty. lifoNull :: LIFO a -> Dynamics Bool@@ -92,6 +108,7 @@   do requestResource (lifoReadRes lifo)      a <- liftIO $ dequeueImpl lifo      releaseResource (lifoWriteRes lifo)+     liftDynamics $ triggerSignal (lifoDequeueSource lifo) a      return a    -- | Try to dequeue from the LIFO queue immediately.  @@ -101,6 +118,7 @@      if x         then do a <- liftIO $ dequeueImpl lifo                releaseResourceInDynamics (lifoWriteRes lifo)+               triggerSignal (lifoDequeueSource lifo) a                return $ Just a        else return Nothing @@ -111,6 +129,7 @@   do requestResource (lifoWriteRes lifo)      liftIO $ enqueueImpl lifo a      releaseResource (lifoReadRes lifo)+     liftDynamics $ triggerSignal (lifoEnqueueSource lifo) a       -- | Try to enqueue the item in the LIFO queue. Return 'False' in -- the monad if the queue is full.@@ -120,6 +139,7 @@      if x         then do liftIO $ enqueueImpl lifo a                releaseResourceInDynamics (lifoReadRes lifo)+               triggerSignal (lifoEnqueueSource lifo) a                return True        else return False @@ -131,7 +151,30 @@      if x        then do liftIO $ enqueueImpl lifo a                releaseResourceInDynamics (lifoReadRes lifo)-       else liftIO $ modifyIORef (lifoLostCountRef lifo) $ (+) 1+               triggerSignal (lifoEnqueueSource lifo) a+       else do liftIO $ modifyIORef (lifoLostCountRef lifo) $ (+) 1+               triggerSignal (lifoEnqueueLostSource lifo) a++-- | Return a signal that notifies when any item is enqueued.+lifoEnqueue :: LIFO a -> Signal a+lifoEnqueue lifo = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (lifoUpdatedSource lifo)+        m2 = publishSignal (lifoEnqueueSource lifo)++-- | Return a signal which notifies that the item was lost when+-- attempting to add it to the full queue with help of+-- 'enqueueLIFOOrLost'.+lifoEnqueueLost :: LIFO a -> Signal a+lifoEnqueueLost lifo = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (lifoUpdatedSource lifo)+        m2 = publishSignal (lifoEnqueueLostSource lifo)++-- | Return a signal that notifies when any item is dequeued.+lifoDequeue :: LIFO a -> Signal a+lifoDequeue lifo = merge2Signals m1 m2    -- N.B. The order is important!+  where m1 = publishSignal (lifoUpdatedSource lifo)+        m2 = publishSignal (lifoDequeueSource lifo)+  -- | An implementation method. dequeueImpl :: LIFO a -> IO a
Simulation/Aivika/Dynamics/Signal.hs view
@@ -122,8 +122,7 @@ newSignalHistoryThrough q signal =   do ts <- liftIO UV.newVector      xs <- liftIO V.newVector-     t  <- time-     enqueue q t $+     enqueueWithCurrentTime q $        handleSignal_ signal $ \a ->        Dynamics $ \p ->        do liftIO $ UV.appendVector ts (pointTime p)@@ -139,72 +138,40 @@      xs <- liftIO $ UV.freezeVector (signalHistoryTimes history)      ys <- liftIO $ V.freezeVector (signalHistoryValues history)      return (xs, ys)     +     +-- | Trigger the signal with the current time.+triggerSignalWithTime :: SignalSource Double -> Dynamics ()+triggerSignalWithTime s =+  Dynamics $ \p ->+  do let Dynamics m = triggerSignal s (pointTime p)+     m p  -- | Return a signal that is triggered in the specified time points. newSignalInTimes :: EventQueue -> [Double] -> Dynamics (Signal Double) newSignalInTimes q xs =   do s <- liftSimulation $ newSignalSource q-     let loop []       = return ()-         loop (x : xs) = enqueue q x $ -                         do triggerSignal s x -                            loop xs-     loop xs-     return $ publishSignal s-       --- | Return a signal that is triggered in the specified time points.-newSignalInPoints :: EventQueue -> [Point] -> Dynamics (Signal Double)-newSignalInPoints q xs =-  do s <- liftSimulation $ newSignalSource q-     let loop []       = return ()-         loop (x : xs) = enqueue q (pointTime x) $ -                         Dynamics $ \p ->-                         do let Dynamics m = triggerSignal s (pointTime x) -                            m x    -- N.B. we substitute the time point!-                            let Dynamics m = loop xs-                            m p-     loop xs+     enqueueWithTimes q xs $ triggerSignalWithTime s      return $ publishSignal s         -- | Return a signal that is triggered in the integration time points. -- It should be called with help of 'runDynamicsInStartTime'. newSignalInIntegTimes :: EventQueue -> Dynamics (Signal Double) newSignalInIntegTimes q =-  Dynamics $ \p ->-  do let sc  = pointSpecs p-         (nl, nu) = integIterationBnds sc-         point n = Point { pointSpecs = sc,-                           pointRun = pointRun p,-                           pointTime = basicTime sc n 0,-                           pointIteration = n,-                           pointPhase = 0 }-         Dynamics m = newSignalInPoints q $ map point [nl .. nu]-     m p+  do s <- liftSimulation $ newSignalSource q+     enqueueWithIntegTimes q $ triggerSignalWithTime s+     return $ publishSignal s       -- | Return a signal that is triggered in the start time. -- It should be called with help of 'runDynamicsInStartTime'. newSignalInStartTime :: EventQueue -> Dynamics (Signal Double) newSignalInStartTime q =-  Dynamics $ \p ->-  do let sc  = pointSpecs p-         (nl, nu) = integIterationBnds sc-         point n = Point { pointSpecs = sc,-                           pointRun = pointRun p,-                           pointTime = basicTime sc n 0,-                           pointIteration = n,-                           pointPhase = 0 }-         Dynamics m = newSignalInPoints q [point nl]-     m p+  do s <- liftSimulation $ newSignalSource q+     enqueueWithStartTime q $ triggerSignalWithTime s+     return $ publishSignal s  -- | Return a signal that is triggered in the stop time. newSignalInStopTime :: EventQueue -> Dynamics (Signal Double) newSignalInStopTime q =-  Dynamics $ \p ->-  do let sc  = pointSpecs p-         (nl, nu) = integIterationBnds sc-         point n = Point { pointSpecs = sc,-                           pointRun = pointRun p,-                           pointTime = basicTime sc n 0,-                           pointIteration = n,-                           pointPhase = 0 }-         Dynamics m = newSignalInPoints q [point nu]-     m p+  do s <- liftSimulation $ newSignalSource q+     enqueueWithStopTime q $ triggerSignalWithTime s+     return $ publishSignal s
Simulation/Aivika/Statistics.hs view
@@ -106,7 +106,7 @@ -- | Return the variance. samplingStatsVariance :: SamplingStats a -> Double samplingStatsVariance stats-  | count == 1 = meanX2 - meanX * meanX+  | count == 1 = 0   | otherwise  = (meanX2 - meanX * meanX) * (n / (n - 1))     where count  = samplingStatsCount stats           meanX  = samplingStatsMean stats@@ -294,6 +294,7 @@      showString "maximum   = " . shows (timingStatsMax stats) .      showString " at t = " . shows (timingStatsMaxTime stats) .      showString "\n" .+     showString tab .      showString "t in [" . shows (timingStatsStartTime stats) .      showString ", " . shows (timingStatsLastTime stats) .      showString "]"
aivika.cabal view
@@ -1,5 +1,5 @@ name:            aivika-version:         0.5+version:         0.5.1 synopsis:        A multi-paradigm simulation library description:     Aivika is a small simulation library that covers many paradigms.