给出以下Z3前导码(采用SMT2格式):
(set-option :smt.auto-config false)
(set-option :smt.mbqi false)
(declare-fun exp (Real) Real)
(declare-fun foo (Real) Real)
(declare-fun bar (Real Real) Real)
(assert (forall ((x Real) (y Real)) (= (* (exp x) (exp y)) (exp (+ x y)))))
(declare-const x Real)
(declare-const y Real)
(declare-const z Real)
unsat
可以在几毫秒内从以下两个目标中推断出来:
(assert (not (= (+ z (* (exp x) (exp y))) (+ z (exp (+ x y))))))
(assert (not (= (foo (bar z (* (exp x) (exp y)))) (foo (bar z (exp (+ x y)))))))
然而,Z3在给出目标时超时:
(assert (not (= (foo (+ z (* (exp x) (exp y)))) (foo (+ z (exp (+ x y)))))))
可以看作是在foo
包裹第一个目标的两边,或者在第二个目标中用bar
替换+
。
如果我们使用以下两种模式中的任何一种来引用引理,就可以证明这个目标:
(assert (forall ((x Real) (y Real)) (! (= (* (exp x) (exp y)) (exp (+ x y))) :pattern (* (exp x) (exp y)))))
(assert (forall ((x Real) (y Real)) (! (= (* (exp x) (exp y)) (exp (+ x y))) :pattern (exp (+ x y)))))
因此,我假设默认情况下会生成多模式((exp x) (exp y))
,但我不确定如果双方都包含在foo
中,或者{{{}},这种模式的行为会有所不同1}}替换为+ z
。
这里发生了什么?感谢。
答案 0 :(得分:0)
我不确定您的情况发生了什么,但您可能会尝试向Z3提供有关exp
功能的其他信息。一种选择是:
(assert (exists ((EULER_E Real)) (forall ((x Real)) (= (exp x) (^ EULER_E x)))))
我非常确定这些内容写得正确,但我还没有在SMT-LIB中使用嵌套量词,所以请小心。另一个更明确的选择是:
(declare-const EULER_E Real)
(assert (> EULER_E 2.718281828459045))
(assert (< EULER_E 2.718281828459046))
(assert (forall ((x Real)) (= (exp x) (^ EULER_E x))))
添加上述任一项会使Z3返回unsat
作为您的示例。