Z3中宏和量词之间的差异

时间:2013-04-02 07:41:56

标签: z3

我想知道以下两个陈述之间有什么区别 -

声明1

(define-fun max_integ ((x Int) (y Int)) Int 
  (ite (< x y) y x))

声明2

(declare-fun max_integ ((Int)(Int)) Int)
(assert (forall ((x Int) (y Int)) (= (max_integ x y) (if (< x y) y x))))

我观察到当我使用Statement1时,我的z3约束在0.03秒内给出了一个结果。而当我使用Statement2时,它在2分钟内没有完成,我终止了解算器。 我还想知道如何使用C-API实现它。

谢谢!

1 个答案:

答案 0 :(得分:2)

声明1是一个宏。 Z3将使用max_integ表达式替换每次出现的ite。它在解析时间内完成。在第二个语句中,默认情况下,Z3不会消除max_integ,并且为了能够返回sat,它必须为未解释的符号max_integ构建解释,以满足量词的需要所有xy。 Z3有一个名为:macro-finder的选项,它将检测基本上编码宏的量词,并将消除它们。以下是一个示例(也可在线提供here):

(set-option :macro-finder true)
(declare-fun max_integ ((Int)(Int)) Int)
(assert (forall ((x Int) (y Int)) (= (max_integ x y) (if (< x y) y x))))
(check-sat)
(get-model) 

话虽这么说,我们可以通过编写给定Z3表达式返回新Z3表达式的函数,轻松地在编程API中模拟宏。这里是一个使用Python API的例子(也可在线提供here):

def max(a, b):
   # The function If builds a Z3 if-then-else expression
   return If(a >= b, a, b)

x, y = Ints('x y')
solve(x == max(x, y), y == max(x, y), x > 0)

另一种选择是使用C API:Z3_substitute_vars。这个想法是一个包含自由变量的表达式。使用API​​ Z3_mk_bound创建自由变量。每个变量代表一个参数。然后,我们使用Z3_substitute_vars将变量替换为其他表达式。