Sort name issue in Z3 - z3

In a previous post Z3 group some group axioms were proved using a sort named S to represent the group. Please run the code code with sort named S But now when the name of the sort is changed to G the code does not work. Please look the issue on line code with sort named G It is necessary to use the name S for the sort or it is an issue of Z3? Please let me know.

A simplified version of the issue.
$ z3 -version
Z3 version 4.3.1
Using the name S:
$ cat S.smt
(declare-sort S)
(declare-fun f (S S) S)
(declare-const a S)
(declare-const b S)
(assert (= (f a a) a))
(assert (= (f a b) b))
(assert (= (f b a) b))
(assert (= (f b b) a))
(check-sat)
;; Restrict the search to models of size at most 2.
(assert (forall ((x S)) (or (= x a) (= x b))))
;; Associativity
(assert (not (forall ((x S) (y S) (z S)) (= (f x (f y z)) (f (f x y) z)))))
(check-sat)
$ z3 -smt2 S.smt
sat
unsat
Using the name G:
$ cat G.smt
(declare-sort G)
(declare-fun f (G G) G)
(declare-const a G)
(declare-const b G)
(assert (= (f a a) a))
(assert (= (f a b) b))
(assert (= (f b a) b))
(assert (= (f b b) a))
(check-sat)
;; Restrict the search to models of size at most 2
(assert (forall ((x G)) (or (= x a) (= x b))))
;; Associativity
(assert (not (forall ((x G) (y G) (z G)) (= (f x (f y z)) (f (f x y) z)))))
(check-sat)
$ z3 -smt2 G.smt
sat
unknown

Please let ne know if the following code with the sort named G is correct. Many thanks
(declare-sort G)
(declare-fun f (G G) G)
(declare-const a G)
(declare-const b G)
(declare-const c G)
(assert (forall ((x G) (y G))
(= (f x y) (f y x))))
(assert (forall ((x G))
(= (f x a) x)))
(assert (= (f b b) c))
(assert (= (f b c) a))
(assert (= (f c c) b))
(check-sat)
(get-model)
(push)
;; prove the left-module axiom
(assert (not (forall ((x G)) (= (f a x) x ))) )
(check-sat)
(pop)
(push)
;; prove the right-module axiom
(assert (not (forall ((x G)) (= (f x a) x ))) )
(check-sat)
(pop)
(declare-fun x () G)
(declare-fun y () G)
(declare-fun z () G)
(push)
;; prove the right-inverse axiom
(assert (not (=> (and (or (= x a) (= x b) (= x c))) (exists ((y G)) (= (f x y) a)))))
(check-sat)
(pop)
(push)
;; prove the left-inverse axiom
(assert (not (=> (and (or (= x a) (= x b) (= x c))) (exists ((y G)) (= (f y x ) a)))))
(check-sat)
(pop)
(push)
;; prove the associativity axiom
(assert (not (=> (and (or (= x a) (= x b) (= x c)) (or (= y a) (= y b) (= y c))
(or (= z a) (= z b) (= z c)))
(= (f x (f y z)) (f (f x y) z)))))
(check-sat)
(pop)
(push)
;; prove the commutative property
(assert (not (=> (and (or (= x a) (= x b) (= x c)) (or (= y a) (= y b) (= y c)))
(= (f x y ) (f y x )))))
(check-sat)
(pop)
and the corresponding output is the expected
sat unsat unsat unsat unsat unsat unsat
Please run this code online here

Related

Why does introducing this existential quantifier cause non-termination?

I am just starting to play with Z3 on my own and I thought one interesting experiment would be to construct a 3-element field.
So I declared my field S to be a scalar enumeration of three elements, A, B, C, and started gradually adding field axioms, asking Z3 for a model after each step, just to see what is going on. All goes well until I assert the possibility of subtraction, ∀ab.(∃x.a+x=b):
(declare-datatypes () ((S A B C)))
; there exist three distinct elements in S
(declare-const someA S)
(declare-const someB S)
(declare-const someC S)
(assert (distinct someA someB someC))
(declare-fun ADD (S S) S)
(declare-fun MUL (S S) S)
; commutative
(assert (forall ((x S) (y S)) (= (ADD x y) (ADD y x))))
(assert (forall ((x S) (y S)) (= (MUL x y) (MUL y x))))
; associative
(assert (forall ((x S) (y S) (z S)) (= (ADD x (ADD y z)) (ADD (ADD x y) z))))
(assert (forall ((x S) (y S) (z S)) (= (MUL x (MUL y z)) (MUL (MUL x y) z))))
; subtractivity
(assert (forall ((a S) (b S)) (exists ((x S)) (= (ADD a x) b))))
(check-sat)
(get-model)
This results in Z3 looping forever. I am surprised. I mean yes, I understand why FOL is in general undecidable, but I'd think this would be one of those "easy" cases because the space of all possible values for a, b and ADD is finite (and in this case even very small)? Why does it loop? and what is the correct way to express the subtractability axiom preferably in a way that doesn't lose being perceivable as its intended intuitive meaning?
While #alias is generally right with his suggestion, you might nevertheless be able to use Z3 if you're willing to weaken your axiomatisation. E.g.:
...
; subtractivity
(declare-fun SUB (S S) S)
(assert (forall ((a S) (b S) (x S)) (iff (= (ADD a x) b) (= (SUB b x) a))))
(check-sat)
(get-model)

SMT: check uniqueness and totality of function

Given is a function and a description of its behavior:
add: (ℤ ∪ {Error, None})² → (ℤ ∪ {Error, None})
For x ∈ (ℤ ∪ {Error, None}):
add(x, None) = add(None, x) = None
For x ∈ (ℤ ∪ {Error}):
add(x, Error) = add(Error, x) = Error
For x, y ∈ ℤ:
add(x, y) = x + y
How can I transform this description to SMT (I'm using Z3) and check whether the description defines a total function?
To give you an idea what I want to achieve: in the end I want to generate Python code implementing this function with the minimum number of branches. For example:
def add(x, y):
if x is None or y is None:
return None
if x is Error or y is Error:
return Error
return x + y
This is what I tried so far:
(declare-datatypes () ((ABC (int (val Int)) error none)))
(declare-fun f (ABC ABC) ABC)
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error) (= x none)) (= (f none x) none))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error) (= x none)) (= (f x none) none))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error)) (= (f error x) error))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error)) (= (f x error) error))))
(assert (forall ((x ABC) (y ABC)) (=> (and (is-int x) (is-int y)) (= (f x y) (int (+ (val x) (val y)))))))
(check-sat)
(get-model)
This timeouts.
EDIT: In Simplify function interpretation in model I described a simpler axiomatization of f where int is a single case, resulting in finitely many cases. Can I somehow tell Z3 that the concrete val in int doesn't matter and there are effectively finitely many cases?
To check uniqueness: Your axiomatization is good; you just need to "replicate" it for two functions then ask for two values such that they differ:
(declare-datatypes () ((ABC (int (val Int)) error none)))
(declare-fun f (ABC ABC) ABC)
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error) (= x none)) (= (f none x) none))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error) (= x none)) (= (f x none) none))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error)) (= (f error x) error))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error)) (= (f x error) error))))
(assert (forall ((x ABC) (y ABC)) (=> (and (is-int x) (is-int y)) (= (f x y) (int (+ (val x) (val y)))))))
(declare-fun g (ABC ABC) ABC)
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error) (= x none)) (= (g none x) none))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error) (= x none)) (= (g x none) none))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error)) (= (g error x) error))))
(assert (forall ((x ABC)) (=> (or (is-int x) (= x error)) (= (g x error) error))))
(assert (forall ((x ABC) (y ABC)) (=> (and (is-int x) (is-int y)) (= (g x y) (int (+ (val x) (val y)))))))
; check that there is no {x,y} such that f and g differ on:
(declare-const x ABC)
(declare-const y ABC)
(assert (not (= (f x y) (g x y))))
(check-sat)
(get-model)
Z3 quickly returns unsat for this; meaning f and g cannot differ. Now, you can try commenting out some of the asserts for f and/or g and ask for a model. Depending on which asserts you comment out, Z3 might come up with a model for f and g such that they have different behavior; OR it can still time-out, trying to construct a model to do so. In the presence of quantifiers, you can't really expect anything better from an SMT solver.

z3 and z3PY giving different results

When I tried following in z3, I got result timeout
(set-option :smt.mbqi true)
(declare-fun R(Int) Int)
(declare-fun Q(Int) Int)
(declare-var X Int)
(declare-var Y Int)
(declare-const k Int)
(assert (>= X 0))
(assert (> Y 0))
(assert (forall ((n Int)) (=> (= n 0) (= (Q n) 0))))
(assert (forall ((n Int)) (=> (= n 0) (= (R n) X))))
(assert (forall ((n Int)) (=> (> n 0) (= (R (+ n 1) ) (+ (R n) (* 2 Y))))))
(assert (forall ((n Int)) (=> (> n 0) (= (Q (+ n 1) ) (- (Q n) 2)))))
(assert (forall ((n Int)) (=> (> n 0) (= X (+ (* (Q n) Y) (R n))))))
(assert (forall ((n Int)) (= X (+ (* (Q n) Y) (R n)))))
(assert (= X (+ (* (Q k) Y) (R k))))
(assert (not (= (* X 2) (+ (* (Q (+ k 1)) Y) (R (+ k 1))))))
(check-sat)
Same when I tried in z3py using following code, I got result unsat which is wrong
from z3 import *
x=Int('x')
y=Int('y')
k=Int('k')
n1=Int('n1')
r=Function('r',IntSort(),IntSort())
q=Function('q',IntSort(),IntSort())
s=Solver()
s.add(x>=0)
s.add(y>0)
s.add(ForAll(n1,Implies(n1==0,r(0)==x)))
s.add(ForAll(n1,Implies(n1==0,q(0)==0)))
s.add(ForAll(n1,Implies(n1>0,r(n1+1)==r(n1)-(2*y))))
s.add(ForAll(n1,Implies(n1>0,q(n1+1)==q(n1)+(2))))
s.add(x==q(k)*y+r(k))
s.add(not(2*x==q(k+1)*y+r(k+1)))
if sat==s.check():
print s.check()
print s.model()
else :
print s.check()
Looking forward to Suggestions.
My suggestion is to use replace the built-in not operator by the Z3 function called Not, e.g.
not(2*x==q(k+1)*y+r(k+1))
is simplified to False by Python before Z3 gets to see it, while
Not(2*x==q(k+1)*y+r(k+1))
has the desired meaning.

Z3 is not able to prove the equivalence between two simple programs using Kleene algebras with test but Mathematica and Reduce are able

Our problem here is to show that
using Kleene algebras with test.
In the case when the value of b is preserved by p, we have the commutativity condition bp = pb; and the equivalence between the two programs is reduced to the equation
In the case when the value of b is not preserved by p, we have the commutativity condition pc = cp; and the equivalence between the two programs is reduced to the equation
I am trying to prove the first equation using the following SMT-LIB code
(declare-sort S)
(declare-fun sum (S S) S)
(declare-fun mult (S S) S)
(declare-fun neg (S) S)
(assert (forall ((x S) (y S) (z S)) (= (mult x (sum y z)) (sum (mult x y) (mult y z))) ) )
(assert (forall ((x S) (y S) (z S)) (= (mult (sum y z) x) (sum (mult y x) (mult z x))) ) )
(assert (forall ((x S) (y S) (z S)) (= (mult x (mult y z)) (mult (mult x y) z)) ))
(check-sat)
(push)
(declare-fun b () S)
(declare-fun p () S)
(declare-fun q () S)
(declare-fun r () S)
(assert (= (mult b p) (mult p b)) )
(check-sat)
(pop)
but I am obtaining timeout; it is to say Z3 is not able to hand the commutativity condition bp = pb. Please run this example online here.
Z3 is not able to prove these equations but Mathematica and Reduce are able. Z3 is not so powerful as a theorem prover. Do you agree?
The first equation is proved using Z3 with the following SMT-LIB code
(declare-sort S)
(declare-fun e () S)
(declare-fun O () S)
(declare-fun mult (S S) S)
(declare-fun sum (S S) S)
(declare-fun leq (S S) Bool)
(declare-fun negation (S) S)
(declare-fun test (S) Bool)
(assert (forall ((x S) (y S)) (= (sum x y) (sum y x ))))
(assert (forall ((x S) (y S) (z S)) (= (sum (sum x y) z) (sum x (sum y z)))))
(assert (forall ((x S)) (= (sum O x) x)))
(assert (forall ((x S)) (= (sum x x) x)))
(assert (forall ((x S) (y S) (z S)) (= (mult (mult x y) z) (mult x (mult y z)))))
(assert (forall ((x S)) (= (mult e x) x)))
(assert (forall ((x S)) (= (mult x e) x)))
(assert (forall ((x S) (y S) (z S)) (= (mult x (sum y z) ) (sum (mult x y) (mult x z)))))
(assert (forall ((x S) (y S) (z S)) (= (mult (sum x y) z ) (sum (mult x z) (mult y z)))))
(assert (forall ((x S)) (= (mult x O) O)))
(assert (forall ((x S)) (= (mult O x) O)))
(assert (forall ((x S) (y S)) (= (leq x y) (= (sum x y) y))))
(assert (forall ((x S) (y S)) (=> (and (test x) (test y) ) (= (mult x y) (mult y x))) ) )
(assert (forall ((x S)) (=> (test x) (= (sum x (negation x)) e) )))
(assert (forall ((x S)) (=> (test x) (= (mult x (negation x)) O) )))
(check-sat)
(push)
;; bpq + b`pr = p(bq + b`r)
(declare-fun b () S)
(declare-fun p () S)
(declare-fun q () S)
(declare-fun r () S)
(assert (=> (test b) (= (mult p b) (mult b p)) ))
(assert (=> (test b) (= (mult p (negation b)) (mult (negation b) p))))
(check-sat)
(assert (not (=> (test b) (= (sum (mult b (mult p q)) (mult (negation b) (mult p r) ))
(mult p (sum (mult b q) (mult (negation b) r))))) ) )
(check-sat)
(pop)
(echo "Proved: bpq + b`pr = p(bq + b`r)")
The output is
sat
sat
unsat
Proved: bpq + b`pr = p(bq + b`r)
Please run this proof online here
The second equation is indirectly proved using Z3 with the following procedure
This indirect procedure is implemented with the following SMT-LIB code
(declare-sort S)
(declare-fun e () S)
(declare-fun O () S)
(declare-fun mult (S S) S)
(declare-fun sum (S S) S)
(declare-fun leq (S S) Bool)
(declare-fun negation (S) S)
(declare-fun test (S) Bool)
(assert (forall ((x S) (y S)) (= (sum x y) (sum y x ))))
(assert (forall ((x S) (y S) (z S)) (= (sum (sum x y) z) (sum x (sum y z)))))
(assert (forall ((x S)) (= (sum O x) x)))
(assert (forall ((x S)) (= (sum x x) x)))
(assert (forall ((x S) (y S) (z S)) (= (mult (mult x y) z) (mult x (mult y z)))))
(assert (forall ((x S)) (= (mult e x) x)))
(assert (forall ((x S)) (= (mult x e) x)))
(assert (forall ((x S) (y S) (z S)) (= (mult x (sum y z) ) (sum (mult x y) (mult x z)))))
(assert (forall ((x S) (y S) (z S)) (= (mult (sum x y) z ) (sum (mult x z) (mult y z)))))
(assert (forall ((x S)) (= (mult x O) O)))
(assert (forall ((x S)) (= (mult O x) O)))
(assert (forall ((x S) (y S)) (= (leq x y) (= (sum x y) y))))
(assert (forall ((x S) (y S)) (=> (and (test x) (test y) ) (= (mult x y) (mult y x))) ) )
(assert (forall ((x S)) (=> (test x) (= (sum x (negation x)) e) )))
(assert (forall ((x S)) (=> (test x) (= (mult x (negation x)) O) )))
(assert (forall ((x S)) (=> (test x) (test (negation x)) )) )
(assert (forall ((x S)) (=> (test x) (= (mult x x) x) )) )
(check-sat)
(push)
(declare-fun c () S)
(declare-fun b () S)
(declare-fun p () S)
(declare-fun q () S)
(declare-fun r () S)
(check-sat)
(assert (not (=> (and (test b) (test c))
(= (mult (sum (mult b c) (mult (negation b) (negation c)))
(sum (mult b (mult p q)) (mult (negation b) (mult p r) ) ))
(sum (mult b (mult c (mult p q)))
(mult (negation b) (mult (negation c) (mult p r) ) ) ))) ) )
(check-sat)
(pop)
(echo "Proved: part 1")
(push)
;;
(assert (=> (test c) (= (mult p c) (mult c p)) ))
(assert (=> (test c) (= (mult p (negation c)) (mult (negation c) p))))
(check-sat)
(assert (not (=> (test c)
(= (mult (sum (mult b c) (mult (negation b) (negation c)))
(mult p (sum (mult c q) (mult (negation c) r))))
(sum (mult b (mult c (mult p q)))
(mult (negation b) (mult (negation c) (mult p r) ) ) ))) ) )
(check-sat)
(pop)
(echo "Proved: part 2")
and the corresponding output is
sat
sat
unsat
Proved: part 1
sat
unsat
Proved: part 2
This output is obtained locally. When the code is executed online the output is
sat
sat
unsat
Proved: part 1
sat
timeout
Please run this example online here
Z3 is not able to prove the second equation directly but Mathematica and Reduce ane able.

Z3 is not able to prove the right-cancellation property in group theory?

I am trying to prove some general properties in group theory.
For example the left-cancellation property : ( x y = x z ) => (y = z) it proved using the following code
(declare-sort S)
(declare-fun e () S)
(declare-fun mult (S S) S)
(declare-fun inv (S) S)
(assert (forall ((x S) (y S) (z S)) (= (mult (mult x y) z) (mult x (mult y z)))))
(assert (forall ((x S)) (= (mult e x) x)))
(assert (forall ((x S)) (= (mult (inv x) x) e)))
(assert (forall ((x S)) (= (mult x e) x)))
(assert (forall ((x S)) (= (mult x (inv x)) e)))
(check-sat)
(assert (not (forall ((x S) (y S) (z S)) (=> (= (mult x y) (mult x z)) (= y z)))))
(check-sat)
and the corresponding output is:
sat
unsat
Now when I try to prove the right-cancellation property: ( y x = z x ) => (y = z) using the following code
(declare-sort S)
(declare-fun e () S)
(declare-fun mult (S S) S)
(declare-fun inv (S) S)
(assert (forall ((x S) (y S) (z S)) (= (mult (mult x y) z) (mult x (mult y z)))))
(assert (forall ((x S)) (= (mult e x) x)))
(assert (forall ((x S)) (= (mult (inv x) x) e)))
(assert (forall ((x S)) (= (mult x e) x)))
(assert (forall ((x S)) (= (mult x (inv x)) e)))
(check-sat)
(assert (not (forall ((x S) (y S) (z S)) (=> (= (mult y x) (mult z x)) (= y z)))))
(check-sat)
I am obtaining
timeout
Please let me know how to prove the right-cancellation property or it is not possible using Z3 ?
As far as I know this style of theorems are better handled by super-position inference engines.
Older versions of Z3 contains a superposition engine, but it is removed from newer versions
as we have seen few uses overall for solving problems in universal algebra. There are several theorem provers specializing in super-position inferences, such as Vampire, E, SPASS and you can use the tools available from www.TPTP.org to try out these engines.
A possible proof of the right cancellation property using Z3 is as follows.
(declare-sort S)
(declare-fun e () S)
(declare-fun mult (S S) S)
(declare-fun inv (S) S)
(assert (forall ((x S) (y S) (z S)) (= (mult (mult x y) z) (mult x (mult y z)))))
(assert (forall ((x S) (y S) (z S)) (= (mult x (mult y z)) (mult (mult x y) z))))
(assert (forall ((x S)) (= (mult e x) x)))
(assert (forall ((x S)) (= (mult (inv x) x) e)))
(assert (forall ((x S)) (= (mult x e) x)))
(assert (forall ((x S)) (= (mult x (inv x)) e)))
(check-sat)
(push)
(assert (not (forall ((x S) (y S) (z S)) (=> (= (mult (mult y x) (inv x))
(mult (mult z x) (inv x) )) (= y z)))))
(check-sat)
(pop)
and the respective output is
sat
unsat

Resources