如何表示约束(A && B)|| (C && D)|| (E && F)||

时间:2019-10-05 08:57:58

标签: python or-tools

我是or-tool的新手,我试图表示约束:

(!A &&!B)|| (!C &&!D)|| (!E &&!F)|| ...

我尝试了以下操作(在我的情况下,A是shift_0LM0,B是shift_0LT0,C是shift_0MM0,D是shift_0MT0,...),将!A &&!B表示为A + B == 0,即。 !(A || B):

    for week in range(4):
        for employee in range(5):
            model.AddBoolOr([
                shift[f'{week}{weekday}M{employee}'] + shift[f'{week}{weekday}T{employee}'] == 0
                for weekday in 'LMXJVSD'
            ])

但是我得到了错误:

TypeError: NotSupported: model.GetOrMakeBooleanIndex((shift_0LM0 + shift_0LT0) == 0

有表达这种约束的简便方法吗?

1 个答案:

答案 0 :(得分:1)

如Laurent所说,AddBoolOr需要布尔文字,因此您必须创建中间变量:

from ortools.sat.python import cp_model

model = cp_model.CpModel()
a, b, c, d = [model.NewBoolVar(x) for x in 'abcd']

not_a_not_b = model.NewBoolVar('!A && !B')
model.Add(a+b == 0).OnlyEnforceIf(not_a_not_b)

not_c_not_d = model.NewBoolVar('!C && !D')
model.Add(c+d == 0).OnlyEnforceIf(not_c_not_d)

model.AddBoolOr([not_a_not_b, not_c_not_d])

solver = cp_model.CpSolver()
solver.Solve(model)

for x in [a, b, c, d]:
    print(solver.Value(x))

编辑:对于(A && B)|| (C && D)只需将a+b == 0更改为a+b == 2

如果要在搜索所有解决方案时避免重复的解决方案,则必须添加其他含义:

model.Add(a+b != 0).OnlyEnforceIf(not_a_not_b.Not())