1 | /* File: shiftcover.mod */ |
---|
2 | |
---|
3 | /* WORKFORCE SHIFT COVERAGE assignment problem */ |
---|
4 | |
---|
5 | /* Written by Larry D'Agostino <larrydag -at- sbcglobal -dot- com> |
---|
6 | |
---|
7 | Maximize Productivity with Industrial Engineer and Operations Research Tools |
---|
8 | http://industrialengineertools.blogspot.com |
---|
9 | |
---|
10 | |
---|
11 | /* The WORKFORCE SHIFT COVERAGE is an assigment problem that determines |
---|
12 | the schedule of crew given available time and shifts. |
---|
13 | |
---|
14 | The objective is to cover the available time given hourly demand with the minimum |
---|
15 | number of crew members. |
---|
16 | |
---|
17 | This is a set covering problem that is very common among finding crew |
---|
18 | and shift allocations. Notice in the data section the workforce shift allocation |
---|
19 | per day of the week.*/ |
---|
20 | |
---|
21 | |
---|
22 | /* ----- Model PARAMTERS and SETS -----*/ |
---|
23 | |
---|
24 | param numhrs; |
---|
25 | /* number of hours of operations in a given day */ |
---|
26 | |
---|
27 | param dys; |
---|
28 | /* number of days in a week */ |
---|
29 | |
---|
30 | set S; |
---|
31 | /* set of crew shifts */ |
---|
32 | |
---|
33 | set H := 1..numhrs; |
---|
34 | /* set of hours of a day*/ |
---|
35 | |
---|
36 | set D; |
---|
37 | /* set of days of a week*/ |
---|
38 | |
---|
39 | param dmnd{h in H, d in D}; |
---|
40 | /* demand for crew members given h hour and d day */ |
---|
41 | |
---|
42 | param shifts{d in D, h in H, s in S}; |
---|
43 | /* shifts to assign to crew members given d day, h hour, and s shift schedule |
---|
44 | |
---|
45 | /*----- Model VARIABLES -----*/ |
---|
46 | |
---|
47 | var crew{s in S}, integer, >=0; |
---|
48 | /* number of crew assigned to shift S */ |
---|
49 | |
---|
50 | |
---|
51 | /*----- Model CONSTRAINTS -----*/ |
---|
52 | |
---|
53 | s.t. Coverage{h in H, d in D}: sum{s in S} crew[s]*shifts[d,h,s] >= dmnd[h,d]; |
---|
54 | /* number of crew to cover with a shift given hourly demand and day */ |
---|
55 | |
---|
56 | |
---|
57 | /*----- Model OBJECTIVE -----*/ |
---|
58 | |
---|
59 | minimize obj: sum{s in S} crew[s]; |
---|
60 | /* minimize number of crew to cover demand*/ |
---|
61 | |
---|
62 | solve; |
---|
63 | display crew; |
---|
64 | |
---|
65 | printf "\n"; |
---|
66 | printf "Total Crew: %3d\n\n", sum{s in S} crew[s]; |
---|
67 | |
---|
68 | |
---|
69 | |
---|
70 | printf "\n\n"; |
---|
71 | printf "Weekly Crew Schedule\n\n"; |
---|
72 | printf "Hour "; |
---|
73 | printf{d in D} " %s ", d; |
---|
74 | printf "\n"; |
---|
75 | for {h in H} { |
---|
76 | printf " %2s ",h; |
---|
77 | printf{d in D} " %3d ", sum{s in S} crew[s]*shifts[d,h,s]; |
---|
78 | printf "\n"; |
---|
79 | } |
---|
80 | printf"\n"; |
---|
81 | |
---|
82 | |
---|
83 | |
---|
84 | data; |
---|
85 | |
---|
86 | param numhrs := 16; |
---|
87 | |
---|
88 | set D := SUN, MON, TUE, WED, THU, FRI, SAT; |
---|
89 | |
---|
90 | set S := Sh1, Sh2, Sh3, Sh4, Sh5, Sh6, Sh7, Sh8, Sh9; |
---|
91 | |
---|
92 | param dmnd : SUN MON TUE WED THU FRI SAT := |
---|
93 | 1 0 3 3 4 3 2 0 |
---|
94 | 2 0 14 14 16 14 12 12 |
---|
95 | 3 0 24 24 27 24 20 15 |
---|
96 | 4 0 28 28 32 28 23 15 |
---|
97 | 5 0 33 33 37 33 24 16 |
---|
98 | 6 0 34 34 38 34 24 15 |
---|
99 | 7 0 35 35 39 35 25 11 |
---|
100 | 8 0 35 35 40 35 27 0 |
---|
101 | 9 0 34 34 39 34 25 0 |
---|
102 | 10 0 31 31 35 31 24 0 |
---|
103 | 11 2 24 24 27 24 25 0 |
---|
104 | 12 3 19 19 21 19 21 0 |
---|
105 | 13 2 24 24 27 24 13 0 |
---|
106 | 14 2 16 16 18 16 0 0 |
---|
107 | 15 0 7 7 7 7 0 0 |
---|
108 | 16 0 5 5 5 5 0 0; |
---|
109 | |
---|
110 | |
---|
111 | param shifts := |
---|
112 | ['SUN',*,*]: |
---|
113 | Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := |
---|
114 | 1 0 0 0 0 0 0 0 0 0 |
---|
115 | 2 0 0 0 0 0 0 0 0 0 |
---|
116 | 3 0 0 0 0 0 0 0 0 0 |
---|
117 | 4 0 0 0 0 0 0 0 0 0 |
---|
118 | 5 0 0 0 0 0 0 0 0 0 |
---|
119 | 6 0 0 0 0 0 0 0 0 0 |
---|
120 | 7 0 0 0 0 0 0 0 0 0 |
---|
121 | 8 0 0 0 0 0 0 0 0 0 |
---|
122 | 9 0 0 0 0 0 0 0 0 0 |
---|
123 | 10 0 0 0 0 0 0 0 0 0 |
---|
124 | 11 0 0 0 0 0 0 0 0 1 |
---|
125 | 12 0 0 0 0 0 0 0 0 1 |
---|
126 | 13 0 0 0 0 0 0 0 0 1 |
---|
127 | 14 0 0 0 0 0 0 0 0 1 |
---|
128 | 15 0 0 0 0 0 0 0 0 0 |
---|
129 | 16 0 0 0 0 0 0 0 0 0 |
---|
130 | |
---|
131 | |
---|
132 | ['MON',*,*]: |
---|
133 | Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := |
---|
134 | 1 1 0 0 0 0 0 0 0 0 |
---|
135 | 2 1 1 0 0 0 0 0 0 0 |
---|
136 | 3 1 1 1 0 0 0 0 0 0 |
---|
137 | 4 1 1 1 1 0 0 0 0 0 |
---|
138 | 5 0 1 1 1 1 0 0 0 0 |
---|
139 | 6 1 0 1 1 1 1 0 0 1 |
---|
140 | 7 1 1 0 1 1 1 1 0 1 |
---|
141 | 8 1 1 1 0 1 1 1 1 1 |
---|
142 | 9 1 1 1 1 0 1 1 1 1 |
---|
143 | 10 0 1 1 1 1 0 1 1 1 |
---|
144 | 11 0 0 1 1 1 1 0 1 0 |
---|
145 | 12 0 0 0 1 1 1 1 0 1 |
---|
146 | 13 0 0 0 0 1 1 1 1 1 |
---|
147 | 14 0 0 0 0 0 1 1 1 1 |
---|
148 | 15 0 0 0 0 0 0 1 1 1 |
---|
149 | 16 0 0 0 0 0 0 0 1 1 |
---|
150 | |
---|
151 | ['TUE',*,*]: |
---|
152 | Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := |
---|
153 | 1 1 0 0 0 0 0 0 0 0 |
---|
154 | 2 1 1 0 0 0 0 0 0 0 |
---|
155 | 3 1 1 1 0 0 0 0 0 0 |
---|
156 | 4 1 1 1 1 0 0 0 0 0 |
---|
157 | 5 0 1 1 1 1 0 0 0 0 |
---|
158 | 6 1 0 1 1 1 1 0 0 1 |
---|
159 | 7 1 1 0 1 1 1 1 0 1 |
---|
160 | 8 1 1 1 0 1 1 1 1 1 |
---|
161 | 9 1 1 1 1 0 1 1 1 1 |
---|
162 | 10 0 1 1 1 1 0 1 1 1 |
---|
163 | 11 0 0 1 1 1 1 0 1 0 |
---|
164 | 12 0 0 0 1 1 1 1 0 1 |
---|
165 | 13 0 0 0 0 1 1 1 1 1 |
---|
166 | 14 0 0 0 0 0 1 1 1 1 |
---|
167 | 15 0 0 0 0 0 0 1 1 1 |
---|
168 | 16 0 0 0 0 0 0 0 1 1 |
---|
169 | |
---|
170 | ['WED',*,*]: |
---|
171 | Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := |
---|
172 | 1 1 0 0 0 0 0 0 0 0 |
---|
173 | 2 1 1 0 0 0 0 0 0 0 |
---|
174 | 3 1 1 1 0 0 0 0 0 0 |
---|
175 | 4 1 1 1 1 0 0 0 0 0 |
---|
176 | 5 0 1 1 1 1 0 0 0 0 |
---|
177 | 6 1 0 1 1 1 1 0 0 1 |
---|
178 | 7 1 1 0 1 1 1 1 0 1 |
---|
179 | 8 1 1 1 0 1 1 1 1 1 |
---|
180 | 9 1 1 1 1 0 1 1 1 1 |
---|
181 | 10 0 1 1 1 1 0 1 1 1 |
---|
182 | 11 0 0 1 1 1 1 0 1 0 |
---|
183 | 12 0 0 0 1 1 1 1 0 1 |
---|
184 | 13 0 0 0 0 1 1 1 1 1 |
---|
185 | 14 0 0 0 0 0 1 1 1 1 |
---|
186 | 15 0 0 0 0 0 0 1 1 1 |
---|
187 | 16 0 0 0 0 0 0 0 1 1 |
---|
188 | |
---|
189 | ['THU',*,*]: |
---|
190 | Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := |
---|
191 | 1 1 0 0 0 0 0 0 0 0 |
---|
192 | 2 1 1 0 0 0 0 0 0 0 |
---|
193 | 3 1 1 1 0 0 0 0 0 0 |
---|
194 | 4 1 1 1 1 0 0 0 0 0 |
---|
195 | 5 0 1 1 1 1 0 0 0 0 |
---|
196 | 6 1 0 1 1 1 1 0 0 0 |
---|
197 | 7 1 1 0 1 1 1 1 0 0 |
---|
198 | 8 1 1 1 0 1 1 1 1 0 |
---|
199 | 9 1 1 1 1 0 1 1 1 0 |
---|
200 | 10 0 1 1 1 1 0 1 1 0 |
---|
201 | 11 0 0 1 1 1 1 0 1 0 |
---|
202 | 12 0 0 0 1 1 1 1 0 0 |
---|
203 | 13 0 0 0 0 1 1 1 1 0 |
---|
204 | 14 0 0 0 0 0 1 1 1 0 |
---|
205 | 15 0 0 0 0 0 0 1 1 0 |
---|
206 | 16 0 0 0 0 0 0 0 1 0 |
---|
207 | |
---|
208 | ['FRI',*,*]: |
---|
209 | Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := |
---|
210 | 1 1 0 0 0 0 0 0 0 0 |
---|
211 | 2 1 1 0 0 0 0 0 0 0 |
---|
212 | 3 1 1 1 0 0 0 0 0 0 |
---|
213 | 4 1 1 1 1 0 0 0 0 0 |
---|
214 | 5 0 1 1 1 1 0 0 0 0 |
---|
215 | 6 1 0 1 1 1 1 0 0 0 |
---|
216 | 7 1 1 0 1 1 1 1 0 0 |
---|
217 | 8 1 1 1 0 1 1 1 1 0 |
---|
218 | 9 1 1 1 1 0 1 1 1 0 |
---|
219 | 10 0 1 1 1 1 0 1 1 0 |
---|
220 | 11 0 0 1 1 1 1 0 1 0 |
---|
221 | 12 0 0 0 1 1 1 1 0 0 |
---|
222 | 13 0 0 0 0 1 1 1 1 0 |
---|
223 | 14 0 0 0 0 0 1 1 1 0 |
---|
224 | 15 0 0 0 0 0 0 1 1 0 |
---|
225 | 16 0 0 0 0 0 0 0 1 0 |
---|
226 | |
---|
227 | ['SAT',*,*]: |
---|
228 | Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := |
---|
229 | 1 0 0 0 0 0 0 0 0 0 |
---|
230 | 2 0 0 0 0 0 0 0 0 1 |
---|
231 | 3 0 0 0 0 0 0 0 0 1 |
---|
232 | 4 0 0 0 0 0 0 0 0 1 |
---|
233 | 5 0 0 0 0 0 0 0 0 1 |
---|
234 | 6 0 0 0 0 0 0 0 0 1 |
---|
235 | 7 0 0 0 0 0 0 0 0 1 |
---|
236 | 8 0 0 0 0 0 0 0 0 0 |
---|
237 | 9 0 0 0 0 0 0 0 0 0 |
---|
238 | 10 0 0 0 0 0 0 0 0 0 |
---|
239 | 11 0 0 0 0 0 0 0 0 0 |
---|
240 | 12 0 0 0 0 0 0 0 0 0 |
---|
241 | 13 0 0 0 0 0 0 0 0 0 |
---|
242 | 14 0 0 0 0 0 0 0 0 0 |
---|
243 | 15 0 0 0 0 0 0 0 0 0 |
---|
244 | 16 0 0 0 0 0 0 0 0 0; |
---|