是的,Z3Py 对此有内置支持。有一个未记录的 API,在 Z3Py 文档中没有提到:使用PbEq
. 特别是,表达式
PbEq(((x1,1),(x2,1),..,(xN,1)),K)
如果 N 个布尔变量中的 K 个恰好设置为 true,则为 true。有一些报道称,这种编码比手动表达约束的简单方法更快。
要表达 1-out-of-N 约束,只需设置 K=1 并使用PbEq
. 要表达最多 K-out-of-N 约束,请使用PbLe
. 要表达至少 K-out-of-N 约束,请使用PbGe
.
你可以在 Python 中这样表达:
import z3
s = z3.Solver()
bvars = [z3.Bool("Var {0}".format(x)) for x in range(10)]
#Exactly 3 of the variables should be true
s.add( z3.PbEq([(x,1) for x in bvars], 3) )
s.check()
m = s.model()
s = z3.Solver()
bvars = [z3.Bool("Var {0}".format(x)) for x in range(10)]
#<=3 of the variables should be true
s.add( z3.PbLe([(x,1) for x in bvars], 3) )
s.check()
m = s.model()
s = z3.Solver()
bvars = [z3.Bool("Var {0}".format(x)) for x in range(10)]
#>=3 of the variables should be true
s.add( z3.PbGe([(x,1) for x in bvars], 3) )
s.check()
m = s.model()