如何在Python OR-Tools中实现x3∈{1,4}的变量取值约束?
解决OrTools SAT约束:让变量仅取特定值
你的代码问题出在两个核心点:
- 没必要引入布尔变量数组
b和AddExactlyOne(b)约束,这完全是多余的,反而打乱了约束逻辑。 - 对x3的约束逻辑完全错误:你用同一个布尔变量
b[3]同时绑定了x[3]==1和x[3]==4的约束,这意味着当b[3]为真时,x3必须同时等于1和4(不可能实现);当b[3]为假时,x3必须既不等于1也不等于4,正好和你的需求相反。
要实现x[3] ∈ {1,4}的约束,OrTools有更直接的方式,不需要复杂的布尔变量嵌套:
方法一:用AddAllowedAssignments(最直观)
这个API专门用来约束变量只能取指定集合内的值,代码极简:
from ortools.sat.python import cp_model model = cp_model.CpModel() # 定义4个变量,范围0-10 x = [model.NewIntVar(0, 10, f'val_{i}') for i in range(4)] # 直接约束x[3]只能取1或4 model.AddAllowedAssignments([x[3]], [[1], [4]]) 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')
方法二:用逻辑或约束
如果想手动构建逻辑约束,可以用AddBoolOr实现x[3]==1 || x[3]==4的逻辑:
from ortools.sat.python import cp_model model = cp_model.CpModel() x = [model.NewIntVar(0, 10, f'val_{i}') for i in range(4)] # 创建两个布尔变量分别表示x3等于1和等于4的情况 b1 = model.NewBoolVar('x3_eq_1') b4 = model.NewBoolVar('x3_eq_4') # 绑定布尔变量与数值约束 model.Add(x[3] == 1).OnlyEnforceIf(b1) model.Add(x[3] != 1).OnlyEnforceIf(b1.Not()) model.Add(x[3] == 4).OnlyEnforceIf(b4) model.Add(x[3] != 4).OnlyEnforceIf(b4.Not()) # 要求至少一个布尔变量为真(即x3是1或4) model.AddBoolOr([b1, b4]) 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')
运行以上任意一种代码,都会得到符合预期的输出:x3只会是1或4,其他变量在0-10范围内任意取值。
内容的提问来源于stack exchange,提问作者rpb
相关产品推荐
相关产品推荐

