/* Number of people */
param P_count, integer, > 0;

/* Number of jobs */
param J_count, integer, > 0;

/* Number of days */
param D_count, integer, > 0;

param WL, integer, > 0;
param WH, integer, > 0;

set P := 1..P_count;
set J := 1..J_count;
set D := 1..D_count;

/* Person p likes to solve jobs j */
param L{p in P, j in J} default 0, binary;

/* Person p hates to solve jobs j */
param H{p in P, j in J} default 0, binary;

/* Person p is capable to perform job j */
param C{p in P, j in J} default 1, binary;

/* How many jobs need to be done on what day */
param R{d in D, j in J}, integer, >= 0;

/* hardcoded */
param Q{p in P, j in J, d in D}, default 0, binary;

/* workload */
param Wl{j in J}, integer, >= 0;

param max_load{p in P, d in D}, default 1, integer;

/* Person p is allocated to do job j on day d */
var A{p in P, j in J, d in D}, binary;

var error{p in P}, integer, >= 0;

s.t. hardcode{p in P, j in J, d in D}: A[p,j,d] >= Q[p,j,d];

/* A person only has one task per day, at most */
s.t. max_load_person{p in P, d in D}: sum{j in J} A[p,j,d] <= max_load[p,d];

/* A person has at least D-1 tasks */
#s.t. min_load_person{p in P}: sum{j in J, d in D} A[p,j,d] >= min_load[p];

/* A person does not perform the same job on all days */
s.t. duplicate_jobs{p in P, j in J}: sum{d in D} A[p,j,d] <= D_count-1;

/* Each task is allocated */
s.t. all_allocated{j in J, d in D}: sum{p in P} A[p,j,d] == R[d, j];

/* A person only performs what (s)he is capable of */
s.t. capability_person{p in P, j in J, d in D}: A[p,j,d] <= C[p,j];

s.t. error_lt{p in P}: error[p] >= ((sum{j in J, d in D} A[p,j,d] * Wl[j]) - 4);
s.t. error_gt{p in P}: error[p] >= 4 - (sum{j in J, d in D} A[p,j,d] * Wl[j]);

/* Maximize enjoyment */
# minimize error_diff: sum{p in P} error[p];
maximize enjoyment: (sum{p in P, d in D, j in J} A[p,j,d] * (L[p, j] * WL - H[p, j] * WH)) - sum{p in P} error[p];
solve;

printf "Sum %d\n", (sum{p in P, d in D, j in J} A[p,j,d] * (L[p, j] * WL - H[p, j] * WH));
printf "p d j W l\n";
printf ">>>>\n";
printf{p in P, d in D, j in J : A[p,j,d] > 0} "%d %d %d %d %d\n", p, d, j, A[p,j,d] * (L[p, j] * WL - H[p, j] * WH), Wl[j];
printf "<<<<\n";
printf "workloads\n";
printf "p l\n";
printf{p in P} "%d %d\n", p, abs((sum{j in J, d in D : A[p,j,d] > 0} Wl[j]) - ((sum{d in D, j in J} Wl[j] * R[d,j]) / P_count));
printf "workload_dev: %d\n", sum{p in P} abs((sum{j in J, d in D : A[p,j,d] > 0} Wl[j]) - ((sum{d in D, j in J} Wl[j] * R[d,j]) / P_count))^2;

data;

/* Test example */

param P_count := 44;
param J_count := 11;
param D_count := 3;
param WL := 1;
param WH := 3;
param Wl := 1 4, 2 4, 3 2, 4 2, 5 4, 6 3, 7 2, 8 1, 9 1, 10 2, 11 2;
# de pol-parameter
param max_load := 25,1,2; #  12,1,0 12,2,0 12,3,0;
param R : 1 2 3 4 5 6 7 8 9 10 11 :=
	      1 1 3 0 0 1 3 4 6 2  5  0
	      2 1 0 6 4 1 3 4 6 2  5  5
	      3 1 0 0 0 1 3 4 6 2  5  5;
/* AUTOGEN STARTS HERE */
param L : 5 6 7 8 9 10 :=
        1 0 1 0 1 0 0
        2 0 0 1 1 0 1
        3 0 0 1 0 0 1
        6 0 1 0 0 0 1
        7 0 0 0 1 0 1
        8 0 1 0 0 1 0
        9 0 1 1 0 0 1
       11 1 0 0 1 0 0
       13 0 1 0 0 1 0
       14 0 1 0 0 0 1
       16 0 1 0 0 0 0
       18 1 0 0 0 0 0
       19 0 0 1 0 1 1
       20 0 0 0 0 0 1
       21 0 0 0 1 1 0
       22 0 1 1 0 0 1
       23 0 1 0 1 0 0
       24 0 0 0 0 1 0
       25 1 0 0 0 0 0
       26 0 1 1 0 0 1
       27 0 1 0 0 0 1
       28 0 1 0 1 0 0
       29 0 0 1 1 0 0
       30 0 1 1 0 0 0
       31 0 1 0 0 0 0
       32 0 0 1 0 1 1
       34 0 0 0 0 1 1
       35 0 1 0 1 1 0
       36 0 1 0 0 0 1
       38 0 0 1 0 1 1
       39 0 0 1 0 0 1
       40 0 1 0 0 0 1
       41 0 1 1 0 0 1
       43 0 1 0 0 0 0
       44 0 0 0 1 0 0;
param H : 6 7 8 9 10 :=
        1 0 0 0 0 1
        2 1 0 0 1 0
        6 0 1 0 0 0
        7 0 1 0 0 0
        8 0 1 1 0 0
        9 0 0 1 0 0
       11 0 1 0 1 0
       13 0 1 1 0 0
       14 0 0 1 1 0
       16 0 0 0 0 1
       18 0 1 0 0 1
       19 1 0 1 0 0
       21 1 1 0 0 0
       22 0 0 1 1 0
       23 0 1 0 0 0
       24 0 0 1 0 0
       25 0 1 0 0 0
       26 0 0 1 0 0
       27 0 0 1 0 0
       28 0 1 0 1 0
       29 0 0 0 0 1
       30 0 0 0 1 0
       31 0 0 0 1 0
       32 1 0 1 0 0
       34 0 0 1 0 0
       35 0 1 0 0 1
       36 0 1 0 1 0
       38 1 0 1 0 0
       39 1 0 1 0 0
       40 0 0 0 1 0
       41 0 0 1 1 0;
param C : 1 2 3 5 6 9 :=
        1 0 0 0 0 1 0
        2 0 1 0 0 0 0
        3 0 0 0 0 0 0
        4 1 0 0 0 0 0
        5 1 0 1 0 0 0
        6 0 1 0 0 1 0
        7 0 0 0 0 0 0
        8 0 0 0 0 1 1
        9 1 0 0 0 1 0
       10 0 0 0 0 0 0
       11 0 0 0 1 0 0
       12 1 0 0 0 0 0
       13 1 0 0 0 1 1
       14 0 0 0 0 1 0
       15 0 0 0 0 0 0
       16 0 0 0 0 1 0
       17 0 0 0 0 0 0
       18 0 0 0 1 0 0
       19 0 0 0 0 0 1
       20 0 0 0 0 0 0
       21 0 0 1 0 0 1
       22 0 0 0 0 1 0
       23 0 0 0 0 1 0
       24 0 0 1 0 0 1
       25 0 1 0 1 0 0
       26 0 0 0 0 1 0
       27 0 0 0 0 1 0
       28 0 0 0 0 1 0
       29 0 0 0 0 0 0
       30 0 0 0 0 1 0
       31 0 0 1 0 1 0
       32 0 0 0 0 0 1
       33 0 0 0 0 0 0
       34 0 0 0 0 0 1
       35 0 0 0 0 1 1
       36 0 0 0 0 1 0
       37 0 0 0 0 0 0
       38 0 0 0 0 0 1
       39 0 0 0 0 0 0
       40 0 0 0 0 1 0
       41 0 0 0 0 1 0
       42 0 0 0 0 0 0
       43 0 0 1 0 1 0
       44 0 0 1 0 0 0;
param Q := 5,1,1,1  25,5,1,1  18,5,2,1  11,5,3,1;


end;