使用SMT 2输入格式在Z3中的BitVec中计算1

使用SMT 2输入格式在Z3中的BitVec中计算1,z3,Z3,在Z3中,是否有一种使用SMT 2输入格式计算BitVec中设置为1的位数的紧凑方法 这个问题的公认答案是: 展示了一种使用Python实现的方法。目前在SMTLib中直接实现这一点并不容易。最好的方法是针对每个位向量大小滚动自己的值;相当难看,但很容易生成代码: (set-logic QF_BV) (set-option :produce-models true) (define-fun popCount8 ((x (_ BitVec 8))) (_ BitVec 8)

在Z3中,是否有一种使用SMT 2输入格式计算BitVec中设置为1的位数的紧凑方法

这个问题的公认答案是:
展示了一种使用Python实现的方法。

目前在SMTLib中直接实现这一点并不容易。最好的方法是针对每个位向量大小滚动自己的值;相当难看,但很容易生成代码:

(set-logic QF_BV)
(set-option :produce-models true)

(define-fun popCount8 ((x (_ BitVec 8))) (_ BitVec 8)
                      (bvadd (ite (= #b1 ((_ extract 0 0) x)) #x01 #x00)
                             (ite (= #b1 ((_ extract 1 1) x)) #x01 #x00)
                             (ite (= #b1 ((_ extract 2 2) x)) #x01 #x00)
                             (ite (= #b1 ((_ extract 3 3) x)) #x01 #x00)
                             (ite (= #b1 ((_ extract 4 4) x)) #x01 #x00)
                             (ite (= #b1 ((_ extract 5 5) x)) #x01 #x00)
                             (ite (= #b1 ((_ extract 6 6) x)) #x01 #x00)
                             (ite (= #b1 ((_ extract 7 7) x)) #x01 #x00)))


; test
(define-fun x () (_ BitVec 8) #xAB)
(declare-fun result () (_ BitVec 8))
(assert (= result (popCount8 x)))
(check-sat)
; Should be 5!
(get-value (result))
这张照片是:

sat
((result #x05))
使用递归 SMTLib标准的最新版本允许使用递归函数来“以编程方式”执行此操作,但当涉及递归函数时,解算器支持仍然相当粗略。以下内容适用于z3,但其他解算器可能不太好。有了这个警告,下面是一个使用递归的奇特方法:

(set-logic BV)
(set-option :produce-models true)

(define-fun-rec popCount8_rec ((x (_ BitVec 8)) (i (_ BitVec 8)) (accum (_ BitVec 8))) (_ BitVec 8)
    (ite (= i #x08)
         accum
         (popCount8_rec (bvshl x #x01)
                        (bvadd i #x01)
                        (bvadd accum (ite (= #b1 ((_ extract 7 7) x)) #x01 #x00)))))

(define-fun popCount8 ((x (_ BitVec 8))) (_ BitVec 8) (popCount8_rec x #x00 #x00))

; test
(define-fun x () (_ BitVec 8) #xAB)
(declare-fun result () (_ BitVec 8))
(assert (= result (popCount8 x)))
(check-sat)
; Should be 5!
(get-value (result))
这还打印:

sat
((result #x05))
参数多态性 请注意,无论选择哪种方法,都必须在
popCountN
中为每个大小的
N
编写一个单独的函数。SMTLib不允许用户定义使用“参数化”类型的函数。这是逻辑的一个基本限制,也是许多人喜欢使用更高级语言编写SMT解算器脚本以避免此类样板代码的主要原因之一(尽管肯定不是唯一原因!)

巨蟒的把戏 您最好的选择是展开您自己的版本,如上所述。在Z3中使用的一个常见技巧是,您可以使用链接的Python程序,在某个时候打印s.sexpr(),并查看生成器生成的内容。然后,如果您愿意,可以将其剪切粘贴到SMTLib中;当然要注意常见的剪切和粘贴错误