情况如下:我正在为工作场所制定每日时间表。每天分为时段,每个时段我都知道必须有多少员工。该计划是使用两个整数决策变量创建的,这些变量描述了每个员工的到达和离开时间段。
目前,我使用一个额外的变量来判断员工 i 是否在 t 时工作,然后我在每个时间段对员工进行总结以与需求。我的代码可归结为以下内容:
using CP;
tuple TimeSlot {
key int id;
int minEmploy;
}
{TimeSlot} TSlots = ...;
{int} timeSlots = {t.id|t in TSlots};
int tMax = max(t in timeSlots) t;
range dayRange = 0..tMax;
range allEmployees = 1..10;
dvar int dayStart[allEmployees] in dayRange;
dvar int dayEnd[allEmployees] in dayRange;
dvar int workTimeT[allEmployees][timeSlots] in 0..1;
minimize ...;
subject to {
/*Indicator constraints*/
forall(i in allEmployees){
forall(t in timeSlots:t>0){
dayStart[i] <= t && t <= dayEnd[i] => workTimeT[i][t] == 1;
dayEnd[i] < t || t < dayStart[i] => workTimeT[i][t] == 0;
}
}
/*Must satisfy requirement*/
forall(t in timeSlots:t>0){
sum(i in allEmployees) workTimeT[i][t] >= item(TSlots,<t>).minEmploy;
}
}
有没有办法绕过这个额外的变量?添加 #employees 次 #timeslots 变量可能是有效的,只是为了检查一个数字是否在两个决策变量之间。
答案 0 :(得分:0)
我会把它写成你所做的反转 - 我会转储整数变量(dayStart [i]和dayEnd [i])并用布尔值替换它们(dayStart [i] [t]和dayStart [i] [T])。 CPLEX和其他解算器非常善于使用这些布尔值,尽管存在更多变量,它实际上可能比你尝试的更快地解决。
它还可以更容易地找出有多少人正在工作 - 它已经开始工作的人数减去完成工作的人数(假设没有围绕墓地转移,你在哪里开始工作一天,第二天早上结束,你的配方似乎认为永远不会发生这种情况。)
dvar int dayStart[allEmployees][timeSlots] in 0..1;
dvar int dayEnd[allEmployees][timeSlots] in 0..1;
forall(i in allEmployees) {
/* Every employee starts exactly once */
sum(t in timeSlots) dayStart[i][t] == 1;
/* Every employee stops exactly once */
sum(t in timeSlots) dayEnd[i][t] == 1;
/* You must start before you stop */
forall(t in timeSlots) dayEnd[i][t] <= sum(tstart in timeSlots: tstart < t) dayStart[i][tstart];
}
/* the number of employees working is the number who have started minus
the number who have stopped */
dexpr int NumWorking[t in timeSlots] =
sum(tstart in timeSlots: tstart <= t) dayStart[i][tstart]
-
sum(tend in timeSlots: tend < t) dayEnd[i][tend];
/* Make sure we've got enough people working */
forall(t in timeSlots)
NumWorking[t] >= item(TSlots,<t>).minEmploy;
如果你真的想要整数的开始和结束时间,你可以用布尔值来轻松写出来:
dvar int+ employeeStartTime[allEmployees];
dvar int+ employeeEndTime[allEmployees];
forall(i in allEmployees) {
employeeStartTime == sum(t in timeSlots) t*dayStart[i][t];
employeeEndTime == sum(t in timeSlots) t*dayEnd[i][t];
}