问题
I have been using Google OR-tools and trying to follow along with their examples for scheduling problems. However, the python documentation is sometimes hard to follow, and the more complex example ( https://github.com/google/or-tools/blob/master/examples/python/shift_scheduling_sat.py) is not described well.
I want to be able to set hard and soft constraints on the amount of shifts employees work. In the above example I believe the function add_soft_sum_constraint()
(I've put its exact code below) does what I want to do. I would like to replicate its functionality but I don't understand how it is doing it.
In the 2 if statements Im unsure what the delta
and excess
variables represent, and why they are adding more constraints, rather than just add more to the 2 cost lists which will be used when they minimize the objective later.
If anyone has any insight into this example I would be grateful, thanks.
def add_soft_sum_constraint(model, works, hard_min, soft_min, min_cost,
soft_max, hard_max, max_cost, prefix):
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)
return cost_variables, cost_coefficients
回答1:
For soft_min:
delta: distance to the soft_min
soft_min - sum_var
, if it is negative it means that we are above that soft_constraint so the penalty should be 0,model.AddMaxEquality(excess, [delta, 0])
.excess: how far are we from the soft_min, used to discard negative deltas, this is what we will multiply by
min_cost
.
For soft_max:
It is pretty much the same but reversed.
delta: distance to the soft_max
sum_var - soft_max
, if it is negative it means that we are below that soft_constraint so the penalty should be 0,model.AddMaxEquality(excess, [delta, 0])
excess: how far are we from the soft_max, used to discard negative deltas, this is what we will multiply by
max_cost
.
Returns:
It returns the coefficients and variables, for example:
Let's say that the soft_min is 3 and the min_cost is 2:
- if someone works 2 days the excess is 1 and the cost will be 1*2.
- if someone works 1 day the excess is 2 and the cost will be 2*2.
Let's also say that the soft_max is 5 and the max_cost is 3:
- if someone works 6 days the excess is 1 and the cost will be 1*3.
Our variables are [1, 2, 1] and their coefficients [2, 2, 3].
来源:https://stackoverflow.com/questions/56787655/understanding-how-to-set-soft-constraints-using-google-or-tools