Is there a general way to add hypothetical assumptions in Z3? - z3

I'm just getting started out and I'm curious if there is a way to add hypotheses. Using (assert ...) isn't what I want as for my application sometimes the assumptions are allowed to be false and therefore everything should become satisfiable. I know I can just use implications such as (assert (implies assumption conclusion)) but if there are many assumptions, it seems clumsy convert all of my assertions into implications. Roughly I'd like to have an interaction model like
(assume ...)
...
(assume ...)
(assert ...)
...
(assert ...)
(check-sat)

Using assert with implications is the way to go, there is no assume (see the SMT-LIB manual, section 3.9, http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.0-r10.12.21.pdf ).
If you have many assertions you'd like to use as assumptions, you may want to use one of the programmatic APIs to help automate this conversion for you: http://z3.codeplex.com/documentation
Alternatively, if the assertions are simple enough, you could just write a script operating on string representations of the assertions to print the SMT-LIB formulas with the implications.
You may also be interested in this: Soft/Hard constraints in Z3

Related

Abstracting over groups of assertions in Z3/SMT-LIB

Are there good mechanisms in Z3 to abstract over assertions? I want to create a “function” that takes in parameters and makes assertions about those parameters, possibly with “local variable” definitions in it.
Imagine that I have a String and I want to assert that it represents a decimal number between 13 and 24. I could write a combination of regular expression assertions about the string and combine it with a str.to.int range assertion. I can do that directly, but if I have dozens of such variables I want to make the assertion about, it gets repetitive. I can use an external language API, or perhaps define a macro/function returning a boolean inside Z3 and assert that it’s true, but that feels a bit indirect. What’s idiomatic here? I want it to be just as easy for Z3 to solve as writing the assertions out by hand
You can use define-fun to define a Boolean function f such that you can (assert (f x y z ...)), where f can of course be a conjunction of multiple conditions. The define-fun will be inlined by Z3's SMT2 frontend, i.e., there should not be any runtime cost to it.
(Z3 also supports macros defined via (forall ((x ...)) (= (f x ...) ...)), but you need to explicitly apply the model-finder tactic to inline them.)

Discrete time steps in Z3 / CVC4 / SMT-LIB

I am defining time steps using an Int in SMT-LIB, which forces me to assert things to make sure nothing happens in the negatives:
(declare-sort Pkg) ; A package
(define-sort Time () Int) ; The installation step
; ...
(assert (forall ((t Time) (p Pkg)) (=> (< t 0) (not (installed p t)))))
I saw that in Z3 we can define inductive Nats in the usual style. Would it be good to use the inductive definition of Nat or is there a better way of doing what I am trying to do above?
You should really stick to Int, and put in >= 0 constraints appropriately. Z3 knows a lot about Int, has all sorts of proof rules and tricks to deal with it. While you can indeed define an inductive Nat type, you'll lose all the internal machinery for dealing with integers, and due to the recursive definition Z3's decision procedures will be less effective; especially in combination with other theories.
Having said that, it is impossible to know unless you try: There might be some problem domains where the inductive definition might fit better. But just by purely looking at the kind of you're problem dealing with, good old Int seems to be the right choice for you.
Also see this related question: Representing temporal constraints in SMT-LIB which is definitely relevant in your context.

Modelling generic datatypes for Z3 and or SMT(v2.6)

I would like to model the behaviour of generic datatypes in SMT v2.6. I am using Z3 as constraint solver. I modelled, based on the official example, a generic list as parameterised datatype in the following way:
(declare-datatypes (T) ((MyList nelem (cons (hd T) (tl MyList)))))
I would like the list to be generic with respect to the datatype. Later on, I would like to declare constants the following way:
(declare-const x (MyList Int))
(declare-const y (MyList Real))
However, now I would like to define functions on the generic datatype MyList (e.g., a length operation, empty operation, ...) so that they are re-usable for all T's. Do you have an idea how I could achieve this? I did try something like:
(declare-sort K)
(define-fun isEmpty ((in (MyList K))) Bool
(= in nelem)
)
but this gives me an error message; for this example to work Z3 would need to do some type-inference, I suppose.
Would be great if you could could give me a hint.
SMT-Lib does not allow polymorphic user-defined functions. Section 4.1.5 of http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf states:
Well-sortedness checks, required for commands that use sorts or terms,
are always done with respect to the current signature. It is an error
to declare or define a symbol that is already in the current
signature. This implies in particular that, contrary to theory
function symbols, user-defined function symbols cannot be overloaded.
Which is further expanded in Footnote-29:
The motivation for not overloading user-defined symbols is to simplify
their processing by a solver. This restriction is significant only for
users who want to extend the signature of the theory used by a script
with a new polymorphic function symbol—i.e., one whose rank would
contain parametric sorts if it was a theory symbol. For instance,
users who want to declare a “reverse” function on arbitrary lists,
must define a different reverse function symbol for each (concrete)
list sort used in the script. This restriction might be removed in
future versions.
So, as you suspected, you cannot define "polymorphic" functions at the user level. But as the footnote indicates, this restriction might be removed in the future, something that will most likely happen as SMT-solvers are more widely deployed. Exactly when that might happen, however, is anyone's guess.

Z3 Doesn't Recognize Insert and Nil Without Type

In the following code, Z3 doesn't recognize nil in line 1 until xs is declared to be List. How to solve this? Is there an import/include like construct in Z3/SMT-LIB2?
(assert (= nil nil)) ; (error "line 1 column 12: unknown constant nil")
(declare-const xs (List Int))
(assert (= nil nil)) ; OK after declare-const List Int
Testing both from the file or using z3 -in will see the error.
This is a general shortcoming of the SMT-Lib standard, unfortunately. The only way to bring symbols to scope is via set-logic declarations, and the list of those logics is fixed. When individual solvers (such as z3) implement new decision procedures they have to bring in the symbols in an ad hoc way. It appears z3 only brings the symbol nil into scope when it sees List in a declaration; which is error-prone to say the least.
This has come up various times in discussions, alas there doesn't seem to be anyone with enough motivation (myself included) to make a concrete proposal and work out all the details. See here, for instance: http://www.cs.nyu.edu/pipermail/smt-lib/2015/000862.html, where a suggestion was made to move away from fixed logic declarations to more import style specifications.
So, you're pretty much stuck with declaring a List first it seems, given the current state of things. Hopefully, SMTLib will evolve in ways to support new features in more flexible ways in the future.

Z3: A better way to model?

I've two SMT problem instances. The first is here:
http://gist.github.com/1232766
Z3 returns a model for this problem in about 2 minutes on my not-so-great machine, which is great.. I also have this one:
http://gist.github.com/1232769
I've ran z3 overnight on this problem, without Z3 completing. If you check the contents of these files, you'll see that the second one is identical to the first, except it has an extra assertion to "reject" the model returned by the first instance. (You can do a "diff" between them to see what I mean.) I happen to know that this problem has multiple satisfying models, and I'm trying to use z3 to find all satisfying models.
I understand that this might be completely expected, but I was curious to know why the second one is a much tougher problem for Z3 compared to the first. Is there a better way to formulate the second problem so Z3 will have an easier time?
Thanks..
It is hard to give you a precise answer without knowing more about your application.
As you suggested, modeling plays a big role in the logic you are using: AUFBV.
The strategy used by Z3 also has a big impact on the overall performance.
Z3 comes equipped with several builtin strategies. It has many parameters that can be used to influence the search.
Z3 also has a strategy specification language. This is a new feature. I’m not advertising it because it is working in progress, and the language will most likely change in the next versions.
You can access more information about the strategy language by executing the commands:
(help check-sat-using)
(help-strategy)
That being said, there is a builtin strategy in Z3 that seems to be effective on your problem.
It is the strategy used for the logic UFBV. Your problem uses arrays, but they can be avoided by transforming table0 into a function with two arguments:
(declare-fun table0 ((_ BitVec 64) (_ BitVec 64)) (_ BitVec 8))
And replacing every term of the form (select (table0 s65) t) with (table0 s65 t) where t is an arbitrary term.
Finally, you must also add the command (set-logic UFBV) in the beginning of the file. With this setting, I managed to generate 4 different models for your query.
I didn’t try to generate more than that. Each call consumed approx 75 secs.

Resources