Вопрос

The following code encodes a "record" with two fields array-fld and blist-fld. I've defined the update functions for these fields, and then asserted a property that should be true (but which z3 reports as unknown). This is Z3 version 4.0, run as z3 -smt2 -in:

(declare-datatypes ()
                   ((mystruct (mk-mystruct
                                 (array-fld (Array Int Int))
                                 (blist-fld (List Bool))))))
(define-fun array-fld-upd ((v (Array Int Int)) (obj mystruct)) mystruct
  (mk-mystruct v (blist-fld obj)))
(define-fun blist-fld-upd ((v (List Bool)) (obj mystruct)) mystruct
  (mk-mystruct (array-fld obj) v))

(push)
(assert
 (forall ((z0 mystruct))
         (exists ((array-val (Array Int Int)))
                 (and (= array-val (array-fld z0))
                      (= (select (array-fld
                                  (array-fld-upd (store array-val 2 4) z0)) 3)
                         (select (array-fld z0) 3))))))
(check-sat)

If I manually unwind/eliminate the existential by substituting out the equation array-val binding, I get

(pop)
(assert
 (forall ((z0 mystruct))
         (= (select (array-fld (array-fld-upd (store (array-fld z0) 2 4) z0)) 3)
            (select (array-fld z0) 3))))
(check-sat)

and this is happily resolved as sat.

I guess there are four questions bound up in this:

  1. Is there a way to invoke z3 to get it to solve the first instance as well as the second?
  2. Should I be encoding my records/structs differently?
  3. Should I be encoding my let-expressions differently (it is these that lead to the existential quantification)?
  4. Or, should I just expand out the let-expressions directly (I could do this myself, but it might lead to large terms if there are lots of references).
Это было полезно?

Решение

It seems from the question that you can use proper let expressions. Then it will be easier for Z3:

(declare-datatypes ()
               ((mystruct (mk-mystruct
                             (array-fld (Array Int Int))
                             (blist-fld (List Bool))))))
(define-fun array-fld-upd ((v (Array Int Int)) (obj mystruct)) mystruct
  (mk-mystruct v (blist-fld obj)))
(define-fun blist-fld-upd ((v (List Bool)) (obj mystruct)) mystruct
  (mk-mystruct (array-fld obj) v))

(push)
(assert
 (forall ((z0 mystruct))
    (let ((array-val (array-fld z0)))
                  (= (select (array-fld
                              (array-fld-upd (store array-val 2 4) z0)) 3)
                     (select (array-fld z0) 3)))))
 (check-sat)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top