Surprising behaviour when trying to prove a forall

北慕城南 提交于 2019-12-20 02:45:10

问题


Consider the following SMT-LIB code:

(set-option :auto_config false)
(set-option :smt.mbqi false)
; (set-option :smt.case_split 3)
(set-option :smt.qi.profile true)

(declare-const x Int)

(declare-fun trigF (Int Int Int) Bool)
(declare-fun trigF$ (Int Int Int) Bool)
(declare-fun trigG (Int) Bool)
(declare-fun trigG$ (Int) Bool)

; Essentially noise
(declare-const y Int)
(assert (!
  (not (= x y))
  :named foo
))

; Essentially noise
(assert (forall ((x Int) (y Int) (z Int)) (!
  (= (trigF$ x y z) (trigF x y z))
  :pattern ((trigF x y z))
  :qid |limited-F|
)))

; Essentially noise
(assert (forall ((x Int)) (!
  (= (trigG$ x) (trigG x))
  :pattern ((trigG x))
  :qid |limited-G|
)))

; This assumption is relevant
(assert (forall ((a Int) (b Int) (c Int)) (!
  (and
    (trigG a)
    (trigF a b c))
  :pattern ((trigF a b c))
  :qid |bar|
)))

Trying to assert that axiom bar holds, i.e.,

(push)
(assert (not (forall ((a Int) (b Int) (c Int))
  (and
    (trigG a)
    (trigF a b c)))))
(check-sat)
(pop)

fails (Z3 4.3.2 - build hashcode 47ac5c06333b):

unknown
[quantifier_instances]  limited-G :      1 :   0 : 1


Question 1: Why did Z3 only instantiate limited-G but neither limited-F nor bar (which would prove the assertion)?

Question 2: Commenting any of the (useless) assertions foo, limited-F or limited-G allows Z3 to prove the assertion - why is that? (Depending on which are commented, either only bar or bar and limited-F are instantiated.)


In case it is related to the observed behaviour: I would like to set smt.case_split to 3 (my configuration follows the one omitted by MSR's Boogie tool), but Z3 gives me WARNING: auto configuration (option AUTO_CONFIG) must be disabled to use option CASE_SPLIT=3, 4 or 5, despite the fact that (set-option :auto_config false).


回答1:


The situation is as follows:

  • when using pattern based instantiation exclusively Z3 takes a somewhat operational approach to finding quantifier instantiations.

  • by disabling MBQI you rely on the equality matching engine.

  • case_split = 3 instructs Z3 to use relevancy heuristic when choosing candidates for equality matching.
  • The assert (not (forall (a, b, c) (and (trigG a) (trigF a b c)))) expands into a disjunction (or (not (trigG a!0)) (not (trigF a!0 b!1 c!2))).
  • only one of the two disjuncts is relevant for satisfying the formula.
  • The search sets (trigG a!0) to false, so the clause is satisfied. The trigger (trigF a b c) is therefore never activated.

You can bypass this issue by distributing in universal quantifiers over conjunctions, and supplying patterns in each case. Thus, you(r tool) could rewrite the axiom:

(assert (forall ((a Int) (b Int) (c Int)) (!
  (and
    (trigG a)
    (trigF a b c))
  :pattern ((trigF a b c))
  :qid |bar|
 )))

to the two axioms.

(assert (forall ((a Int)) (! (trigG a) :pattern ((trigG a))))
(assert (forall ((a Int) (b Int) (c Int)) (!
    (trigF a b c)
  :pattern ((trigF a b c))
  :qid |bar|
 )))

The issue of setting auto-completion seems fixed. I somewhat recently fixed bug in the way that some top-level configurations were reset if multiple top-level configurations were set in the smt-lib input.



来源:https://stackoverflow.com/questions/25622964/surprising-behaviour-when-trying-to-prove-a-forall

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!