packages feed

aivika 0.6 → 0.6.1

raw patch · 12 files changed

+112/−33 lines, 12 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Simulation.Aivika.Dynamics.EventQueue: runQueueBefore :: EventQueue -> Dynamics ()
+ Simulation.Aivika.Dynamics.EventQueue: runQueueSyncBefore :: EventQueue -> Dynamics ()

Files

Simulation/Aivika/Dynamics/Agent.hs view
@@ -46,6 +46,7 @@ import Simulation.Aivika.Dynamics.Internal.Dynamics import Simulation.Aivika.Dynamics.EventQueue import Simulation.Aivika.Dynamics.Internal.Signal+import Simulation.Aivika.Dynamics.Signal  -- -- Agent-based Modeling@@ -220,7 +221,7 @@   do modeRef    <- newIORef CreationMode      stateRef   <- newIORef Nothing      let Simulation m1 = newSignalSourceUnsafe-         Simulation m2 = newSignalSourceWithUpdate $ runQueue queue+         Simulation m2 = newSignalSource queue      stateChangedSource <- m1 r      stateUpdatedSource <- m2 r      return Agent { agentQueue = queue,
Simulation/Aivika/Dynamics/Buffer.hs view
@@ -40,6 +40,7 @@ import Simulation.Aivika.Dynamics.Process import Simulation.Aivika.Dynamics.Resource import Simulation.Aivika.Dynamics.Internal.Signal+import Simulation.Aivika.Dynamics.Signal  import Simulation.Aivika.Dynamics.LIFO import Simulation.Aivika.Dynamics.FIFO@@ -68,7 +69,7 @@      s1 <- newSignalSourceUnsafe      s2 <- newSignalSourceUnsafe      s3 <- newSignalSourceUnsafe-     s4 <- newSignalSourceWithUpdate (runQueue q)+     s4 <- newSignalSource q      return Buffer { bufferQueue = q,                      bufferMaxCount = count,                      bufferReadRes  = r,
Simulation/Aivika/Dynamics/EventQueue.hs view
@@ -7,10 +7,10 @@ -- Stability  : experimental -- Tested with: GHC 7.6.3 ----- The module introduces the event queue. Any event is the Dynamics computation,--- or, saying differently, a dynamic process that has a single purpose --- to perform some side effect at the desired time. To pass the message, --- we actually use a closure.+-- The module introduces the event queue. An event handler is+-- the Dynamics computation that has a single purpose to perform+-- some side effect at the desired time. To pass in any message+-- to the event, you can use a closure. -- module Simulation.Aivika.Dynamics.EventQueue        (EventQueue,@@ -23,6 +23,8 @@         enqueueWithCurrentTime,         runQueue,         runQueueSync,+        runQueueBefore,+        runQueueSyncBefore,         queueCount) where  import Data.IORef@@ -40,8 +42,28 @@   -- Optimization   runQueue  :: Dynamics (),   -- ^ Run the event queue processing its events.-  runQueueSync :: Dynamics ()-  -- ^ Run the event queue synchronously, i.e. without past.+  -- There is no restiction on the time of the queue itself. It this time+  -- is greater than the current simulation time then nothing happens.+  runQueueSync :: Dynamics (),+  -- ^ Run the event queue synchronously, i.e. the current time cannot be+  -- less than the actual time of the queue itself.+  --+  -- You will rarely need to run the event queue explicitly, but+  -- if you do want then this function is probably that one you should use.+  runQueueBefore :: Dynamics (),+  -- ^ Run the event queue processing only those events+  -- which time is less than the current simulation time.+  -- There is no restiction on the time of the queue itself. It this time+  -- is greater than the current simulation time then nothing happens.+  runQueueSyncBefore :: Dynamics ()+  -- ^ Run the event queue synchronously processing only those events+  -- which time is less than the current simulation time. But the current+  -- time cannot be less than the actual time of the queue itself.+  --+  -- This function is usually called before a handler is subscribed+  -- to the signal. Earlier 'runQueueSync' was called instead, which could+  -- lead to the lost of the signal by the handler at time of direct+  -- subscribing. Changed in version 0.6.1.   }  -- | Create a new event queue.@@ -55,8 +77,10 @@      let q = EventQueue { queuePQ   = pq,                           queueBusy = f,                           queueTime = t, -                          runQueue  = runQueueCore q,-                          runQueueSync = runQueueSyncCore q }+                          runQueue  = runQueueCore True q,+                          runQueueSync = runQueueSyncCore True q,+                          runQueueBefore = runQueueCore False q,+                          runQueueSyncBefore = runQueueSyncCore False q }      return q               -- | Enqueue the event which must be actuated at the specified time.@@ -65,8 +89,8 @@   r p = let pq = queuePQ q in PQ.enqueue pq t c      -- | Run the event queue processing its events.-runQueueCore :: EventQueue -> Dynamics ()-runQueueCore q = Dynamics r where+runQueueCore :: Bool -> EventQueue -> Dynamics ()+runQueueCore includingCurrentTime q = Dynamics r where   r p =     do let f = queueBusy q        f' <- readIORef f@@ -82,8 +106,9 @@             let t = queueTime q             t' <- readIORef t             when (t2 < t') $ -              error "The time value is too small: runQueue"-            when (t2 <= pointTime p) $+              error "The time value is too small: runQueueCore"+            when ((t2 < pointTime p) ||+                  (includingCurrentTime && (t2 == pointTime p))) $               do writeIORef t t2                  PQ.dequeue pq                  let sc  = pointSpecs p@@ -97,17 +122,19 @@                  call q p  -- | Run the event queue synchronously, i.e. without past.-runQueueSyncCore :: EventQueue -> Dynamics ()-runQueueSyncCore q = Dynamics r where+runQueueSyncCore :: Bool -> EventQueue -> Dynamics ()+runQueueSyncCore includingCurrentTime q = Dynamics r where   r p =     do let t = queueTime q        t' <- readIORef t        if pointTime p < t'          then error $               "The current time is less than " ++-              "the time in the queue: runQueueSync"-         else let Dynamics m = runQueue q-              in m p+              "the time in the queue: runQueueSyncCore"+         else m p+  Dynamics m = if includingCurrentTime+               then runQueue q+               else runQueueBefore q    -- | Return the number of pending events that should -- be yet actuated.
Simulation/Aivika/Dynamics/FIFO.hs view
@@ -40,6 +40,7 @@ import Simulation.Aivika.Dynamics.Process import Simulation.Aivika.Dynamics.Resource import Simulation.Aivika.Dynamics.Internal.Signal+import Simulation.Aivika.Dynamics.Signal  -- | Represents the FIFO queue with rule: first input - first output. data FIFO a =@@ -70,7 +71,7 @@      s1 <- newSignalSourceUnsafe      s2 <- newSignalSourceUnsafe      s3 <- newSignalSourceUnsafe-     s4 <- newSignalSourceWithUpdate (runQueue q)+     s4 <- newSignalSource q      return FIFO { fifoQueue = q,                    fifoMaxCount = count,                    fifoReadRes  = r,
Simulation/Aivika/Dynamics/Internal/Signal.hs view
@@ -61,8 +61,22 @@            -- signal and return a nested computation             -- that, being applied, unsubscribes the             -- handler from this signal.+           --+           -- If the signal is bound up with the event queue+           -- then the signal in the current time is not lost+           -- by the handler any more. Changed in version 0.6.1.            updateSignal :: Dynamics ()            -- ^ Update the signal to its actual state.+           --+           -- You will rarely need to call this function directly+           -- as it is usually called implicitly.+           --+           -- Since version 0.6.1 it processes only those events+           -- which time is less than the current simulation time+           -- if the signal is bound up with the event queue,+           -- although you can define your own 'updateSignal'+           -- function when creating a new signal source with help of+           -- 'newSignalSourceWithUpdate'.          }    -- | The queue of signal handlers.@@ -78,6 +92,10 @@  -- | Subscribe the handler to the specified signal. -- To subscribe the disposable handlers, use function 'handleSignal'.+--+-- If the signal is bound up with the event queue then the signal in+-- the current time is not lost by the handler any more.+-- Changed in version 0.6.1. handleSignal_ :: Signal a -> (a -> Dynamics ()) -> Dynamics () handleSignal_ signal h =    do x <- handleSignal signal h
Simulation/Aivika/Dynamics/LIFO.hs view
@@ -40,6 +40,7 @@ import Simulation.Aivika.Dynamics.Process import Simulation.Aivika.Dynamics.Resource import Simulation.Aivika.Dynamics.Internal.Signal+import Simulation.Aivika.Dynamics.Signal  -- | Represents the LIFO queue with rule: last input - first output. data LIFO a =@@ -66,7 +67,7 @@      s1 <- newSignalSourceUnsafe      s2 <- newSignalSourceUnsafe      s3 <- newSignalSourceUnsafe-     s4 <- newSignalSourceWithUpdate (runQueue q)+     s4 <- newSignalSource q      return LIFO { lifoQueue = q,                    lifoMaxCount = count,                    lifoReadRes  = r,
Simulation/Aivika/Dynamics/Ref.hs view
@@ -27,6 +27,7 @@ import Simulation.Aivika.Dynamics.Internal.Dynamics import Simulation.Aivika.Dynamics.EventQueue import Simulation.Aivika.Dynamics.Internal.Signal+import Simulation.Aivika.Dynamics.Signal  -- | The 'Ref' type represents a mutable variable similar to the 'IORef' variable  -- but only bound to some event queue, which makes the variable coordinated @@ -43,7 +44,7 @@ newRef q a =   do x <- liftIO $ newIORef a      s <- newSignalSourceUnsafe-     u <- newSignalSourceWithUpdate (runQueue q)+     u <- newSignalSource q      return Ref { refQueue = q,                   refRun   = runQueueSync q,                   refValue = x, 
Simulation/Aivika/Dynamics/Signal.hs view
@@ -61,9 +61,20 @@ import qualified Simulation.Aivika.UVector as UV  -- | Create a new signal source when the state depends on the event queue.+--+-- Since version 0.6.1 its 'updateSignal' function calls 'runQueueSyncBefore'+-- instead of 'runQueueSync' as it was before. In case of need you can+-- define your own update function with help of 'newSignalSourceWithUpdate'.+--+-- The function has the following defintion:+--+-- @+-- newSignalSource queue = +--   newSignalSourceWithUpdate $ runQueueSyncBefore queue+-- @ newSignalSource :: EventQueue -> Simulation (SignalSource a) newSignalSource queue = -  newSignalSourceWithUpdate $ runQueueSync queue+  newSignalSourceWithUpdate $ runQueueSyncBefore queue  -- | Await the signal. awaitSignal :: Signal a -> Process a@@ -111,13 +122,9 @@ -- The history will be created at the same simulation time, just the corresponded  -- handler will be subscribed to the signal after the new event will be processed  -- by the queue. --- --- It is very useful if we want the signal won't be triggered at the current --- time until we complete some preparation. This is relatated to the fact that--- the signal is updated at time of subscribing the handler. So, if we subscribe--- to the signal which must be triggered at the current time then it will be--- triggered. Using the event queue allows us to complete some preparation logic--- before the signal will be triggered at the same simulation time point.+--+-- Since version 0.6.1, this function has less meaning than before. Please use+-- carefully as the behavior depends on the state of the event queue. newSignalHistoryThrough :: EventQueue -> Signal a -> Dynamics (SignalHistory a) newSignalHistoryThrough q signal =   do ts <- liftIO UV.newVector
Simulation/Aivika/Dynamics/UVar.hs view
@@ -32,6 +32,7 @@ import Simulation.Aivika.Dynamics.Internal.Dynamics import Simulation.Aivika.Dynamics.EventQueue import Simulation.Aivika.Dynamics.Internal.Signal+import Simulation.Aivika.Dynamics.Signal  import qualified Simulation.Aivika.UVector as UV @@ -54,7 +55,7 @@      UV.appendVector xs $ spcStartTime $ runSpecs r      UV.appendVector ys a      s  <- invokeSimulation r newSignalSourceUnsafe-     u  <- invokeSimulation r $ newSignalSourceWithUpdate $ runQueue q+     u  <- invokeSimulation r $ newSignalSource q      return UVar { uvarQueue = q,                    uvarRun   = runQueue q,                    uvarXS = xs,
Simulation/Aivika/Dynamics/Var.hs view
@@ -29,6 +29,7 @@ import Simulation.Aivika.Dynamics.Internal.Dynamics import Simulation.Aivika.Dynamics.EventQueue import Simulation.Aivika.Dynamics.Internal.Signal+import Simulation.Aivika.Dynamics.Signal  import qualified Simulation.Aivika.Vector as V import qualified Simulation.Aivika.UVector as UV@@ -54,7 +55,7 @@      UV.appendVector xs $ spcStartTime $ runSpecs r      V.appendVector ys a      s  <- invokeSimulation r newSignalSourceUnsafe-     u  <- invokeSimulation r $ newSignalSourceWithUpdate $ runQueue q+     u  <- invokeSimulation r $ newSignalSource q      return Var { varQueue = q,                   varRun   = runQueue q,                   varXS = xs,
aivika.cabal view
@@ -1,5 +1,5 @@ name:            aivika-version:         0.6+version:         0.6.1 synopsis:        A multi-paradigm simulation library description:     Aivika is a multi-paradigm simulation library which has @@ -92,6 +92,7 @@                      examples/Furnace.hs                      examples/TimeOut.hs                      examples/TimeOutInt.hs+                     examples/README  data-files:          doc/aivika.pdf 
+ examples/README view
@@ -0,0 +1,19 @@+More examples are bundled with packages aivika-experiment and aivika-experiment-chart. +They plot charts, save the simulation results in the CSV files and generate +an HTML web page which can be observed in your favourite Internet browser.++Some examples define a parametric Monte-Carlo simulation, after which the deviation +charts and histograms are plotted, for example.++The reason why these packages are separated is that they have more heavy dependencies+while the engine itself is very light-weight and compact. But the additional packages +should work on Linux, Windows and OS X. I tested on all three platforms.++Also you may find more examples on GitHub by the following link:++https://github.com/dsorokin/aivika-models++I'm going to add new models to that Git repository. At least, one of them will use+arrays or vectors. ++July 18, 2013