使用SMT 2输入格式在Z3中的BitVec中计算1
在Z3中,是否有一种使用SMT 2输入格式计算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)
展示了一种使用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中;当然要注意常见的剪切和粘贴错误