Reputation: 412
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:
Upvotes: 2
Views: 1416
Reputation: 8359
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)
Upvotes: 3