我说有10个布尔变量。我希望模型能够满足,如果其中只有3个是真的。
我如何将此编码为SAT问题?一种方法是创建所有可能的组合然后或它们在一起。是否有更好或更简洁的方式来表达这一点?
答案 0 :(得分:3)
如果您的应用程序允许,我建议使用不同的编码(例如,bitvectors或ints),因为这会使事情变得更容易并且避免编码级别的置换部分。例如,使用整数并将值限制为0或1,然后断言它们的总和为3。
这是一个编码(rise4fun链接:http://rise4fun.com/Z3/wswe):
(declare-fun b0 () Int)
(declare-fun b1 () Int)
(declare-fun b2 () Int)
(declare-fun b3 () Int)
(declare-fun b4 () Int)
(declare-fun b5 () Int)
(declare-fun b6 () Int)
(declare-fun b7 () Int)
(declare-fun b8 () Int)
(declare-fun b9 () Int)
(assert (= (+ b0 b1 b2 b3 b4 b5 b6 b7 b8 b9) 3))
(assert (or (= b0 0) (= b0 1)))
(assert (or (= b1 0) (= b1 1)))
(assert (or (= b2 0) (= b2 1)))
(assert (or (= b3 0) (= b3 1)))
(assert (or (= b4 0) (= b4 1)))
(assert (or (= b5 0) (= b5 1)))
(assert (or (= b6 0) (= b6 1)))
(assert (or (= b7 0) (= b7 1)))
(assert (or (= b8 0) (= b8 1)))
(assert (or (= b9 0) (= b9 1)))
(check-sat)
(get-model)
结果是:
sat
(model
(define-fun b6 () Int
0)
(define-fun b5 () Int
0)
(define-fun b9 () Int
1)
(define-fun b3 () Int
0)
(define-fun b2 () Int
0)
(define-fun b7 () Int
0)
(define-fun b1 () Int
0)
(define-fun b8 () Int
1)
(define-fun b4 () Int
0)
(define-fun b0 () Int
1)
)
编辑:为了完整性添加了bitvector示例,可以通过填充来改进,这样我们就可以比较不同大小的bitvectors(rise4fun link:http://rise4fun.com/Z3/UsldZ):
(declare-fun b0 () (_ BitVec 3))
(declare-fun b1 () (_ BitVec 3))
(declare-fun b2 () (_ BitVec 3))
(declare-fun b3 () (_ BitVec 3))
(declare-fun b4 () (_ BitVec 3))
(declare-fun b5 () (_ BitVec 3))
(declare-fun b6 () (_ BitVec 3))
(declare-fun b7 () (_ BitVec 3))
(declare-fun b8 () (_ BitVec 3))
(declare-fun b9 () (_ BitVec 3))
(assert (= (bvadd b0 b1 b2 b3 b4 b5 b6 b7 b8 b9) #b011))
; can probably avoid the next by using a length 1 bitvector and padding, but not sure how to do padding
(assert (or (= b0 #b000) (= b0 #b001)))
(assert (or (= b1 #b000) (= b1 #b001)))
(assert (or (= b2 #b000) (= b2 #b001)))
(assert (or (= b3 #b000) (= b3 #b001)))
(assert (or (= b4 #b000) (= b4 #b001)))
(assert (or (= b5 #b000) (= b5 #b001)))
(assert (or (= b6 #b000) (= b6 #b001)))
(assert (or (= b7 #b000) (= b7 #b001)))
(assert (or (= b8 #b000) (= b8 #b001)))
(assert (or (= b9 #b000) (= b9 #b001)))
(check-sat)
(get-model)
结果是:
sat
(model
(define-fun b6 () (_ BitVec 3)
#b000)
(define-fun b5 () (_ BitVec 3)
#b000)
(define-fun b9 () (_ BitVec 3)
#b001)
(define-fun b3 () (_ BitVec 3)
#b000)
(define-fun b0 () (_ BitVec 3)
#b001)
(define-fun b2 () (_ BitVec 3)
#b000)
(define-fun b7 () (_ BitVec 3)
#b000)
(define-fun b1 () (_ BitVec 3)
#b001)
(define-fun b8 () (_ BitVec 3)
#b000)
(define-fun b4 () (_ BitVec 3)
#b000)
)