Reputation: 173
I'm getting back into Google's OR tools and trying a (relatively) simple optimization. I'm using the CP SAT solver and I'm probably missing something elementary here. I have some variables x, y and some constant c. I'd like x to be equal to 1 if y is smaller than that c, and 0 otherwise.
from ortools.sat.python import cp_model
solver = cp_model.CpSolver()
model = cp_model.CpModel()
c = 50
x = model.NewBoolVar(name='x')
y = model.NewIntVar(name='y', lb=0, ub=2**10)
model.Add(x == (y < c))
model.Maximize(x+y)
status = solver.Solve(model)
I'm getting an error message
TypeError: bad operand type for unary -: 'BoundedLinearExpression'
It seems I'm misusing OR tools syntax for my constraint here. I'm having difficulties understanding the documentation for OR tools online, and I seem to have forgotten quite a bit more about it than I thought.
Upvotes: 5
Views: 3134
Reputation: 14660
According to an example from here, you're almost there.
x == (y < c)
constraintx = true
If x
is true
, then y < c
must also be true
. That's exactly what OnlyEnforceIf
method is for. If an argument of OnlyEnforceIf
is true
, then the constraint in the Add
method will be activated:
model.Add(y < c).OnlyEnforceIf(x)
x = false
,As mentioned in Case 1, OnlyEnforceIf
won't activate the constraint, if its argument is not evaluated to true
. Hence, you cannot just leave case y >= c
on its own and hope that it will be implied if x = false
. So, add a reverse constraint for this case as below:
model.Add(y >= c).OnlyEnforceIf(x.Not())
Since, for x = false
, x.Not()
will be true
, the constraint y >= c
will be activated and used when solving your equation.
from ortools.sat.python import cp_model
solver = cp_model.CpSolver()
model = cp_model.CpModel()
c = 50
x = model.NewBoolVar(name='x')
y = model.NewIntVar(name='y', lb=0, ub=2**10)
model.Add(y < c).OnlyEnforceIf(x)
model.Add(y >= c).OnlyEnforceIf(x.Not())
model.Maximize(x+y)
status = solver.Solve(model)
Upvotes: 3