在z3 smt2中使用整数除法时未知

时间:2016-09-18 19:17:13

标签: z3

我试图找到函数penta(n)=(n *(3n-1))/ 2的解,并且对于所有数量的正数,penta(z)= penta(a)+ penta(b)。这可以工作,直到整数除法(div)是定义的一部分,但是当它在定义中添加时,我得到超时未知。 我希望能得到8,7,4。我对错误的做法有什么看法?

(declare-const a Int)
(declare-const b Int)
(declare-const z Int)

(define-fun penta ((n Int)) Int (div (* (- (* 3 n ) 1) n) 2) )  

(assert (= (penta z) (+ (penta a) (penta b))  ))
(assert (> a 1))
(assert (> b 1))
(assert (> z 1))

(check-sat)
(get-model)

我使用http://rise4fun.com/Z3网站上的版本和版本4.1(x64)。

1 个答案:

答案 0 :(得分:2)

主要问题是问题在两个非数字参数之间使用整数乘法。一般的丢番图问题没有决策程序,所以Z3尽力而为,这不利于模型枚举。

当你不使用整数除法时,Z3会尝试基于的部分启发式算法 将问题转换为有限域位向量以找到模型。它调用 这种启发式方法是对公式进行语法检查。使用运算符时,语法检查失败(div ... 2)。 您可以编码(div x 2),以便启发式选择问题 通过引入新变量并对它们进行限制:

(declare-const penta_z Int)
(declare-const penta_a Int)
(declare-const penta_b Int)
(assert (or (= (* 2 penta_z) (penta z)) (= (+ 1 (* 2 penta_z)) (penta z))))
(assert (or (= (* 2 penta_a) (penta a)) (= (+ 1 (* 2 penta_a)) (penta a))))
(assert (or (= (* 2 penta_b) (penta b)) (= (+ 1 (* 2 penta_b)) (penta b))))
(assert (= penta_z (+ penta_a penta_b)  ))
(assert (> a 1))
(assert (> b 1))
(assert (> z 1))
(assert (>= penta_z 0))
(assert (<= penta_z 100))

你也可以使用位向量直接编码你的问题,虽然这开始容易出错,因为你必须处理如何处理溢出。