max element in Z3 Seq Int

拥有回忆 提交于 2020-01-16 09:43:06

问题


I'm trying to write a max function that operates on Seq Int. It should return the index with maximal value. Here is what I have:

(declare-fun max ((Seq Int)) Int)
(assert (forall ((A (Seq Int)))
    (=>
        (> (seq.len A) 0)
        (and
            (<= 0 (max A))
            (<  (max A) (seq.len A))
            (forall ((i Int))
                (=>
                    (and
                        (<= 0 i)
                        (<  i (seq.len A)))
                    (<= (seq.nth A i) (seq.nth A (max A))))))))
)

 (assert (= (max (seq.++ (seq.unit 8) (seq.unit 3))) 0))
;(assert (= (max (seq.++ (seq.unit 8) (seq.unit 3))) 1))

(check-sat)

When I run it like this, Z3 gets stuck. If I use the commented line instead, Z3 immediately answers unsat (like it should). Am I missing something here? Is there a way to define max properly?


回答1:


This sort of quantified problems are just not a good match for z3. (Or any other SMT solver.) To prove properties of such recursive predicates, you need induction. Traditional SMT solvers have no induction capabilities.

Having said that, you can help z3 by making your quantified assertions separated out, like this:

(declare-fun max ((Seq Int)) Int)
(assert (forall ((A (Seq Int))) (=> (> (seq.len A) 0) (<= 0 (max A)))))
(assert (forall ((A (Seq Int))) (=> (> (seq.len A) 0) (< (max A) (seq.len A)))))
(assert (forall ((A (Seq Int)) (i Int)) (=> (and (> (seq.len A) 0) (<= 0 i) (< i (seq.len A)))
                        (<= (seq.nth A i) (seq.nth A (max A))))))

(assert (= (max (seq.++ (seq.unit 8) (seq.unit 3))) 0))
;(assert (= (max (seq.++ (seq.unit 8) (seq.unit 3))) 1))

(check-sat)

If you run this, it succesfully says:

sat

While this is correct, don't be fooled into thinking you've completely specified how max should work or z3 can handle all such problems. To wit, let's add (get-model) and see what it says:

sat
(model
  (define-fun max ((x!0 (Seq Int))) Int
    (ite (= x!0 (seq.++ (seq.unit 7718) (seq.++ (seq.unit 15) (seq.unit 7719))))
      2
      0))
)

Oh look, it simply found an interpretation of max that doesn't even satisfy the quantified axioms you've given. Looks like this is a z3 bug and should probably be reported. But the moral of the story is the same: Sequence logic and quantifiers are a soft spot, and I wouldn't count on the solver response even if you got a sat answer.

Long story short Recursion requires induction, and if that's what your specification requires, use a tool that understands induction. Isabelle, HOL, Coq, Agda, Lean; to name a few. There are many choices. And most of those tools automatically call z3 (or other SMT solvers) under the hood to establish properties as necessary (or as guided by the user) anyhow; so you have the best of both worlds.



来源:https://stackoverflow.com/questions/57242139/max-element-in-z3-seq-int

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