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)
Related
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 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!
I am trying to prove with Z3 the theorem in general topology given at
TPTP-Topology
I am translating the code given there using the following Z3-SMT-LIB code
;; File : TOP001-2 : TPTP v6.0.0. Released v1.0.0.
;; Domain : Topology
;; Problem : Topology generated by a basis forms a topological space, part 1
(declare-sort S)
(declare-sort Q)
(declare-sort P)
(declare-fun elemcoll (S Q) Bool)
(declare-fun elemset (P S) Bool)
(declare-fun unionmemb (Q) S)
(declare-fun f1 (Q P) S)
(declare-fun f11 (Q S) P)
(declare-fun basis (S Q) Bool)
(declare-fun Subset (S S) Bool)
(declare-fun topbasis (Q) Q)
;; union of members axiom 1.
(assert (forall ((U P) (Vf Q)) (or (not (elemset U (unionmemb Vf)))
(elemset U (f1 Vf U) ) ) ))
;; union of members axiom 2.
(assert (forall ((U P) (Vf Q)) (or (not (elemset U (unionmemb Vf)))
(elemcoll (f1 Vf U) Vf ) ) ))
;; basis for topology, axiom 28
(assert (forall ((X S) (Vf Q)) (or (not (basis X Vf)) (= (unionmemb Vf) X ) ) ))
;; Topology generated by a basis, axiom 40.
(assert (forall ((Vf Q) (U S)) (or (elemcoll U (topbasis Vf))
(elemset (f11 Vf U) U)) ))
;; Set theory, axiom 7.
(assert (forall ((X S) (Y Q)) (or (not (elemcoll X Y)) (Subset X (unionmemb Y) ) ) ))
;; Set theory, axiom 8.
(assert (forall ((X S) (Y S) (U P)) (or (not (Subset X Y)) (not (elemset U X))
(elemset U Y) )))
;; Set theory, axiom 9.
(assert (forall ((X S)) (Subset X X ) ))
;; Set theory, axiom 10.
(assert (forall ((X S) (Y S) (Z S)) (or (not (= X Y)) (not (Subset Z X)) (Subset Z Y) ) ))
;; Set theory, axiom 11.
(assert (forall ((X S) (Y S) (Z S)) (or (not (= X Y)) (not (Subset X Z)) (Subset Y Z) ) ))
(check-sat)
(push)
(declare-fun cx () S)
(declare-fun f () Q)
(assert (basis cx f))
(assert (not (elemcoll cx (topbasis f))))
(check-sat)
(pop)
(push)
(assert (basis cx f))
(assert (elemcoll cx (topbasis f)))
(check-sat)
(pop)
The corresponding output is
sat
sat
sat
Please run this example online here
The first sat is correct; but the second sat is wrong, it must be unsat. In other words, Z3 is saying that the theorem and its negation are true simultaneously.
Please let me know what happens in this case. Many thanks. All the best.
It is possible that both a formula and the negation of the formula is consistent with respect to a background theory T. In particular, when T is not complete, then there are sentences that are neither consequences of T nor inconsistent with T. In your case the theory T is the set of topology axioms.
You can use the command (get-model) to obtain a model that satisfies the axioms and the sentence.
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
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