我正在 OR Tools (Python) 上的 CP-Sat 中开发调度程序,并且我正在尝试扩展 这个约束
// Cover constraints
foreach (int s in Range(1, numShifts))
{
foreach (int w in Range(numWeeks))
{
foreach (int d in Range(7))
{
var works = new BoolVar[numEmployees];
foreach (int e in Range(numEmployees))
{
works[e] = work[e, s, w * 7 + d];
}
// Ignore off shift
var minDemand = weeklyCoverDemands[d][s - 1];
var worked = model.NewIntVar(minDemand, numEmployees, "");
model.Add(LinearExpr.Sum(works) == worked);
var overPenalty = excessCoverPenalties[s - 1];
if (overPenalty > 0)
{
var name = $"excess_demand(shift={s}, week={w}, day={d}";
var excess = model.NewIntVar(0, numEmployees - minDemand, name);
model.Add(excess == worked - minDemand);
obj.AddTerm(excess, overPenalty);
}
}
}
据我了解,每天轮班次数过多会受到惩罚。
我如何扩展/编辑它,以便它尝试达到目标(
minDemand
)?换句话说:我如何惩罚过度和不足?理想情况下,采用某种成本乘法,因此距离目标越远,成本就越高。
我所有的努力都以“不可行”或“未知”状态结束。
cost_variables = []
cost_coefficients = []
sum_var = model.NewIntVar(hard_min, hard_max, "")
# This adds the hard constraints on the sum.
model.Add(sum_var == sum(works))
# Penalize sums below the soft_min target.
if soft_min > hard_min and min_cost > 0:
delta = model.NewIntVar(-len(works), len(works), "")
model.Add(delta == soft_min - sum_var)
# TODO(user): Compare efficiency with only excess >= soft_min - sum_var.
excess = model.NewIntVar(0, 7, prefix + ": under_sum")
model.AddMaxEquality(excess, [delta, 0])
cost_variables.append(excess)
cost_coefficients.append(min_cost)
# Penalize sums above the soft_max target.
if soft_max < hard_max and max_cost > 0:
delta = model.NewIntVar(-7, 7, "")
model.Add(delta == sum_var - soft_max)
excess = model.NewIntVar(0, 7, prefix + ": over_sum")
model.AddMaxEquality(excess, [delta, 0])
cost_variables.append(excess)
cost_coefficients.append(max_cost)