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