简体   繁体   中英

Problem taking infinite time to satisfy constraints and produce output

I am writing a minizinc program for scheduling workers for a restaurant for everyday work. The constraints are that each worker works only five consecutive days per week and each day has a minimum requirement per day that is present in the array 'minempl_perday' of the code below.

The task is to minimize the number of persons employed while satisfying all the constraints of above. It is stored in the variable 'nb_personnes'.

The code runs with no error but it runs infinitely without any output. Could someone help me resolve it please?

include "globals.mzn";

int: n_jour = 7; 
int: maxpersonnes = 40;
var 1..maxpersonnes : nb_personnes ;

set of int: jours = 1..n_jour;
array[1..n_jour] of int: minempl_perday = [14,13,15,16,19,18,11] ;
%set of int var: personnes = 1..n_personnes;

array[1..maxpersonnes, jours] of var 0..1: planning;

% Now pad all remaining rows to 0
constraint forall(i in nb_personnes+1..maxpersonnes,j in jours)(planning[i,j]=0);

% Constraints

% Each value of every point in array can only be 1 or 0
%constraint forall(p in 1..nb_personnes, d in jours)(planning[p,d] = 1 \/ planning[p,d] = 0);

% Each employee only works 5 days a week.
%constraint forall(p in 1..nb_personnes)(forall(d in jours))(sum(planning[p][d]) = 5); 
constraint forall(p in 1..nb_personnes)(sum(d in jours)(planning[p,d]) = 5);

% Minimum number of employees respected each day
constraint forall(i in 1..n_jour )(sum(p in 1..nb_personnes)(planning[p,i]) >= minempl_perday[i]);


% Five days consecutive worked by every employee
% First day - monday
constraint forall(p in 1..nb_personnes)(if planning[p,1] = 1 /\ planning[p,7] = 0 then planning[p,2] = 1 /\ planning[p,3]= 1 /\ planning[p,4] = 1/\ planning[p,5] = 1 endif);

% First day - tuesday
constraint forall(p in 1..nb_personnes)(if planning[p,2] = 1 /\ planning[p,1] = 0 then planning[p,3] = 1 /\ planning[p,4]= 1 /\ planning[p,5] = 1/\ planning[p,6] = 1 endif);

% First day - wednesday
constraint forall(p in 1..nb_personnes)(if planning[p,3] = 1 /\ planning[p,2] = 0 then planning[p,4] = 1 /\ planning[p,5]= 1 /\ planning[p,6] = 1/\ planning[p,7] = 1 endif);

% First day - tnursday
constraint forall(p in 1..nb_personnes)(if planning[p,4] = 1 /\ planning[p,3] = 0 then planning[p,5] = 1 /\ planning[p,6]= 1 /\ planning[p,7] = 1/\ planning[p,1] = 1 endif);

% First day - friday
constraint forall(p in 1..nb_personnes)(if planning[p,5] = 1 /\ planning[p,4] = 0 then planning[p,6] = 1 /\ planning[p,7]= 1 /\ planning[p,1] = 1/\ planning[p,2] = 1 endif);

% First day - saturday
constraint forall(p in 1..nb_personnes)(if planning[p,6] = 1 /\ planning[p,5] = 0 then planning[p,7] = 1 /\ planning[p,1]= 1 /\ planning[p,2] = 1/\ planning[p,3] = 1 endif);

% First day - sunday
constraint forall(p in 1..nb_personnes)(if planning[p,7] = 1 /\ planning[p,6] = 0 then planning[p,1] = 1 /\ planning[p,2]= 1 /\ planning[p,3] = 1/\ planning[p,4] = 1 endif);


% Minimize the nb_personnes such that all the constraints of above are satisfied
solve minimize(nb_personnes);

output [show(planning[p,j])++" "++
     if j==n_jour 
       then "\n" 
       else "" 
     endif 
     |p in 1..maxpersonnes, j in jours];

When using optimization (minimize or maximize) it's recommended to use the -a options to see all intermediate solutions. Without this option, only the last, optimal, solution is shown.

If the solution takes too long time, you can experiment with different search options, eg

solve ::int_search(array1d(planning), anti_first_fail, indomain_split, complete)  minimize nb_personnes;

Also, you can also test to use the Chuffed solver which might be faster. Note that for this model you have to add the following include line to handle set variables:

include "nosets.mzn";

However, for this problem it's probably better to use a MIP solver, eg CBC. Note that you still have to add the include "nosets.mzn; line.

Later (and a bit off-topic): Your seven day constraints can be replaced with the following:

function int: modadd(int: n, int: s, int: m) =
  let {
     int: r = (n + s) mod m;
     int: t = if r == 0 then m else r  endif
  }
  in t;

constraint
  forall(t in 1..7) (
    forall(p in 1..nb_personnes)(
       if planning[p,t] = 1 /\ planning[p,modadd(t,-1,7)] = 0 then
         forall(a in 1..4) (
            planning[p,modadd(t,a,7)] = 1
         )
      endif
    )
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM