目标是限制某些变量仅分配给特定值。
假设有 4 个变量,但 var x3 只能分配给 1 和 4。形式上,
x[3] ∈ {1,4}
我尝试使用如下的
OnlyEnforceIf
,但是,它没有产生预期的结果。
我可以知道如何解决这个问题吗?
from ortools.sat.python import cp_model
model = cp_model.CpModel()
x = [model.NewIntVar(0, 10, f'val_{i}') for i in range(4)]
b = [model.NewBoolVar(f'b{i}') for i in range(4)]
model.AddExactlyOne(b)
for idx in range(4):
if idx == 3:
for hval in [1,4]:
model.Add(x[idx] == hval).OnlyEnforceIf(b[idx])
model.Add(x[idx] != hval).OnlyEnforceIf(b[idx].Not())
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
for n,dval in enumerate(x):
print(f'int: {n}: sol: {solver.Value(dval)}')
else:
print('unsat')
哪些产品
int: 0: sol: 0
int: 1: sol: 0
int: 2: sol: 0
int: 3: sol: 0
但是,我期望可能的输出(不限于)如下
int: 0: sol: 0
int: 1: sol: 0
int: 2: sol: 0
int: 3: sol: 1
或
int: 0: sol: 8
int: 1: sol: 8
int: 2: sol: 0
int: 3: sol: 4
很可能您忘记添加其中一项必须为真。
model.AddExactlyOne(b)
否则,求解器会很乐意将它们全部设置为 false。 您还在
OnlyEnforceIf
部分使用了错误的索引。
您没有限制所有 bi 和所有 hval (使用 [] 而不是范围)
完整的代码应该是:
from ortools.sat.python import cp_model
model = cp_model.CpModel()
x = [model.NewIntVar(0, 10, f'x_{i}') for i in range(4)]
b = [model.NewBoolVar(f'b_{i}') for i in range(4)]
# Exactly one of the b[i] must be true.
model.AddExactlyOne(b)
for idx in range(4):
if idx == 3:
for hval in range(4):
model.Add(x[idx] == hval + 1).OnlyEnforceIf(b[hval])
model.Add(x[idx] != hval + 1).OnlyEnforceIf(b[hval].Not())
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
for dvar in x:
print(f'{dvar.Name()}: {solver.Value(dvar)}')
for bvar in b:
print(f'{bvar.Name()}: {solver.BooleanValue(bvar)}')
else:
print('unsat')
现在可以正确打印了
x_0: 0
x_1: 0
x_2: 0
x_3: 4
b_0: False
b_1: False
b_2: False
b_3: True