x
is a variable with lower and upper bounds 0
and 20
.
x_is_in_the_defined_domain
is a bool variable indicating what its name tells.
The defined_domain is [1, 3], [5, 7]
.
We can link x
and x_is_in_the_defined_domain
by finding its complementary set (domain) of intervals [0], [4], [8, 20]
.
from ortools.sat.python import cp_model
model = cp_model.CpModel()
x = model.NewIntVar(0, 20, 'x')
x_is_in_the_domain = model.NewBoolVar('indicator')
a_domain = cp_model.Domain.FromIntervals([[1, 3], [5, 7]])
b_domain = cp_model.Domain.FromIntervals([[0], [4], [8, 20]])
model.AddLinearExpressionInDomain(x, a_domain).OnlyEnforceIf(x_is_in_the_domain)
model.AddLinearExpressionInDomain(x, b_domain).OnlyEnforceIf(x_is_in_the_domain.Not())
solver = cp_model.CpSolver()
status = solver.Solve(model=model)
I doubt if my approach is unnecesssary and wonder if there is any more 'built-in' way of doing this?
So the answer is that no, there is not Not() of a linear constraint in domain. The good news is that complementing a domain can be automated:
print(a_domain)
print(b_domain)
print(a_domain.Complement())
print(a_domain.Complement().IntersectionWith(cp_model.Domain(0, 20)))
outputs
[1,3][5,7]
[0][4][8,20]
[-9223372036854775808,0][4][8,9223372036854775807]
[0][4][8,20]