packages feed

aivika 4.1.1 → 4.2

raw patch · 25 files changed

+2428/−55 lines, 25 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Simulation.Aivika.Activity.Random: newPreemptibleRandomBetaActivity :: Bool -> Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newPreemptibleRandomDiscreteActivity :: Bool -> DiscretePDF Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newPreemptibleRandomGammaActivity :: Bool -> Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newPreemptibleRandomLogNormalActivity :: Bool -> Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newPreemptibleRandomTriangularActivity :: Bool -> Double -> Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newPreemptibleRandomWeibullActivity :: Bool -> Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newRandomBetaActivity :: Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newRandomDiscreteActivity :: DiscretePDF Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newRandomGammaActivity :: Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newRandomLogNormalActivity :: Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newRandomTriangularActivity :: Double -> Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.Activity.Random: newRandomWeibullActivity :: Double -> Double -> Simulation (Activity () a a)
+ Simulation.Aivika.DoubleLinkedList: listRemove :: Eq a => DoubleLinkedList a -> a -> IO Bool
+ Simulation.Aivika.DoubleLinkedList: listRemoveBy :: DoubleLinkedList a -> (a -> Bool) -> IO (Maybe a)
+ Simulation.Aivika.Dynamics.Random: memoRandomBetaDynamics :: Dynamics Double -> Dynamics Double -> Simulation (Dynamics Double)
+ Simulation.Aivika.Dynamics.Random: memoRandomDiscreteDynamics :: Unboxed a => Dynamics (DiscretePDF a) -> Simulation (Dynamics a)
+ Simulation.Aivika.Dynamics.Random: memoRandomGammaDynamics :: Dynamics Double -> Dynamics Double -> Simulation (Dynamics Double)
+ Simulation.Aivika.Dynamics.Random: memoRandomLogNormalDynamics :: Dynamics Double -> Dynamics Double -> Simulation (Dynamics Double)
+ Simulation.Aivika.Dynamics.Random: memoRandomTriangularDynamics :: Dynamics Double -> Dynamics Double -> Dynamics Double -> Simulation (Dynamics Double)
+ Simulation.Aivika.Dynamics.Random: memoRandomWeibullDynamics :: Dynamics Double -> Dynamics Double -> Simulation (Dynamics Double)
+ Simulation.Aivika.Gate: awaitGateClosed :: Gate -> Process ()
+ Simulation.Aivika.Gate: awaitGateOpened :: Gate -> Process ()
+ Simulation.Aivika.Gate: closeGate :: Gate -> Event ()
+ Simulation.Aivika.Gate: data Gate
+ Simulation.Aivika.Gate: gateChanged_ :: Gate -> Signal ()
+ Simulation.Aivika.Gate: gateClosed :: Gate -> Event Bool
+ Simulation.Aivika.Gate: gateOpened :: Gate -> Event Bool
+ Simulation.Aivika.Gate: newGate :: Bool -> Simulation Gate
+ Simulation.Aivika.Gate: newGateClosed :: Simulation Gate
+ Simulation.Aivika.Gate: newGateOpened :: Simulation Gate
+ Simulation.Aivika.Gate: openGate :: Gate -> Event ()
+ Simulation.Aivika.Generator: generateBeta :: Generator -> Double -> Double -> IO Double
+ Simulation.Aivika.Generator: generateDiscrete :: Generator -> forall a. DiscretePDF a -> IO a
+ Simulation.Aivika.Generator: generateGamma :: Generator -> Double -> Double -> IO Double
+ Simulation.Aivika.Generator: generateLogNormal :: Generator -> Double -> Double -> IO Double
+ Simulation.Aivika.Generator: generateTriangular :: Generator -> Double -> Double -> Double -> IO Double
+ Simulation.Aivika.Generator: generateWeibull :: Generator -> Double -> Double -> IO Double
+ Simulation.Aivika.Generator: type DiscretePDF a = [(a, Double)]
+ Simulation.Aivika.Net.Random: randomBetaNet :: Double -> Double -> Net a a
+ Simulation.Aivika.Net.Random: randomDiscreteNet :: DiscretePDF Double -> Net a a
+ Simulation.Aivika.Net.Random: randomGammaNet :: Double -> Double -> Net a a
+ Simulation.Aivika.Net.Random: randomLogNormalNet :: Double -> Double -> Net a a
+ Simulation.Aivika.Net.Random: randomTriangularNet :: Double -> Double -> Double -> Net a a
+ Simulation.Aivika.Net.Random: randomWeibullNet :: Double -> Double -> Net a a
+ Simulation.Aivika.Parameter.Random: randomBeta :: Double -> Double -> Parameter Double
+ Simulation.Aivika.Parameter.Random: randomDiscrete :: DiscretePDF a -> Parameter a
+ Simulation.Aivika.Parameter.Random: randomGamma :: Double -> Double -> Parameter Double
+ Simulation.Aivika.Parameter.Random: randomLogNormal :: Double -> Double -> Parameter Double
+ Simulation.Aivika.Parameter.Random: randomTriangular :: Double -> Double -> Double -> Parameter Double
+ Simulation.Aivika.Parameter.Random: randomWeibull :: Double -> Double -> Parameter Double
+ Simulation.Aivika.PriorityQueue: queueDelete :: Eq a => PriorityQueue a -> a -> IO Bool
+ Simulation.Aivika.PriorityQueue: queueDeleteBy :: PriorityQueue a -> (a -> Bool) -> IO (Maybe a)
+ Simulation.Aivika.Process.Random: randomBetaProcess :: Double -> Double -> Process Double
+ Simulation.Aivika.Process.Random: randomBetaProcess_ :: Double -> Double -> Process ()
+ Simulation.Aivika.Process.Random: randomDiscreteProcess :: DiscretePDF Double -> Process Double
+ Simulation.Aivika.Process.Random: randomDiscreteProcess_ :: DiscretePDF Double -> Process ()
+ Simulation.Aivika.Process.Random: randomGammaProcess :: Double -> Double -> Process Double
+ Simulation.Aivika.Process.Random: randomGammaProcess_ :: Double -> Double -> Process ()
+ Simulation.Aivika.Process.Random: randomLogNormalProcess :: Double -> Double -> Process Double
+ Simulation.Aivika.Process.Random: randomLogNormalProcess_ :: Double -> Double -> Process ()
+ Simulation.Aivika.Process.Random: randomTriangularProcess :: Double -> Double -> Double -> Process Double
+ Simulation.Aivika.Process.Random: randomTriangularProcess_ :: Double -> Double -> Double -> Process ()
+ Simulation.Aivika.Process.Random: randomWeibullProcess :: Double -> Double -> Process Double
+ Simulation.Aivika.Process.Random: randomWeibullProcess_ :: Double -> Double -> Process ()
+ Simulation.Aivika.Processor.Random: randomBetaProcessor :: Double -> Double -> Processor a a
+ Simulation.Aivika.Processor.Random: randomDiscreteProcessor :: DiscretePDF Double -> Processor a a
+ Simulation.Aivika.Processor.Random: randomGammaProcessor :: Double -> Double -> Processor a a
+ Simulation.Aivika.Processor.Random: randomLogNormalProcessor :: Double -> Double -> Processor a a
+ Simulation.Aivika.Processor.Random: randomTriangularProcessor :: Double -> Double -> Double -> Processor a a
+ Simulation.Aivika.Processor.Random: randomWeibullProcessor :: Double -> Double -> Processor a a
+ Simulation.Aivika.Queue: clearQueue :: (DequeueStrategy si, DequeueStrategy sm) => Queue si sm so a -> Event ()
+ Simulation.Aivika.Queue: queueDelete :: (Eq a, DequeueStrategy si, DeletingQueueStrategy sm, DequeueStrategy so) => Queue si sm so a -> a -> Event Bool
+ Simulation.Aivika.Queue: queueDeleteBy :: (DequeueStrategy si, DeletingQueueStrategy sm, DequeueStrategy so) => Queue si sm so a -> (a -> Bool) -> Event (Maybe a)
+ Simulation.Aivika.Queue: queueDeleteBy_ :: (DequeueStrategy si, DeletingQueueStrategy sm, DequeueStrategy so) => Queue si sm so a -> (a -> Bool) -> Event ()
+ Simulation.Aivika.Queue: queueDelete_ :: (Eq a, DequeueStrategy si, DeletingQueueStrategy sm, DequeueStrategy so) => Queue si sm so a -> a -> Event ()
+ Simulation.Aivika.Queue.Infinite: clearQueue :: DequeueStrategy sm => Queue sm so a -> Event ()
+ Simulation.Aivika.Queue.Infinite: queueDelete :: (Eq a, DeletingQueueStrategy sm, DequeueStrategy so) => Queue sm so a -> a -> Event Bool
+ Simulation.Aivika.Queue.Infinite: queueDeleteBy :: (DeletingQueueStrategy sm, DequeueStrategy so) => Queue sm so a -> (a -> Bool) -> Event (Maybe a)
+ Simulation.Aivika.Queue.Infinite: queueDeleteBy_ :: (DeletingQueueStrategy sm, DequeueStrategy so) => Queue sm so a -> (a -> Bool) -> Event ()
+ Simulation.Aivika.Queue.Infinite: queueDelete_ :: (Eq a, DeletingQueueStrategy sm, DequeueStrategy so) => Queue sm so a -> a -> Event ()
+ Simulation.Aivika.QueueStrategy: class DequeueStrategy s => DeletingQueueStrategy s where strategyQueueDelete s i = fmap isJust $ strategyQueueDeleteBy s (== i)
+ Simulation.Aivika.QueueStrategy: instance DeletingQueueStrategy FCFS
+ Simulation.Aivika.QueueStrategy: instance DeletingQueueStrategy LCFS
+ Simulation.Aivika.QueueStrategy: instance DeletingQueueStrategy SIRO
+ Simulation.Aivika.QueueStrategy: instance DeletingQueueStrategy StaticPriorities
+ Simulation.Aivika.QueueStrategy: strategyQueueDelete :: (DeletingQueueStrategy s, Eq i) => StrategyQueue s i -> i -> Event Bool
+ Simulation.Aivika.QueueStrategy: strategyQueueDeleteBy :: DeletingQueueStrategy s => StrategyQueue s i -> (i -> Bool) -> Event (Maybe i)
+ Simulation.Aivika.Results.Transform: Activity :: ResultTransform -> Activity
+ Simulation.Aivika.Results.Transform: ArrivalTimer :: ResultTransform -> ArrivalTimer
+ Simulation.Aivika.Results.Transform: Queue :: ResultTransform -> Queue
+ Simulation.Aivika.Results.Transform: Resource :: ResultTransform -> Resource
+ Simulation.Aivika.Results.Transform: SamplingCounter :: ResultTransform -> SamplingCounter
+ Simulation.Aivika.Results.Transform: SamplingStats :: ResultTransform -> SamplingStats
+ Simulation.Aivika.Results.Transform: Server :: ResultTransform -> Server
+ Simulation.Aivika.Results.Transform: TimingCounter :: ResultTransform -> TimingCounter
+ Simulation.Aivika.Results.Transform: TimingStats :: ResultTransform -> TimingStats
+ Simulation.Aivika.Results.Transform: activityIdleFactor :: Activity -> ResultTransform
+ Simulation.Aivika.Results.Transform: activityIdleTime :: Activity -> SamplingStats
+ Simulation.Aivika.Results.Transform: activityInitState :: Activity -> ResultTransform
+ Simulation.Aivika.Results.Transform: activityPreemptionFactor :: Activity -> ResultTransform
+ Simulation.Aivika.Results.Transform: activityPreemptionTime :: Activity -> SamplingStats
+ Simulation.Aivika.Results.Transform: activityState :: Activity -> ResultTransform
+ Simulation.Aivika.Results.Transform: activityTotalIdleTime :: Activity -> ResultTransform
+ Simulation.Aivika.Results.Transform: activityTotalPreemptionTime :: Activity -> ResultTransform
+ Simulation.Aivika.Results.Transform: activityTotalUtilisationTime :: Activity -> ResultTransform
+ Simulation.Aivika.Results.Transform: activityUtilisationFactor :: Activity -> ResultTransform
+ Simulation.Aivika.Results.Transform: activityUtilisationTime :: Activity -> SamplingStats
+ Simulation.Aivika.Results.Transform: arrivalProcessingTime :: ArrivalTimer -> SamplingStats
+ Simulation.Aivika.Results.Transform: class ResultTransformer a
+ Simulation.Aivika.Results.Transform: dequeueCount :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: dequeueExtractCount :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: dequeueExtractRate :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: dequeueRate :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: dequeueStrategy :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: dequeueWaitTime :: Queue -> SamplingStats
+ Simulation.Aivika.Results.Transform: enqueueCount :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: enqueueLostCount :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: enqueueRate :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: enqueueStoreCount :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: enqueueStoreRate :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: enqueueStoringStrategy :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: enqueueStrategy :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: enqueueWaitTime :: Queue -> SamplingStats
+ Simulation.Aivika.Results.Transform: instance ResultTransformer Activity
+ Simulation.Aivika.Results.Transform: instance ResultTransformer ArrivalTimer
+ Simulation.Aivika.Results.Transform: instance ResultTransformer Queue
+ Simulation.Aivika.Results.Transform: instance ResultTransformer Resource
+ Simulation.Aivika.Results.Transform: instance ResultTransformer ResultTransform
+ Simulation.Aivika.Results.Transform: instance ResultTransformer SamplingCounter
+ Simulation.Aivika.Results.Transform: instance ResultTransformer SamplingStats
+ Simulation.Aivika.Results.Transform: instance ResultTransformer Server
+ Simulation.Aivika.Results.Transform: instance ResultTransformer TimingCounter
+ Simulation.Aivika.Results.Transform: instance ResultTransformer TimingStats
+ Simulation.Aivika.Results.Transform: newtype Activity
+ Simulation.Aivika.Results.Transform: newtype ArrivalTimer
+ Simulation.Aivika.Results.Transform: newtype Queue
+ Simulation.Aivika.Results.Transform: newtype Resource
+ Simulation.Aivika.Results.Transform: newtype SamplingCounter
+ Simulation.Aivika.Results.Transform: newtype SamplingStats
+ Simulation.Aivika.Results.Transform: newtype Server
+ Simulation.Aivika.Results.Transform: newtype TimingCounter
+ Simulation.Aivika.Results.Transform: newtype TimingStats
+ Simulation.Aivika.Results.Transform: queueCount :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: queueCountStats :: Queue -> TimingStats
+ Simulation.Aivika.Results.Transform: queueFull :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: queueLoadFactor :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: queueMaxCount :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: queueNull :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: queueRate :: Queue -> ResultTransform
+ Simulation.Aivika.Results.Transform: queueTotalWaitTime :: Queue -> SamplingStats
+ Simulation.Aivika.Results.Transform: queueWaitTime :: Queue -> SamplingStats
+ Simulation.Aivika.Results.Transform: resourceCount :: Resource -> ResultTransform
+ Simulation.Aivika.Results.Transform: resourceCountStats :: Resource -> TimingStats
+ Simulation.Aivika.Results.Transform: resourceQueueCount :: Resource -> ResultTransform
+ Simulation.Aivika.Results.Transform: resourceQueueCountStats :: Resource -> TimingStats
+ Simulation.Aivika.Results.Transform: resourceTotalWaitTime :: Resource -> ResultTransform
+ Simulation.Aivika.Results.Transform: resourceUtilisationCount :: Resource -> ResultTransform
+ Simulation.Aivika.Results.Transform: resourceUtilisationCountStats :: Resource -> TimingStats
+ Simulation.Aivika.Results.Transform: resourceWaitTime :: Resource -> SamplingStats
+ Simulation.Aivika.Results.Transform: samplingCounterStats :: SamplingCounter -> SamplingStats
+ Simulation.Aivika.Results.Transform: samplingCounterValue :: SamplingCounter -> ResultTransform
+ Simulation.Aivika.Results.Transform: samplingStatsCount :: SamplingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: samplingStatsDeviation :: SamplingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: samplingStatsMax :: SamplingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: samplingStatsMean :: SamplingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: samplingStatsMean2 :: SamplingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: samplingStatsMin :: SamplingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: samplingStatsVariance :: SamplingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverInitState :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverInputWaitFactor :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverInputWaitTime :: Server -> SamplingStats
+ Simulation.Aivika.Results.Transform: serverOutputWaitFactor :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverOutputWaitTime :: Server -> SamplingStats
+ Simulation.Aivika.Results.Transform: serverPreemptionFactor :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverPreemptionTime :: Server -> SamplingStats
+ Simulation.Aivika.Results.Transform: serverProcessingFactor :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverProcessingTime :: Server -> SamplingStats
+ Simulation.Aivika.Results.Transform: serverState :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverTotalInputWaitTime :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverTotalOutputWaitTime :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverTotalPreemptionTime :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: serverTotalProcessingTime :: Server -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingCounterStats :: TimingCounter -> TimingStats
+ Simulation.Aivika.Results.Transform: timingCounterValue :: TimingCounter -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsCount :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsDeviation :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsLastTime :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsMax :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsMaxTime :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsMean :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsMin :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsMinTime :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsStartTime :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsSum :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsSum2 :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: timingStatsVariance :: TimingStats -> ResultTransform
+ Simulation.Aivika.Results.Transform: tr :: ResultTransformer a => a -> ResultTransform
+ Simulation.Aivika.Server.Random: newPreemptibleRandomBetaServer :: Bool -> Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newPreemptibleRandomDiscreteServer :: Bool -> DiscretePDF Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newPreemptibleRandomGammaServer :: Bool -> Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newPreemptibleRandomLogNormalServer :: Bool -> Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newPreemptibleRandomTriangularServer :: Bool -> Double -> Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newPreemptibleRandomWeibullServer :: Bool -> Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newRandomBetaServer :: Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newRandomDiscreteServer :: DiscretePDF Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newRandomGammaServer :: Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newRandomLogNormalServer :: Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newRandomTriangularServer :: Double -> Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Server.Random: newRandomWeibullServer :: Double -> Double -> Simulation (Server () a a)
+ Simulation.Aivika.Stream.Random: randomBetaStream :: Double -> Double -> Stream (Arrival Double)
+ Simulation.Aivika.Stream.Random: randomDiscreteStream :: DiscretePDF Double -> Stream (Arrival Double)
+ Simulation.Aivika.Stream.Random: randomGammaStream :: Double -> Double -> Stream (Arrival Double)
+ Simulation.Aivika.Stream.Random: randomLogNormalStream :: Double -> Double -> Stream (Arrival Double)
+ Simulation.Aivika.Stream.Random: randomTriangularStream :: Double -> Double -> Double -> Stream (Arrival Double)
+ Simulation.Aivika.Stream.Random: randomWeibullStream :: Double -> Double -> Stream (Arrival Double)
+ Simulation.Aivika.Vector: vectorDelete :: Eq a => Vector a -> a -> IO Bool
+ Simulation.Aivika.Vector: vectorDeleteBy :: Vector a -> (a -> Bool) -> IO (Maybe a)
+ Simulation.Aivika.Vector: vectorIndexBy :: Vector a -> (a -> Bool) -> IO Int
+ Simulation.Aivika.Vector.Unboxed: vectorDelete :: (Unboxed a, Eq a) => Vector a -> a -> IO Bool
+ Simulation.Aivika.Vector.Unboxed: vectorDeleteBy :: Unboxed a => Vector a -> (a -> Bool) -> IO Bool
+ Simulation.Aivika.Vector.Unboxed: vectorIndexBy :: Unboxed a => Vector a -> (a -> Bool) -> IO Int
- Simulation.Aivika.Generator: Generator :: (Double -> Double -> IO Double) -> (Int -> Int -> IO Int) -> (Double -> Double -> IO Double) -> (Double -> IO Double) -> (Double -> Int -> IO Double) -> (Double -> IO Int) -> (Double -> Int -> IO Int) -> Generator
+ Simulation.Aivika.Generator: Generator :: (Double -> Double -> IO Double) -> (Int -> Int -> IO Int) -> (Double -> Double -> Double -> IO Double) -> (Double -> Double -> IO Double) -> (Double -> Double -> IO Double) -> (Double -> IO Double) -> (Double -> Int -> IO Double) -> (Double -> IO Int) -> (Double -> Int -> IO Int) -> (Double -> Double -> IO Double) -> (Double -> Double -> IO Double) -> (Double -> Double -> IO Double) -> (forall a. DiscretePDF a -> IO a) -> Generator

Files

CHANGELOG.md view
@@ -1,4 +1,17 @@ +Version 4.2+-----++* Added new random distributions: lognormal, Gamma, Beta, Weibull and +  a generic discrete by pdf.++* The items can be removed from the queue; moreover, the queue can be +  cleared.++* Added a simplified API for accessing the results of simulation.++* Added the Gate entity.+ Version 4.1.1 ----- 
Simulation/Aivika.hs view
@@ -23,6 +23,7 @@         module Simulation.Aivika.Dynamics.Memo.Unboxed,         module Simulation.Aivika.Dynamics.Random,         module Simulation.Aivika.Event,+        module Simulation.Aivika.Gate,         module Simulation.Aivika.Generator,         module Simulation.Aivika.Net,         module Simulation.Aivika.Net.Random,@@ -65,6 +66,7 @@ import Simulation.Aivika.Dynamics.Memo.Unboxed import Simulation.Aivika.Dynamics.Random import Simulation.Aivika.Event+import Simulation.Aivika.Gate import Simulation.Aivika.Generator import Simulation.Aivika.Net import Simulation.Aivika.Net.Random
Simulation/Aivika/Activity/Random.hs view
@@ -15,19 +15,32 @@ module Simulation.Aivika.Activity.Random        (newRandomUniformActivity,         newRandomUniformIntActivity,+        newRandomTriangularActivity,         newRandomNormalActivity,+        newRandomLogNormalActivity,         newRandomExponentialActivity,         newRandomErlangActivity,         newRandomPoissonActivity,         newRandomBinomialActivity,+        newRandomGammaActivity,+        newRandomBetaActivity,+        newRandomWeibullActivity,+        newRandomDiscreteActivity,         newPreemptibleRandomUniformActivity,         newPreemptibleRandomUniformIntActivity,+        newPreemptibleRandomTriangularActivity,         newPreemptibleRandomNormalActivity,+        newPreemptibleRandomLogNormalActivity,         newPreemptibleRandomExponentialActivity,         newPreemptibleRandomErlangActivity,         newPreemptibleRandomPoissonActivity,-        newPreemptibleRandomBinomialActivity) where+        newPreemptibleRandomBinomialActivity,+        newPreemptibleRandomGammaActivity,+        newPreemptibleRandomBetaActivity,+        newPreemptibleRandomWeibullActivity,+        newPreemptibleRandomDiscreteActivity) where +import Simulation.Aivika.Generator import Simulation.Aivika.Simulation import Simulation.Aivika.Process import Simulation.Aivika.Process.Random@@ -62,6 +75,22 @@   newPreemptibleRandomUniformIntActivity False  -- | Create a new activity that holds the process for a random time interval+-- having the triangular distribution, when processing every input element.+--+-- By default, it is assumed that the activity process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomTriangularActivity :: Double+                               -- ^ the minimum time interval+                               -> Double+                               -- ^ the median of the time interval+                               -> Double+                               -- ^ the maximum time interval+                               -> Simulation (Activity () a a)+newRandomTriangularActivity =+  newPreemptibleRandomTriangularActivity False++-- | Create a new activity that holds the process for a random time interval -- distributed normally, when processing every input element. -- -- By default, it is assumed that the activity process cannot be preempted,@@ -76,6 +105,22 @@   newPreemptibleRandomNormalActivity False           -- | Create a new activity that holds the process for a random time interval+-- having the lognormal distribution, when processing every input element.+--+-- By default, it is assumed that the activity process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomLogNormalActivity :: Double+                              -- ^ the mean of a normal distribution which+                              -- this distribution is derived from+                              -> Double+                              -- ^ the deviation of a normal distribution which+                              -- this distribution is derived from+                              -> Simulation (Activity () a a)+newRandomLogNormalActivity =+  newPreemptibleRandomLogNormalActivity False++-- | Create a new activity that holds the process for a random time interval -- distributed exponentially with the specified mean (the reciprocal of the rate), -- when processing every input element. --@@ -132,6 +177,63 @@   newPreemptibleRandomBinomialActivity False  -- | Create a new activity that holds the process for a random time interval+-- having the Gamma distribution with the specified shape and scale,+-- when processing every input element.+--+-- By default, it is assumed that the activity process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomGammaActivity :: Double+                          -- ^ the shape+                          -> Double+                          -- ^ the scale (a reciprocal of the rate)+                          -> Simulation (Activity () a a)+newRandomGammaActivity =+  newPreemptibleRandomGammaActivity False++-- | Create a new activity that holds the process for a random time interval+-- having the Beta distribution with the specified shape parameters (alpha and beta),+-- when processing every input element.+--+-- By default, it is assumed that the activity process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomBetaActivity :: Double+                         -- ^ shape (alpha)+                         -> Double+                         -- ^ shape (beta)+                         -> Simulation (Activity () a a)+newRandomBetaActivity =+  newPreemptibleRandomBetaActivity False++-- | Create a new activity that holds the process for a random time interval+-- having the Weibull distribution with the specified shape and scale,+-- when processing every input element.+--+-- By default, it is assumed that the activity process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomWeibullActivity :: Double+                            -- ^ shape+                            -> Double+                            -- ^ scale+                            -> Simulation (Activity () a a)+newRandomWeibullActivity =+  newPreemptibleRandomWeibullActivity False++-- | Create a new activity that holds the process for a random time interval+-- having the specified discrete distribution, when processing every input element.+--+-- By default, it is assumed that the activity process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomDiscreteActivity :: DiscretePDF Double+                             -- ^ the discrete probability density function+                             -> Simulation (Activity () a a)+newRandomDiscreteActivity =+  newPreemptibleRandomDiscreteActivity False++-- | Create a new activity that holds the process for a random time interval -- distributed uniformly, when processing every input element. newPreemptibleRandomUniformActivity :: Bool                                        -- ^ whether the activity process can be preempted@@ -160,6 +262,22 @@      return a  -- | Create a new activity that holds the process for a random time interval+-- having the triangular distribution, when processing every input element.+newPreemptibleRandomTriangularActivity :: Bool+                                          -- ^ whether the activity process can be preempted+                                          -> Double+                                          -- ^ the minimum time interval+                                          -> Double+                                          -- ^ the median of the time interval+                                          -> Double+                                          -- ^ the maximum time interval+                                          -> Simulation (Activity () a a)+newPreemptibleRandomTriangularActivity preemptible min median max =+  newPreemptibleActivity preemptible $ \a ->+  do randomTriangularProcess_ min median max+     return a++-- | Create a new activity that holds the process for a random time interval -- distributed normally, when processing every input element. newPreemptibleRandomNormalActivity :: Bool                                       -- ^ whether the activity process can be preempted@@ -172,8 +290,24 @@   newPreemptibleActivity preemptible $ \a ->   do randomNormalProcess_ mu nu      return a-         + -- | Create a new activity that holds the process for a random time interval+-- having the lognormal distribution, when processing every input element.+newPreemptibleRandomLogNormalActivity :: Bool+                                         -- ^ whether the activity process can be preempted+                                         -> Double+                                         -- ^ the mean of a normal distribution which+                                         -- this distribution is derived from+                                         -> Double+                                         -- ^ the deviation of a normal distribution which+                                         -- this distribution is derived from+                                         -> Simulation (Activity () a a)+newPreemptibleRandomLogNormalActivity preemptible mu nu =+  newPreemptibleActivity preemptible $ \a ->+  do randomLogNormalProcess_ mu nu+     return a++-- | Create a new activity that holds the process for a random time interval -- distributed exponentially with the specified mean (the reciprocal of the rate), -- when processing every input element. newPreemptibleRandomExponentialActivity :: Bool@@ -227,4 +361,61 @@ newPreemptibleRandomBinomialActivity preemptible prob trials =   newPreemptibleActivity preemptible $ \a ->   do randomBinomialProcess_ prob trials+     return a++-- | Create a new activity that holds the process for a random time interval+-- having the Gamma distribution with the specified shape and scale,+-- when processing every input element.+newPreemptibleRandomGammaActivity :: Bool+                                     -- ^ whether the activity process can be preempted+                                     -> Double+                                     -- ^ the shape+                                     -> Double+                                     -- ^ the scale+                                     -> Simulation (Activity () a a)+newPreemptibleRandomGammaActivity preemptible kappa theta =+  newPreemptibleActivity preemptible $ \a ->+  do randomGammaProcess_ kappa theta+     return a++-- | Create a new activity that holds the process for a random time interval+-- having the Beta distribution with the specified shape parameters (alpha and beta),+-- when processing every input element.+newPreemptibleRandomBetaActivity :: Bool+                                    -- ^ whether the activity process can be preempted+                                    -> Double+                                    -- ^ shape (alpha)+                                    -> Double+                                    -- ^ shape (beta)+                                    -> Simulation (Activity () a a)+newPreemptibleRandomBetaActivity preemptible alpha beta =+  newPreemptibleActivity preemptible $ \a ->+  do randomBetaProcess_ alpha beta+     return a++-- | Create a new activity that holds the process for a random time interval+-- having the Weibull distribution with the specified shape and scale,+-- when processing every input element.+newPreemptibleRandomWeibullActivity :: Bool+                                       -- ^ whether the activity process can be preempted+                                       -> Double+                                       -- ^ shape+                                       -> Double+                                       -- ^ scale+                                       -> Simulation (Activity () a a)+newPreemptibleRandomWeibullActivity preemptible alpha beta =+  newPreemptibleActivity preemptible $ \a ->+  do randomWeibullProcess_ alpha beta+     return a++-- | Create a new activity that holds the process for a random time interval+-- having the specified discrete distribution, when processing every input element.+newPreemptibleRandomDiscreteActivity :: Bool+                                        -- ^ whether the activity process can be preempted+                                        -> DiscretePDF Double+                                        -- ^ the discrete probability density function+                                        -> Simulation (Activity () a a)+newPreemptibleRandomDiscreteActivity preemptible dpdf =+  newPreemptibleActivity preemptible $ \a ->+  do randomDiscreteProcess_ dpdf      return a
Simulation/Aivika/DoubleLinkedList.hs view
@@ -18,10 +18,14 @@         listAddLast,         listRemoveFirst,         listRemoveLast,+        listRemove,+        listRemoveBy,         listFirst,         listLast) where   import Data.IORef+import Data.Maybe+ import Control.Monad  -- | A cell of the double-linked list.@@ -62,7 +66,8 @@ listInsertFirst :: DoubleLinkedList a -> a -> IO () listInsertFirst x v =   do size <- readIORef (listSize x)-     writeIORef (listSize x) (size + 1)+     let size' = size + 1+     size' `seq` writeIORef (listSize x) size'      head <- readIORef (listHead x)      case head of        Nothing ->@@ -86,7 +91,8 @@ listAddLast :: DoubleLinkedList a -> a -> IO () listAddLast x v =   do size <- readIORef (listSize x)-     writeIORef (listSize x) (size + 1)+     let size' = size + 1+     size' `seq` writeIORef (listSize x) size'      tail <- readIORef (listTail x)      case tail of        Nothing ->@@ -115,7 +121,8 @@          error "Empty list: listRemoveFirst"        Just h ->          do size  <- readIORef (listSize x)-            writeIORef (listSize x) (size - 1)+            let size' = size - 1+            size' `seq` writeIORef (listSize x) size'             head' <- readIORef (itemNext h)             case head' of               Nothing ->@@ -134,7 +141,8 @@          error "Empty list: listRemoveLast"        Just t ->          do size  <- readIORef (listSize x)-            writeIORef (listSize x) (size - 1)+            let size' =  size - 1+            size' `seq` writeIORef (listSize x) size'             tail' <- readIORef (itemPrev t)             case tail' of               Nothing ->@@ -163,3 +171,39 @@          error "Empty list: listLast"        Just t ->          return $ itemVal t++-- | Remove the specified element from the list and return a flag+-- indicating whether the element was found and removed.+listRemove :: Eq a => DoubleLinkedList a -> a -> IO Bool+listRemove x v = fmap isJust $ listRemoveBy x (== v)++-- | Remove an element satisfying the specified predicate and return+-- the element if found.+listRemoveBy :: DoubleLinkedList a -> (a -> Bool) -> IO (Maybe a)+listRemoveBy x p = readIORef (listHead x) >>= loop+  where loop item =+          case item of+            Nothing   -> return Nothing+            Just item ->+              do let f = p (itemVal item)+                 if not f+                   then readIORef (itemNext item) >>= loop+                   else do size <- readIORef (listSize x)+                           prev <- readIORef (itemPrev item)+                           next <- readIORef (itemNext item)+                           let size' = size - 1+                           size' `seq` writeIORef (listSize x) size'+                           case (prev, next) of+                             (Nothing, Nothing) ->+                               do writeIORef (listHead x) Nothing+                                  writeIORef (listTail x) Nothing+                             (Nothing, head' @ (Just item')) ->+                               do writeIORef (itemPrev item') Nothing+                                  writeIORef (listHead x) head'+                             (tail' @ (Just item'), Nothing) ->+                               do writeIORef (itemNext item') Nothing+                                  writeIORef (listTail x) tail'+                             (Just prev', Just next') ->+                               do writeIORef (itemNext prev') (Just next')+                                  writeIORef (itemPrev next') (Just prev')+                           return (Just $ itemVal item)
Simulation/Aivika/Dynamics/Random.hs view
@@ -22,11 +22,17 @@ module Simulation.Aivika.Dynamics.Random        (memoRandomUniformDynamics,         memoRandomUniformIntDynamics,+        memoRandomTriangularDynamics,         memoRandomNormalDynamics,+        memoRandomLogNormalDynamics,         memoRandomExponentialDynamics,         memoRandomErlangDynamics,         memoRandomPoissonDynamics,-        memoRandomBinomialDynamics) where+        memoRandomBinomialDynamics,+        memoRandomGammaDynamics,+        memoRandomBetaDynamics,+        memoRandomWeibullDynamics,+        memoRandomDiscreteDynamics) where  import System.Random @@ -38,9 +44,10 @@ import Simulation.Aivika.Internal.Simulation import Simulation.Aivika.Internal.Dynamics import Simulation.Aivika.Dynamics.Memo.Unboxed+import Simulation.Aivika.Unboxed  -- | Computation that generates random numbers distributed uniformly and--- memoizes them in the integration time points.+-- memoizes the numbers in the integration time points. memoRandomUniformDynamics :: Dynamics Double     -- ^ minimum                              -> Dynamics Double  -- ^ maximum                              -> Simulation (Dynamics Double)@@ -53,7 +60,7 @@      generateUniform g min' max'  -- | Computation that generates random integer numbers distributed uniformly and--- memoizes them in the integration time points.+-- memoizes the numbers in the integration time points. memoRandomUniformIntDynamics :: Dynamics Int     -- ^ minimum                                 -> Dynamics Int  -- ^ maximum                                 -> Simulation (Dynamics Int)@@ -65,8 +72,23 @@      max' <- invokeDynamics p max      generateUniformInt g min' max' +-- | Computation that generates random numbers from the triangular distribution+-- and memoizes the numbers in the integration time points.+memoRandomTriangularDynamics :: Dynamics Double     -- ^ minimum+                                -> Dynamics Double  -- ^ median+                                -> Dynamics Double  -- ^ maximum+                                -> Simulation (Dynamics Double)+memoRandomTriangularDynamics min median max =+  memo0Dynamics $+  Dynamics $ \p ->+  do let g = runGenerator $ pointRun p+     min' <- invokeDynamics p min+     median' <- invokeDynamics p median+     max' <- invokeDynamics p max+     generateTriangular g min' median' max'+ -- | Computation that generates random numbers distributed normally and--- memoizes them in the integration time points.+-- memoizes the numbers in the integration time points. memoRandomNormalDynamics :: Dynamics Double     -- ^ mean                             -> Dynamics Double  -- ^ deviation                             -> Simulation (Dynamics Double)@@ -78,10 +100,27 @@      nu' <- invokeDynamics p nu      generateNormal g mu' nu' +-- | Computation that generates random numbers from the lognormal distribution+-- and memoizes the numbers in the integration time points.+memoRandomLogNormalDynamics :: Dynamics Double+                               -- ^ the mean of a normal distribution which+                               -- this distribution is derived from+                               -> Dynamics Double+                               -- ^ the deviation of a normal distribution which+                               -- this distribution is derived from+                               -> Simulation (Dynamics Double)+memoRandomLogNormalDynamics mu nu =+  memo0Dynamics $+  Dynamics $ \p ->+  do let g = runGenerator $ pointRun p+     mu' <- invokeDynamics p mu+     nu' <- invokeDynamics p nu+     generateLogNormal g mu' nu'+ -- | Computation that generates exponential random numbers with the specified mean--- (the reciprocal of the rate) and memoizes them in the integration time points.+-- (the reciprocal of the rate) and memoizes the numbers in the integration time points. memoRandomExponentialDynamics :: Dynamics Double-                                 -- ^ the mean (the reciprocal of the rate)+                                 -- ^ the mean (a reciprocal of the rate)                                  -> Simulation (Dynamics Double) memoRandomExponentialDynamics mu =   memo0Dynamics $@@ -91,10 +130,10 @@      generateExponential g mu'  -- | Computation that generates the Erlang random numbers with the specified scale--- (the reciprocal of the rate) and integer shape but memoizes them in the integration--- time points.+-- (the reciprocal of the rate) and integer shape but memoizes the numbers in+-- the integration time points. memoRandomErlangDynamics :: Dynamics Double-                            -- ^ the scale (the reciprocal of the rate)+                            -- ^ the scale (a reciprocal of the rate)                             -> Dynamics Int                             -- ^ the shape                             -> Simulation (Dynamics Double)@@ -107,7 +146,7 @@      generateErlang g beta' m'  -- | Computation that generats the Poisson random numbers with the specified mean--- and memoizes them in the integration time points.+-- and memoizes the numbers in the integration time points. memoRandomPoissonDynamics :: Dynamics Double                              -- ^ the mean                              -> Simulation (Dynamics Int)@@ -119,7 +158,7 @@      generatePoisson g mu'  -- | Computation that generates binomial random numbers with the specified--- probability and trials but memoizes them in the integration time points.+-- probability and trials but memoizes the numbers in the integration time points. memoRandomBinomialDynamics :: Dynamics Double  -- ^ the probability                               -> Dynamics Int  -- ^ the number of trials                               -> Simulation (Dynamics Int)@@ -130,3 +169,55 @@      prob' <- invokeDynamics p prob      trials' <- invokeDynamics p trials      generateBinomial g prob' trials'++-- | Computation that generates random numbers from the Gamma distribution+-- with the specified shape and scale but memoizes the numbers in+-- the integration time points.+memoRandomGammaDynamics :: Dynamics Double     -- ^ shape+                           -> Dynamics Double  -- ^ scale (a reciprocal of the rate)+                           -> Simulation (Dynamics Double)+memoRandomGammaDynamics kappa theta =+  memo0Dynamics $+  Dynamics $ \p ->+  do let g = runGenerator $ pointRun p+     kappa' <- invokeDynamics p kappa+     theta' <- invokeDynamics p theta+     generateGamma g kappa' theta'++-- | Computation that generates random numbers from the Beta distribution+-- by the specified shape parameters and memoizes the numbers in+-- the integration time points.+memoRandomBetaDynamics :: Dynamics Double     -- ^ shape (alpha)+                          -> Dynamics Double  -- ^ shape (beta)+                          -> Simulation (Dynamics Double)+memoRandomBetaDynamics alpha beta =+  memo0Dynamics $+  Dynamics $ \p ->+  do let g = runGenerator $ pointRun p+     alpha' <- invokeDynamics p alpha+     beta'  <- invokeDynamics p beta+     generateBeta g alpha' beta'++-- | Computation that generates random numbers from the Weibull distribution+-- with the specified shape and scale but memoizes the numbers in+-- the integration time points.+memoRandomWeibullDynamics :: Dynamics Double     -- ^ shape+                             -> Dynamics Double  -- ^ scale+                             -> Simulation (Dynamics Double)+memoRandomWeibullDynamics alpha beta =+  memo0Dynamics $+  Dynamics $ \p ->+  do let g = runGenerator $ pointRun p+     alpha' <- invokeDynamics p alpha+     beta'  <- invokeDynamics p beta+     generateWeibull g alpha' beta'++-- | Computation that generates random values from the specified discrete+-- distribution and memoizes the values in the integration time points.+memoRandomDiscreteDynamics :: Unboxed a => Dynamics (DiscretePDF a) -> Simulation (Dynamics a)+memoRandomDiscreteDynamics dpdf =+  memo0Dynamics $+  Dynamics $ \p ->+  do let g = runGenerator $ pointRun p+     dpdf' <- invokeDynamics p dpdf+     generateDiscrete g dpdf'
+ Simulation/Aivika/Gate.hs view
@@ -0,0 +1,91 @@++-- |+-- Module     : Simulation.Aivika.Gate+-- Copyright  : Copyright (c) 2009-2015, David Sorokin <david.sorokin@gmail.com>+-- License    : BSD3+-- Maintainer : David Sorokin <david.sorokin@gmail.com>+-- Stability  : experimental+-- Tested with: GHC 7.10.1+--+-- The module defines a gate which can be either opened or closed.+--+module Simulation.Aivika.Gate+       (Gate,+        newGate,+        newGateOpened,+        newGateClosed,+        openGate,+        closeGate,+        gateOpened,+        gateClosed,+        awaitGateOpened,+        awaitGateClosed,+        gateChanged_) where++import Control.Monad++import Simulation.Aivika.Simulation+import Simulation.Aivika.Event+import Simulation.Aivika.Process+import Simulation.Aivika.Signal+import Simulation.Aivika.Ref++-- | Represents a gate, which can be either opened or closed.+data Gate = Gate { gateRef :: Ref Bool }++-- | Create a new gate, specifying whether the gate is initially open.+newGate :: Bool -> Simulation Gate+newGate opened =+  do r <- newRef opened+     return Gate { gateRef = r }++-- | Create a new initially open gate.+newGateOpened :: Simulation Gate+newGateOpened = newGate True++-- | Create a new initially close gate.+newGateClosed :: Simulation Gate+newGateClosed = newGate False++-- | Open the gate if it was closed.+openGate :: Gate -> Event ()+openGate gate =+  writeRef (gateRef gate) True++-- | Close the gate if it was open.+closeGate :: Gate -> Event ()+closeGate gate =+  writeRef (gateRef gate) False++-- | Test whether the gate is open.+gateOpened :: Gate -> Event Bool+gateOpened gate =+  readRef (gateRef gate)++-- | Test whether the gate is closed.+gateClosed :: Gate -> Event Bool+gateClosed gate =+  fmap not $ readRef (gateRef gate)++-- | Await the gate to be opened if required. If the gate is already open+-- then the computation returns immediately.+awaitGateOpened :: Gate -> Process ()+awaitGateOpened gate =+  do f <- liftEvent $ readRef (gateRef gate)+     unless f $+       do processAwait $ refChanged_ (gateRef gate)+          awaitGateOpened gate++-- | Await the gate to be closed if required. If the gate is already closed+-- then the computation returns immediately.+awaitGateClosed :: Gate -> Process ()+awaitGateClosed gate =+  do f <- liftEvent $ readRef (gateRef gate)+     when f $+       do processAwait $ refChanged_ (gateRef gate)+          awaitGateClosed gate++-- | Signal triggered when the state of the gate changes.+gateChanged_ :: Gate -> Signal ()+gateChanged_ gate =+  refChanged_ (gateRef gate)
Simulation/Aivika/Generator.hs view
@@ -1,4 +1,6 @@ +{-# LANGUAGE RankNTypes #-}+ -- | -- Module     : Simulation.Aivika.Generator -- Copyright  : Copyright (c) 2009-2015, David Sorokin <david.sorokin@gmail.com>@@ -12,12 +14,16 @@ module Simulation.Aivika.Generator         (Generator(..),         GeneratorType(..),+        DiscretePDF(..),         newGenerator,         newRandomGenerator) where  import System.Random import Data.IORef +-- | A discrete probability density function.+type DiscretePDF a = [(a, Double)]+ -- | Defines a random number generator. data Generator =   Generator { generateUniform :: Double -> Double -> IO Double,@@ -26,9 +32,15 @@               generateUniformInt :: Int -> Int -> IO Int,               -- ^ Generate an uniform integer random number               -- with the specified minimum and maximum.+              generateTriangular :: Double -> Double -> Double -> IO Double,+              -- ^ Generate a triangular random number+              -- by the specified minimum, median and maximum.               generateNormal :: Double -> Double -> IO Double,               -- ^ Generate the normal random number               -- with the specified mean and deviation.+              generateLogNormal :: Double -> Double -> IO Double,+              -- ^ Generate a random number from the lognormal distribution derived+              -- from a normal distribution with the specified mean and deviation.               generateExponential :: Double -> IO Double,               -- ^ Generate the random number distributed exponentially               -- with the specified mean (the reciprocal of the rate).@@ -38,9 +50,28 @@               generatePoisson :: Double -> IO Int,               -- ^ Generate the Poisson random number               -- with the specified mean.-              generateBinomial :: Double -> Int -> IO Int+              generateBinomial :: Double -> Int -> IO Int,               -- ^ Generate the binomial random number               -- with the specified probability and number of trials.+              generateGamma :: Double -> Double -> IO Double,+              -- ^ Generate a random number from the Gamma distribution with+              -- the specified shape (kappa) and scale (theta, a reciprocal of the rate).+              --+              -- The probability density for the Gamma distribution is+              --+              -- @f x = x ** (kappa - 1) * exp (- x \/ theta) \/ theta ** kappa * Gamma kappa@+              generateBeta :: Double -> Double -> IO Double,+              -- ^ Generate a random number from the Beta distribution by+              -- the specified shape parameters (alpha and beta).+              --+              -- The probability density for the Beta distribution is+              --+              -- @f x = x ** (alpha - 1) * (1 - x) ** (beta - 1) \/ B alpha beta@+              generateWeibull :: Double -> Double -> IO Double,+              -- ^ Generate a random number from the Weibull distribution by+              -- the specified shape and scale.+              generateDiscrete :: forall a. DiscretePDF a -> IO a+              -- ^ Generate a random value from the specified discrete distribution.             }  -- | Generate the uniform random number with the specified minimum and maximum.@@ -69,6 +100,22 @@          max' = fromIntegral max      return $ round (min' + x * (max' - min')) +-- | Generate the triangular random number by the specified minimum, median and maximum.+generateTriangular01 :: IO Double+                        -- ^ the generator+                        -> Double+                        -- ^ minimum+                        -> Double+                        -- ^ median+                        -> Double+                        -- ^ maximum+                        -> IO Double+generateTriangular01 g min median max =+  do x <- g+     if x <= (median - min) / (max - min)+       then return $ min + sqrt ((median - min) * (max - min) * x)+       else return $ max - sqrt ((max - median) * (max - min) * (1 - x))+ -- | Create a normal random number generator with mean 0 and variance 1 -- by the specified generator of uniform random numbers from 0 to 1. newNormalGenerator01 :: IO Double@@ -169,6 +216,79 @@                        then loop (n - 1) (acc + 1)                        else loop (n - 1) acc +-- | Generate a random number from the Gamma distribution using Marsaglia and Tsang method.+generateGamma01 :: IO Double+                   -- ^ a normal random number ~ N (0,1)+                   -> IO Double+                   -- ^ an uniform random number ~ U (0, 1)+                   -> Double+                   -- ^ the shape parameter (kappa) +                   -> Double+                   -- ^ the scale parameter (theta)+                   -> IO Double+generateGamma01 gn gu kappa theta+  | kappa <= 0 = error "The shape parameter (kappa) must be positive: generateGamma01"+  | kappa > 1  =+    let d = kappa - 1 / 3+        c = 1 / sqrt (9 * d)+        loop =+          do z <- gn+             if z <= - (1 / c)+               then loop+               else do let v = (1 + c * z) ** 3+                       u <- gu+                       if log u > 0.5 * z * z + d - d * v + d * log v+                         then loop+                         else return $ d * v * theta+    in loop+  | otherwise  =+    do x <- generateGamma01 gn gu (1 + kappa) theta+       u <- gu+       return $ x * u ** (1 / kappa)++-- | Generate a random number from the Beta distribution.+generateBeta01 :: IO Double+                  -- ^ a normal random number ~ N (0, 1)+                  -> IO Double+                  -- ^ an uniform random number ~ U (0, 1)+                  -> Double+                  -- ^ the shape parameter alpha+                  -> Double+                  -- ^ the shape parameter beta+                  -> IO Double+generateBeta01 gn gu alpha beta =+  do g1 <- generateGamma01 gn gu alpha 1+     g2 <- generateGamma01 gn gu beta 1+     return $ g1 / (g1 + g2)++-- | Generate a random number from the Weibull distribution.+generateWeibull01 :: IO Double+                     -- ^ an uniform random number ~ U (0, 1)+                     -> Double+                     -- ^ shape+                     -> Double+                     -- ^ scale+                     -> IO Double+generateWeibull01 g alpha beta =+  do x <- g+     return $ beta * (- log x) ** (1 / alpha)++-- | Generate a random value from the specified discrete distribution.+generateDiscrete01 :: IO Double+                      -- ^ an uniform random number ~ U (0, 1)+                      -> DiscretePDF a+                      -- ^ a discrete probability density function+                      -> IO a+generateDiscrete01 g []   = error "Empty PDF: generateDiscrete01"+generateDiscrete01 g dpdf =+  do x <- g+     let loop acc [(a, p)] = a+         loop acc ((a, p) : dpdf) =+           if x <= acc + p+           then a+           else loop (acc + p) dpdf+     return $ loop 0 dpdf+ -- | Defines a type of the random number generator. data GeneratorType = SimpleGenerator                      -- ^ The simple random number generator.@@ -208,13 +328,18 @@ newRandomGenerator01 g =   do let g1 = g      g2 <- newNormalGenerator01 g1-     let g3 mu nu =-           do x <- g2-              return $ mu + nu * x+     let g3 mu nu = do { x <- g2; return $ mu + nu * x }+         g4 mu nu = do { x <- g2; return $ exp (mu + nu * x) }      return Generator { generateUniform = generateUniform01 g1,                         generateUniformInt = generateUniformInt01 g1,+                        generateTriangular = generateTriangular01 g1,                         generateNormal = g3,+                        generateLogNormal = g4,                         generateExponential = generateExponential01 g1,                         generateErlang = generateErlang01 g1,                         generatePoisson = generatePoisson01 g1,-                        generateBinomial = generateBinomial01 g1 }+                        generateBinomial = generateBinomial01 g1,+                        generateGamma = generateGamma01 g2 g1,+                        generateBeta = generateBeta01 g2 g1,+                        generateWeibull = generateWeibull01 g1,+                        generateDiscrete = generateDiscrete01 g1 }
Simulation/Aivika/Net/Random.hs view
@@ -15,12 +15,19 @@ module Simulation.Aivika.Net.Random        (randomUniformNet,         randomUniformIntNet,+        randomTriangularNet,         randomNormalNet,+        randomLogNormalNet,         randomExponentialNet,         randomErlangNet,         randomPoissonNet,-        randomBinomialNet) where+        randomBinomialNet,+        randomGammaNet,+        randomBetaNet,+        randomWeibullNet,+        randomDiscreteNet) where +import Simulation.Aivika.Generator import Simulation.Aivika.Process import Simulation.Aivika.Process.Random import Simulation.Aivika.Net@@ -48,6 +55,19 @@   randomUniformIntProcess_ min max  -- | When processing every input element, hold the process+-- for a random time interval having the triangular distribution.+randomTriangularNet :: Double+                       -- ^ the minimum time interval+                       -> Double+                       -- ^ the median of the time interval+                       -> Double+                       -- ^ the maximum time interval+                       -> Net a a+randomTriangularNet min median max =+  withinNet $+  randomTriangularProcess_ min median max++-- | When processing every input element, hold the process -- for a random time interval distributed normally. randomNormalNet :: Double                    -- ^ the mean time interval@@ -59,6 +79,19 @@   randomNormalProcess_ mu nu           -- | When processing every input element, hold the process+-- for a random time interval having the lognormal distribution.+randomLogNormalNet :: Double+                      -- ^ the mean of a normal distribution which+                      -- this distribution is derived from+                      -> Double+                      -- ^ the deviation of a normal distribution which+                      -- this distribution is derived from+                      -> Net a a+randomLogNormalNet mu nu =+  withinNet $+  randomLogNormalProcess_ mu nu++-- | When processing every input element, hold the process -- for a random time interval distributed exponentially -- with the specified mean (the reciprocal of the rate). randomExponentialNet :: Double@@ -101,3 +134,48 @@ randomBinomialNet prob trials =   withinNet $   randomBinomialProcess_ prob trials++-- | When processing every input element, hold the process+-- for a random time interval having the Gamma distribution+-- with the specified shape and scale.+randomGammaNet :: Double+                  -- ^ the shape+                  -> Double+                  -- ^ the scale (a reciprocal of the rate)+                  -> Net a a+randomGammaNet kappa theta =+  withinNet $+  randomGammaProcess_ kappa theta++-- | When processing every input element, hold the process+-- for a random time interval having the Beta distribution+-- with the specified shape parameters (alpha and beta).+randomBetaNet :: Double+                 -- ^ shape (alpha)+                 -> Double+                 -- ^ shape (beta)+                 -> Net a a+randomBetaNet alpha beta =+  withinNet $+  randomBetaProcess_ alpha beta++-- | When processing every input element, hold the process+-- for a random time interval having the Weibull distribution+-- with the specified shape and scale.+randomWeibullNet :: Double+                    -- ^ shape+                    -> Double+                    -- ^ scale+                    -> Net a a+randomWeibullNet alpha beta =+  withinNet $+  randomWeibullProcess_ alpha beta++-- | When processing every input element, hold the process+-- for a random time interval having the specified discrete distribution.+randomDiscreteNet :: DiscretePDF Double+                     -- ^ the discrete probability density function+                     -> Net a a+randomDiscreteNet dpdf =+  withinNet $+  randomDiscreteProcess_ dpdf
Simulation/Aivika/Parameter/Random.hs view
@@ -22,11 +22,17 @@ module Simulation.Aivika.Parameter.Random        (randomUniform,         randomUniformInt,+        randomTriangular,         randomNormal,+        randomLogNormal,         randomExponential,         randomErlang,         randomPoisson,         randomBinomial,+        randomGamma,+        randomBeta,+        randomWeibull,+        randomDiscrete,         randomTrue,         randomFalse) where @@ -58,6 +64,16 @@   let g = runGenerator r   in generateUniformInt g min max +-- | Computation that generates a new random number from the triangular distribution.+randomTriangular :: Double     -- ^ minimum+                    -> Double  -- ^ median+                    -> Double  -- ^ maximum+                    -> Parameter Double+randomTriangular min median max =+  Parameter $ \r ->+  let g = runGenerator r+  in generateTriangular g min median max+ -- | Computation that generates a new random number distributed normally. randomNormal :: Double     -- ^ mean                 -> Double  -- ^ deviation@@ -67,6 +83,19 @@   let g = runGenerator r   in generateNormal g mu nu +-- | Computation that generates a new random number from the lognormal distribution.+randomLogNormal :: Double+                   -- ^ the mean of a normal distribution+                   -- which this distribution is derived from+                   -> Double+                   -- ^ the deviation of a normal distribution+                   -- which this distribution is derived from+                   -> Parameter Double+randomLogNormal mu nu =+  Parameter $ \r ->+  let g = runGenerator r+  in generateLogNormal g mu nu+ -- | Computation that returns a new exponential random number with the specified mean -- (the reciprocal of the rate). randomExponential :: Double@@ -121,3 +150,38 @@ randomFalse p =   do x <- randomUniform 0 1      return (x > p)     ++-- | Computation that returns a new random number from the Gamma distribution.+randomGamma :: Double     -- ^ the shape+               -> Double  -- ^ the scale (a reciprocal of the rate)+               -> Parameter Double+randomGamma kappa theta =+  Parameter $ \r ->+  let g = runGenerator r+  in generateGamma g kappa theta++-- | Computation that returns a new random number from the Beta distribution.+randomBeta :: Double     -- ^ the shape (alpha)+              -> Double  -- ^ the shape (beta)+              -> Parameter Double+randomBeta alpha beta =+  Parameter $ \r ->+  let g = runGenerator r+  in generateBeta g alpha beta++-- | Computation that returns a new random number from the Weibull distribution.+randomWeibull :: Double     -- ^ shape+                 -> Double  -- ^ scale+                 -> Parameter Double+randomWeibull alpha beta =+  Parameter $ \r ->+  let g = runGenerator r+  in generateWeibull g alpha beta++-- | Computation that returns a new random value from the specified discrete distribution.+randomDiscrete :: DiscretePDF a -> Parameter a+randomDiscrete dpdf =+  Parameter $ \r ->+  let g = runGenerator r+  in generateDiscrete g dpdf+
Simulation/Aivika/PriorityQueue.hs view
@@ -19,6 +19,8 @@         enqueue,          dequeue,          queueFront,+        queueDelete,+        queueDeleteBy,         remove,         removeBy) where  @@ -26,6 +28,8 @@ import Data.Array.MArray.Safe import Data.Array.IO.Safe import Data.IORef+import Data.Maybe+ import Control.Monad  -- | The 'PriorityQueue' type represents an imperative heap-based @@ -171,25 +175,26 @@ -- indicating whether the element was actually removed. -- -- Note that unlike other functions it has complexity O(n).-remove :: Eq a => PriorityQueue a -> a -> IO Bool-remove pq a = removeBy pq (== a)+queueDelete :: Eq a => PriorityQueue a -> a -> IO Bool+queueDelete pq a = fmap isJust $ queueDeleteBy pq (== a) --- | Remove an element satisfying the predicate and return a computation of the flag--- indicating whether the element was actually removed.+-- | Remove an element satisfying the predicate and return a computation of+-- the element if found. -- -- Note that unlike other functions it has complexity O(n).-removeBy :: PriorityQueue a -> (a -> Bool) -> IO Bool-removeBy pq pred =-  do index <- indexBy pq pred+queueDeleteBy :: PriorityQueue a -> (a -> Bool) -> IO (Maybe a)+queueDeleteBy pq pred =+  do index <- queueIndexBy pq pred      if index < 0-       then return False+       then return Nothing        else do size <- readIORef (pqSize pq)                when (size == 0) $-                 error "Internal error in the priority queue implementation: removeBy"+                 error "Internal error in the priority queue implementation: queueDeleteBy"                let i = size - 1                writeIORef (pqSize pq) i                keys <- readIORef (pqKeys pq)                vals <- readIORef (pqVals pq)+               x <- readArray vals index                k <- readArray keys i                v <- readArray vals i                let k0 = 0.0@@ -198,11 +203,11 @@                writeArray vals i v0                when (i > 0) $                  siftDown keys vals i index k v-               return True+               return (Just x)       -- | Return the index of the item satisfying the predicate or -1.     -indexBy :: PriorityQueue a -> (a -> Bool) -> IO Int-indexBy pq pred =+queueIndexBy :: PriorityQueue a -> (a -> Bool) -> IO Int+queueIndexBy pq pred =   do size <- readIORef (pqSize pq)      vals <- readIORef (pqVals pq)      let loop index =@@ -213,3 +218,13 @@                      then return index                      else loop $ index + 1      loop 0++-- | Use 'queueDelete' instead.+remove :: Eq a => PriorityQueue a -> a -> IO Bool+{-# DEPRECATED remove "Use queueDelete instead." #-}+remove = queueDelete++-- | Use 'queueDeleteBy' instead.+removeBy :: PriorityQueue a -> (a -> Bool) -> IO Bool+{-# DEPRECATED removeBy "Use queueDeleteBy instead." #-}+removeBy pq pred = fmap isJust $ queueDeleteBy pq pred
Simulation/Aivika/Process/Random.hs view
@@ -17,8 +17,12 @@         randomUniformProcess_,         randomUniformIntProcess,         randomUniformIntProcess_,+        randomTriangularProcess,+        randomTriangularProcess_,         randomNormalProcess,         randomNormalProcess_,+        randomLogNormalProcess,+        randomLogNormalProcess_,         randomExponentialProcess,         randomExponentialProcess_,         randomErlangProcess,@@ -26,11 +30,20 @@         randomPoissonProcess,         randomPoissonProcess_,         randomBinomialProcess,-        randomBinomialProcess_) where+        randomBinomialProcess_,+        randomGammaProcess,+        randomGammaProcess_,+        randomBetaProcess,+        randomBetaProcess_,+        randomWeibullProcess,+        randomWeibullProcess_,+        randomDiscreteProcess,+        randomDiscreteProcess_) where  import Control.Monad import Control.Monad.Trans +import Simulation.Aivika.Generator import Simulation.Aivika.Parameter import Simulation.Aivika.Parameter.Random import Simulation.Aivika.Process@@ -81,6 +94,33 @@   do t <- liftParameter $ randomUniformInt min max      holdProcess $ fromIntegral t +-- | Hold the process for a random time interval having the triangular distribution.+randomTriangularProcess :: Double+                           -- ^ the minimum time interval+                           -> Double+                           -- ^ a median of the time interval+                           -> Double+                           -- ^ the maximum time interval+                           -> Process Double+                           -- ^ a computation of the time interval+                           -- for which the process was actually held+randomTriangularProcess min median max =+  do t <- liftParameter $ randomTriangular min median max+     holdProcess t+     return t++-- | Hold the process for a random time interval having the triangular distribution.+randomTriangularProcess_ :: Double+                            -- ^ the minimum time interval+                            -> Double+                            -- ^ a median of the time interval+                            -> Double+                            -- ^ the maximum time interval+                            -> Process ()+randomTriangularProcess_ min median max =+  do t <- liftParameter $ randomTriangular min median max+     holdProcess t+ -- | Hold the process for a random time interval distributed normally. randomNormalProcess :: Double                        -- ^ the mean time interval@@ -105,7 +145,34 @@   do t <- liftParameter $ randomNormal mu nu      when (t > 0) $        holdProcess t-         ++-- | Hold the process for a random time interval having the lognormal distribution.+randomLogNormalProcess :: Double+                          -- ^ the mean for a normal distribution+                          -- which this distribution is derived from+                          -> Double+                          -- ^ the deviation for a normal distribution+                          -- which this distribution is derived from+                          -> Process Double+                          -- ^ a computation of the time interval+                          -- for which the process was actually held+randomLogNormalProcess mu nu =+  do t <- liftParameter $ randomLogNormal mu nu+     holdProcess t+     return t++-- | Hold the process for a random time interval having the lognormal distribution.+randomLogNormalProcess_ :: Double+                           -- ^ the mean for a normal distribution+                           -- which this distribution is derived from+                           -> Double+                           -- ^ the deviation for a normal distribution+                           -- which this distribution is derived from+                           -> Process ()+randomLogNormalProcess_ mu nu =+  do t <- liftParameter $ randomLogNormal mu nu+     holdProcess t+ -- | Hold the process for a random time interval distributed exponentially -- with the specified mean (the reciprocal of the rate). randomExponentialProcess :: Double@@ -197,3 +264,97 @@ randomBinomialProcess_ prob trials =   do t <- liftParameter $ randomBinomial prob trials      holdProcess $ fromIntegral t++-- | Hold the process for a random time interval having the Gamma distribution+-- with the specified shape and scale.+randomGammaProcess :: Double+                      -- ^ the shape+                      -> Double+                      -- ^ the scale (a reciprocal of the rate)+                      -> Process Double+                      -- ^ a computation of the time interval+                      -- for which the process was actually held+randomGammaProcess kappa theta =+  do t <- liftParameter $ randomGamma kappa theta+     holdProcess t+     return t++-- | Hold the process for a random time interval having the Gamma distribution+-- with the specified shape and scale.+randomGammaProcess_ :: Double+                       -- ^ the shape+                       -> Double+                       -- ^ the scale (a reciprocal of the rate)+                       -> Process ()+randomGammaProcess_ kappa theta =+  do t <- liftParameter $ randomGamma kappa theta+     holdProcess t++-- | Hold the process for a random time interval having the Beta distribution+-- with the specified shape parameters (alpha and beta).+randomBetaProcess :: Double+                     -- ^ the shape (alpha)+                     -> Double+                     -- ^ the shape (beta)+                     -> Process Double+                     -- ^ a computation of the time interval+                     -- for which the process was actually held+randomBetaProcess alpha beta =+  do t <- liftParameter $ randomBeta alpha beta+     holdProcess t+     return t++-- | Hold the process for a random time interval having the Beta distribution+-- with the specified shape parameters (alpha and beta).+randomBetaProcess_ :: Double+                      -- ^ the shape (alpha)+                      -> Double+                      -- ^ the shape (beta)+                      -> Process ()+randomBetaProcess_ alpha beta =+  do t <- liftParameter $ randomBeta alpha beta+     holdProcess t++-- | Hold the process for a random time interval having the Weibull distribution+-- with the specified shape and scale.+randomWeibullProcess :: Double+                        -- ^ the shape+                        -> Double+                        -- ^ the scale+                        -> Process Double+                        -- ^ a computation of the time interval+                        -- for which the process was actually held+randomWeibullProcess alpha beta =+  do t <- liftParameter $ randomWeibull alpha beta+     holdProcess t+     return t++-- | Hold the process for a random time interval having the Weibull distribution+-- with the specified shape and scale.+randomWeibullProcess_ :: Double+                         -- ^ the shape+                         -> Double+                         -- ^ the scale+                         -> Process ()+randomWeibullProcess_ alpha beta =+  do t <- liftParameter $ randomWeibull alpha beta+     holdProcess t++-- | Hold the process for a random time interval having the specified discrete distribution.+randomDiscreteProcess :: DiscretePDF Double+                         -- ^ the discrete probability density function+                         -> Process Double+                         -- ^ a computation of the time interval+                         -- for which the process was actually held+randomDiscreteProcess dpdf =+  do t <- liftParameter $ randomDiscrete dpdf+     holdProcess t+     return t++-- | Hold the process for a random time interval having the specified discrete distribution.+randomDiscreteProcess_ :: DiscretePDF Double+                          -- ^ the discrete probability density function+                          -> Process ()+randomDiscreteProcess_ dpdf =+  do t <- liftParameter $ randomDiscrete dpdf+     holdProcess t
Simulation/Aivika/Processor/Random.hs view
@@ -15,12 +15,19 @@ module Simulation.Aivika.Processor.Random        (randomUniformProcessor,         randomUniformIntProcessor,+        randomTriangularProcessor,         randomNormalProcessor,+        randomLogNormalProcessor,         randomExponentialProcessor,         randomErlangProcessor,         randomPoissonProcessor,-        randomBinomialProcessor) where+        randomBinomialProcessor,+        randomGammaProcessor,+        randomBetaProcessor,+        randomWeibullProcessor,+        randomDiscreteProcessor) where +import Simulation.Aivika.Generator import Simulation.Aivika.Process import Simulation.Aivika.Process.Random import Simulation.Aivika.Processor@@ -48,6 +55,19 @@   randomUniformIntProcess_ min max  -- | When processing every input element, hold the process+-- for a random time interval having the triangular distribution.+randomTriangularProcessor :: Double+                             -- ^ the minimum time interval+                             -> Double+                             -- ^ the median of the time interval+                             -> Double+                             -- ^ the maximum time interval+                             -> Processor a a+randomTriangularProcessor min median max =+  withinProcessor $+  randomTriangularProcess_ min median max++-- | When processing every input element, hold the process -- for a random time interval distributed normally. randomNormalProcessor :: Double                          -- ^ the mean time interval@@ -59,6 +79,19 @@   randomNormalProcess_ mu nu           -- | When processing every input element, hold the process+-- for a random time interval having the lognormal distribution.+randomLogNormalProcessor :: Double+                            -- ^ the mean for a normal distribution+                            -- which this distribution is derived from+                            -> Double+                            -- ^ the deviation for a normal distribution+                            -- which this distribution is derived from+                            -> Processor a a+randomLogNormalProcessor mu nu =+  withinProcessor $+  randomLogNormalProcess_ mu nu++-- | When processing every input element, hold the process -- for a random time interval distributed exponentially -- with the specified mean (the reciprocal of the rate). randomExponentialProcessor :: Double@@ -101,3 +134,48 @@ randomBinomialProcessor prob trials =   withinProcessor $   randomBinomialProcess_ prob trials++-- | When processing every input element, hold the process+-- for a random time interval having the Gamma distribution+-- with the specified shape and scale.+randomGammaProcessor :: Double+                        -- ^ the shape+                        -> Double+                        -- ^ the scale (a reciprocal of the rate)+                        -> Processor a a+randomGammaProcessor kappa theta =+  withinProcessor $+  randomGammaProcess_ kappa theta++-- | When processing every input element, hold the process+-- for a random time interval having the Beta distribution+-- with the specified shape parameters (alpha and beta).+randomBetaProcessor :: Double+                       -- ^ shape (alpha)+                       -> Double+                       -- ^ shape (beta)+                       -> Processor a a+randomBetaProcessor alpha beta =+  withinProcessor $+  randomBetaProcess_ alpha beta++-- | When processing every input element, hold the process+-- for a random time interval having the Weibull distribution+-- with the specified shape and scale.+randomWeibullProcessor :: Double+                          -- ^ shape+                          -> Double+                          -- ^ scale+                          -> Processor a a+randomWeibullProcessor alpha beta =+  withinProcessor $+  randomWeibullProcess_ alpha beta++-- | When processing every input element, hold the process+-- for a random time interval having the specified discrete distribution.+randomDiscreteProcessor :: DiscretePDF Double+                           -- ^ the discrete probability density function+                           -> Processor a a+randomDiscreteProcessor dpdf =+  withinProcessor $+  randomDiscreteProcess_ dpdf
Simulation/Aivika/Queue.hs view
@@ -63,6 +63,11 @@         enqueueOrLost_,         enqueueWithStoringPriorityOrLost,         enqueueWithStoringPriorityOrLost_,+        queueDelete,+        queueDelete_,+        queueDeleteBy,+        queueDeleteBy_,+        clearQueue,         -- * Awaiting         waitWhileFullQueue,         -- * Summary@@ -107,6 +112,7 @@  import Data.IORef import Data.Monoid+import Data.Maybe  import Control.Monad import Control.Monad.Trans@@ -487,7 +493,7 @@ -- | Return the total wait time from the time at which the enqueueing operation -- was initiated to the time at which the item was dequeued. ----- In some sense, @queueTotalWaitTime == queueInputWaitTime + queueWaitTime@.+-- In some sense, @queueTotalWaitTime == enqueueWaitTime + queueWaitTime@. -- -- See also 'queueTotalWaitTimeChanged' and 'queueTotalWaitTimeChanged_'. queueTotalWaitTime :: Queue si sm so a -> Event (SamplingStats Double)@@ -607,6 +613,77 @@                fmap Just $ dequeueExtract q t        else return Nothing +-- | Remove the item from the queue and return a flag indicating+-- whether the item was found and actually removed.+queueDelete :: (Eq a,+                DequeueStrategy si,+                DeletingQueueStrategy sm,+                DequeueStrategy so)+               => Queue si sm so a+               -- ^ the queue+               -> a+               -- ^ the item to remove from the queue+               -> Event Bool+               -- ^ whether the item was found and removed+queueDelete q a = fmap isJust $ queueDeleteBy q (== a)++-- | Remove the specified item from the queue.+queueDelete_ :: (Eq a,+                 DequeueStrategy si,+                 DeletingQueueStrategy sm,+                 DequeueStrategy so)+                => Queue si sm so a+                -- ^ the queue+                -> a+                -- ^ the item to remove from the queue+                -> Event ()+queueDelete_ q a = fmap (const ()) $ queueDeleteBy q (== a)++-- | Remove an item satisfying the specified predicate and return the item if found.+queueDeleteBy :: (DequeueStrategy si,+                  DeletingQueueStrategy sm,+                  DequeueStrategy so)+                 => Queue si sm so a+                 -- ^ the queue+                 -> (a -> Bool)+                 -- ^ the predicate+                 -> Event (Maybe a)+queueDeleteBy q pred =+  do x <- tryRequestResourceWithinEvent (dequeueRes q)+     if x+       then do i <- strategyQueueDeleteBy (queueStore q) (pred . itemValue)+               case i of+                 Nothing ->+                   do releaseResourceWithinEvent (dequeueRes q)+                      return Nothing+                 Just i ->+                   do t <- dequeueRequest q+                      fmap Just $ dequeuePostExtract q t i+       else return Nothing+               +-- | Remove an item satisfying the specified predicate.+queueDeleteBy_ :: (DequeueStrategy si,+                   DeletingQueueStrategy sm,+                   DequeueStrategy so)+                  => Queue si sm so a+                  -- ^ the queue+                  -> (a -> Bool)+                  -- ^ the predicate+                  -> Event ()+queueDeleteBy_ q pred = fmap (const ()) $ queueDeleteBy q pred++-- | Clear the queue immediately.+clearQueue :: (DequeueStrategy si,+               DequeueStrategy sm)+              => Queue si sm so a+              -- ^ the queue+              -> Event ()+clearQueue q =+  do x <- tryDequeue q+     case x of+       Nothing -> return ()+       Just a  -> clearQueue q+               -- | Enqueue the item suspending the process if the queue is full.   enqueue :: (EnqueueStrategy si,             EnqueueStrategy sm,@@ -921,7 +998,23 @@   Event $ \p ->   do i <- invokeEvent p $           strategyDequeue (queueStore q)-     c <- readIORef (queueCountRef q)+     invokeEvent p $+       dequeuePostExtract q t' i++-- | A post action after extracting the item by the dequeuing request.  +dequeuePostExtract :: (DequeueStrategy si,+                       DequeueStrategy sm)+                      => Queue si sm so a+                      -- ^ the queue+                      -> Double+                      -- ^ the time of the dequeuing request+                      -> QueueItem a+                      -- ^ the item to dequeue+                      -> Event a+                      -- ^ the dequeued value+dequeuePostExtract q t' i =+  Event $ \p ->+  do c <- readIORef (queueCountRef q)      let c' = c - 1          t  = pointTime p      c' `seq` writeIORef (queueCountRef q) c'
Simulation/Aivika/Queue/Infinite.hs view
@@ -43,6 +43,11 @@         tryDequeue,         enqueue,         enqueueWithStoringPriority,+        queueDelete,+        queueDelete_,+        queueDeleteBy,+        queueDeleteBy_,+        clearQueue,         -- * Summary         queueSummary,         -- * Derived Signals for Properties@@ -71,6 +76,7 @@  import Data.IORef import Data.Monoid+import Data.Maybe  import Control.Monad import Control.Monad.Trans@@ -408,6 +414,72 @@                fmap Just $ dequeueExtract q t        else return Nothing +-- | Remove the item from the queue and return a flag indicating+-- whether the item was found and actually removed.+queueDelete :: (Eq a,+                DeletingQueueStrategy sm,+                DequeueStrategy so)+               => Queue sm so a+               -- ^ the queue+               -> a+               -- ^ the item to remove from the queue+               -> Event Bool+               -- ^ whether the item was found and removed+queueDelete q a = fmap isJust $ queueDeleteBy q (== a)++-- | Remove the specified item from the queue.+queueDelete_ :: (Eq a,+                 DeletingQueueStrategy sm,+                 DequeueStrategy so)+                => Queue sm so a+                -- ^ the queue+                -> a+                -- ^ the item to remove from the queue+                -> Event ()+queueDelete_ q a = fmap (const ()) $ queueDeleteBy q (== a)++-- | Remove an item satisfying the specified predicate and return the item if found.+queueDeleteBy :: (DeletingQueueStrategy sm,+                  DequeueStrategy so)+                 => Queue sm so a+                 -- ^ the queue+                 -> (a -> Bool)+                 -- ^ the predicate+                 -> Event (Maybe a)+queueDeleteBy q pred =+  do x <- tryRequestResourceWithinEvent (dequeueRes q)+     if x+       then do i <- strategyQueueDeleteBy (queueStore q) (pred . itemValue)+               case i of+                 Nothing ->+                   do releaseResourceWithinEvent (dequeueRes q)+                      return Nothing+                 Just i ->+                   do t <- dequeueRequest q+                      fmap Just $ dequeuePostExtract q t i+       else return Nothing+               +-- | Remove an item satisfying the specified predicate.+queueDeleteBy_ :: (DeletingQueueStrategy sm,+                   DequeueStrategy so)+                  => Queue sm so a+                  -- ^ the queue+                  -> (a -> Bool)+                  -- ^ the predicate+                  -> Event ()+queueDeleteBy_ q pred = fmap (const ()) $ queueDeleteBy q pred++-- | Clear the queue immediately.+clearQueue :: DequeueStrategy sm+              => Queue sm so a+              -- ^ the queue+              -> Event ()+clearQueue q =+  do x <- tryDequeue q+     case x of+       Nothing -> return ()+       Just a  -> clearQueue q+ -- | Enqueue the item.   enqueue :: (EnqueueStrategy sm,             DequeueStrategy so)@@ -520,7 +592,22 @@   Event $ \p ->   do i <- invokeEvent p $           strategyDequeue (queueStore q)-     c <- readIORef (queueCountRef q)+     invokeEvent p $+       dequeuePostExtract q t' i++-- | A post action after extracting the item by the dequeuing request.  +dequeuePostExtract :: DequeueStrategy sm+                      => Queue sm so a+                      -- ^ the queue+                      -> Double+                      -- ^ the time of the dequeuing request+                      -> QueueItem a+                      -- ^ the item to dequeue+                      -> Event a+                      -- ^ the dequeued value+dequeuePostExtract q t' i =+  Event $ \p ->+  do c <- readIORef (queueCountRef q)      let c' = c - 1          t  = pointTime p      c' `seq` writeIORef (queueCountRef q) c'
Simulation/Aivika/QueueStrategy.hs view
@@ -15,6 +15,7 @@  import System.Random import Control.Monad.Trans+import Data.Maybe  import Simulation.Aivika.Simulation import Simulation.Aivika.Event@@ -73,6 +74,28 @@                                  -> Event ()                                  -- ^ the action of enqueuing +-- | Defines a strategy with support of the deleting operation.+class DequeueStrategy s => DeletingQueueStrategy s where++  -- | Remove the element and return a flag indicating whether+  -- the element was found and removed.+  strategyQueueDelete :: Eq i+                         => StrategyQueue s i+                         -- ^ the queue+                         -> i+                         -- ^ the element+                         -> Event Bool+                         -- ^ whether the element was found and removed+  strategyQueueDelete s i = fmap isJust $ strategyQueueDeleteBy s (== i)++  -- | Remove an element satisfying the predicate and return the element if found.+  strategyQueueDeleteBy :: StrategyQueue s i+                           -- ^ the queue+                           -> (i -> Bool)+                           -- ^ the predicate+                           -> Event (Maybe i)+                           -- ^ the element if it was found and removed+ -- | Strategy: First Come - First Served (FCFS). data FCFS = FCFS deriving (Eq, Ord, Show) @@ -109,6 +132,11 @@    strategyEnqueue (FCFSQueue q) i = liftIO $ listAddLast q i +-- | An implementation of the 'FCFS' queue strategy.+instance DeletingQueueStrategy FCFS where++  strategyQueueDeleteBy (FCFSQueue q) p = liftIO $ listRemoveBy q p+ -- | An implementation of the 'LCFS' queue strategy. instance QueueStrategy LCFS where @@ -133,6 +161,11 @@    strategyEnqueue (LCFSQueue q) i = liftIO $ listInsertFirst q i +-- | An implementation of the 'LCFS' queue strategy.+instance DeletingQueueStrategy LCFS where++  strategyQueueDeleteBy (LCFSQueue q) p = liftIO $ listRemoveBy q p+ -- | An implementation of the 'StaticPriorities' queue strategy. instance QueueStrategy StaticPriorities where @@ -157,6 +190,11 @@    strategyEnqueueWithPriority (StaticPriorityQueue q) p i = liftIO $ PQ.enqueue q p i +-- | An implementation of the 'StaticPriorities' queue strategy.+instance DeletingQueueStrategy StaticPriorities where++  strategyQueueDeleteBy (StaticPriorityQueue q) p = liftIO $ PQ.queueDeleteBy q p+ -- | An implementation of the 'SIRO' queue strategy. instance QueueStrategy SIRO where @@ -185,3 +223,8 @@ instance EnqueueStrategy SIRO where    strategyEnqueue (SIROQueue q) i = liftIO $ V.appendVector q i++-- | An implementation of the 'SIRO' queue strategy.+instance DeletingQueueStrategy SIRO where++  strategyQueueDeleteBy (SIROQueue q) p = liftIO $ V.vectorDeleteBy q p
Simulation/Aivika/Resource/Preemption.hs view
@@ -46,6 +46,7 @@  import Data.IORef import Data.Monoid+import Data.Maybe  import Control.Monad import Control.Monad.Trans@@ -308,7 +309,7 @@   Process $ \pid ->   Cont $ \c ->   Event $ \p ->-  do f <- PQ.removeBy (resourceActingQueue r) (\item -> actingItemId item == pid)+  do f <- fmap isJust $ PQ.queueDeleteBy (resourceActingQueue r) (\item -> actingItemId item == pid)      if f        then do invokeEvent p $ updateResourceUtilisationCount r (-1)                invokeEvent p $ releaseResource' r
Simulation/Aivika/Resource/Preemption/Base.hs view
@@ -32,6 +32,7 @@         alterResourceCount) where  import Data.IORef+import Data.Maybe  import Control.Monad import Control.Monad.Trans@@ -186,7 +187,7 @@   Process $ \pid ->   Cont $ \c ->   Event $ \p ->-  do f <- PQ.removeBy (resourceActingQueue r) (\item -> actingItemId item == pid)+  do f <- fmap isJust $ PQ.queueDeleteBy (resourceActingQueue r) (\item -> actingItemId item == pid)      if f        then do invokeEvent p $ releaseResource' r                invokeEvent p $ resumeCont c ()
+ Simulation/Aivika/Results/Transform.hs view
@@ -0,0 +1,610 @@++{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}++-- |+-- Module     : Simulation.Aivika.Results.Transform+-- Copyright  : Copyright (c) 2009-2015, David Sorokin <david.sorokin@gmail.com>+-- License    : BSD3+-- Maintainer : David Sorokin <david.sorokin@gmail.com>+-- Stability  : experimental+-- Tested with: GHC 7.10.1+--+-- The module defines useful result transformations that can+-- be used in simulation experiments.+--+module Simulation.Aivika.Results.Transform+       (-- * Basic Class Type+        ResultTransformer(..),+        -- * Sampling Statistics+        SamplingStats(..),+        samplingStatsCount,+        samplingStatsMin,+        samplingStatsMax,+        samplingStatsMean,+        samplingStatsMean2,+        samplingStatsVariance,+        samplingStatsDeviation,+        -- * Time-dependent Statistics+        TimingStats(..),+        timingStatsCount,+        timingStatsMin,+        timingStatsMax,+        timingStatsMean,+        timingStatsVariance,+        timingStatsDeviation,+        timingStatsMinTime,+        timingStatsMaxTime,+        timingStatsStartTime,+        timingStatsLastTime,+        timingStatsSum,+        timingStatsSum2,+        -- * Sampling-based Counter+        SamplingCounter(..),+        samplingCounterValue,+        samplingCounterStats,+        -- * Time-dependent Counter+        TimingCounter(..),+        timingCounterValue,+        timingCounterStats,+        -- * Queue+        Queue(..),+        enqueueStrategy,+        enqueueStoringStrategy,+        dequeueStrategy,+        queueNull,+        queueFull,+        queueMaxCount,+        queueCount,+        queueCountStats,+        enqueueCount,+        enqueueLostCount,+        enqueueStoreCount,+        dequeueCount,+        dequeueExtractCount,+        queueLoadFactor,+        enqueueRate,+        enqueueStoreRate,+        dequeueRate,+        dequeueExtractRate,+        queueWaitTime,+        queueTotalWaitTime,+        enqueueWaitTime,+        dequeueWaitTime,+        queueRate,+        -- * Arrival Timer+        ArrivalTimer(..),+        arrivalProcessingTime,+        -- * Server+        Server(..),+        serverInitState,+        serverState,+        serverTotalInputWaitTime,+        serverTotalProcessingTime,+        serverTotalOutputWaitTime,+        serverTotalPreemptionTime,+        serverInputWaitTime,+        serverProcessingTime,+        serverOutputWaitTime,+        serverPreemptionTime,+        serverInputWaitFactor,+        serverProcessingFactor,+        serverOutputWaitFactor,+        serverPreemptionFactor,+        -- * Activity+        Activity(..),+        activityInitState,+        activityState,+        activityTotalUtilisationTime,+        activityTotalIdleTime,+        activityTotalPreemptionTime,+        activityUtilisationTime,+        activityIdleTime,+        activityPreemptionTime,+        activityUtilisationFactor,+        activityIdleFactor,+        activityPreemptionFactor,+        -- * Resource+        Resource(..),+        resourceCount,+        resourceCountStats,+        resourceUtilisationCount,+        resourceUtilisationCountStats,+        resourceQueueCount,+        resourceQueueCountStats,+        resourceTotalWaitTime,+        resourceWaitTime) where++import Control.Arrow++import Simulation.Aivika.Results+import Simulation.Aivika.Results.Locale++-- | Something that can transform the results.+class ResultTransformer a where++  -- | Return the result transform.+  tr :: a -> ResultTransform++instance ResultTransformer ResultTransform where+  tr = id++-- | Represents a statistics based upon observations.+newtype SamplingStats = SamplingStats ResultTransform++instance ResultTransformer SamplingStats where+  tr (SamplingStats a) = a++-- | The total number of samples.+samplingStatsCount :: SamplingStats -> ResultTransform+samplingStatsCount (SamplingStats a) =+  a >>> expandResults >>> resultById SamplingStatsCountId++-- | The minimum value among the samples.+samplingStatsMin :: SamplingStats -> ResultTransform+samplingStatsMin (SamplingStats a) =+  a >>> expandResults >>> resultById SamplingStatsMinId++-- | The maximum value among the samples.+samplingStatsMax :: SamplingStats -> ResultTransform+samplingStatsMax (SamplingStats a) =+  a >>> expandResults >>> resultById SamplingStatsMaxId+  +-- | The average value.+samplingStatsMean :: SamplingStats -> ResultTransform+samplingStatsMean (SamplingStats a) =+  a >>> expandResults >>> resultById SamplingStatsMeanId++-- | The average square value.+samplingStatsMean2 :: SamplingStats -> ResultTransform+samplingStatsMean2 (SamplingStats a) =+  a >>> expandResults >>> resultById SamplingStatsMean2Id++-- | Return tha variance.+samplingStatsVariance :: SamplingStats -> ResultTransform+samplingStatsVariance (SamplingStats a) =+  a >>> expandResults >>> resultById SamplingStatsVarianceId++-- | Return the deviation.+samplingStatsDeviation :: SamplingStats -> ResultTransform+samplingStatsDeviation (SamplingStats a) =+  a >>> expandResults >>> resultById SamplingStatsDeviationId++-- | A counter for which the statistics is collected too.+newtype SamplingCounter = SamplingCounter ResultTransform++instance ResultTransformer SamplingCounter where+  tr (SamplingCounter a) = a++-- | The counter value.+samplingCounterValue :: SamplingCounter -> ResultTransform+samplingCounterValue (SamplingCounter a) =+  a >>> resultById SamplingCounterValueId++-- | The counter statistics.+samplingCounterStats :: SamplingCounter -> SamplingStats+samplingCounterStats (SamplingCounter a) =+  SamplingStats (a >>> resultById SamplingCounterStatsId)++-- | The time-dependent statistics.+newtype TimingStats = TimingStats ResultTransform++instance ResultTransformer TimingStats where+  tr (TimingStats a) = a++-- | Return the number of samples.+timingStatsCount :: TimingStats -> ResultTransform+timingStatsCount (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsCountId++-- | Return the minimum value.+timingStatsMin :: TimingStats -> ResultTransform+timingStatsMin (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsMinId++-- | Return the maximum value.+timingStatsMax :: TimingStats -> ResultTransform+timingStatsMax (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsMaxId++-- | Return the average value.+timingStatsMean :: TimingStats -> ResultTransform+timingStatsMean (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsMeanId++-- | Return the variance.+timingStatsVariance :: TimingStats -> ResultTransform+timingStatsVariance (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsVarianceId++-- | Return the deviation.+timingStatsDeviation :: TimingStats -> ResultTransform+timingStatsDeviation (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsDeviationId++-- | Return the time at which the minimum is attained.+timingStatsMinTime :: TimingStats -> ResultTransform+timingStatsMinTime (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsMinTimeId++-- | Return the time at which the maximum is attained.+timingStatsMaxTime :: TimingStats -> ResultTransform+timingStatsMaxTime (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsMaxTimeId++-- | Return the start time of sampling.+timingStatsStartTime :: TimingStats -> ResultTransform+timingStatsStartTime (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsStartTimeId++-- | Return the last time of sampling.+timingStatsLastTime :: TimingStats -> ResultTransform+timingStatsLastTime (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsLastTimeId++-- | Return the sum of values.+timingStatsSum :: TimingStats -> ResultTransform+timingStatsSum (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsSumId++-- | Return the sum of square values.+timingStatsSum2 :: TimingStats -> ResultTransform+timingStatsSum2 (TimingStats a) =+  a >>> expandResults >>> resultById TimingStatsSum2Id++-- | A time-dependent counter that collects the statistics too.+newtype TimingCounter = TimingCounter ResultTransform++instance ResultTransformer TimingCounter where+  tr (TimingCounter a) = a++-- | The counter value.+timingCounterValue :: TimingCounter -> ResultTransform+timingCounterValue (TimingCounter a) =+  a >>> resultById TimingCounterValueId++-- | The counter statistics.+timingCounterStats :: TimingCounter -> TimingStats+timingCounterStats (TimingCounter a) =+  TimingStats (a >>> resultById TimingCounterStatsId)++-- | Represents either finite or infinite queue.+newtype Queue = Queue ResultTransform++instance ResultTransformer Queue where+  tr (Queue a) = a++-- | The strategy applied to the enqueueing (input) processes when the finite queue is full.+enqueueStrategy :: Queue -> ResultTransform+enqueueStrategy (Queue a) =+  a >>> resultById EnqueueStrategyId++-- | The strategy applied when storing (in memory) items in the queue.+enqueueStoringStrategy :: Queue -> ResultTransform+enqueueStoringStrategy (Queue a) =+  a >>> resultById EnqueueStoringStrategyId++-- | The strategy applied to the dequeueing (output) processes when the queue is empty.+dequeueStrategy :: Queue -> ResultTransform+dequeueStrategy (Queue a) =+  a >>> resultById DequeueStrategyId++-- | Test whether the queue is empty.+queueNull :: Queue -> ResultTransform+queueNull (Queue a) =+  a >>> resultById QueueNullId++-- | Test whether the finite queue is full.+queueFull :: Queue -> ResultTransform+queueFull (Queue a) =+  a >>> resultById QueueFullId++-- | The finite queue capacity.+queueMaxCount :: Queue -> ResultTransform+queueMaxCount (Queue a) =+  a >>> resultById QueueMaxCountId++-- | Return the current queue size.+queueCount :: Queue -> ResultTransform+queueCount (Queue a) =+  a >>> resultById QueueCountId++-- | Return the queue size statistics.+queueCountStats :: Queue -> TimingStats+queueCountStats (Queue a) =+  TimingStats (a >>> resultById QueueCountStatsId)++-- | Return the total number of input items that were enqueued in the finite queue.+enqueueCount :: Queue -> ResultTransform+enqueueCount (Queue a) =+  a >>> resultById EnqueueCountId++-- | Return the number of lost items for the finite queue.+enqueueLostCount :: Queue -> ResultTransform+enqueueLostCount (Queue a) =+  a >>> resultById EnqueueLostCountId++-- | Return the total number of input items that were stored.+enqueueStoreCount :: Queue -> ResultTransform+enqueueStoreCount (Queue a) =+  a >>> resultById EnqueueStoreCountId++-- | Return the total number of requests for dequeueing the items, not taking+-- into account the failed attempts to dequeue immediately without suspension.+dequeueCount :: Queue -> ResultTransform+dequeueCount (Queue a) =+  a >>> resultById DequeueCountId++-- | Return the total number of output items that were actually dequeued.+dequeueExtractCount :: Queue -> ResultTransform+dequeueExtractCount (Queue a) =+  a >>> resultById DequeueExtractCountId++-- | Return the load factor: the finite queue size divided by its capacity.+queueLoadFactor :: Queue -> ResultTransform+queueLoadFactor (Queue a) =+  a >>> resultById QueueLoadFactorId++-- | Return the rate of the input items that were enqueued in the finite queue:+-- how many items per time.+enqueueRate :: Queue -> ResultTransform+enqueueRate (Queue a) =+  a >>> resultById EnqueueRateId++-- | Return the rate of the items that were stored: how many items per time.+enqueueStoreRate :: Queue -> ResultTransform+enqueueStoreRate (Queue a) =+  a >>> resultById EnqueueStoreRateId++-- | Return the rate of the requests for dequeueing the items: how many+-- requests per time. It does not include the failed attempts to dequeue+-- immediately without suspension.+dequeueRate :: Queue -> ResultTransform+dequeueRate (Queue a) =+  a >>> resultById DequeueRateId++-- | Return the rate of the output items that were dequeued: how many items per time.+dequeueExtractRate :: Queue -> ResultTransform+dequeueExtractRate (Queue a) =+  a >>> resultById DequeueExtractRateId++-- | Return the wait time from the time at which the item was stored in+-- the queue to the time at which it was dequeued.+queueWaitTime :: Queue -> SamplingStats+queueWaitTime (Queue a) =+  SamplingStats (a >>> resultById QueueWaitTimeId)++-- | Return the total wait time for the finite queue from the time at which+-- the enqueueing operation was initiated to the time at which the item was dequeued.+queueTotalWaitTime :: Queue -> SamplingStats+queueTotalWaitTime (Queue a) =+  SamplingStats (a >>> resultById QueueTotalWaitTimeId)++-- | Return the wait time from the time at which the item was stored in+-- the queue to the time at which it was dequeued.+enqueueWaitTime :: Queue -> SamplingStats+enqueueWaitTime (Queue a) =+  SamplingStats (a >>> resultById EnqueueWaitTimeId)++-- | Return the dequeue wait time from the time at which the item was requested+-- for dequeueing to the time at which it was actually dequeued.+dequeueWaitTime :: Queue -> SamplingStats+dequeueWaitTime (Queue a) =+  SamplingStats (a >>> resultById DequeueWaitTimeId)++-- | Return a long-term average queue rate calculated as the average queue size+-- divided by the average wait time.+queueRate :: Queue -> ResultTransform+queueRate (Queue a) =+  a >>> resultById QueueRateId++-- | Accumulates the statistics about that how long the arrived events are processed.+newtype ArrivalTimer = ArrivalTimer ResultTransform++instance ResultTransformer ArrivalTimer where+  tr (ArrivalTimer a) = a++-- | Return the statistics about that how long the arrived events were processed.+arrivalProcessingTime :: ArrivalTimer -> SamplingStats+arrivalProcessingTime (ArrivalTimer a) =+  SamplingStats (a >>> resultById ArrivalProcessingTimeId)++-- | It models the server that prodives a service.+newtype Server = Server ResultTransform++instance ResultTransformer Server where+  tr (Server a) = a++-- | The initial state of the server.+serverInitState :: Server -> ResultTransform+serverInitState (Server a) =+  a >>> resultById ServerInitStateId++-- | Return the current state of the server.+serverState :: Server -> ResultTransform+serverState (Server a) =+  a >>> resultById ServerStateId++-- | Return the counted total time when the server was locked while+-- awaiting the input.+serverTotalInputWaitTime :: Server -> ResultTransform+serverTotalInputWaitTime (Server a) =+  a >>> resultById ServerTotalInputWaitTimeId++-- | Return the counted total time spent by the server while+-- processing the tasks.+serverTotalProcessingTime :: Server -> ResultTransform+serverTotalProcessingTime (Server a) =+  a >>> resultById ServerTotalProcessingTimeId++-- | Return the counted total time when the server was locked while+-- trying to deliver the output.+serverTotalOutputWaitTime :: Server -> ResultTransform+serverTotalOutputWaitTime (Server a) =+  a >>> resultById ServerTotalOutputWaitTimeId++-- | Return the counted total time spent by the server while it was+-- preempted waiting for the further proceeding.+serverTotalPreemptionTime :: Server -> ResultTransform+serverTotalPreemptionTime (Server a) =+  a >>> resultById ServerTotalPreemptionTimeId++-- | Return the statistics of the time when the server was locked+-- while awaiting the input.+serverInputWaitTime :: Server -> SamplingStats+serverInputWaitTime (Server a) =+  SamplingStats (a >>> resultById ServerInputWaitTimeId)++-- | Return the statistics of the time spent by the server while+-- processing the tasks.+serverProcessingTime :: Server -> SamplingStats+serverProcessingTime (Server a) =+  SamplingStats (a >>> resultById ServerProcessingTimeId)++-- | Return the statistics of the time when the server was locked+-- while trying to deliver the output.+serverOutputWaitTime :: Server -> SamplingStats+serverOutputWaitTime (Server a) =+  SamplingStats (a >>> resultById ServerOutputWaitTimeId)++-- | Return the statistics of the time spent by the server while+-- it was preempted waiting for the further proceeding.+serverPreemptionTime :: Server -> SamplingStats+serverPreemptionTime (Server a) =+  SamplingStats (a >>> resultById ServerPreemptionTimeId)++-- | It returns the factor changing from 0 to 1, which estimates+-- how often the server was awaiting for the next input task.+serverInputWaitFactor :: Server -> ResultTransform+serverInputWaitFactor (Server a) =+  a >>> resultById ServerInputWaitFactorId++-- | It returns the factor changing from 0 to 1, which estimates+-- how often the server was busy with direct processing its tasks.+serverProcessingFactor :: Server -> ResultTransform+serverProcessingFactor (Server a) =+  a >>> resultById ServerProcessingFactorId++-- | It returns the factor changing from 0 to 1, which estimates+-- how often the server was locked trying to deliver the output+-- after the task is finished.+serverOutputWaitFactor :: Server -> ResultTransform+serverOutputWaitFactor (Server a) =+  a >>> resultById ServerOutputWaitFactorId++-- | It returns the factor changing from 0 to 1, which estimates+-- how often the server was preempted waiting for the further proceeding.+serverPreemptionFactor :: Server -> ResultTransform+serverPreemptionFactor (Server a) =+  a >>> resultById ServerPreemptionFactorId++-- | It models an activity that can be utilised.+newtype Activity = Activity ResultTransform++instance ResultTransformer Activity where+  tr (Activity a) = a++-- | The initial state of the activity.+activityInitState :: Activity -> ResultTransform+activityInitState (Activity a) =+  a >>> resultById ActivityInitStateId++-- | Return the current state of the activity.+activityState :: Activity -> ResultTransform+activityState (Activity a) =+  a >>> resultById ActivityStateId++-- | Return the counted total time when the activity was utilised.+activityTotalUtilisationTime :: Activity -> ResultTransform+activityTotalUtilisationTime (Activity a) =+  a >>> resultById ActivityTotalUtilisationTimeId++-- | Return the counted total time when the activity was idle.+activityTotalIdleTime :: Activity -> ResultTransform+activityTotalIdleTime (Activity a) =+  a >>> resultById ActivityTotalIdleTimeId++-- | Return the counted total time when the activity was preemted+-- waiting for the further proceeding.+activityTotalPreemptionTime :: Activity -> ResultTransform+activityTotalPreemptionTime (Activity a) =+  a >>> resultById ActivityTotalPreemptionTimeId++-- | Return the statistics for the time when the activity was utilised.+activityUtilisationTime :: Activity -> SamplingStats+activityUtilisationTime (Activity a) =+  SamplingStats (a >>> resultById ActivityUtilisationTimeId)++-- | Return the statistics for the time when the activity was idle.+activityIdleTime :: Activity -> SamplingStats+activityIdleTime (Activity a) =+  SamplingStats (a >>> resultById ActivityIdleTimeId)++-- | Return the statistics for the time when the activity was preempted+-- waiting for the further proceeding.+activityPreemptionTime :: Activity -> SamplingStats+activityPreemptionTime (Activity a) =+  SamplingStats (a >>> resultById ActivityPreemptionTimeId)++-- | It returns the factor changing from 0 to 1, which estimates how often+-- the activity was utilised.+activityUtilisationFactor :: Activity -> ResultTransform+activityUtilisationFactor (Activity a) =+  a >>> resultById ActivityUtilisationFactorId++-- | It returns the factor changing from 0 to 1, which estimates how often+-- the activity was idle.+activityIdleFactor :: Activity -> ResultTransform+activityIdleFactor (Activity a) =+  a >>> resultById ActivityIdleFactorId++-- | It returns the factor changing from 0 to 1, which estimates how often+-- the activity was preempted waiting for the further proceeding.+activityPreemptionFactor :: Activity -> ResultTransform+activityPreemptionFactor (Activity a) =+  a >>> resultById ActivityPreemptionFactorId++-- | The resource which can be acquired and then released.+newtype Resource = Resource ResultTransform++instance ResultTransformer Resource where+  tr (Resource a) = a++-- | Return the current available count of the resource.+resourceCount :: Resource -> ResultTransform+resourceCount (Resource a) =+  a >>> resultById ResourceCountId++-- | Return the statistics for the available count of the resource.+resourceCountStats :: Resource -> TimingStats+resourceCountStats (Resource a) =+  TimingStats (a >>> resultById ResourceCountStatsId)++-- | Return the current utilisation count of the resource.+resourceUtilisationCount :: Resource -> ResultTransform+resourceUtilisationCount (Resource a) =+  a >>> resultById ResourceUtilisationCountId++-- | Return the statistics for the utilisation count of the resource.+resourceUtilisationCountStats :: Resource -> TimingStats+resourceUtilisationCountStats (Resource a) =+  TimingStats (a >>> resultById ResourceUtilisationCountStatsId)++-- | Return the current queue length of the resource.+resourceQueueCount :: Resource -> ResultTransform+resourceQueueCount (Resource a) =+  a >>> resultById ResourceQueueCountId++-- | Return the statistics for the queue length of the resource.+resourceQueueCountStats :: Resource -> TimingStats+resourceQueueCountStats (Resource a) =+  TimingStats (a >>> resultById ResourceQueueCountStatsId)++-- | Return the total wait time of the resource.+resourceTotalWaitTime :: Resource -> ResultTransform+resourceTotalWaitTime (Resource a) =+  a >>> resultById ResourceTotalWaitTimeId++-- | Return the statistics for the wait time of the resource.+resourceWaitTime :: Resource -> SamplingStats+resourceWaitTime (Resource a) =+  SamplingStats (a >>> resultById ResourceWaitTimeId)
Simulation/Aivika/Server/Random.hs view
@@ -15,19 +15,32 @@ module Simulation.Aivika.Server.Random        (newRandomUniformServer,         newRandomUniformIntServer,+        newRandomTriangularServer,         newRandomNormalServer,+        newRandomLogNormalServer,         newRandomExponentialServer,         newRandomErlangServer,         newRandomPoissonServer,         newRandomBinomialServer,+        newRandomGammaServer,+        newRandomBetaServer,+        newRandomWeibullServer,+        newRandomDiscreteServer,         newPreemptibleRandomUniformServer,         newPreemptibleRandomUniformIntServer,+        newPreemptibleRandomTriangularServer,         newPreemptibleRandomNormalServer,+        newPreemptibleRandomLogNormalServer,         newPreemptibleRandomExponentialServer,         newPreemptibleRandomErlangServer,         newPreemptibleRandomPoissonServer,-        newPreemptibleRandomBinomialServer) where+        newPreemptibleRandomBinomialServer,+        newPreemptibleRandomGammaServer,+        newPreemptibleRandomBetaServer,+        newPreemptibleRandomWeibullServer,+        newPreemptibleRandomDiscreteServer) where +import Simulation.Aivika.Generator import Simulation.Aivika.Simulation import Simulation.Aivika.Process import Simulation.Aivika.Process.Random@@ -62,6 +75,22 @@   newPreemptibleRandomUniformIntServer False  -- | Create a new server that holds the process for a random time interval+-- having the triangular distribution, when processing every input element.+--+-- By default, it is assumed that the server process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomTriangularServer :: Double+                             -- ^ the minimum time interval+                             -> Double+                             -- ^ the median of the time interval+                             -> Double+                             -- ^ the maximum time interval+                             -> Simulation (Server () a a)+newRandomTriangularServer =+  newPreemptibleRandomTriangularServer False++-- | Create a new server that holds the process for a random time interval -- distributed normally, when processing every input element. -- -- By default, it is assumed that the server process cannot be preempted,@@ -76,6 +105,22 @@   newPreemptibleRandomNormalServer False           -- | Create a new server that holds the process for a random time interval+-- having the lognormal distribution, when processing every input element.+--+-- By default, it is assumed that the server process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomLogNormalServer :: Double+                            -- ^ the mean of a normal distribution which+                            -- this distribution is derived from+                            -> Double+                            -- ^ the deviation of a normal distribution which+                            -- this distribution is derived from+                            -> Simulation (Server () a a)+newRandomLogNormalServer =+  newPreemptibleRandomLogNormalServer False++-- | Create a new server that holds the process for a random time interval -- distributed exponentially with the specified mean (the reciprocal of the rate), -- when processing every input element. --@@ -132,6 +177,63 @@   newPreemptibleRandomBinomialServer False  -- | Create a new server that holds the process for a random time interval+-- having the Gamma distribution with the specified shape and scale,+-- when processing every input element.+--+-- By default, it is assumed that the server process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomGammaServer :: Double+                        -- ^ the shape+                        -> Double+                        -- ^ the scale (a reciprocal of the rate)+                        -> Simulation (Server () a a)+newRandomGammaServer =+  newPreemptibleRandomGammaServer False++-- | Create a new server that holds the process for a random time interval+-- having the Beta distribution with the specified shape parameters (alpha and beta),+-- when processing every input element.+--+-- By default, it is assumed that the server process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomBetaServer :: Double+                       -- ^ shape (alpha)+                       -> Double+                       -- ^ shape (beta)+                       -> Simulation (Server () a a)+newRandomBetaServer =+  newPreemptibleRandomBetaServer False++-- | Create a new server that holds the process for a random time interval+-- having the Weibull distribution with the specified shape and scale,+-- when processing every input element.+--+-- By default, it is assumed that the server process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomWeibullServer :: Double+                          -- ^ shape+                          -> Double+                          -- ^ scale+                          -> Simulation (Server () a a)+newRandomWeibullServer =+  newPreemptibleRandomWeibullServer False++-- | Create a new server that holds the process for a random time interval+-- having the specified discrete distribution, when processing every input element.+--+-- By default, it is assumed that the server process cannot be preempted,+-- because the handling of possible task preemption is rather costly+-- operation.+newRandomDiscreteServer :: DiscretePDF Double+                           -- ^ the discrete probability density function+                           -> Simulation (Server () a a)+newRandomDiscreteServer =+  newPreemptibleRandomDiscreteServer False++-- | Create a new server that holds the process for a random time interval -- distributed uniformly, when processing every input element. newPreemptibleRandomUniformServer :: Bool                                      -- ^ whether the server process can be preempted@@ -160,6 +262,22 @@      return a  -- | Create a new server that holds the process for a random time interval+-- having the triangular distribution, when processing every input element.+newPreemptibleRandomTriangularServer :: Bool+                                        -- ^ whether the server process can be preempted+                                        -> Double+                                        -- ^ the minimum time interval+                                        -> Double+                                        -- ^ the median of the time interval+                                        -> Double+                                        -- ^ the maximum time interval+                                        -> Simulation (Server () a a)+newPreemptibleRandomTriangularServer preemptible min median max =+  newPreemptibleServer preemptible $ \a ->+  do randomTriangularProcess_ min median max+     return a++-- | Create a new server that holds the process for a random time interval -- distributed normally, when processing every input element. newPreemptibleRandomNormalServer :: Bool                                     -- ^ whether the server process can be preempted@@ -172,8 +290,24 @@   newPreemptibleServer preemptible $ \a ->   do randomNormalProcess_ mu nu      return a-         + -- | Create a new server that holds the process for a random time interval+-- having the lognormal distribution, when processing every input element.+newPreemptibleRandomLogNormalServer :: Bool+                                       -- ^ whether the server process can be preempted+                                       -> Double+                                       -- ^ the mean of a normal distribution which+                                       -- this distribution is derived from+                                       -> Double+                                       -- ^ the deviation of a normal distribution which+                                       -- this distribution is derived from+                                       -> Simulation (Server () a a)+newPreemptibleRandomLogNormalServer preemptible mu nu =+  newPreemptibleServer preemptible $ \a ->+  do randomLogNormalProcess_ mu nu+     return a++-- | Create a new server that holds the process for a random time interval -- distributed exponentially with the specified mean (the reciprocal of the rate), -- when processing every input element. newPreemptibleRandomExponentialServer :: Bool@@ -227,4 +361,61 @@ newPreemptibleRandomBinomialServer preemptible prob trials =   newPreemptibleServer preemptible $ \a ->   do randomBinomialProcess_ prob trials+     return a++-- | Create a new server that holds the process for a random time interval+-- having the Gamma distribution with the specified shape and scale,+-- when processing every input element.+newPreemptibleRandomGammaServer :: Bool+                                   -- ^ whether the server process can be preempted+                                   -> Double+                                   -- ^ the shape+                                   -> Double+                                   -- ^ the scale (a reciprocal of the rate)+                                   -> Simulation (Server () a a)+newPreemptibleRandomGammaServer preemptible kappa theta =+  newPreemptibleServer preemptible $ \a ->+  do randomGammaProcess_ kappa theta+     return a++-- | Create a new server that holds the process for a random time interval+-- having the Beta distribution with the specified shape parameters (alpha and beta),+-- when processing every input element.+newPreemptibleRandomBetaServer :: Bool+                                  -- ^ whether the server process can be preempted+                                  -> Double+                                  -- ^ shape (alpha)+                                  -> Double+                                  -- ^ shape (beta)+                                  -> Simulation (Server () a a)+newPreemptibleRandomBetaServer preemptible alpha beta =+  newPreemptibleServer preemptible $ \a ->+  do randomBetaProcess_ alpha beta+     return a++-- | Create a new server that holds the process for a random time interval+-- having the Weibull distribution with the specified shape and scale,+-- when processing every input element.+newPreemptibleRandomWeibullServer :: Bool+                                  -- ^ whether the server process can be preempted+                                  -> Double+                                  -- ^ shape+                                  -> Double+                                  -- ^ scale+                                  -> Simulation (Server () a a)+newPreemptibleRandomWeibullServer preemptible alpha beta =+  newPreemptibleServer preemptible $ \a ->+  do randomWeibullProcess_ alpha beta+     return a++-- | Create a new server that holds the process for a random time interval+-- having the specified discrete distribution, when processing every input element.+newPreemptibleRandomDiscreteServer :: Bool+                                      -- ^ whether the server process can be preempted+                                      -> DiscretePDF Double+                                      -- ^ the discrete probability density function+                                      -> Simulation (Server () a a)+newPreemptibleRandomDiscreteServer preemptible dpdf =+  newPreemptibleServer preemptible $ \a ->+  do randomDiscreteProcess_ dpdf      return a
Simulation/Aivika/Stream/Random.hs view
@@ -16,15 +16,22 @@         randomStream,         randomUniformStream,         randomUniformIntStream,+        randomTriangularStream,         randomNormalStream,+        randomLogNormalStream,         randomExponentialStream,         randomErlangStream,         randomPoissonStream,-        randomBinomialStream) where+        randomBinomialStream,+        randomGammaStream,+        randomBetaStream,+        randomWeibullStream,+        randomDiscreteStream) where  import Control.Monad import Control.Monad.Trans +import Simulation.Aivika.Generator import Simulation.Aivika.Parameter import Simulation.Aivika.Parameter.Random import Simulation.Aivika.Simulation@@ -66,7 +73,7 @@                                    Just t0 -> Just delay }        return (arrival, Cons $ loop (Just t2)) --- | Create a new stream with delays distributed uniformly.+-- | Create a new stream with random delays distributed uniformly. randomUniformStream :: Double                        -- ^ the minimum delay                        -> Double@@ -78,7 +85,7 @@   randomUniform min max >>= \x ->   return (x, x) --- | Create a new stream with integer delays distributed uniformly.+-- | Create a new stream with integer random delays distributed uniformly. randomUniformIntStream :: Int                           -- ^ the minimum delay                           -> Int@@ -90,7 +97,21 @@   randomUniformInt min max >>= \x ->   return (fromIntegral x, x) --- | Create a new stream with delays distributed normally.+-- | Create a new stream with random delays having the triangular distribution.+randomTriangularStream :: Double+                          -- ^ the minimum delay+                          -> Double+                          -- ^ the median of the delay+                          -> Double+                          -- ^ the maximum delay+                          -> Stream (Arrival Double)+                          -- ^ the stream of random events with the delays generated+randomTriangularStream min median max =+  randomStream $+  randomTriangular min median max >>= \x ->+  return (x, x)++-- | Create a new stream with random delays distributed normally. randomNormalStream :: Double                       -- ^ the mean delay                       -> Double@@ -101,8 +122,22 @@   randomStream $   randomNormal mu nu >>= \x ->   return (x, x)-         --- | Return a new stream with delays distibuted exponentially with the specified mean++-- | Create a new stream with random delays having the lognormal distribution.+randomLogNormalStream :: Double+                         -- ^ the mean of a normal distribution which+                         -- this distribution is derived from+                         -> Double+                         -- ^ the deviation of a normal distribution which+                         -- this distribution is derived from+                         -> Stream (Arrival Double)+                         -- ^ the stream of random events with the delays generated+randomLogNormalStream mu nu =+  randomStream $+  randomLogNormal mu nu >>= \x ->+  return (x, x)++-- | Return a new stream with random delays distibuted exponentially with the specified mean -- (the reciprocal of the rate). randomExponentialStream :: Double                            -- ^ the mean delay (the reciprocal of the rate)@@ -113,7 +148,7 @@   randomExponential mu >>= \x ->   return (x, x)          --- | Return a new stream with delays having the Erlang distribution with the specified+-- | Return a new stream with random delays having the Erlang distribution with the specified -- scale (the reciprocal of the rate) and shape parameters. randomErlangStream :: Double                       -- ^ the scale (the reciprocal of the rate)@@ -126,7 +161,7 @@   randomErlang beta m >>= \x ->   return (x, x) --- | Return a new stream with delays having the Poisson distribution with+-- | Return a new stream with random delays having the Poisson distribution with -- the specified mean. randomPoissonStream :: Double                        -- ^ the mean delay@@ -137,7 +172,7 @@   randomPoisson mu >>= \x ->   return (fromIntegral x, x) --- | Return a new stream with delays having the binomial distribution with the specified+-- | Return a new stream with random delays having the binomial distribution with the specified -- probability and trials. randomBinomialStream :: Double                         -- ^ the probability@@ -149,3 +184,52 @@   randomStream $   randomBinomial prob trials >>= \x ->   return (fromIntegral x, x)++-- | Return a new stream with random delays having the Gamma distribution by the specified+-- shape and scale.+randomGammaStream :: Double+                     -- ^ the shape+                     -> Double+                     -- ^ the scale (a reciprocal of the rate)+                     -> Stream (Arrival Double)+                     -- ^ the stream of random events with the delays generated+randomGammaStream kappa theta =+  randomStream $+  randomGamma kappa theta >>= \x ->+  return (x, x)++-- | Return a new stream with random delays having the Beta distribution by the specified+-- shape parameters (alpha and beta).+randomBetaStream :: Double+                    -- ^ the shape (alpha)+                    -> Double+                    -- ^ the shape (beta)+                    -> Stream (Arrival Double)+                    -- ^ the stream of random events with the delays generated+randomBetaStream alpha beta =+  randomStream $+  randomBeta alpha beta >>= \x ->+  return (x, x)++-- | Return a new stream with random delays having the Weibull distribution by the specified+-- shape and scale.+randomWeibullStream :: Double+                       -- ^ shape+                       -> Double+                       -- ^ scale+                       -> Stream (Arrival Double)+                       -- ^ the stream of random events with the delays generated+randomWeibullStream alpha beta =+  randomStream $+  randomWeibull alpha beta >>= \x ->+  return (x, x)++-- | Return a new stream with random delays having the specified discrete distribution.+randomDiscreteStream :: DiscretePDF Double+                        -- ^ the discrete probability density function+                        -> Stream (Arrival Double)+                        -- ^ the stream of random events with the delays generated+randomDiscreteStream dpdf =+  randomStream $+  randomDiscrete dpdf >>= \x ->+  return (x, x)
Simulation/Aivika/Vector.hs view
@@ -22,7 +22,10 @@         vectorBinarySearch,         vectorInsert,         vectorDeleteAt,+        vectorDelete,+        vectorDeleteBy,         vectorIndex,+        vectorIndexBy,         freezeVector) where   import Data.Array@@ -183,3 +186,37 @@                      then return index                      else loop $ index + 1      loop 0+     +-- | Return an index of the item satisfying the predicate or -1.     +vectorIndexBy :: Vector a -> (a -> Bool) -> IO Int+vectorIndexBy vector pred =+  do count <- readIORef (vectorCountRef vector)+     array <- readIORef (vectorArrayRef vector)+     let loop index =+           if index >= count+           then return $ -1+           else do x <- readArray array index+                   if pred x+                     then return index+                     else loop $ index + 1+     loop 0++-- | Remove the specified element and return a flag indicating+-- whether the element was found and removed.+vectorDelete :: Eq a => Vector a -> a -> IO Bool+vectorDelete vector item =+  do index <- vectorIndex vector item+     if index >= 0+       then do vectorDeleteAt vector index+               return True+       else return False+            +-- | Remove an element by the specified predicate and return the element if found.+vectorDeleteBy :: Vector a -> (a -> Bool) -> IO (Maybe a)+vectorDeleteBy vector pred =+  do index <- vectorIndexBy vector pred+     if index >= 0+       then do a <- readVector vector index+               vectorDeleteAt vector index+               return (Just a)+       else return Nothing
Simulation/Aivika/Vector/Unboxed.hs view
@@ -22,7 +22,10 @@         vectorBinarySearch,         vectorInsert,         vectorDeleteAt,+        vectorDelete,+        vectorDeleteBy,         vectorIndex,+        vectorIndexBy,         freezeVector) where   import Data.Array@@ -186,3 +189,36 @@                      else loop $ index + 1      loop 0      +-- | Return an index of the item satisfying the predicate or -1.     +vectorIndexBy :: Unboxed a => Vector a -> (a -> Bool) -> IO Int+vectorIndexBy vector pred =+  do count <- readIORef (vectorCountRef vector)+     array <- readIORef (vectorArrayRef vector)+     let loop index =+           if index >= count+           then return $ -1+           else do x <- readArray array index+                   if pred x+                     then return index+                     else loop $ index + 1+     loop 0++-- | Remove the specified element and return a flag indicating+-- whether the element was found and removed.+vectorDelete :: (Unboxed a, Eq a) => Vector a -> a -> IO Bool+vectorDelete vector item =+  do index <- vectorIndex vector item+     if index >= 0+       then do vectorDeleteAt vector index+               return True+       else return False+            +-- | Remove an element by the specified predicate and return a flag indicating+-- whether the element was found and removed.+vectorDeleteBy :: Unboxed a => Vector a -> (a -> Bool) -> IO Bool+vectorDeleteBy vector pred =+  do index <- vectorIndexBy vector pred+     if index >= 0+       then do vectorDeleteAt vector index+               return True+       else return False
aivika.cabal view
@@ -1,5 +1,5 @@ name:            aivika-version:         4.1.1+version:         4.2 synopsis:        A multi-paradigm simulation library description:     Aivika is a multi-paradigm simulation library with a strong emphasis@@ -119,6 +119,8 @@                      examples/TimeOutWait.hs                      examples/PingPong.hs                      examples/PortOperations.hs+                     examples/SingleLaneTraffic.hs+                     examples/RenegingFromQueue.hs                      CHANGELOG.md  library@@ -137,6 +139,7 @@                      Simulation.Aivika.Dynamics.Memo.Unboxed                      Simulation.Aivika.Dynamics.Random                      Simulation.Aivika.Event+                     Simulation.Aivika.Gate                      Simulation.Aivika.Generator                      Simulation.Aivika.Net                      Simulation.Aivika.Net.Random@@ -158,6 +161,7 @@                      Simulation.Aivika.Resource.Preemption                      Simulation.Aivika.Resource.Preemption.Base                      Simulation.Aivika.Results.Locale+                     Simulation.Aivika.Results.Transform                      Simulation.Aivika.Results                      Simulation.Aivika.Results.IO                      Simulation.Aivika.Server@@ -209,6 +213,8 @@                         ExistentialQuantification,                         TypeFamilies,                         DeriveDataTypeable,+                        TypeSynonymInstances,+                        RankNTypes,                         CPP                           ghc-options:     -O2
+ examples/RenegingFromQueue.hs view
@@ -0,0 +1,85 @@++-- Example: Reneging from a Queue+--+-- It is described in [1]. This is section 7.8.+-- +-- This example models customers arriving to a queue and leaving a queue+-- after a prescribed period of time. The time between arrivals is +-- exponentially distributed with a mean of 20 minutes. The service time +-- for customers is uniformly distributed between 15 and 25 minutes. +-- Customers will only wait for service if the waiting time is less than+-- a renege time which is lognormally distributed with a mean of 10 minutes+-- and a standard deviation of 2 minutes. It is desired to estimate the time+-- in the system for those customers served, the percent of customers that+-- renege and the length of the waiting time.+-- +-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.++import Control.Monad+import Control.Monad.Trans++import Data.Array++import Simulation.Aivika+import qualified Simulation.Aivika.Queue.Infinite as IQ++-- | The simulation specs.+specs = Specs { spcStartTime = 0.0,+                spcStopTime = 10000.0,+                spcDT = 0.1,+                spcMethod = RungeKutta4,+                spcGeneratorType = SimpleGenerator }++mu = 10+nu = 2++logMu = log mu - logNu * logNu / 2+logNu = sqrt $ log ((nu * nu) / (mu * mu) + 1) ++model :: Simulation Results+model = do+  let customers = randomExponentialStream 20+  timeInSystem <- newRef emptySamplingStats+  renegeEvents <- newRef (0 :: Int)+  queue <- runEventInStartTime $ IQ.newFCFSQueue+  let queueProcess =+        do x <- IQ.dequeue queue+           randomUniformProcess_ 15 25+           t <- liftDynamics time+           liftEvent $+             modifyRef timeInSystem $+             addSamplingStats (t - arrivalTime x)+           queueProcess+      renegingProcess x =+        do randomLogNormalProcess_ logMu logNu+           liftEvent $+             do f <- IQ.queueDelete queue x+                when f $ modifyRef renegeEvents ((+) 1)+  runProcessInStartTime queueProcess+  runProcessInStartTime $+    flip consumeStream customers $ \x ->+    liftEvent $+    do IQ.enqueue queue x+       runProcess $ renegingProcess x+  return $+    results+    [resultSource+     "queue" "the queue"+     queue,+     --+     resultSource+     "timeInSystem" "time in system"+     timeInSystem,+     --+     resultSource+     "renegeEvents" "renege events"+     renegeEvents]++modelSummary :: Simulation Results+modelSummary =+  fmap resultSummary model++main =+  do printSimulationResultsInStopTime+       printResultSourceInEnglish+       modelSummary specs
+ examples/SingleLaneTraffic.hs view
@@ -0,0 +1,146 @@++-- Example: Single-Lane Traffic Analysis +--+-- It is described in different sources [1, 2]. So, this is chapter 15 of [2] and section 6.18 of [1].+--+-- The system to be modeled in this example consists of the traffic flow from+-- two directions along a two-lane road, one lane of which has been closed for+-- 500 meters for repairs. Traffic lights have been placed at each end of+-- the closed lane to control the flow of traffic through the repair section.+-- The lights allow traffic to flow for a specified time interval from only+-- one direction. When a light turns green, the waiting cars start and pass+-- the light every two seconds. If a car arrives at a green light when there+-- are no waiting cars, the car passes through the light without delay. The car+-- arrival pattern is exponentially distributed, with an average of 9 seconds+-- between cars from direction 1 and 12 seconds between cars from direction 2.+-- A light cycle consists of green in direction 1, both red, green in direction 2,+-- both red, and then the cycle is repeated. Both lights remain red for 55 seconds+-- to allow the cars in transit to leave the repair section before traffic from+-- the other direction can be initiated.+-- +-- The objective is to simulate the above system to determine values for+-- the green time for direction 1 and the green time for direction 2 which+-- yield a low average waiting time for all cars.+-- +-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.+-- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006++import Control.Monad+import Control.Monad.Trans+import Control.Arrow++import Data.Array++import Simulation.Aivika+import qualified Simulation.Aivika.Resource as R++-- | The simulation specs.+specs = Specs { spcStartTime = 0.0,+                spcStopTime = 3600.0,+                spcDT = 0.1,+                spcMethod = RungeKutta4,+                spcGeneratorType = SimpleGenerator }++data LightTime =+  LightTime { greenLightTime1 :: Double,+              greenLightTime2 :: Double }++model :: LightTime -> Simulation Results+model lightTime = do+  let greenLightTime =+        array (1, 2)+        [(1, return $ greenLightTime1 lightTime :: Event Double),+         (2, return $ greenLightTime2 lightTime :: Event Double)]+  waitTime1 <- newRef emptySamplingStats+  waitTime2 <- newRef emptySamplingStats+  let waitTime =+        array (1, 2) [(1, waitTime1), (2, waitTime2)]+  start1 <-+    runEventInStartTime $+    R.newFCFSResource 1+  start2 <-+    runEventInStartTime $+    R.newFCFSResource 1+  let start =+        array (1, 2) [(1, start1), (2, start2)]+  light1 <- newGateClosed+  light2 <- newGateClosed+  let stream1 = randomExponentialStream 9+      stream2 = randomExponentialStream 12+  runProcessInStartTime $+    flip consumeStream stream1 $ \x ->+    liftEvent $+    runProcess $+    do R.requestResource start1+       awaitGateOpened light1+       t <- liftDynamics time+       liftEvent $+         modifyRef waitTime1 $+         addSamplingStats (t - arrivalTime x)+       when (t > arrivalTime x) $+         holdProcess 2+       R.releaseResource start1+  runProcessInStartTime $+    flip consumeStream stream2 $ \x ->+    liftEvent $+    runProcess $+    do R.requestResource start2+       awaitGateOpened light2+       t <- liftDynamics time+       liftEvent $+         modifyRef waitTime2 $+         addSamplingStats (t - arrivalTime x)+       when (t > arrivalTime x) $+         holdProcess 2+       R.releaseResource start2+  let lighting =+        do holdProcess 55+           liftEvent $+             openGate light1+           holdProcess $+             greenLightTime1 lightTime+           liftEvent $+             closeGate light1+           holdProcess 55+           liftEvent $+             openGate light2+           holdProcess $+             greenLightTime2 lightTime+           liftEvent $+             closeGate light2+           lighting+  runProcessInStartTime lighting+  return $+    results+    [resultSource+     "start" "Start Resource"+     start,+     --+     resultSource+     "waitTime" "Wait Time"+     waitTime,+     --+     resultSource+     "greenLightTime" "Green Light Time"+     greenLightTime]++modelSummary :: LightTime -> Simulation Results+modelSummary lightTime =+  fmap resultSummary $ model lightTime++lightTime1 = LightTime 60 45+lightTime2 = LightTime 80 60+lightTime3 = LightTime 40 30++model1 = model lightTime1+model2 = model lightTime2+model3 = model lightTime3++modelSummary1 = fmap resultSummary model1+modelSummary2 = fmap resultSummary model2+modelSummary3 = fmap resultSummary model3++main =+  do printSimulationResultsInStopTime+       printResultSourceInEnglish+       modelSummary1 specs