Yes, Z3Py has built-in support for this. There is an undocumented API for this, that isn't mentioned in the Z3Py docs: use PbEq
. In particular, the expression
PbEq(((x1,1),(x2,1),..,(xN,1)),K)
will be true if exactly K out of the N boolean variables are set to true. There are some reports that this encoding will be faster than naive ways of manually expressing the constraint.
To express a 1-out-of-N constraint, just set K=1 and use PbEq
. To express an at-most-K-out-of-N constraint, use PbLe
. To express an at-least-K-out-of-N constraint, use PbGe
.
You can express this in Python like this:
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()
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…