## 29Timetabling

### 29.1Assigning personnel to machines

```% function Result = assigningpersonneltomachinesEx(PriLev)
%
% Creates a TOMLAB MILP problem for assigning personnel to machines
%
% ASSIGNING PERSONNEL TO MACHINES
%
% An operator needs to be assigned to each of the six machines in a
% workshop. Six workers have been pre-selected. Everyone has
% undergone a test of her productivity on every machine. The table
% below lists the productivities in pieces per hour. The machines run
% in parallel, that is, the total productivity of the workshop is the
% sum of the productivities of the people assigned to the machines.
%
% Productivity in pieces per hour
%
% +-------+-----------------+
% |       |    Machines     |
% +-------+--+--+--+--+--+--+
% |Workers| 1| 2| 3| 4| 5| 6|
% +-------+--+--+--+--+--+--+
% |   1   |13|24|31|19|40|29|
% |   2   |18|25|30|15|43|22|
% |   3   |20|20|27|25|34|33|
% |   4   |23|26|28|18|37|30|
% |   5   |28|33|34|17|38|20|
% |   6   |19|36|25|27|45|24|
% +-------+--+--+--+--+--+--+
%
% The objective is to determine an assignment of workers to machines
% that maximizes the total productivity. We may start by calculating
% a (non-optimal) heuristic solution using the following fairly
% natural method: choose the assignment p -> m with the highest
% productivity, cross out the line p and the column m (since the
% person has been placed and the machine has an operator), and
% restart this process until we have assigned all persons. The
% problem should then be solved to optimality using Mathematical
% Programming. And finally, solve the same problem to optimality,
% but for machines working in series.
%
% VARIABLES
%
% prodmat                    The productivity matrix
%
% RESULTS
%
% For an interpretation of the results, run:
% [Result1, Result2] = assigningpersonneltomachinesEx(2);
%
% REFERENCES
%
% Applications of optimization... Gueret, Prins, Seveaux
% http://web.univ-ubs.fr/lester/~sevaux/pl/index.php
%
% INPUT PARAMETERS
% PriLev       Print Level
%
% OUTPUT PARAMETERS
% Result       Result structure

% Marcus Edvall, Tomlab Optimization Inc, E-mail: tomlab@tomopt.com
% Copyright (c) 2005-2005 by Tomlab Optimization Inc., \$Release: 5.0.0\$

function [Result1, Result2] = assigningpersonneltomachinesEx(PriLev)

if nargin < 1
PriLev = 1;
end

prodmat       = [ 13 24 31 19 40 29;...
18 25 30 15 43 22;...
20 20 27 25 34 33;...
23 26 28 18 37 30;...
28 33 34 17 38 20;...
19 36 25 27 45 24];

flag = 0; % Parallel

Prob = assigningpersonneltomachines(prodmat, flag);
Result1 = tomRun('cplex', Prob, PriLev);

flag = 1; % Series

Prob = assigningpersonneltomachines(prodmat, flag);
Result2 = tomRun('cplex', Prob, PriLev);

if PriLev > 1,
m   = size(prodmat,1); % number of machines
w   = m;               % number of workers
x1  = reshape(Result1.x_k,m,w);
disp(['Best parallel work (' num2str(-Result1.f_k) ') when '])
[worker,machine] = find(x1);
for i = 1:length(worker)
disp(['   worker '           num2str(worker(i)) ...
' operates machine ' num2str(machine(i))])
end
x2  = reshape(Result2.x_k(1:m*w),m,w);
disp(['Best serial work (' num2str(-Result2.f_k) ') when '])
[worker,machine] = find(x2);
for i = 1:length(worker)
disp(['   worker '           num2str(worker(i)) ...
' operates machine ' num2str(machine(i))])
end
end

% MODIFICATION LOG
%
% 051202 med   Created.
% 060126 per   Moved disp to end
```

### 29.2Scheduling nurses

```% function Result = schedulingnursesEx(PriLev)
%
% Creates a TOMLAB MILP problem for scheduling nurses
%
% SCHEDULING NURSES
%
% Mr. Schedule has been asked to organize the schedule of nurses for
% the Cardiology service at St. Joseph’s hospital. A working day in
% this service is subdivided into twelve periods of two hours. The
% personnel requirement changes from period to period: for instance,
% only a few nurses are required during the night, but the total
% number must be relatively high during the morning to provide
% specific care to the patients. The following table lists the
% personnel requirement for every time period.
%
% Question 1:
% Determine the minimum number of nurses required to cover all the
% requirements, knowing that a nurse works eight hours per day and
% that she is entitled to a break of two hours after she has worked
% for four hours.
%
% Question 2:
% The service only has 80 nurses, which is not sufficient with the
% given requirements. Mr. Schedule therefore proposes that part of
% the personnel works two additional hours per day. These two
% without any break. Determine the schedule of the nurses in this
% service that minimizes the number of nurses working overtime.
%
% Personnel requirement per time period
%
% +------+-------------+------------------------+
% |Number|Time interval|Minimum number of nurses|
% +------+-------------+------------------------+
% |   0  | 00am - 02am |          15            |
% |   1  | 02am - 04am |          15            |
% |   2  | 04am - 06am |          15            |
% |   3  | 06am - 08am |          35            |
% |   4  | 08am - 10am |          40            |
% |   5  | 10am - 12pm |          40            |
% |   6  | 12pm - 02pm |          40            |
% |   7  | 02pm - 04pm |          30            |
% |   8  | 04pm - 06pm |          31            |
% |   9  | 06pm - 08pm |          35            |
% |  10  | 08pm - 10pm |          30            |
% |  11  | 10pm - 12am |          20            |
% +------+-------------+------------------------+
%
%
% VARIABLES
%
% demand                     nurses needed per shift
% hoursperday                hours of work per day
% breakinterval              work this long before break
% breaklength                length of break
% intervallength             length of an interval
% maxdemand                  max number of nurses in Q 2
%
% RESULTS
%
% For an interpretation of the results, run:
% [Result1, Result2] = schedulingnursesEx(2);
%
% REFERENCES
%
% Applications of optimization... Gueret, Prins, Seveaux
% http://web.univ-ubs.fr/lester/~sevaux/pl/index.php
%
% INPUT PARAMETERS
% PriLev       Print Level
%
% OUTPUT PARAMETERS
% Result       Result structure

% Marcus Edvall, Tomlab Optimization Inc, E-mail: tomlab@tomopt.com
% Copyright (c) 2005-2005 by Tomlab Optimization Inc., \$Release: 5.0.0\$

function [Result1, Result2] = schedulingnursesEx(PriLev)

if nargin < 1
PriLev = 1;
end

demand         = [15 15 15 35 40 40 40 30 31 35 30 20]';
hoursperday    = 8;
breakinterval  = 4;
breaklength    = 2;
intervallength = 2;
maxdemand      = 80;

flag = 0; % No max on nurses

Prob = schedulingnurses(demand, hoursperday, breakinterval, breaklength, ...
intervallength, maxdemand, flag);
Result1 = tomRun('cplex', Prob, PriLev);

flag = 1; % Max on nurses
Prob = schedulingnurses(demand, hoursperday, breakinterval, breaklength, ...
intervallength, maxdemand, flag);
Result2 = tomRun('cplex', Prob, PriLev);

if PriLev > 1,
x1        = Result1.x_k;                      % nurses working
intervals = length(x1);                       % number of intervals
work      = [x1 circshift(x1,-1) circshift(x1,-3) circshift(x1,-4)];
work_1    = sum(work')';                      % total nurses
n         = Result2.x_k(1:intervals);         % regular shifts
o         = Result2.x_k(intervals+1:end);     % overtime
work1     = [n circshift(n,-1) ...            % regular -> 4 intervals
circshift(n,-3) circshift(n,-4)];
work2     = [o circshift(o,-1) ...            % overtime -> 5 intervals
circshift(o,-3) circshift(o,-4) circshift(o,-5)];
work_2    = sum(work1')' + sum(work2')';      % total work

disp(['Without overtime we need ' num2str(Result1.f_k) ' nurses.'])
disp(['   This is the schedule:'])
for i = 1:intervals,
disp(['   ' num2str((i-1)*2) '.00: ' num2str(x1(i)) ...
' start and ' num2str(work_1(i)) ' are working.' ...
' ( demand is ' num2str(demand(i)) ')'  ])
end

disp(['With overtime we have ' num2str(sum(n)) ...
' nurses, and ' num2str(sum(o)) ...
' of them will work overtime.'])
disp(['   This is the schedule:'])
for i = 1:intervals,
disp(['   ' num2str((i-1)*2) '.00: ' num2str(n(i)) ...
' start a regular shift, '     num2str(o(i)) ...
' start an overtime shift and ' num2str(work_2(i)) ...
' are working.' ...
' ( demand is ' num2str(demand(i)) ')'  ])
end
end

% MODIFICATION LOG
%
% 051202 med   Created.
% 060126 per   Moved disp to end
```

### 29.3Establishing a college timetable

```% function Result = establishingacollegetimetableEx(PriLev)
%
% Creates a TOMLAB MILP problem for establishing a college time table
%
% ESTABLISHING A COLLEGE TIMETABLE
%
% Mr. Miller is in charge of establishing the weekly timetable for
% two classes of the last year in a college. The two classes have
% the same teachers, except for mathematics and sport. In the
% college all lessons have a duration of two hours. Furthermore,
% all students of the same class attend exactly the same courses.
% From Monday to Friday, the slots for courses are the following:
% 8:00–10:00, 10:15–12:15, 14:00–16:00, and 16:15–18:15. The
% following table lists the number of two-hour lessons that every
% teacher has to teach the students of the two classes per week.
%
% Number of 2-hour lessons per teacher and class
%+------------+-----------------+-------------------+-------------------+
%|Teacher     |Subject          |Lessons for class 1|Lessons for class 2|
%+------------+-----------------+-------------------+-------------------+
%|Mr Cheese   |English          |         1         |         1         |
%|Mrs Insulin |Biology          |         3         |         3         |
%|Mr Map      |History-Geography|         2         |         2         |
%|Mr Effofecks|Mathematics      |         0         |         4         |
%|Mrs Derivate|Mathematics      |         4         |         0         |
%|Mrs Electron|Physics          |         3         |         3         |
%|Mr Wise     |Philosophy       |         1         |         1         |
%|Mr Muscle   |Sport            |         1         |         0         |
%|Mrs Biceps  |Sport            |         0         |         1         |
%+------------+-----------------+-------------------+-------------------+
%
% The sport lessons have to take place on Thursday afternoon from
% 14:00 to 16:00. Furthermore, the first time slot on Monday morning
% is reserved for supervised homework. Mr Effofecks is absent every
% Monday morning because he teaches some courses at another college.
% Mrs Insulin does not work on Wednesday. And finally, to prevent
% students from getting bored, every class may only have one two-hour
% lesson per subject on a single day. Write a mathematical program
% that allows Mr Miller to determine the weekly timetable for the two
% classes.
%
% VARIABLES
%
% lessons1/2                 Number of lessons per subject and class
% subject                    Subject indices
% slots                      Possible slots
%
% RESULTS
%
% For an interpretation of the results, run:
% Result = establishingacollegetimetableEx(2);
%
% REFERENCES
%
% Applications of optimization... Gueret, Prins, Seveaux
% http://web.univ-ubs.fr/lester/~sevaux/pl/index.php
%
% INPUT PARAMETERS
% PriLev       Print Level
%
% OUTPUT PARAMETERS
% Result       Result structure

% Marcus Edvall, Tomlab Optimization Inc, E-mail: tomlab@tomopt.com
% Copyright (c) 2005-2005 by Tomlab Optimization Inc., \$Release: 5.0.0\$

function Result = establishingacollegetimetableEx(PriLev)

if nargin < 1
PriLev = 1;
end

lessons1        = [ 1  3  2  0  4  3  1  1  0]';
lessons2        = [ 1  3  2  4  0  3  1  0  1]';
subject         = [ 1  2  3  4  4  5  6  7  7]';
slots           = 4*5;

Prob = establishingacollegetimetable(lessons1, lessons2, subject, slots);
Result = tomRun('cplex', Prob, PriLev);

if PriLev > 1,
t_names = ['Cheese   '; 'Insulin  '; 'Map      ';
'Effofecks'; 'Derivate '; 'Electron ';
'Wise     '; 'Muscle   '; 'Biceps   ' ];
s_names = ['English    '; 'Biology    '; 'Histo-Geo  ';
'Mathematics'; 'Physics    '; 'Philosophy ';
'Sport      ' ];
subject = [ 1  2  3  4  4  5  6  7  7]';
d_names = ['Mon'; 'Tue'; 'Wed'; 'Thu'; 'Fri' ];
l_times = ['0800-1000'; '1015-1215'; '1400-1600'; '1615-1815'; ];
t_nr   = length(t_names);
s_nr   = 20 ; % number of slots
temp   = reshape(Result.x_k,t_nr*2,s_nr);
class1 = temp(1:t_nr,:);
class2 = temp(t_nr+1:end,:);
classes= [class1 class2];
for c = 1:2,
this_class = class1;
if c == 2,
this_class = class2;
end
disp(' ')
disp(['TIMETABLE FOR CLASS ' num2str(c)])
counter = 0;
for i = 1:length(d_names),
day = d_names(i,:);
disp(['--' day '--'])
for j = 1:size(l_times,1),
time = l_times(j,:);
counter = counter + 1;
if sum(this_class(:,counter)) == 1,
teacher = find(this_class(:,counter));
disp(['   ' time ' ' s_names(subject(teacher),:) ...
' (' t_names(teacher,:) ')'])
end
end
end
end
end

% MODIFICATION LOG
%
% 051205 med   Created.
% 060126 per   Moved disp to end
```

### 29.4Exam scheduling

```% function Result = examschedulingEx(PriLev)
%
% Creates a TOMLAB MILP problem for exam scheduling
%
% EXAM SCHEDULING
%
% At a technical university every term the third-year students choose
% eight modules from the eleven modules that are taught, depending on
% the option they wish to choose in the fourth year (there are two
% possible choices: "Production planning" and "Quality and security
% management"). In the current term, certain modules are obligatory
% for students who wish to continue with one of these options. The
% obligatory courses are Statistics (S), Graph models and algorithms
% (GMA), Production management (PM), and Discrete systems and events
% (DSE). The optional modules are: Data analysis (DA), Numerical
% analysis (NA), Mathematical programming (MP), C++, Java (J), Logic
% programming (LP), and Software engineering (SE).
%
% Incompatibilities between different exams
%
% +---+---+---+---+---+---+---+---+---+---+---+---+
% |   | DA| NA|C++| SE| PM| J |GMA| LP| MP| S |DSE|
% +---+---+---+---+---+---+---+---+---+---+---+---+
% |DA | - | X | - | - | X | - | X | - | - | X | X |
% |NA | X | - | - | - | X | - | X | - | - | X | X |
% |C++| - | - | - | X | X | X | X | - | X | X | X |
% |SE | - | - | X | - | X | X | X | - | - | X | X |
% |PM | X | X | X | X | - | X | X | X | X | X | X |
% |J  | - | - | X | X | X | - | X | - | X | X | X |
% |GMA| X | X | X | X | X | X | - | X | X | X | X |
% |LP | - | - | - | - | X | - | X | - | - | X | X |
% |MP | - | - | X | - | X | X | X | - | - | X | X |
% |S  | X | X | X | X | X | X | X | X | X | - | X |
% |DSE| X | X | X | X | X | X | X | X | X | X | - |
% +---+---+---+---+---+---+---+---+---+---+---+---+
%
% Mrs Edeetee needs to schedule the exams at the end of the term.
% Every exam lasts two hours. Two days have been reserved for the
% exams with the following time slices: 8:00-10:00, 10:15-12:15,
% 14:00-16:00, and 16:15-18:15. For every exam she knows the set of
% incompatible exams that may not take place at the same time because
% they have to be taken by the same students. These incompatibilities
% are summarized in the table above.
%
% Help Mrs Edeetee construct a timetable so that no student has more
% than one exam at a time.
%
% VARIABLES
%
% incompatmat                Matrix of incompatabilities
% slots                      Timeslots (2 days * 4 per day)
%
% RESULTS
%
% For an interpretation of the results, run:
% Result = examschedulingEx(2);

%
% REFERENCES
%
% Applications of optimization... Gueret, Prins, Seveaux
% http://web.univ-ubs.fr/lester/~sevaux/pl/index.php
%
% INPUT PARAMETERS
% PriLev       Print Level
%
% OUTPUT PARAMETERS
% Result       Result structure

% Marcus Edvall, Tomlab Optimization Inc, E-mail: tomlab@tomopt.com
% Copyright (c) 2005-2005 by Tomlab Optimization Inc., \$Release: 5.0.0\$

function Result = examschedulingEx(PriLev)

if nargin < 1
PriLev = 1;
end

incompatmat     = [ 0 1 0 0 1 0 1 0 0 1 1;...
1 0 0 0 1 0 1 0 0 1 1;...
0 0 0 1 1 1 1 0 1 1 1;...
0 0 1 0 1 1 1 0 0 1 1;...
1 1 1 1 0 1 1 1 1 1 1;...
0 0 1 1 1 0 1 0 1 1 1;...
1 1 1 1 1 1 0 1 1 1 1;...
0 0 0 0 1 0 1 0 0 1 1;...
0 0 1 0 1 1 1 0 0 1 1;...
1 1 1 1 1 1 1 1 1 0 1;...
1 1 1 1 1 1 1 1 1 1 0];

slots           = 8;

Prob = examscheduling(incompatmat, slots);
Result = tomRun('cplex', Prob, PriLev);

if PriLev > 1,
e_names = ['DA  '; 'NA  '; 'C++ '; 'SE  ';
'PM  '; 'J   '; 'GMA '; 'LP  ';
'MP  '; 'S   '; 'DSE '] ;
exams   = length(e_names); % number of exams
days    = 2;               % number of days
times   = ['0800-1000'; '1015-1215'; '1400-1600'; '1615-1815'; ];
slots   = size(times,1);   % time slots per day
temp    = reshape(Result.x_k,exams,days*slots);

for d = 1:days,
disp([' day number ' num2str(d)])
for s = 1:slots,
i = s + (slots)*(d-1);
exams_now = find(temp(:,i));
e_list = [];
for e = 1:length(exams_now),
e_list = [e_list e_names(exams_now(e),:)];
end
if ~isempty(e_list),
disp(['  during ' times(s,:) ': ' num2str(e_list)])
end
end
end
end

% MODIFICATION LOG
%
% 051205 med   Created.
% 060126 per   Moved disp to end
```

### 29.5Production planning with personnel assignment

```% function Result = prodplanwithpersonnelassignEx(PriLev)
%
% Creates a TOMLAB MILP problem for production planning with personnel assignment
%
% PRODUCTION PLANNING WITH PERSONNEL ASSIGNMENT
%
% The company Line Production decides to plan the production of four
% of its products (P1, P2, P3, P4) on its five production lines (L1
% to L5). The company gains net profits of \$ 7 for the products P1
% and P4, \$ 8 for P2, and \$ 9 for P3. The maximum times during
% which the five production lines may operate are different during
% the planning period. The maximum capacities for L1 to L5 are 4500
% hours, 5000 hours, 4500 hours, 1500 hours, and 2500 hours
% respectively. The table below lists the processing time in hours
% necessary for the production of one unit of every product on every
% production line. Which quantities of P1 to P4 should be produced to
% maximize the total profit? If subsequently a transfer of personnel
% (and hence of working hours) is authorized between production lines
% during the planning period as shown in the second table below,
% which is the maximum profit? How many hours are transfered and
% under what conditions?
%
% Unitary processing times
%
% +--------+-------------------+
% |        |   Lines           |
% +--------+---+---+---+---+---+
% |Products| L1| L2| L3| L4| L5|
% +--------+---+---+---+---+---+
% |   P1   |1.3|0.9|2.0|0.3|0.9|
% |   P2   |1.8|1.7|1.4|0.6|1.1|
% |   P3   |1.3|1.2|1.3|1.0|1.4|
% |   P4   |0.9|1.1|1.0|0.9|1.0|
% +--------+---+---+---+---+---+
%
% Possible transfers of personnel
%
% +------+-------------------+------------------+
% |      |  Destination      |                  |
% +------+---+---+---+---+---+Maximum number of |
% |Origin| L1| L2| L3| L4| L5|transferable hours|
% +------+---+---+---+---+---+------------------+
% |  L1  |  -|yes|yes|yes| no|     400          |
% |  L2  | no|  -|yes| no|yes|     800          |
% |  L3  |yes|yes|  -|yes| no|     500          |
% |  L4  | no| no| no|  -|yes|     200          |
% |  L5  |yes|yes|yes| no|  -|     300          |
% +------+---+---+---+---+---+------------------+
%
% VARIABLES
%
% profit                     Profit per product
% capacity                   Hours at each site
% timemat                    Time to produce products
% transfermat                Transfer matrix
% maxtransfer                Maximum hours to transfer
%
% RESULTS
%
% For an interpretation of the results, run:
% [Result1, Result2] = prodplanwithpersonnelassignEx(2);
%
% REFERENCES
%
% Applications of optimization... Gueret, Prins, Seveaux
% http://web.univ-ubs.fr/lester/~sevaux/pl/index.php
%
% INPUT PARAMETERS
% PriLev       Print Level
%
% OUTPUT PARAMETERS
% Result       Result structure

% Marcus Edvall, Tomlab Optimization Inc, E-mail: tomlab@tomopt.com
% Copyright (c) 2005-2005 by Tomlab Optimization Inc., \$Release: 5.0.0\$

function [Result1, Result2] = prodplanwithpersonnelassignEx(PriLev)

if nargin < 1
PriLev = 1;
end

profit        = [7 8 9 7]';
capacity      = [4500 5000 4500 1500 2500]';

timemat       = [ 1.3 0.9 2.0 0.3 0.9;...
1.8 1.7 1.4 0.6 1.1;...
1.3 1.2 1.3 1.0 1.4;...
0.9 1.1 1.0 0.9 1.0];

transfermat   = [0 1 1 1 0;...
0 0 1 0 1;...
1 1 0 1 0;...
0 0 0 0 1;...
1 1 1 0 0];

maxtransfer   = [400 800 200 500 300]';

flag          = 0;

Prob = prodplanwithpersonnelassign(profit, capacity, timemat,...
transfermat, maxtransfer, flag);
Result1 = tomRun('cplex', Prob, PriLev);

flag          = 1;

Prob = prodplanwithpersonnelassign(profit, capacity, timemat,...
transfermat, maxtransfer, flag);
Result2 = tomRun('cplex', Prob, PriLev);

if PriLev > 1,
disp('without transfer')
x1 = Result1.x_k;
for i = 1:length(x1),
if x1(i) > 0,
disp(['    produce ' num2str(x1(i)) ' units of P' num2str(i)  ])
end
end
disp('with transfer')
x2 = Result2.x_k;
length(x2);
n1    = 5;
n2    = 4;
n     = n1 + n2*n2 + n2;   %amount, transfers, hours
x2 = Result2.x_k;
for i = 1:length(x1),
if x2(i) > 0,
disp(['    produce ' num2str(x2(i)) ' units of P' num2str(i)  ])
end
end
transfer = reshape(x2(n1:n1+n1*n1-1),n1,n1);
for i = 1:size(transfer,1),
idx = find(transfer(i,:));
for j = 1: length(idx),
disp(['    transfer ' num2str(transfer(i,idx(j))) ...
' hours from ' num2str(i) ' to ' num2str(idx(j)) ])
end
end
hours = x2(n1+n1*n1:end);
for j = 1:length(hours),
disp(['    work ' num2str(hours(j)) ' hours at L' num2str(j) ])
end
end

% MODIFICATION LOG
%
% 051205 med   Created.
% 060126 per   Moved disp to end
% 060131 per   Really moved disp to end
```

### 29.6Plan the personnel at a construction site

```% function Result = planthepersonnelataconstrEx(PriLev)
%
% Creates a TOMLAB MILP problem for planning the personnel at a construction site
%
% PLANNING THE PERSONNEL AT A CONSTRUCTION SITE
%
% Construction workers who erect the metal skeleton of skyscrapers
% are called steel erectors. The following table lists the
% requirements for steel erectors at a construction site during a
% period of six months. Transfers from other sites to this one are
% possible on the first day of every month and cost \$100 per person.
% At the end of every month workers may leave to other sites at a
% transfer cost of \$160 per person. It is estimated that
% understaffing as well as overstaffing cost \$200 per month per post
% (in the case of unoccupied posts the missing hours have to be
% filled through overtime work).
%
% Monthly requirement for steel erectors
%
% +---+---+---+---+---+---+
% |Mar|Apr|May|Jun|Jul|Aug|
% +---+---+---+---+---+---+
% | 4 | 6 | 7 | 4 | 6 | 2 |
% +---+---+---+---+---+---+
%
% Overtime work is limited to 25% of the hours worked normally. Every
% month, at most three workers may arrive at the site. The departure
% to other sites is limited by agreements with labor unions to 1/3 of
% the total personnel of the month. We suppose that three steel
% erectors are already present on site at the end of February, that
% nobody leaves at the end of February and that three workers need to
% remain on-site at the end of August. Which are the number of
% arrivals and departures every month to minimize the total cost?
%
% VARIABLES
%
% transferin                 Cost to transfer in
% transferout                Cost to transfer out
% staffingdevcost            Cost for over or under employment
% overtimemax                Maximum overtime
% maxtransferin              Maximum amount to transfer in
% maxtransferout             Maximum amount to transfer out
% startstaff                 Starting staff
% endstaff                   Staff required at the end of the period
% demands                    Staff required each month
%
% RESULTS
%
% For an interpretation of the results, run:
% Result = planthepersonnelataconstrEx(2);
%
% REFERENCES
%
% Applications of optimization... Gueret, Prins, Seveaux
% http://web.univ-ubs.fr/lester/~sevaux/pl/index.php
%
% INPUT PARAMETERS
% PriLev       Print Level
%
% OUTPUT PARAMETERS
% Result       Result structure

% Marcus Edvall, Tomlab Optimization Inc, E-mail: tomlab@tomopt.com
% Copyright (c) 2005-2005 by Tomlab Optimization Inc., \$Release: 5.0.0\$

function Result = planthepersonnelataconstrEx(PriLev)

if nargin < 1
PriLev = 1;
end

transferin      = 100;
transferout     = 160;
staffingdevcost = 200;

overtimemax     = 0.25;
maxtransferin   = 3;
maxtransferout  = 1/3;

startstaff      = 3;
endstaff        = 3;

demands         = [4 6 7 4 6 2]';

Prob = planthepersonnelataconstr(transferin, transferout,...
staffingdevcost, overtimemax, maxtransferin, maxtransferout, ...
startstaff, endstaff, demands);
Result = tomRun('cplex', Prob, PriLev);

if PriLev > 1,
months = ['Mar'; 'Apr'; 'May'; 'Jun'; 'Jul'; 'Aug'];
temp   = reshape(Result.x_k,size(months,1),5);
for m = 1:size(months,1),
disp(['-- ' months(m,:) ' --' ])
disp(['  ' num2str(temp(m,1)) ' worker(s) on site'])
disp(['  ' num2str(temp(m,2)) ' worker(s) have arrived'])
disp(['  ' num2str(temp(m,3)) ' worker(s) will leave'])
disp(['  ' num2str(temp(m,4)) ' worker(s) too many'])
disp(['  ' num2str(temp(m,5)) ' worker(s) too few'])
end
end

% MODIFICATION LOG
%
% 051205 med   Created.