Z3 tactic for conjunction elimination in formulas with quantifiers - z3

Is there a Z3 tactic that rewrites the goal (say, one assertion with quantifiers and uninterpreted functions) into a set of conjunction-free formulas? For example, the following formula:
(declare-fun P (Int) Bool)
(declare-fun Q (Int Int) Bool)
(declare-fun R (Int Int) Bool)
(assert (forall ((x Int)) (!
(or
(P x)
(forall ((x Int) (y Int)) (!
(and
(Q x y)
(R x y))
:pattern ((Q x y)) )) )
:pattern ((P x)))))
Should be rewritten to
(declare-fun P (Int) Bool)
(declare-fun Q (Int Int) Bool)
(declare-fun R (Int Int) Bool)
(assert (forall ((x Int)) (!
(or
(P x)
(forall ((x Int) (y Int)) (!
(Q x y)
:pattern ((Q x y)))))
:pattern ((P x)))))
(assert (forall ((x Int)) (!
(or
(P x)
(forall ((x Int) (y Int)) (!
(R x y)
:pattern ((Q x y)))))
:pattern ((P x)))))

You can obtain a list of tactics via (help-tactic). Searching for "conjunction" yields a few hits, including tactic simplify with option elim_and, which removes all conjunctions from your example.
Rewriting the quantifiers is a different matter. I've tried a few tactics that sound potentially related, but none had any useful effects.
; (help-tactic)
(declare-fun P (Int) Bool)
(declare-fun Q (Int Int) Bool)
(declare-fun R (Int Int) Bool)
(assert (forall ((x Int)) (!
(or
(P x)
(forall ((x Int) (y Int)) (!
(and
(Q x y)
(R x y))
:pattern ((Q x y)) )) )
:pattern ((P x)))))
; (apply (try-for qe-light 5000)) ; no effect
; (apply (try-for qe_rec 5000)) ; appears to fail
; (apply (try-for qe2 5000)) ; appears to fail
(apply
(then
distribute-forall ; no effect
(using-params simplify :elim_and true)
))
;;; RESULT:
; (forall ((x Int))
; (! (let ((a!1 (forall ((x!1 Int) (y Int))
; (! (not (or (not (Q x!1 y)) (not (R x!1 y))))
; :pattern ((Q x!1 y))))))
; (or (P x) a!1))
; :pattern ((P x))))

Related

Z3 Solver outputting the satisfying model?

In Z3, if the input script is written in SMTLib format, is it possible to output the model (value assignments satisfying the model)? The get-model returns an interpretation satisfying the constraints. Is there any way to extract the concrete values from these interpretations. I am aware that we can use the python/C++ API to get model values.
You probably want to use get-value, here's a minimal example (rise4fun link: http://rise4fun.com/Z3/wR81 ):
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (>= (* 2 x) (+ y z)))
(declare-fun f (Int) Int)
(declare-fun g (Int Int) Int)
(assert (< (f x) (g x x)))
(assert (> (f y) (g x x)))
(check-sat) ; sat
(get-model) ; returns:
; (model
; (define-fun z () Int
; 0)
; (define-fun y () Int
; (- 38))
; (define-fun x () Int
; 0)
; (define-fun g ((x!1 Int) (x!2 Int)) Int
; (ite (and (= x!1 0) (= x!2 0)) 0
; 0))
; (define-fun f ((x!1 Int)) Int
; (ite (= x!1 0) (- 1)
; (ite (= x!1 (- 38)) 1
; (- 1))))
;)
(get-value (x)) ; returns ((x 0))
(get-value ((f x))) ; returns (((f x) (- 1)))
You'd potentially then have to parse this depending on what you're trying to do, etc.
For more details, check out the SMT-LIB standard:
http://smtlib.cs.uiowa.edu/language.shtml
The latest version is: http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.0-r12.09.09.pdf
You can see some examples of get-value on page 39 / figure 3.5.

How to obtain a non-trivial model of an idempotent quasigroup using Z3

I am trying to obtain a non-trivial model of an idempotent quasigroup using Z3 with the following code
(set-logic AUFNIRA)
(set-option :macro-finder true)
(set-option :mbqi true)
(set-option :pull-nested-quantifiers true)
(declare-sort S 0)
(declare-fun prod (S S) S)
(declare-fun left (S S) S)
(declare-fun right (S S) S)
(assert (forall ((x S) (y S))
(= (prod (left x y) y) x)))
(assert (forall ((x S) (y S))
(= (prod x (right x y) ) y)))
(assert (forall ((x S) (y S))
(= (left (prod x y) y ) x)))
(assert (forall ((x S) (y S))
(= (right x (prod x y)) y)))
(assert (forall ((x S)) (= (prod x x) x) ))
(check-sat)
(get-model)
but I am obtaining only a trivial model:
sat
(model
;; universe for S:
;; S!val!0
;; -----------
;; definitions for universe elements:
(declare-fun S!val!0 () S)
;; cardinality constraint:
(forall ((x S)) (= x S!val!0))
;; -----------
(define-fun elem!3 () S
S!val!0)
(define-fun elem!2 () S
S!val!0)
(define-fun elem!0 () S
S!val!0)
(define-fun elem!1 () S
S!val!0)
(define-fun left ((x!1 S) (x!2 S)) S
S!val!0)
(define-fun right ((x!1 S) (x!2 S)) S
S!val!0)
(define-fun prod ((x!1 S) (x!2 S)) S
x!1)
)
Run this example online here
Please let me know how we can obtain a non-trivial model. Many thanks.
If I understand right, you want to find more than one sat model for the original assertions.
I have a dull solution here. You can define another set of functions in the same way as prod, left and right, which are named prod2, left2 and right2. Add assertions for them similarly. Then, you want prod2 to differ from prod.
Like this:
(assert (exists ((x S) (y S)) (not (= (prod x y) (prod2 x y)))))
or maybe expression meaning or(prod != prod2, left != left2, right != right2) will be more proper.
I took a little attempt to run that online, but returned 'time out'. I think you have to do it on your machine.
This may be not a best answer, but best regards!

Why the unstable branch is not able to prove a theorem but the master branch is able?

I am trying to prove a theorem in group theory using the following Z3 SMT-LIB code
(declare-sort S)
(declare-fun identity () S)
(declare-fun product (S S S) Bool)
(declare-fun inverse (S) S)
(declare-fun multiply (S S) S)
(assert (forall ((X S)) (product identity X X) ))
(assert (forall ((X S)) (product X identity X) ))
(assert (forall ((X S)) (product (inverse X) X identity) ))
(assert (forall ((X S)) (product X (inverse X) identity) ))
(assert (forall ((X S) (Y S)) (product X Y (multiply X Y)) ))
;;(assert (forall ((X S) (Y S) (Z S) (W S)) (or (not (product X Y Z))
;; (not (product X Y W))
;; (= Z W))))
(assert (forall ((X S) (Y S) (Z S) (U S) (V S) (W S)) (or (not (product X Y U))
(not (product Y Z V))
(not (product U Z W) )
(product X V W))))
(assert (forall ((X S) (Y S) (Z S) (U S) (V S) (W S)) (or (not (product X Y U))
(not (product Y Z V))
(not (product X V W) )
(product U Z W))))
(check-sat)
(push)
;; File : GRP001-1 : TPTP v6.0.0. Released v1.0.0.
;; Domain : Group Theory
;; Problem : X^2 = identity => commutativity
;; Version : [MOW76] axioms.
;; English : If the square of every element is the identity, the system
;; is commutative.
(declare-fun a () S)
(declare-fun b () S)
(declare-fun c () S)
(assert (forall ((X S)) (product X X identity) ))
(assert (product a b c))
(assert (not (product b a c)))
(check-sat)
(pop)
Please run this code online here.
The master branch Z3 is able to prove such theorem but the unstable branch is not able. Please let me know why. Many thanks.

z3 times out in case of a formula with quantifiers

I am getting timeout on the following example.
http://rise4fun.com/Z3/zbOcW
Is there any trick to make this work (eg.by reformulating the problem or using triggers)?
For this example, the macro finder will be useful (I think often with forall quantifiers with implications), you can enable it with:
(set-option :macro-finder true)
Here's your updated example that gets sat quickly (rise4fun link: http://rise4fun.com/Z3/Ux7gN ):
(set-option :macro-finder true)
(declare-const a (Array Int Bool))
(declare-const sz Int)
(declare-const n Int)
(declare-const d Int)
(declare-const r Bool)
(declare-const x Int)
(declare-const y Int)
;;ttff
(declare-fun ttff (Int Int Int) Bool)
(assert
(forall ((x1 Int) (y1 Int) (n1 Int))
(= (ttff x1 y1 n1)
(and
(forall ((i Int))
(=> (and (<= x1 i) (< i y1))
(= (select a i) true)))
(forall ((i Int))
(=> (and (<= y1 i) (< i n1))
(= (select a i) false)))))))
;; A1
(assert (and (<= 0 n) (<= n sz)))
;; A2
(assert (< 0 d))
;; A3
(assert (and (and (<= 0 x) (<= x y)) (<= y n)))
;; A4
(assert (ttff x y n))
;; A6
(assert
(=> (< 0 y)
(= (select a (- y 1)) true)))
;; A7
(assert
(=> (< 0 x)
(= (select a (- x 1)) false)))
;;G
(assert
(not
(iff
(and (<= (* 2 d) (+ n 1)) (ttff (- (+ n 1) (* 2 d)) (- (+ n 1) d) (+ n 1)))
(and (= (- (+ n 1) y) d) (<= d (- y x))))))
(check-sat)
(get-model)

Defining injective functions in Z3

My goal is to define an injective function f: Int -> Term, where Term is some new sort. Having referred to the definition of the injective function, I wrote the following:
(declare-sort Term)
(declare-fun f (Int) Term)
(assert (forall ((x Int) (y Int))
(=> (= (f x) (f y)) (= x y))))
(check-sat)
This causes a timeout. I suspect that this is because the solver tries to validate the assertion for all values in the Int domain, which is infinite.
I also checked that the model described above works for some custom sort instead of Int:
(declare-sort Term)
(declare-sort A)
(declare-fun f (A) Term)
(assert (forall ((x A) (y A))
(=> (= (f x) (f y)) (= x y))))
(declare-const x A)
(declare-const y A)
(assert (and (not (= x y)) (= (f x) (f y))))
(check-sat)
(get-model)
The first question is how to implement the same model for Int sort instead of A. Can solver do this?
I also found the injective function example in the tutorial in multi-patterns section. I don't quite get why :pattern annotation is helpful. So the second question is why :pattern is used and what does it brings to this example particularly.
I am trying this
(declare-sort Term)
(declare-const x Int)
(declare-const y Int)
(declare-fun f (Int) Term)
(define-fun biyect () Bool
(=> (= (f x) (f y)) (= x y)))
(assert (not biyect))
(check-sat)
(get-model)
and I am obtaining this
sat
(model
;; universe for Term:
;; Term!val!0
;; -----------
;; definitions for universe elements:
(declare-fun Term!val!0 () Term)
;; cardinality constraint:
(forall ((x Term)) (= x Term!val !0))
;; -----------
(define-fun y () Int
1)
(define-fun x () Int
0)
(define-fun f ((x!1 Int)) Term
(ite (= x!1 0) Term!val!0
(ite (= x!1 1) Term!val!0
Term!val!0)))
)
What do you think about this
(declare-sort Term)
(declare-fun f (Int) Term)
(define-fun biyect () Bool
(forall ((x Int) (y Int))
(=> (= (f x) (f y)) (= x y))))
(assert (not biyect))
(check-sat)
(get-model)
and the output is
sat
(model
;; universe for Term:
;; Term!val!0
;; -----------
;; definitions for universe elements:
(declare-fun Term!val!0 () Term)
;; cardinality constraint:
(forall ((x Term)) (= x Term!val!0))
;; -----------
(define-fun x!1 () Int 0)
(define-fun y!0 () Int 1)
(define-fun f ((x!1 Int)) Term
(ite (= x!1 0) Term!val!0
(ite (= x!1 1) Term!val!0
Term!val!0)))
)

Resources