I'm trying out Z3 with quantifier examples from http://rise4fun.com/Z3/tutorial/guide .
The two example works fine with the online version of Z3 ( I guess it would be Z3 4.0) .
(set-option :auto-config false) ; disable automatic self configuration
(set-option :mbqi false) ; disable model-based quantifier instantiation
(declare-fun f (Int) Int)
(declare-fun g (Int) Int)
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (forall ((x Int))
(! (= (f (g x)) x)
:pattern ((f (g x))))))
(assert (= (g a) c))
(assert (= (g b) c))
(assert (not (= a b)))
(check-sat)
and
(set-option :auto-config false) ; disable automatic self configuration
(set-option :mbqi false) ; disable model-based quantifier instantiation
(declare-fun f (Int) Int)
(declare-fun g (Int) Int)
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (forall ((x Int))
(! (= (f (g x)) x)
:pattern ((g x)))))
(assert (= (g a) c))
(assert (= (g b) c))
(assert (not (= a b)))
(check-sat)
The difference is the pattern we used for the "forall" assertion. The result should be "unknow" and "unsat".
I'm using the linux version of Z3 3.2 from http://research.microsoft.com/projects/z3/z3-3.2.tar.gz
I tried the two examples through z3 binary
./z3 -smt2 ex1.smt
./z3 -smt2 ex2.smt
The result is correct.
However, when I was using the ocaml api, the two examples are both "unknow".
I've tried:
Z3.parse_smtlib2_file ctx "ex2.smt" [||] [||] [||] [||];;
and
let mk_unary_app ctx f x = Z3.mk_app ctx f [|x|];;
let example () =
let ctx = Z3.mk_context_x [|("MBQI","false")|] in
let int = Z3.mk_int_sort ctx in
let f = Z3.mk_func_decl ctx (Z3.mk_string_symbol ctx "f") [|int|] int in
let g = Z3.mk_func_decl ctx (Z3.mk_string_symbol ctx "g") [|int|] int in
let a = Z3.mk_const ctx (Z3.mk_string_symbol ctx "a") int in
let b = Z3.mk_const ctx (Z3.mk_string_symbol ctx "b") int in
let c = Z3.mk_const ctx (Z3.mk_string_symbol ctx "c") int in
let sym = Z3.mk_int_symbol ctx 0 in
let bv = Z3.mk_bound ctx 0 int in
let pat = Z3.mk_pattern ctx [| Z3.mk_app ctx g [| bv |] |] in
let forall = Z3.mk_forall ctx 0 [| pat |] [|int|] [|sym|]
(Z3.mk_not ctx (Z3.mk_eq ctx (Z3.mk_app ctx f [|Z3.mk_app ctx g [|bv|]|]) bv)) in
Z3.assert_cnstr ctx forall;
Z3.assert_cnstr ctx (Z3.mk_eq ctx (mk_unary_app ctx g a) c);
Z3.assert_cnstr ctx (Z3.mk_eq ctx (mk_unary_app ctx g b) c);
Z3.assert_cnstr ctx (Z3.mk_not ctx (Z3.mk_eq ctx a b));
Z3.check ctx ;;
Thanks!
There is a typo in the OCaml code.
let forall = Z3.mk_forall ctx 0 [| pat |] [|int|] [|sym|]
(Z3.mk_not ctx (Z3.mk_eq ctx (Z3.mk_app ctx f [|Z3.mk_app ctx g [|bv|]|]) bv))
The problem is the Z3.mk_not. The ! in the SMT input is not a negation.
In SMT 2.0, ! is used to "attach" attributes to formulas. In the example above, the attribute is the pattern.
Related
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))))
I am trying to use the JAVA API of Z3 to construct the following formula
(assert (forall ((x_0 fcn_sort_2) (x_1 fcn_sort_2))
(=> (and (= (domain x_0)
(domain x_1))
(forall ((y Int))
(= (alpha x_0 y)
(alpha x_1 y))))))
(= x_0 x_1)))))
by the following code
Sort[] types1 = new Sort[2]; // for x_0 and x_1
Expr[] xs1 = new Expr[2];
for (int j = 0; j < 2; j++) {
types1[j] = this.getZ3Sort("fcn_sort_2");
xs1[j] = ctx.mkConst(ctx.mkSymbol("x_" + Integer.toString(j)), types1[j]);
}
Sort[] types2 = new Sort[1]; // for y
Expr[] xs2 = new Expr[1];
types2[0] = ctx.mkIntSort();
xs2[0] = ctx.mkConst(ctx.mkSymbol("y"), types2[0]);
FuncDecl alpha_fcn = this.getFuncSymbol("alpha");
Expr[] arg0 = new Expr[] { xs1[0], xs2[0] };
Expr[] arg1 = new Expr[] { xs1[1], xs2[0] };
BoolExpr
// (= (alpha x_0 y) (alpha x_1 y))
body2 = ctx.mkEq(ctx.mkApp(alpha_fcn, arg0), ctx.mkApp(alpha_fcn, arg1)),
// forall ((y Int)) ...
bf2 = ctx.mkForall(xs2, body2, 1, null, null, null, null);
FuncDecl domain_fcn = this.getFuncSymbol("domain");
BoolExpr
// (= x_0 x_1)
eqX = ctx.mkEq(xs1[0], xs1[1]),
// (= (domain x_0) (domain x_1))
eqDo = ctx.mkEq(ctx.mkApp(domain_fcn, new Expr[] {xs1[0]}), ctx.mkApp(domain_fcn, new Expr[] {xs1[1]})),
// (and ...)
andNode = ctx.mkAnd(eqDo, bf2),
// (=> ...)
body1 = ctx.mkImplies(andNode, eqX),
// (forall ((x_0 ...) (x_1 ...))
bf1 = ctx.mkForall(xs1, body1, 1, null, null, null, null);
where getFuncSymbol is my own function to get a FuncDecl which is declared before.
Unfortunately, I have the wrong result with "let" and "a!1"
(assert (forall ((x_0 fcn_sort_2) (x_1 fcn_sort_2))
(let ((a!1 (and (= (domain_fcn_sort_2 x_0) (domain_fcn_sort_2 x_1))
(forall ((y Int))
(= (alpha_fcn_sort_2 x_0 y) (alpha_fcn_sort_2 x_1 y))))))
(=> a!1 (= x_0 x_1)))))
I found that something wrong, "let ((a!1", happens at the line
body1 = ctx.mkImplies(andNode, eqX)
Am I missing something? Thank you
let-expressions are introduced during pretty-printing in an attempt to make the output more concise. Here, it simply means that whenever the name a!1 occurs in the output, you can replace it with (and ...). Semantically, this doesn't make a difference.
I'm trying to use Z3 to solve equations involving unknown projection functions, to find a valid interpretation of the functions that satisfy the equation. So for example for the equation: snd . f = g . fst a valid interpretation would be f = \(x,y) -> (y,x) and g = id. I know that Z3 isn't higher order so I've been trying to encode the problem in first order form. So for example for f = g.fst I use:
(declare-datatypes (T) ((Tree (leaf (value T)) (node (children TreeList)))
(TreeList nil (cons (head Tree) (tail TreeList)))))
(define-fun fst ((x (Tree Int))) (Tree Int) (head (children x)))
(define-fun snd ((x (Tree Int))) (Tree Int) (head (tail (children x))))
(declare-fun f ((Tree Int)) (Tree Int))
(declare-fun g ((Tree Int)) (Tree Int))
(assert (forall ((x (Tree Int))) (= (f x) (g (fst x)))))
(check-sat)
(get-model)
Which sort of works returning:
(define-fun g ((x!1 (Tree Int))) (Tree Int)
(leaf 0))
(define-fun f ((x!1 (Tree Int))) (Tree Int)
(g (head (children x!1))))
However for snd . f = g . fst (I've simplified trees to pairs to try and help):
(declare-datatypes (T) ((Pair (leaf (value T)) (pair (fst Pair) (snd Pair)))))
(declare-fun f ((Pair Int)) (Pair Int))
(declare-fun g ((Pair Int)) (Pair Int))
(assert (forall ((x (Pair Int))) (= (snd (f x)) (g (fst x)))))
I get unknown.
I've also tried to encode a similar problem without the ADT just using booleans or ints as parameters, but then the model just assigns constant values to the functions. I've also tried to define a simple ADT for function constants, the identity function, and pairwise and sequential composition, and then define an "equals" function that can simplify expressions like f.id = f, but this either involves a recursive function like:
(declare-datatypes () (
(Fun id
(fun (funnum Int))
(seq (after Fun) (before Fun))
(pair (fst Fun) (snd Fun)) )))
(define-fun eq ((x Fun) (y Fun)) Bool (or
(= x y)
(eq x (seq y id)) ; id neutral for seq
(eq x (seq id y))
(eq y (seq x id))
(eq y (seq id x))))
(declare-const f Fun)
(declare-const g Fun)
(assert (eq f (seq id g)))
(check-sat)
(get-model)
Which is obviously invalid. Or if I use an uninterpretted function, it makes "eq" a constant function i.e.
(declare-fun eq (Fun Fun) Bool)
(assert (forall ((x Fun) (y Fun)) ; semantic equality
(= (eq x y) (or
(= x y) ; syntactic eq
(eq x (seq y id)) ; id neutral for seq
(eq x (seq id y))
(eq y (seq x id))
(eq y (seq id x))
))
))
=>
(define-fun eq ((x!1 Fun) (x!2 Fun)) Bool
true)
And similarly with equations involving functions with type Int -> Int, this returns constant functions for f and g:
(declare-fun f (Int) Int)
(declare-fun g (Int) Int)
(assert (forall ((x Int)) (= (+ (f x) 1) (+ (g x) 2)) ))
and adding these times out:
(assert (forall ((x Int) (y Int)) (=>
(not (= x y))
(not (= (g x) (g y))))))
(assert (forall ((x Int) (y Int)) (=>
(not (= x y))
(not (= (f x) (f y))))))
Any ideas how I can get this sort of thing to work?
Many thanks!
Z3 searches for essentially finite models so isn't well suited for solving functional equations directly. The main trick for finding models of these kinds is to strengthen the formulas by providing a finite set of alternative interpretations of functions that can be composed. For example, you can allow f(x) to be either identity, permutation, or repeat x or y, or return a constant value in one of the fields, This may be composed with functions that perform simple arithmetical operations. You will have to bound the number of compositions you are willing to admit. You assert a similar set of templates for g. So far this has worked best for bit-vectors.
The search space for such interpretations can easily get overwhelming. I tried your example with algebraic data-types and templates. Z3 is not able to find an interpretation in this case, at least not by stating the problem directly as a template search.
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.
Using the Z3 .NET API I'm trying to do something similar as the following example which I have taken from the Z3 Guide:
(define-sort A () (Array Int Int Int))
(define-fun bag-union ((x A) (y A)) A
((_ map (+ (Int Int) Int)) x y))
(declare-const s1 A)
(declare-const s2 A)
(declare-const s3 A)
(assert (= s3 (bag-union s1 s2)))
(assert (= (select s1 0 0) 5))
(assert (= (select s2 0 0) 3))
(assert (= (select s2 1 2) 4))
(check-sat)
(get-model)
How do I define the + function such that I can use it in MkMap?
MkMap expects a function declaration, so you need to get a reference to the + function declaration, which you can do by using MkAdd and getting a reference to its function declaration with .FuncDecl:
Context z3 = new Context();
Sort twoInt = z3.MkTupleSort(z3.MkSymbol("twoInt"), new Symbol[] { z3.MkSymbol("a"), z3.MkSymbol("b") }, new Sort[] { z3.IntSort, z3.IntSort });
Sort A = z3.MkArraySort(twoInt, z3.IntSort);
ArrayExpr x = z3.MkArrayConst("x", twoInt, z3.IntSort);
ArrayExpr y = z3.MkArrayConst("y", twoInt, z3.IntSort);
ArrayExpr map = z3.MkMap(z3.MkAdd(z3.MkIntConst("a"), z3.MkIntConst("b")).FuncDecl, x, y);