I want to solve this in the z3 solver with bit vector 48:
(declare-fun x () Int)
(declare-fun y () Int)
(assert (= *someNumber* (* x y)))
(assert (> x 1))
(assert (> y 1))
(check-sat)
(get-model)
(exit)
I'm trying to figure out how to use the arithmetic function however, it does not work out very well.
The problems with that (for me) are the correct Syntax of the functions && how to set the values in there.
(set-option :produce-models true)
(set-logic QF_BV)
;; Declaring all the variables
(declare-const a (_ BitVec 48))
(declare-const b (_ BitVec 48))
(declare-const c (_ BitVec 48))
;; Soft constraints to limit reuse
(assert (= c #xnumberInHex))
(assert-soft (not (= a b)))
(check-sat-using (then simplify solve-eqs bit-blast sat))
(simplify (= c (bvmul a b))
(simplify (bvugt a #b000000000001))
(simplify (bvugt b #b000000000001))
(check-sat)
(get-model)
Any help is much appreciated.
Syntax / how to write the correct bit vector there
Looks like you've got almost all the pieces in there, but perhaps not exactly getting the syntax right. Here's a complete encoding with c = 18:
(set-option :produce-models true)
(set-logic ALL)
;; Declaring all the variables
(declare-const a (_ BitVec 48))
(declare-const b (_ BitVec 48))
(declare-const c (_ BitVec 48))
(assert (= c #x000000000012)) ; 18 is 0x12 in hex
(assert (= c (bvmul a b)))
; don't allow overflow
(assert (bvumul_noovfl a b))
(assert (bvult #x000000000001 a))
(assert (bvult #x000000000001 b))
;; Soft constraints to limit reuse
(assert-soft (not (= a b)))
(check-sat)
(get-model)
Note the use of the ALL logic and the function bvumul_noovfl which detects unsigned bit-vector multiplication overflow. (This function is z3 specific, and is only available when you pick the logic to be ALL.) Since you're doing bit-vector arithmetic, it is subject to wrap-around, and I'm guessing this is something you'd like to avoid. By explicitly stating we do not want the multiplication of a and b to overflow, we're achieving that goal.
For this input, z3 says:
sat
(model
(define-fun b () (_ BitVec 48)
#x000000000009)
(define-fun a () (_ BitVec 48)
#x000000000002)
(define-fun c () (_ BitVec 48)
#x000000000012)
)
which correctly factors the number 18 (written here in hexadecimal as 12) into 2 and 9.
Note that multiplication is a hard problem. As you increase the bit-size (here you picked 48, but could be larger), or if the number c itself gets larger, the problem will become harder and harder for z3 to solve. This is, of course, not surprising: Factorization is a hard problem in general, and there's no magic here for z3 to correctly factor your input value without solving a huge set of internal equations, which increase exponentially in size as the bit-width increases.
But fear not: Bit-vector logic is complete: This means that z3 will always be able to factor, albeit slowly, assuming you do not run out of memory or patience first!
This is what I did now.
It might help others in the future:
(set-option :produce-models true)
(set-logic ALL)
;; Declaring all the variables
(declare-const a (_ BitVec 48))
(declare-const b (_ BitVec 48))
(declare-const c (_ BitVec 48))
(assert (= c #x00000000affe))
(assert (= c (bvmul a b)))
; don't allow overflow
(assert (= c (bvumul_noovfl a b)))
(assert (bvult #x000000000001 a))
(assert (bvult a c))
(assert (bvult #x000000000001 b))
(assert (bvult b c))
;; Soft constraints to limit reuse
(assert-soft (not (= a b)))
(check-sat)
(get-model)
I added two more asserts to make sure a or b does not exceed c (the input in hexadecimal)
in this example, I used "affe" that's 45054 in decimal.
it should work for bigger ones as well.
Output:
sat
(model
(define-fun b () (_ BitVec 48)
#x00000000138e)
(define-fun a () (_ BitVec 48)
#x000000000009)
(define-fun c () (_ BitVec 48)
#x00000000affe)
)
hex: 138e * 9 = affe
dec: 5006 * 9 = 45054
Hope this will help someone else in the future.
Related
I'm trying to write a max function that operates on Seq Int.
It should return the index with maximal value. Here is what I have:
(declare-fun max ((Seq Int)) Int)
(assert (forall ((A (Seq Int)))
(=>
(> (seq.len A) 0)
(and
(<= 0 (max A))
(< (max A) (seq.len A))
(forall ((i Int))
(=>
(and
(<= 0 i)
(< i (seq.len A)))
(<= (seq.nth A i) (seq.nth A (max A))))))))
)
(assert (= (max (seq.++ (seq.unit 8) (seq.unit 3))) 0))
;(assert (= (max (seq.++ (seq.unit 8) (seq.unit 3))) 1))
(check-sat)
When I run it like this, Z3 gets stuck. If I use the commented line instead, Z3 immediately answers unsat (like it should). Am I missing something here? Is there a way to define max properly?
This sort of quantified problems are just not a good match for z3. (Or any other SMT solver.) To prove properties of such recursive predicates, you need induction. Traditional SMT solvers have no induction capabilities.
Having said that, you can help z3 by making your quantified assertions separated out, like this:
(declare-fun max ((Seq Int)) Int)
(assert (forall ((A (Seq Int))) (=> (> (seq.len A) 0) (<= 0 (max A)))))
(assert (forall ((A (Seq Int))) (=> (> (seq.len A) 0) (< (max A) (seq.len A)))))
(assert (forall ((A (Seq Int)) (i Int)) (=> (and (> (seq.len A) 0) (<= 0 i) (< i (seq.len A)))
(<= (seq.nth A i) (seq.nth A (max A))))))
(assert (= (max (seq.++ (seq.unit 8) (seq.unit 3))) 0))
;(assert (= (max (seq.++ (seq.unit 8) (seq.unit 3))) 1))
(check-sat)
If you run this, it succesfully says:
sat
While this is correct, don't be fooled into thinking you've completely specified how max should work or z3 can handle all such problems. To wit, let's add (get-model) and see what it says:
sat
(model
(define-fun max ((x!0 (Seq Int))) Int
(ite (= x!0 (seq.++ (seq.unit 7718) (seq.++ (seq.unit 15) (seq.unit 7719))))
2
0))
)
Oh look, it simply found an interpretation of max that doesn't even satisfy the quantified axioms you've given. Looks like this is a z3 bug and should probably be reported. But the moral of the story is the same: Sequence logic and quantifiers are a soft spot, and I wouldn't count on the solver response even if you got a sat answer.
Long story short Recursion requires induction, and if that's what your specification requires, use a tool that understands induction. Isabelle, HOL, Coq, Agda, Lean; to name a few. There are many choices. And most of those tools automatically call z3 (or other SMT solvers) under the hood to establish properties as necessary (or as guided by the user) anyhow; so you have the best of both worlds.
I am trying to model sets in Z3 such that I am able to find models to
constraints involving sets.
I currently represent a set using an array. An element belongs to the set
if the corresponding entry in the array is true. I then have some axioms
which I use in constraints.
Here is an example in SMT 2.0.
(define-sort Set (T) (Array T Bool))
(declare-fun |Set#Card| ((Set Int)) Int)
(assert (forall ((s (Set Int)))
(!
(<= 0 (|Set#Card| s))
:pattern ((|Set#Card| s)))))
(declare-fun |Set#Singleton| (Int) (Set Int))
(assert (forall ((r Int))
(!
(select (|Set#Singleton| r) r)
:pattern ((|Set#Singleton| r)))))
(assert (forall ((r Int) (o Int))
(iff (select (|Set#Singleton| r) o) (= r o))))
(assert (forall ((r Int)) (= (|Set#Card| (|Set#Singleton| r)) 1)))
(declare-fun s () (Set Int))
(assert (= 1 (|Set#Card| s)))
;(assert (= 1 (|Set#Card| (|Set#Singleton| 1))))
;(assert (not (= 1 (|Set#Card| (|Set#Singleton| 1)))))
(check-sat)
(get-info :reason-unknown)
(get-model)
My problem is that I get unknown and therefore no model for most cases.
I think my axiomatization is too weak. In the example above I would
like to get a model for a set s which contains one element.
Does anyone know how I could use Z3 to get models for constraints
involving sets?
Every answer is helpful. I.e., perhaps I misunderstand what Z3 can
and cannot do. Ideas on how I could deal with this problem are welcome
too (other tool suggestions, ...).
The problem is that Z3 will fail to build a model that satisfies assertions such as:
(assert (forall ((r Int) (o Int))
(iff (select (|Set#Singleton| r) o) (= r o))))
One possible workaround is to define |Set#Singleton| instead of axiomatizing it.
We can define it using the const array operator, and store. Here is a possible definition:
(define-fun |Set#Singleton| ((r Int)) (Set Int)
(store ((as const (Set Int)) false) r true))
Here is a link for your modified example with this definition. Z3 returns sat and a model after I use the definition.
In the textual interface, we have to use as construct to specify the kind of constant array we want.
Note that, we can encode several set operations using the extended array theory available in Z3. This paper has additional details. However, this approach can't encode the |Set#Card| function.
Another option is to use "candidate models" for unknown results. This is not the ideal solution, but several users do that.
I have a simple proposition. I would like to assert that first element from a strictly sorted list of integers is the minimum of all elements in the list. The way I define sorted list is by defining a local invariant that every element is less than its next element. I have formulated my proposition in following way in Z3 -
(set-option :mbqi true)
(set-option :model-compact true)
(declare-fun S (Int) Bool)
(declare-fun preceeds (Int Int) Bool)
(declare-fun occurs-before (Int Int) Bool)
;; preceeds is anti-reflexive
(assert (forall ((x Int)) (=> (S x) (not (preceeds x x)))))
;; preceeds is monotonic
(assert (forall ((x Int) (y Int)) (=> (and (S x) (and (S y) (and (preceeds x y))))
(not (preceeds y x)))))
;; preceeds is a function
(assert (forall ((x Int) (y Int) (z Int)) (=> (and (S x) (and (S y) (and (S z) (and (preceeds x y)
(preceeds x z)))))
(= y z))))
;; preceeds induces local order
(assert (forall ((x Int) (y Int)) (=> (and (S x) (and (S y) (preceeds x y)))
(< x y))))
;; preceeds implies occurs-before
(assert (forall ((x Int) (y Int)) (=> (and (and (S x) (S y)) (preceeds x y))
(occurs-before x y))))
;;occurs-before is transitivie
(assert (forall ((x Int)(y Int)(z Int))
(=> (and (S x) (and (S y) (and (S z)(and (occurs-before x y) (occurs-before y z)))))
(occurs-before x z))
))
(declare-const h Int)
(assert (S h))
(assert (forall ((x Int)) (=> (S x) (occurs-before h x))))
(assert (forall ((y Int)) (=> (S y) (< h y))))
(check-sat)
(get-model)
Firstly, I would like to know exactly what class of formulas are effectively propositional. Can my assertion be classified as effectively propositional?
Secondly, is my formulation shown above correct?
Thirdly, what options should I set in Z3 to make it accept quantified formulas only if they are effectively propositional?
We say a formula is in the effectively propositional fragment when it contains only predicates, constants, universal quantifiers, and does not use theories (e.g., arithmetic). It is very common to find alternative definitions that says that the formula has a Exists* Forall* quantifier prefix and uses only predicates. These definitions are equivalent since the existential quantifier can be eliminated using fresh uninterpreted constants. For more information see here.
Your assertions are not in the effectively propositional fragment because you use arithmetic. Z3 can decide other fragments. The Z3 tutorial has a list of fragments that can be decided by Z3.
Your assertions is not in any of the fragments listed, but Z3 should be able to handle them and other similar assertions without problems.
Regarding the correctness of your assertions, the following two assertions cannot be satisfied.
(assert (S h))
(assert (forall ((y Int)) (=> (S y) (< h y))))
If we instantiate the quantifier with h we can deduce (< h h) which is false.
I see what you are trying to do. You may also consider the following simple encoding (maybe it is too simple). It is also available online here.
;; Encode a 'list' as a "mapping" from position to value
(declare-fun list (Int) Int)
;; Asserting that the list is sorted
(assert (forall ((i Int) (j Int)) (=> (<= i j) (<= (list i) (list j)))))
;; Now, we prove that for every i >= 0 the element at position 0 is less than equal to element at position i
;; That is, we show that the negation is unsatisfiable with the previous assertion
(assert (not (forall ((i Int)) (=> (>= i 0) (<= (list 0) (list i))))))
(check-sat)
Finally, Z3 does not have any command line for checking whether a formula is in the effectively propositional fragment or not.
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.
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))