Equality for constants in Z3 SMT solver - logic

I am using the Z3 SMT solver by Microsoft, and I am trying to define constants of a custom sort. It seems like such constants are not unequal by default. Suppose you have the following program:
(declare-sort S 0)
(declare-const x S)
(declare-const y S)
(assert (= x y))
(check-sat)
This will give "sat", because it is of course perfectly possible that two constants of the same sort are equal. Since I am making model in which constants have to be different from each other, this means that I would need to add an axiom of the form
(assert (not (= x y)))
for every pair of constants of the same sort. I was wondering if there is some way to do this generic, so that each constant of a sort is unique by default.

You can use datatypes to encode enumeration types found in many programming languages. In the following example, the sort S has three elements and they are different from each other.
(declare-datatypes () ((S a b c)))
Here is a complete example: http://rise4fun.com/Z3/ncPc
(declare-datatypes () ((S a b c)))
(echo "a and b are different")
(simplify (= a b))
; x must be equal to a, b or c
(declare-const x S)
; since x != a, then it must be b or c
(assert (not (= x a)))
(check-sat)
(get-model)
; in the next check-sat x must be c
(assert (not (= x b)))
(check-sat)
(get-model)
Another possibility is to use distinct.
(assert (distinct a b c d e))

Related

Is my implementation of SICP Exercise 1.3 going in the right direction?

Exercise 1.3 in SICP asks to define a procedure that takes 3 numbers as arguments and returns the sum of the squares of the 2 largest numbers. I think I've gotten it correct but I wasn't totally sure if I've covered all cases. My implementation is as follows:
(define (bigsq a b c)
(cond ((and (> a b) (> b c)) (+ (* a a) (* b b)))
((and (> a b) (not (> b c))) (+ (* a a) (* c c)))
((> c a) (+ (* b b) (* c c)))
(else (+ (* a a) (* b b))))
Is there a way to write those first 2 conditions as one, as well? Also any comments on efficiency are welcome as well.
For starters, we could use a helper procedure for implementing the sum just once:
(define (sum x y)
(+ (* x x) (* y y)))
Now, for the conditions: given that the order doesn't matter - (sum a b) is the same as (sum b a), there's only 4 cases to consider, and we can avoid repeating some of the comparisons by nesting ifs:
(define (sum-max a b c)
(if (>= a b)
(if (>= b c)
(sum a b)
(sum a c))
(if (>= a c)
(sum b a)
(sum b c))))

#f output for scheme result inside repl.it

I'm doing some problems from Structure and Interpretation of Computer Programs
My case outputs #f as a valid result in the repl.it interpreter. I'm applying (and (not (max a b c)) (not (min a b c))) to get mid value.
I've tried rearranging the values for the mid function. The max and min functions work alright.
(define (max a b c)
(cond
((and(>= a b)(>= a c)) a)
((and(>= b a)(>= b c)) b)
((and(>= c a)(>= c b)) c)
))
(define (min a b c)
(cond
((and(<= a b)(<= a c)) a)
((and(<= b a)(<= b c)) b)
((and(<= c a)(<= c b)) c)
))
(define (mid a b c)
(and
(not (max a b c))
(not (min a b c))
))
(mid 10 8 6)
The output in the repl.it scheme interpreter is:
=> #f
I'd expect an error of some sort or a number value but this code returns a green #f so I'm assuming it means something is false? How can I fix this code to return a mid using conditional expressions?
I think it's worth thinking about how many tests you have to do to compute these things: to compute the extremum of three elements under any ordering operator you need to do no more than three comparisons:
(define (extremum/3 ordered? a b c)
;; find the extremum of three elements under ordered?
(cond ((and (ordered? a b) (ordered? a c)) a)
((ordered? b c) b)
(else c)))
And given this general function you can now define max/3 and min/3 easily:
(define (max/3 a b c)
(extremum/3 >= a b c))
(define (min/3 a b c)
(extremum/3 <= a b c))
Computing the mid point of three elements also requires no more than three tests:
(define (mid/3 a b c)
(if (>= a b)
(if (>= a c)
;; a is greatest, so we need to pick b or c
(if (>= b c) b c)
;; a is the mid point
a)
(if (>= a c)
;; a is the mid point
a
;; a is the minimum, pick b or c
(if (>= c b) b c))))
It's interesting to consider how many comparisons you need to find the mid point of n items.
I realized that I was passing a NOT from max AND min which is why it was evaluating false every time since there's always a false result from those expressions. I continued using comparisons to get the correct solution and adjusted the exceptions to take the mid to be a value which is either repeated three times or twice if it's not less than max or greater than min. The only thing that is unsettling is that I had to essentially express all conditions that are valid to isolate a mid number and couldn't explicitly define mid as NOT the max number AND NOT the min number. That being said there's got to be a better way to reduce these functions and eliminate the bulk of the comparisons...
(define (mid a b c)
(cond
((and(< a (max a b c))(> a (min a b c))) a)
((and(< b (max a b c))(> b (min a b c))) b)
((and(< c (max a b c))(> c (min a b c))) c)
(else (cond
((= (min a b c) (max a b c)) a)
((= a b) a)
((= a c) a)
((= b c) b)
))
))

parthood definition in Z3

I'm trying to define in Z3 the parthood relation (called C in the code below) between pairs of sets (defined using array).
I wrote 3 asserts to define reflexivity, transitivity, and antisymmetry but Z3 returns "unknown" and I don't understand why.
(define-sort Set () (Array Int Bool))
(declare-rel C (Set Set))
; reflexivity
(assert (forall ((X Set)) (C X X)))
; transitive
(assert (forall ((X Set)(Y Set)(Z Set))
(=>
(and (C X Y) (C Y Z))
(C X Z)
)
))
; antisymmetric
(assert (forall ((X Set)(Y Set))
(=>
(and (C X Y) (C Y X))
(= X Y)
)
))
(check-sat)
I noticed that the unknown is returned only when the antisymmetry is considered with one of the other 2 asserts. If I only consider the antisymmetry property Z3 doesn't return unknown. The same if I consider reflexivity and transitivity without antisymmetry.
Quantifiers are inherently incomplete. So, it's not surprising that Z3 (or any other SMT solver) will return unknown when they are present. There are a few heuristics that solvers use for handling quantifiers, such as e-matching; but those will only apply when you have ground-terms around. Your formulation, having only quantified axioms, is unlikely to benefit from that.
For reasoning about quantifiers in general, an SMT solver is simply not the best choice; use a theorem prover (Isabelle, Lean, Coq, etc.) for that.
Here's a nice slide deck by Leonardo on the use of quantifiers in SMT solving: https://leodemoura.github.io/files/qsmt.pdf. It can help provide some further insight into the techniques and the difficulties associated.

EPR formulas with equality and inequality

I am encoding sets as relations and operations over sets as universally quantified implications. I have a selection operator over sets that produces new sets by selecting elements satisfying a unary predicate p (eg: v<4, v>4, ..). Due to this operator, I have simple arithmetic predicates in my formulas. An example Z3 encoding of such a formula is given below -
(set-option :mbqi true)
(set-option :model-compact true)
;; Rmem and Rmem1 are sets of Int
(declare-fun Rmem (Int) Bool)
(declare-fun Rmem1 (Int) Bool)
(declare-const v Int)
(declare-const v1 Int)
(declare-const x Int)
;; Rmem = Rmem1 U {x}
(assert (forall ((n Int)) (= (Rmem n)(or (Rmem1 n) (= n x)))))
;; Select(m<v1) from Rmem1 = {}
(assert (forall ((m Int)) (= false (and (Rmem1 m) (< m v1)))))
(assert (or (< v x) (= v x)))
(assert (or (< v v) (= v v1)))
(assert (exists ((q Int)) (and (Rmem q) (< q v))))
(check-sat)
(get-model)
As expected, Z3 returns UNSAT for the above formula. However, my questions are -
Given that I can write my formula in prenex normal form, is it still in EPR class?
Are such formulas decidable? Is z3 a decision procedure for such formulas? How should I constrain my predicates such that the formulas are decidable?
Update - The aforementioned set of formulas can be expressed as conjunctive queries in relational algebra, but with inequality.
Your formula is in decidable fragment that is supported by Z3. Technically, the formula is not in EPR because you use atoms of the form x < c in quantifiers. The Z3 guide (Quantifiers section) describes many fragments that can be decided by Z3. Note that some of these fragments are very expensive (e.g., NEXPTIME-hard). So, Z3 may still fail to solve them in a reasonable amount of time, or run out of memory.

Z3 Theorem Prover: Pythagorean Theorem (Non-Linear Artithmetic)

Wherefore?
The usecase context in which my problem occures
I define 3 random item of a triangle. Microsoft Z3 should output:
Are the constraints satisfiabe or are there invalid input values?
A model for all the other triangle items where all the variables are assigned to concrete values.
In order to constrain the items i need to assert triangle equalities - i wanted to start out with the Pythagorean Theorem ((h_c² + p² = b²) ^ (h_c² + q² = a²)).
The Problem
I know that Microsoft Z3 has only limited capabilities to solve non-linear arithematic problems. But even some hand calculators are able to solve a very simplified version like this:
(set-option :print-success true)
(set-option :produce-proofs true)
(declare-const a Real)
(declare-const b Real)
(assert (= a 1.0))
(assert (= b 1.0))
(assert
(exists
((c Real))
(=
(+
(* a a)
(* b b)
)
(* c c)
)
)
)
(check-sat)
(get-model)
The Question
Is there a way to get Microsoft Z3 to solve the Pythagorean Theorem if two values are given?
Or: Is there another theorem prover which is able to handle these case of non-linear arithmetic?
Thanks for your help concerning that - If anything is unclear, please comment.
Z3 has a new solver (nlsat) for nonlinear arithmetic. It is more efficient than other solvers (see this article). The new solver is complete for quantifier-free problems.
However, the new solver does not support proof generation. If we disable proof generation, then Z3 will use nlsat and easily solve the problem. Based on your question, it seems you are really looking for solutions, thus disabling proof generation does not seem to be an issue.
Moreover, Z3 does not produce approximate solutions (like hand calculators).
It uses a precise representation for real algebraic numbers.
We can also ask Z3 to display the result in decimal notation (option :pp-decimal).
Here is your example online.
In this example, when precise representation is used, Z3 will display the following result for c.
(root-obj (+ (^ x 2) (- 2)) 1)
It is saying that c is the first root of the polynomial x^2 - 2.
When we use (set-option :pp-decimal true), it will display
(- 1.4142135623?)
The question mark is used to indicate the result is truncated.
Note that, the result is negative. However, it is indeed a solution for the problem you posted.
Since, you are looking for triangles, you should assert that the constants are all > 0.
BTW, you do not need the existential quantifier. We can simply use a constant c.
Here is an example (also available online at rise4fun):
(set-option :pp-decimal true)
(declare-const a Real)
(declare-const b Real)
(declare-const c Real)
(assert (= a 1.0))
(assert (= b 1.0))
(assert (> c 0))
(assert (= (+ (* a a) (* b b)) (* c c)))
(check-sat)
(get-model)
Here is another example that does not have a solution (also available online at rise4fun):
(set-option :pp-decimal true)
(declare-const a Real)
(declare-const b Real)
(declare-const c Real)
(assert (> c 0))
(assert (> a c))
(assert (= (+ (* a a) (* b b)) (* c c)))
(check-sat)
BTW, you should consider the Python interface for Z3. It is much more user friendly. The tutorial that I linked has examples in Kinematics. They also use nonlinear arithmetic to encode simple high-school physics problems.

Resources