aivika-4.0: examples/MachineBreakdowns.hs
-- Example: Machine Tool with Breakdowns
--
-- It is described in different sources [1, 2]. So, this is chapter 13 of [2] and section 6.12 of [1].
--
-- [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.Category
import Data.Monoid
import Data.List
import Simulation.Aivika
import qualified Simulation.Aivika.Queue.Infinite as IQ
import qualified Simulation.Aivika.Resource.Preemption as PR
-- | The simulation specs.
specs = Specs { spcStartTime = 0.0,
spcStopTime = 500.0,
spcDT = 0.1,
spcMethod = RungeKutta4,
spcGeneratorType = SimpleGenerator }
-- | How often do jobs arrive to a machine tool (exponential)?
jobArrivingMu = 1
-- | A mean of time to process a job (normal).
jobProcessingMu = 0.5
-- | The standard deviation of time to process a job (normal).
jobProcessingSigma = 0.1
-- | The minimum set-up time (uniform).
minSetUpTime = 0.2
-- | The maximum set-up time (uniform).
maxSetUpTime = 0.5
-- | A mean of time between breakdowns (normal).
breakdownMu = 20
-- | The standard deviation of time between breakdowns (normal).
breakdownSigma = 2
-- | A mean of each of the three repair phases (Erlang).
repairMu = 3/4
-- | A priority of the job (less is higher)
jobPriority = 1
-- | A priority of the breakdown (less is higher)
breakdownPriority = 0
-- | The simulation model.
model :: Simulation Results
model = do
-- create an input queue
inputQueue <- runEventInStartTime IQ.newFCFSQueue
-- a counter of jobs completed
jobsCompleted <- newArrivalTimer
-- a counter of interrupted jobs
jobsInterrupted <- newRef (0 :: Int)
-- create an input stream
let inputStream =
randomExponentialStream jobArrivingMu
-- create a preemptible resource
tool <- PR.newResource 1
-- the machine setting up
machineSettingUp <-
newPreemptibleRandomUniformServer True minSetUpTime maxSetUpTime
-- the machine processing
machineProcessing <-
newPreemptibleRandomNormalServer True jobProcessingMu jobProcessingSigma
-- the machine breakdown
let machineBreakdown =
do randomNormalProcess_ breakdownMu breakdownSigma
PR.usingResourceWithPriority tool breakdownPriority $
randomErlangProcess_ repairMu 3
machineBreakdown
-- start the process of breakdowns
runProcessInStartTime machineBreakdown
-- update a counter of job interruptions
runEventInStartTime $
handleSignal_ (serverTaskPreempting machineProcessing) $ \a ->
modifyRef jobsInterrupted (+ 1)
-- define the queue network
let network =
queueProcessor
(\a -> liftEvent $ IQ.enqueue inputQueue a)
(IQ.dequeue inputQueue) >>>
(withinProcessor $ PR.requestResourceWithPriority tool jobPriority) >>>
serverProcessor machineSettingUp >>>
serverProcessor machineProcessing >>>
(withinProcessor $ PR.releaseResource tool) >>>
arrivalTimerProcessor jobsCompleted
-- start the machine tool
runProcessInStartTime $
sinkStream $ runProcessor network inputStream
-- return the simulation results in start time
return $
results
[resultSource
"inputQueue" "the queue of jobs"
inputQueue,
--
resultSource
"machineSettingUp" "the machine setting up"
machineSettingUp,
--
resultSource
"machineProcessing" "the machine processing"
machineProcessing,
--
resultSource
"jobsInterrupted" "a counter of the interrupted jobs"
jobsInterrupted,
--
resultSource
"jobsCompleted" "a counter of the completed jobs"
jobsCompleted]
main =
printSimulationResultsInStopTime
printResultSourceInEnglish
(fmap resultSummary model) specs