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 +2/−1
- Simulation/Aivika/Dynamics/Buffer.hs +2/−1
- Simulation/Aivika/Dynamics/EventQueue.hs +44/−17
- Simulation/Aivika/Dynamics/FIFO.hs +2/−1
- Simulation/Aivika/Dynamics/Internal/Signal.hs +18/−0
- Simulation/Aivika/Dynamics/LIFO.hs +2/−1
- Simulation/Aivika/Dynamics/Ref.hs +2/−1
- Simulation/Aivika/Dynamics/Signal.hs +15/−8
- Simulation/Aivika/Dynamics/UVar.hs +2/−1
- Simulation/Aivika/Dynamics/Var.hs +2/−1
- aivika.cabal +2/−1
- examples/README +19/−0
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