{-# LANGUAGE RecursiveDo, Arrows #-} -- Example: Inspection and Adjustment Stations on a Production Line -- -- This is a model of the workflow with a loop. Also there are two infinite queues. -- -- It is described in different sources [1, 2]. So, this is chapter 8 of [2] and section 5.15 of [1]. -- -- Assembled television sets move through a series of testing stations in the final -- stage of their production. At the last of these stations, the vertical control -- setting on the TV sets is tested. If the setting is found to be functioning improperly, -- the offending set is routed to an adjustment station where the setting is adjusted. -- After adjustment, the television set is sent back to the last inspection station where -- the setting is again inspected. Television sets passing the final inspection phase, -- whether for the first time of after one or more routings through the adjustment station, -- are routed to a packing area. -- -- The time between arrivals of television sets to the final inspection station is uniformly -- distributed between 3.5 and 7.5 minutes. Two inspectors work side-by-side at the final -- inspection station. The time required to inspect a set is uniformly distributed between -- 6 and 12 minutes. On the average, 85 percent of the sets are routed to the adjustment -- station which is manned by a single worker. Adjustment of the vertical control setting -- requires between 20 and 40 minutes, uniformly distributed. -- -- The inspection station and adjustor are to be simulated for 480 minutes to estimate -- the time to process television sets through the final production stage and to determine -- the utilization of the inspectors and the adjustors. -- -- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed. -- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006 module Model (model) where import Prelude hiding (id, (.)) import Control.Monad import Control.Monad.Trans import Control.Arrow import Control.Category (id, (.)) import Simulation.Aivika import Simulation.Aivika.Queue.Infinite -- | The simulation specs. specs = Specs { spcStartTime = 0.0, spcStopTime = 480.0, spcDT = 0.1, spcMethod = RungeKutta4, spcGeneratorType = SimpleGenerator } -- the minimum delay of arriving the next TV set minArrivalDelay = 3.5 -- the maximum delay of arriving the next TV set maxArrivalDelay = 7.5 -- the minimum time to inspect the TV set minInspectionTime = 6 -- the maximum time to inspect the TV set maxInspectionTime = 12 -- the probability of passing the inspection phase inspectionPassingProb = 0.85 -- how many are inspection stations? inspectionStationCount = 2 -- the minimum time to adjust an improper TV set minAdjustmentTime = 20 -- the maximum time to adjust an improper TV set maxAdjustmentTime = 40 -- how many are adjustment stations? adjustmentStationCount = 1 -- create an inspection station (server) newInspectionStation = newServer $ \a -> do holdProcess =<< (liftParameter $ randomUniform minInspectionTime maxInspectionTime) passed <- liftParameter $ randomTrue inspectionPassingProb if passed then return $ Right a else return $ Left a -- create an adjustment station (server) newAdjustmentStation = newServer $ \a -> do holdProcess =<< (liftParameter $ randomUniform minAdjustmentTime maxAdjustmentTime) return a model :: Simulation Results model = mdo -- to count the arrived TV sets for inspecting and adjusting inputArrivalTimer <- newArrivalTimer -- it will gather the statistics of the processing time outputArrivalTimer <- newArrivalTimer -- define a stream of input events let inputStream = randomUniformStream minArrivalDelay maxArrivalDelay -- create a queue before the inspection stations inspectionQueue <- runEventInStartTime newFCFSQueue -- create a queue before the adjustment stations adjustmentQueue <- runEventInStartTime newFCFSQueue -- create the inspection stations (servers) inspectionStations <- forM [1 .. inspectionStationCount] $ \_ -> newInspectionStation -- create the adjustment stations (servers) adjustmentStations <- forM [1 .. adjustmentStationCount] $ \_ -> newAdjustmentStation -- a processor loop for the inspection stations' queue let inspectionQueueProcessorLoop = queueProcessorLoopSeq (liftEvent . enqueue inspectionQueue) (dequeue inspectionQueue) inspectionProcessor (adjustmentQueueProcessor >>> adjustmentProcessor) -- a processor for the adjustment stations' queue let adjustmentQueueProcessor = queueProcessor (liftEvent . enqueue adjustmentQueue) (dequeue adjustmentQueue) -- a parallel work of the inspection stations let inspectionProcessor = processorParallel (map serverProcessor inspectionStations) -- a parallel work of the adjustment stations let adjustmentProcessor = processorParallel (map serverProcessor adjustmentStations) -- the entire processor from input to output let entireProcessor = arrivalTimerProcessor inputArrivalTimer >>> inspectionQueueProcessorLoop >>> arrivalTimerProcessor outputArrivalTimer -- start simulating the model runProcessInStartTime $ sinkStream $ runProcessor entireProcessor inputStream -- return the simulation results in start time return $ results [resultSource "inspectionQueue" "the inspection queue" inspectionQueue, -- resultSource "adjustmentQueue" "the adjustment queue" adjustmentQueue, -- resultSource "inputArrivalTimer" "the input arrival timer" inputArrivalTimer, -- resultSource "outputArrivalTimer" "the output arrival timer" outputArrivalTimer, -- resultSource "inspectionStations" "the inspection stations" inspectionStations, -- resultSource "adjustmentStations" "the adjustment stations" adjustmentStations]