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
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)
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.
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.
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.
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