/
WorkStationsInSeries.hs
151 lines (135 loc) · 5.26 KB
/
WorkStationsInSeries.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
-- Example: Work Stations in Series
--
-- This is a model of two work stations connected in a series and separated by finite queues.
--
-- It is described in different sources [1, 2]. So, this is chapter 7 of [2] and section 5.14 of [1].
--
-- The maintenance facility of a large manufacturer performs two operations.
-- These operations must be performed in series; operation 2 always follows operation 1.
-- The units that are maintained are bulky, and space is available for only eight units
-- including the units being worked on. A proposed design leaves space for two units
-- between the work stations, and space for four units before work station 1. [..]
-- Current company policy is to subcontract the maintenance of a unit if it cannot
-- gain access to the in-house facility.
--
-- Historical data indicates that the time interval between requests for maintenance
-- is exponentially distributed with a mean of 0.4 time units. Service times are also
-- exponentially distributed with the first station requiring on the average 0.25 time
-- units and the second station, 0.5 time units. Units are transported automatically
-- from work station 1 to work station 2 in a negligible amount of time. If the queue of
-- work station 2 is full, that is, if there are two units awaiting for work station 2,
-- the first station is blocked and a unit cannot leave the station. A blocked work
-- station cannot server other units.
--
-- [1] A. Alan B. Pritsker, Simulation with Visual SLAM and AweSim, 2nd ed.
-- [2] Труб И.И., Объектно-ориентированное моделирование на C++: Учебный курс. - СПб.: Питер, 2006
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
-- | The simulation specs.
specs = Specs { spcStartTime = 0.0,
spcStopTime = 300.0,
spcDT = 0.1,
spcMethod = RungeKutta4,
spcGeneratorType = SimpleGenerator }
-- the mean delay of the input arrivals distributed exponentially
meanOrderDelay = 0.4
-- the capacity of the queue before the first work places
queueMaxCount1 = 4
-- the capacity of the queue before the second work places
queueMaxCount2 = 2
-- the mean processing time distributed exponentially in
-- the first work stations
meanProcessingTime1 = 0.25
-- the mean processing time distributed exponentially in
-- the second work stations
meanProcessingTime2 = 0.5
-- the number of the first work stations
-- (in parallel but the commented code allocates them sequentially)
workStationCount1 = 1
-- the number of the second work stations
-- (in parallel but the commented code allocates them sequentially)
workStationCount2 = 1
-- create a work station (server) with the exponential processing time
newWorkStationExponential meanTime =
newServer $ \a ->
do holdProcess =<<
(liftParameter $
randomExponential meanTime)
return a
model :: Simulation Results
model = do
-- it will gather the statistics of the processing time
arrivalTimer <- newArrivalTimer
-- define a stream of input events
let inputStream = randomExponentialStream meanOrderDelay
-- create a queue before the first work stations
queue1 <-
runEventInStartTime $
newFCFSQueue queueMaxCount1
-- create a queue before the second work stations
queue2 <-
runEventInStartTime $
newFCFSQueue queueMaxCount2
-- create the first work stations (servers)
workStation1s <- forM [1 .. workStationCount1] $ \_ ->
newWorkStationExponential meanProcessingTime1
-- create the second work stations (servers)
workStation2s <- forM [1 .. workStationCount2] $ \_ ->
newWorkStationExponential meanProcessingTime2
-- processor for the queue before the first work station
let queueProcessor1 =
queueProcessor
(\a -> liftEvent $ enqueueOrLost_ queue1 a)
(dequeue queue1)
-- processor for the queue before the second work station
let queueProcessor2 =
queueProcessor
(enqueue queue2)
(dequeue queue2)
-- the entire processor from input to output
let entireProcessor =
queueProcessor1 >>>
processorParallel (map serverProcessor workStation1s) >>>
-- processorSeq (map serverProcessor workStation1s) >>>
queueProcessor2 >>>
processorParallel (map serverProcessor workStation2s) >>>
-- processorSeq (map serverProcessor workStation2s) >>>
arrivalTimerProcessor arrivalTimer
-- start simulating the model
runProcessInStartTime $
sinkStream $ runProcessor entireProcessor inputStream
-- return the simulation results
return $
results
[resultSource
"queue1" "Queue no. 1"
queue1,
--
resultSource
"workStation1s" "Work Stations of line no. 1"
workStation1s,
--
resultSource
"queue2" "Queue no. 2"
queue2,
--
resultSource
"workStation2s" "Work Stations of line no. 2"
workStation2s,
--
resultSource
"arrivalTimer" "The arrival timer"
arrivalTimer]
modelSummary :: Simulation Results
modelSummary =
fmap resultSummary model
main =
printSimulationResultsInStopTime
printResultSourceInEnglish
-- model specs
modelSummary specs