Using define-fun-rec in SMT - z3

I'm currently trying to write an SMT script using define-fun-rec. I've tested with both Z3, version 4.4.2, and CVC4, version 1.4. As far as I can tell, these are the most recent versions of both, and both support the feature*. However, both do not seem to recognize the command.
(I made some changes to this based on Nikolaj's reply. It still gives the error messages.) Specifically, given:
(define-fun-rec
fac ((x Int)) Int
(
ite (<= x 1)
1
(* x (fac (- x 1)))
)
)
(assert (= (fac 4) 24))
(check-sat)
Z3 outputs:
unsupported
; define-fun-rec
(error "line 10 column 17: unknown function/constant fac")
sat
And CVC4 outputs:
(error "Parse Error: fac.smt2:1.15: expected SMT-LIBv2 command, got `define-fun-rec'.
(define-fun-rec
^
")
My best guess is that there is some sort of flag I need to set or I need to be using some specific logic, but I've had a lot of trouble finding any sort of detailed instructions or examples with define-fun-rec. Any advice would be appreciated. Thanks!
*Z3 has support: How to deal with recursive function in Z3?
CVC4 has support: http://lara.epfl.ch/~reynolds/pres-smt15.pdf

The latest version of CVC4 can be downloaded under "Development versions" (on the right hand side) of:
http://cvc4.cs.nyu.edu/downloads/
The latest development version has support for recursive function definitions. You can use the cvc4 command line option "--fmf-fun" to enable a technique that finds small models for problems involving recursive function applications, assuming definitions are admissible.
(Although, unfortunately your example with factorial also requires non-linear arithmetic, which CVC4 does not yet support.)

Don't set the logic to LIA. This is not in the LIA fragment and Z3 will use the wrong tactic to solve the problem.Just remove the set-logic line.
It helps to not use an undefined function "f" inside the definition of "fib".
I would suggest that you call the function "fac" and not "fib" since you are defining a factorial function.
Thus,
(define-fun-rec
fac ((x Int)) Int
(
ite (<= x 1)
1
(* x (fac (- x 1)))
)
)
(assert (= (fac 4) 24))
(check-sat)
z3 -version
Z3 version 4.4.2
z3 fac.smt2
sat
If you change 24 to 25 you get unsat.

Related

z3 with LIA logic can return real?

I am experimenting with z3. I am surprised that, when setting the logic to LIA, z3 can return real numbers. For example, the following:
from z3 import *
sol = SolverFor("LIA")
vB = Real('vB')
sol.add(vB < 3)
sol.add(vB > 2)
sol.check()
print(sol.model())
returns:
[vB = 5/2]
Can someone please explain how it can be the case?
Strictly speaking, this is a "bug" in z3. Here's the equivalent SMT script:
(set-logic LIA)
(declare-fun vB () Real)
(assert (< vB 3.0))
(assert (> vB 2.0))
(check-sat)
(get-model)
If you run this with cvc4/cvc5, you get:
(error "Parse Error: a.smt2:2.23: Symbol 'Real' not declared as a type
(declare-fun vB () Real)
^
")
And Yices says:
(error "at line 2, column 20: undefined sort: Real")
CVC and Yices are correct here, since you restricted the logic to "LIA", the name "Real" is no longer defined. Z3, however, is playing loose here, and allowing reals by default. (It internally uses logics to pick which algorithms to run, but it's not always consistent in making sure the logic restricts the names available.)
You can report this at the z3 issue tracker here: https://github.com/Z3Prover/z3/issues. I suspect they're already aware of this, but would be good to have it recorded.

z3 returns unknown when asserting division of 0 by 0 is 1

I was trying out examples from the article Z3: a tutorial. There is an example demonstrating that all functions are total, including "div":
(push)
(assert (= 1 (div 0 0)))
(check-sat)
;sat (pop)
I noticed that z3 version 4.8.5 returns different results depending on whether one uses "push" or not.
With the code below, z3 returns unknown:
(get-info :version)
;(push)
(assert (= 1 (div 0 0)))
(check-sat)
The output from z3 is:
(:version "4.8.5 - build hashcode 8c085f1a1850")
unknown
In contrast, with the code below, z3 returns sat:
(get-info :version)
(push)
(assert (= 1 (div 0 0)))
(check-sat)
(get-model)
The output from z3 is:
(:version "4.8.5 - build hashcode 8c085f1a1850")
sat
(model
)
In the rise4fun tutorial, it says that "The command push creates a new scope by saving the current stack size", it seems that the usage of "push" should not cause different results here since there is only one assertion?
Strictly speaking unknown and sat are not contradictory: The solver is allowed to bail out at any moment and say unknown. For instance, this sort of behavior can happen if you explicitly use tactics.
But you're absolutely correct that it's bizarre push is causing this discrepancy. Please file a ticket at the z3 github issues site: https://github.com/Z3Prover/z3/issues and let us know what you find out!

Z3 v4.1 does not accept negative integers as input

I have installed Z3 version 4.1 and I attempt to use it programmatically in a java application. My application is communicating with the Z3 via ProcessBuilder. The version of Z3 is verified as 4.1 by using the /version command line argument.
However, Z3 does not accept negative constants as part of expressions. When I attempt to provide a negative integers I get the following message:
(error "line 4 column 31: unknown constant -1")
This is the input I provide to Z3:
(push)
(declare-fun y () Int )
(define-fun x () Int y )
(assert (and (<= y 1000) (>= y -1) ) )
(assert (= x 42) )
(check-sat)
(pop)
I am using the following arguments to instantiate the Z3:
Z3 /smt2 /in /t:2
Any help is appreciated. Thank you in advance.
Try (- 1). See bottom of page 38 in http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf

Z3: eliminate don't care variables

I have a test.smt2 file:
(set-logic QF_IDL)
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (or (< a 2) (< b 2 )) )
(check-sat)
(get-model)
(exit)
Is there anyway to tell Z3 to only output a=1 (or b=1)? Because when a is 1, b's value does not matter any more.
I executed z3 smt.relevancy=2 -smt2 test.smt2
(following How do I get Z3 to return minimal model?, although smt.relevancy seems has default value 2), but it still outputs:
sat
(model
(define-fun b () Int
2)
(define-fun a () Int
1)
)
Thank you!
The example given in the answer to the question referred to is slightly out of date. A Solver() will pick a suitable tactic to solve the problem, and it appears that it picks a different one now. We can still get that behavior by using a SimpleSolver() (at a possibly significant performance loss). Here's an updated example:
from z3 import *
x, y = Bools('x y')
s = SimpleSolver()
s.set(auto_config=False,relevancy=2)
s.add(Or(x, y))
print s.check()
print s.model()
Note that the (check-sat) command will not execute the same tactic as the SimpleSolver(); to get the same behavior when solving SMT2 files, we need to use the smt tactic, i.e., use (check-sat-using smt). In many cases it will be beneficial to additionally run the simplifier on the problem first which we can achieve by constructing a custom tactic, e.g., (check-sat-using (then simplify smt))

z3 produces unknown for assertions without quantifiers

I have some simple constraints involving multiplication of reals in z3 that are producing unknown. The problem seems to be that they are wrapped in a datatype, as the unwrapped version produces sat.
Here is a simplified case:
(declare-datatypes () ((T (NUM (n Real)))))
(declare-const a T)
(declare-const b T)
(declare-const c T)
(assert (is-NUM a))
(assert (is-NUM b))
(assert (is-NUM c))
(assert (= c (NUM (* (n a) (n b)))))
(check-sat)
;unknown
And without the datatype:
(declare-const a Real)
(declare-const b Real)
(declare-const c Real)
(assert (= c (* a b)))
(check-sat)
;sat
I'm using z3 3.2, but this also is reproducible in the web interface.
Yes, Z3 can return unknown in quantifier-free problems.
Here are the main reasons:
Run out of time or memory
The quantifier-free fragment is undecidable (e.g., nonlinear integer arithmetic)
The quantifier-free fragment is too expensive, and/or the procedure implemented in Z3 is incomplete.
Your problems are in a decidable fragment, and the unknown is due to the incomplete procedure for nonlinear arithmetic used in Z3. Z3 4.0 has a complete procedure for nonlinear real arithmetic, but it is still not integrated with the other theories. So, it will not help in the first problem.
The different in behavior in the first and second queries is due to different strategies used for each query. Z3 has a new framework for defining custom strategies. You can get sat for the first query by using the command
(check-sat-using (then simplify solve-eqs smt))
instead of
(check-sat)
The first command forces Z3 to eliminate variables by solving equalities (i.e., tactic solve-eqs). It will eliminate the equality (= c (NUM (* (n a) (n b)))). This tactic is automatically used in the second problem in Z3 3.x. Note that this tactic will not help if we replace the equality with (>= c (NUM (* (n a) (n b)))).
Moreover, the second problem contains only nonlinear arithmetic. So, in Z3 4.0, the new (and complete) solver for nonlinear real arithmetic will be automatically used.
You can learn about the new strategy framework at http://rise4fun.com/Z3/tutorial/strategies, http://rise4fun.com/Z3Py/tutorial/strategies
Your examples are in non-linear arithmetic. Z3 4.0 is able to solve problems with only non-linear arithmetic assertions, but not along with uninterpreted functions and other theories. That explains why it produces unknown in the first example. This limitation is likely to be addressed in Z3's future versions.

Resources