不可行的解决方案,绝对可行 - CPLEX
Infeasible Solution, Definitely Feasible - CPLEX
基本上,我有两个员工,每个员工都可以分配到两个花名册模式中的一个,这又为每个员工分配一组轮班。
为员工分配一个花名册模式 -> 该员工只能在该花名册模式中规定的轮班工作,并且必须完成所有工作。
为此,我有一个约束,基本上规定每个员工所做的所有班次的总和应该等于输入 shiftsPerRP
。因此,如果一个花名册模式,例如0,被选为员工 Allan,那么 Allan 应该恰好工作 45 个班次。
然而,此约束不断失败并导致不可行的解决方案。我无法弄清楚我在这里缺少什么。感谢任何帮助。
相关数据:
days={
1, 2, 3, 4, 5, 6, 7
}
People = {
Allan,
Joe,
};
rosterPatterns = {
0,1
};
shiftsPerRP = {
<0,45>
<1,5>
};
Skills= {
A,
B,
C
};
相关代码:
dvar boolean Assign[days][Hours][People][Skills]; // Indicates a shift assignment
range Hours = 0..23;
forall(h in Hours, d in days, p in People, rp in rosterPatterns, shiftsInRP in shiftsPerRP : shiftsInRP.ID == rp)
sum(s in Skills)
Assign[d][h][p][s] == shiftsInRP.shifts;
为了对此进行分析,请标记您的约束条件(请参阅添加的 'c1'):
forall(h in Hours,
d in days,
p in People,
rp in rosterPatterns,
shiftsInRP in shiftsPerRP
: shiftsInRP.ID == rp)
c1:
sum(s in Skills)
Assign[d][h][p][s] == shiftsInRP.shifts;
据此,OPL 应计算最小冲突,以显示哪些约束不可行。这样做(在命令行上)我发现生成的第一个约束是不可行的。约束在 left-hand 一侧只有三个变量,但 right-hand 一侧是 5。这永远无法满足。
鉴于集合 Skills
中只有三个元素,约束的 left-hand 端将始终有 3 个变量。因此它可以采用 {0, 1, 2, 3} 中的值。如果任何元组 shifts
的值大于 3 那么显然不能满足此约束。
编辑:看起来您可能混淆了应该进入 forall
的内容和应该进入 sum
的内容。为了正确表述,我认为你需要一个辅助变量
dvar boolean RosterAssigned[People][rosterPatterns];
如果一个人被分配到花名册模式则为 1,否则为 0。
有了它,您可以将约束表述为
forall(p in People)
sum(h in Hours, s in Skills, d in days)
Assign[d][h][p][s]
== sum(rp in rosterPatterns, shiftsInRP in shiftsPerRP : shitsInRP.ID == rp) (RosterAssigned[p][rp] * shiftsInRP.shifts);
left-hand 方给出了一个人 p
实际工作的班次数。 right-hand 侧给出了花名册模式所需的班次数。当然,您还必须添加约束,以保证每个员工都被分配到一个名册模式。
基本上,我有两个员工,每个员工都可以分配到两个花名册模式中的一个,这又为每个员工分配一组轮班。
为员工分配一个花名册模式 -> 该员工只能在该花名册模式中规定的轮班工作,并且必须完成所有工作。
为此,我有一个约束,基本上规定每个员工所做的所有班次的总和应该等于输入 shiftsPerRP
。因此,如果一个花名册模式,例如0,被选为员工 Allan,那么 Allan 应该恰好工作 45 个班次。
然而,此约束不断失败并导致不可行的解决方案。我无法弄清楚我在这里缺少什么。感谢任何帮助。
相关数据:
days={
1, 2, 3, 4, 5, 6, 7
}
People = {
Allan,
Joe,
};
rosterPatterns = {
0,1
};
shiftsPerRP = {
<0,45>
<1,5>
};
Skills= {
A,
B,
C
};
相关代码:
dvar boolean Assign[days][Hours][People][Skills]; // Indicates a shift assignment
range Hours = 0..23;
forall(h in Hours, d in days, p in People, rp in rosterPatterns, shiftsInRP in shiftsPerRP : shiftsInRP.ID == rp)
sum(s in Skills)
Assign[d][h][p][s] == shiftsInRP.shifts;
为了对此进行分析,请标记您的约束条件(请参阅添加的 'c1'):
forall(h in Hours,
d in days,
p in People,
rp in rosterPatterns,
shiftsInRP in shiftsPerRP
: shiftsInRP.ID == rp)
c1:
sum(s in Skills)
Assign[d][h][p][s] == shiftsInRP.shifts;
据此,OPL 应计算最小冲突,以显示哪些约束不可行。这样做(在命令行上)我发现生成的第一个约束是不可行的。约束在 left-hand 一侧只有三个变量,但 right-hand 一侧是 5。这永远无法满足。
鉴于集合 Skills
中只有三个元素,约束的 left-hand 端将始终有 3 个变量。因此它可以采用 {0, 1, 2, 3} 中的值。如果任何元组 shifts
的值大于 3 那么显然不能满足此约束。
编辑:看起来您可能混淆了应该进入 forall
的内容和应该进入 sum
的内容。为了正确表述,我认为你需要一个辅助变量
dvar boolean RosterAssigned[People][rosterPatterns];
如果一个人被分配到花名册模式则为 1,否则为 0。 有了它,您可以将约束表述为
forall(p in People)
sum(h in Hours, s in Skills, d in days)
Assign[d][h][p][s]
== sum(rp in rosterPatterns, shiftsInRP in shiftsPerRP : shitsInRP.ID == rp) (RosterAssigned[p][rp] * shiftsInRP.shifts);
left-hand 方给出了一个人 p
实际工作的班次数。 right-hand 侧给出了花名册模式所需的班次数。当然,您还必须添加约束,以保证每个员工都被分配到一个名册模式。