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.
Related
Are functions in z3 realized by inlining? E.g. would this
(define-fun f ((parameter Int)) Int (* parameter parameter))
(assert (= (f x) y))
automatically be replaced by this?:
(assert (= (* x x) y))
I know that in https://smtlib.github.io/jSMTLIB/SMTLIBTutorial.pdf#subsection.3.9.4 (page 38) it is mentioned that they are "equivalent"/"an abbreviation", but I just wanted to make sure whether this means that the function calls themselves are replaced.
Thanks so much!
Yes, the SMT-LIB standard indeed defines define-fun to be a C-style macro that is syntactically expanded to its defining expression.
However, while this defines its semantics, the definition does not necessarily require SMT-LIB tools, most notably SMT solvers, to actually implement define-fun like this. Hence, it could be that an SMT solver behaved differently, e.g. in terms of performance, if you ran it on two versions of a program: one with define-funs, and a second where you manually replaced all define-funs with their corresponding expressions.
The last bit is pure speculation from my side, though; you'd have to look at, e.g. Z3's sources (or maybe just its verbose debug output) to find out what a particular tool actually does.
Even for simplest arithmetic SMT problems the existential quantifier is required to declare symbolic variables. And ∀ quantifier can be turned into ∃ by inverting the constraint. So, I can use both of them in QF_* logics and it works.
I take it, "quantifier free" means something else for such SMT logics, but what exactly?
The claim is that
∀ quantifier can be turned into ∃ by inverting the constraint
AFAIK, the following two relations hold:
∀x.φ(x) <=> ¬∃x.¬φ(x)
¬∀x.φ(x) <=> ∃x.¬φ(x)
Since a quantifier-free SMT formula φ(x) is equisatisfiable to its existential closure ∃x.φ(x), we can use the quantifier-free fragment of an SMT Theory to express a (simple) negated occurrence of universal quantification, and [AFAIK] also a (simple) positive occurrence of universal quantification over trivial formulas (e.g. if [∃x.]φ(x) is unsat then ∀x.¬φ(x)¹).
¹: assuming φ(x) is quantifier-free; As #Levent Erkok points out in his answer, this approach is inconclusive when both φ(x) and ¬φ(x) are satisfiable
However, we cannot, for example, find a model for the following quantified formula using the quantifier-free fragment of SMT:
[∃y.]((∀x.y <= f(x)) and (∃z.y = f(z)))
For the records, this is an encoding of the OMT problem min(y), y=f(x) as a quantified SMT formula. [related paper]
A term t is quantifier-free iff t syntactically contains no quantifiers. A quantifier-free formula φ is equisatisfiable with its existential closure
(∃x1. (∃x2 . . .(∃xn.φ ). . .))
where x1, x2, . . . , xn is any enumeration of free(φ), the free variables in φ.
The set of free variables of a term t, free(t), is defined inductively as:
free(x) = {x} if x is a variable,
free((f t1 t2 . . . tk)) = \cup_{i∈[1,k]} free(ti) for function applications,
free(∀x.φ) = free(φ) \ {x}, and
free(∃x.φ) = free(φ) \ {x}.
[source]
Patrick gave an excellent answer, but here're a few more thoughts. (I'd have put this up as a comment, but StackOverflow thinks it's too long for that!)
Notice that you cannot always play the "negate and check the opposite" trick. This only works because if the negation of a property is unsatisfiable, then the property must be true for all inputs. But it doesn't go the other way around: A property can be satisfiable, and its negation can be satisfiable as well. Simple example: x < 10. This is obviously satisfiable, and so is its negation x >= 10. So, you cannot always get rid of quantifiers by playing this trick. It only works if you want to prove something: Then you can negate it and see if that negation is unsatisfiable. If you're concerned about finding a model to a formula, the method doesn't apply.
You can always skolemize a formula and eliminate all the existential quantifiers by replacing them with uninterpreted functions. What you then end up with is an equisatisfiable formula that has all prefix universals. Clearly, this is not quantifier free, but this is a very common trick that most tools do for you automatically.
Where all this hurts is alternating quantifiers. Regardless of skolemization, if you have alternating quantifiers than your problem is already too difficult to deal with. The wikipedia page on quantifier elimination is rather terse, but it gives a very good introduction: https://en.wikipedia.org/wiki/Quantifier_elimination Bottom line: Not every theory admits quantifier elimination, and even those that do might require exponential algorithms to get rid of them; causing performance issues.
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.
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.
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