我正在写一个迷你程序,为一家餐馆的员工安排日常工作。限制条件是每个工人每周只连续工作五天,并且每一天都有一个最低要求,该要求出现在下面代码的数组“minempl_perday”中。
任务是在满足上述所有限制的同时最小化受雇人员的数量。它存储在变量'nb_personnes‘中。
代码运行时没有错误,但是它无限地运行,没有任何输出。有人能帮我解决这个问题吗?
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];
发布于 2019-12-23 00:49:17
当使用优化(最小化或最大化)时,建议使用-a选项来查看所有中间解决方案。如果没有此选项,则仅显示最后一个最优解决方案。
如果解决方案花费的时间太长,你可以尝试不同的搜索选项,例如
solve ::int_search(array1d(planning), anti_first_fail, indomain_split, complete) minimize nb_personnes;
此外,您还可以测试使用Chuffed求解器,它可能会更快。请注意,对于此模型,您必须添加以下include行来处理集合变量:
include "nosets.mzn";
然而,对于这个问题,使用MIP解算器可能更好,例如CBC。请注意,您仍然需要添加include "nosets.mzn;
行。
稍后(有点离题):您的七天限制可以替换为以下内容:
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
)
);
https://stackoverflow.com/questions/59446018
复制相似问题