Syntax 位向量函数Z3
我想用位向量48在z3解算器中解决这个问题:Syntax 位向量函数Z3,syntax,z3,smt,bitvector,vector-multiplication,Syntax,Z3,Smt,Bitvector,Vector Multiplication,我想用位向量48在z3解算器中解决这个问题: (declare-fun x () Int) (declare-fun y () Int) (assert (= *someNumber* (* x y))) (assert (> x 1)) (assert (> y 1)) (check-sat) (get-model) (exit) 我正在试图弄清楚如何使用算术函数,但是,它的效果不是很好。 对我来说,问题在于函数的正确语法以及如何在其中设置值 (set-option :produ
(declare-fun x () Int)
(declare-fun y () Int)
(assert (= *someNumber* (* x y)))
(assert (> x 1))
(assert (> y 1))
(check-sat)
(get-model)
(exit)
我正在试图弄清楚如何使用算术函数,但是,它的效果不是很好。
对我来说,问题在于函数的正确语法以及如何在其中设置值
(set-option :produce-models true)
(set-logic QF_BV)
;; Declaring all the variables
(declare-const a (_ BitVec 48))
(declare-const b (_ BitVec 48))
(declare-const c (_ BitVec 48))
;; Soft constraints to limit reuse
(assert (= c #xnumberInHex))
(assert-soft (not (= a b)))
(check-sat-using (then simplify solve-eqs bit-blast sat))
(simplify (= c (bvmul a b))
(simplify (bvugt a #b000000000001))
(simplify (bvugt b #b000000000001))
(check-sat)
(get-model)
非常感谢您的帮助。
语法/如何在那里写入正确的位向量看起来您已经掌握了其中的几乎所有部分,但可能并不完全掌握正确的语法。下面是一个完整的编码,使用
c=18
:
(set-option :produce-models true)
(set-logic ALL)
;; Declaring all the variables
(declare-const a (_ BitVec 48))
(declare-const b (_ BitVec 48))
(declare-const c (_ BitVec 48))
(assert (= c #x000000000012)) ; 18 is 0x12 in hex
(assert (= c (bvmul a b)))
; don't allow overflow
(assert (bvumul_noovfl a b))
(assert (bvult #x000000000001 a))
(assert (bvult #x000000000001 b))
;; Soft constraints to limit reuse
(assert-soft (not (= a b)))
(check-sat)
(get-model)
注意使用了ALL
逻辑和检测无符号位向量乘法溢出的函数bvumul_noovfl
。(此函数特定于z3,仅当您选择逻辑为ALL
时才可用)由于您正在执行位向量运算,因此它会受到环绕,我猜这是您希望避免的。通过明确声明我们不希望a
和b
的乘法溢出,我们实现了这个目标
对于该输入,z3表示:
sat
(model
(define-fun b () (_ BitVec 48)
#x000000000009)
(define-fun a () (_ BitVec 48)
#x000000000002)
(define-fun c () (_ BitVec 48)
#x000000000012)
)
它正确地将数字18
(这里用十六进制写成12
)分解为2
和9
请注意,乘法是一个困难的问题。随着位大小的增加(这里选择了48,但可能更大),或者如果数字c
本身变大,z3将越来越难解决问题。当然,这并不奇怪:一般来说,因子分解是一个困难的问题,z3在这里没有魔法可以正确地对输入值进行因子分解,而不需要求解大量的内部方程组,这些方程组的大小随着位宽度的增加呈指数增长
但不要担心:位向量逻辑是完整的:这意味着z3将始终能够考虑,尽管速度很慢,假设您没有首先耗尽内存或耐心 这就是我现在所做的。
它可能会在未来帮助其他人:
(set-option :produce-models true)
(set-logic ALL)
;; Declaring all the variables
(declare-const a (_ BitVec 48))
(declare-const b (_ BitVec 48))
(declare-const c (_ BitVec 48))
(assert (= c #x00000000affe))
(assert (= c (bvmul a b)))
; don't allow overflow
(assert (= c (bvumul_noovfl a b)))
(assert (bvult #x000000000001 a))
(assert (bvult a c))
(assert (bvult #x000000000001 b))
(assert (bvult b c))
;; Soft constraints to limit reuse
(assert-soft (not (= a b)))
(check-sat)
(get-model)
我又添加了两个断言,以确保a或b不超过c(十六进制输入)
在本例中,我使用了“affe”,十进制数为45054。
它应该也适用于更大的公司
输出:
sat
(model
(define-fun b () (_ BitVec 48)
#x00000000138e)
(define-fun a () (_ BitVec 48)
#x000000000009)
(define-fun c () (_ BitVec 48)
#x00000000affe)
)
十六进制:138e*9=Aff
十二月:5006*9=45054
希望这将在将来帮助其他人。请注意,此解决方案不能保证
a*b
不会溢出。从你最初的帖子来看,你似乎想计算数字,在这种情况下,溢出将是一个问题。看看为什么,让我们考虑8位数字。以a=69
、b=22
和c=238
为例。我们有69*22=238(mod 256)
,但你几乎不会把69
和22
称为238
的因式分解。当然,这真的取决于你想要实现什么,但一般来说,仅仅因为a
和b
小于c
并不意味着它们的乘法不等于c
,除非它们是适当的因子。希望这有意义!是的,我正在尝试分解一个大的数字,比如说“12345678”。感谢您的澄清。如果您正在进行保理,您将无法避免使用bvumul_noovfl
。仅仅断言a
和b
小于c
是不够的。