Z3 具有定义不正确的函数定义公理的意外未知

Z3 具有定义不正确的函数定义公理的意外未知,z3,Z3,SMT程序进一步向下编码(定义不清的)函数定义∀ s·wild(s)=1+wild(s)以稍微迂回的方式(应用Dafny对递归函数的“有限函数”编码),然后尝试证明wild(emp)=1+wild(emp)。然而,Z3 4.6.0(以及最近的4.7.0夜间版本)意外地产生了未知,而不是unsat (set-option :auto_config false) ;; true -> no change in behaviour (set-option :smt.mbqi false) ;;

SMT程序进一步向下编码(定义不清的)函数定义
∀ s·wild(s)=1+wild(s)
以稍微迂回的方式(应用Dafny对递归函数的“有限函数”编码),然后尝试证明
wild(emp)=1+wild(emp)
。然而,Z3 4.6.0(以及最近的4.7.0夜间版本)意外地产生了
未知
,而不是
unsat

(set-option :auto_config false) ;; true -> no change in behaviour
(set-option :smt.mbqi false) ;; true -> no change in behaviour

(declare-sort Snap)      ;; In the full example, this is ...
(declare-const emp Snap) ;; ... declared using declare-datatypes

(declare-fun wild (Snap) Int)
(declare-fun wild%limited (Snap) Int)

(assert (forall ((s Snap)) (! ;; AX-1
  (= (wild%limited s) (wild s))
  :pattern ((wild s))
)))

(assert (forall ((s Snap)) (! ;; AX-2
  (=
    (wild s)
    (+ 1 (wild%limited emp)))
  :pattern ((wild s))
)))

(push) ;; Full examples uses incremental mode
(assert
  (not 
    (= 
      (wild emp)
      (+ 1 (wild emp)))))
(check-sat) ;; UNKNOWN --- but why?
(pop)
鉴于我对Z3和触发器的理解,我预计会发生以下证明步骤:

  ¬(wild(emp) = 1 + wild(emp))  // Source assertion
≡ ¬(1 + wild%limited(emp) = 1 + wild(emp))  // By AX-2
≡ ¬(1 + wild%limited(emp) = 1 + wild%limited(emp))  // By AX-1
≡ ¬(true)  // Done: UNSAT
但这似乎没有发生。我的猜测是这些公理没有被实例化——事实上,
get info:all statistics
没有报告量化的实例化


有人能解释一下吗?

最后一个断言简化为“true”,因此没有(野生emp)会触发量词实例化的基础事件。

该死的简化器!好的,有道理,谢谢你的回答。但是,这种行为可能会令人困惑:SMT代码是由程序验证器(Viper)从包含定义错误的
wild
函数的程序生成的。编写程序的用户希望它能够验证(他们知道逻辑,但不知道所用工具链的内部),因为他们只是断言
wild
等于它的主体。您认为我们可以在这里采取任何合理的措施来保护
野生
触发条款吗?或者你会考虑改变简化器,这样Z3保留了触发项吗?