or-toolsconstraint-programmingcp-sat

Is there any way to add "Not" constraint for AddLinearExpressionInDomain besides creating a complementary set of domain in CP-SAT?


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?


Solution

  • 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]