Syntax 位向量函数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

我想用位向量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 :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
是不够的。