I am trying to encode some imperative program using HORN logic of Z3 (set-logic HORN) but getting some difficulties of defining clause (using SMT2). Could anyone tell me where can I find a good source of documentations for this feature of Z3?
Well, there's more to it when it comes to "encoding" a program in horn clauses.
First you need to check an appropriate proof rule: does the program has recursive functions, should you do function summarization? and so on.
There are a few papers on the subject, but I don't think there's any tutorial on VC gen.
You may also want to take a look to some benchmarks in Horn SMT format to draw inspiration: https://svn.sosy-lab.org/software/sv-benchmarks/trunk/clauses/
Feel free to ask if you have a specific question.
Related
I'm trying to solve a question answering task. There are several approaches to this like Deep Learning methods, querying Knowledge Graphs, Semantic Search etc. But I thought if it would be possible to use Z3 theorem prover for that task as well? For example, if we can present knowledge as a set of axioms, each axiom consists of the predicates (relations), subjects and objects and is expressed in FOL clauses, then we can traverse through them and find an answer to the query (which can be expressed as axiom as well). For example, I can encode a simple knowledge "English is language" in FOL clause:
exists l.(language(l) & exists n.(name(n) & :op1(n,"English") & :name(l,n)))
How can I translate it into Z3? And how can I extract an answer to the query "{unknown} is language" to find an {unknown} variable or clause? Note that the {unknown} can be anything. It can be an atom or logical clause depending on the match with the query.
I don't think an SMT solver is very suitable for this task. Not because you can't do it using z3, but a system like Prolog or a custom-program you build will work just as fine as well. SMT solvers shine when you have combination of theories (numbers, arithmetic, arrays, data-structures, etc.); for your problem domain, all you need is a Prolog like simple-database and a query engine.
Encoding your suggested statement really depends on what sort of predicates you have in mind. Note that SMTLib is a "typed" language; so a predicate like language(l) is redundant: You'd have a value of the type language only when that call type-checks; i.e., you can't pass the predicate language anything that's not a language anyways. (This is similar to programming in a typed-language like Haskell/O'Caml etc., vs. in a dynamically typed language like Lisp/Scheme/Python etc.)
See Solving predicate calculus problems with Z3 SMT for an example of how to use an SMT solver to deal with first-order-logic modeling problems.
I'm trying to inspect a simple looping program that finds the maximal element in an integer array. Here is the permalink here. Everything works fine, but I'm really interested in
the resulting SMT file, so I extracted it using:
$ dafny /compile:3 /proverLog:./mySMT.smt myCode.dfy
Then ran with z3 as follows:
$ z3 ./mySMT.smt
I got 3 unsat responses and I was wondering what are the corresponding 3 queries?
I looked at the *.smt file and found 11K of machine-generated SMT.
Any tips on deciphering the smt file? thanks!
If you want the resulting SMT file, then that 11K file is your answer. I imagine that looking at it will lead you to the conclusion that you don't actually want to look at the resulting SMT file.
So, I don't know what it is that you want to accomplish. If you want to learn more about your program, then the best way is to work (only) from the Dafny program text. For example, you can add more assert statements to, essentially, ask the verifier if the given condition is provable at the location of the statement.
If you're interested in how Dafny encodes its verification conditions (that is, if you yourself are a tool developer and want to learn how to generate good verification conditions), then I suggest you use the /print switch to generate the Boogie program that Dafny generates. With some understanding of the Boogie intermediate verification language, the Boogie code is readable. For a more tutorial account of how to encode a Dafny-like language into Boogie, I recommend:
"Specification and verification of object-oriented software",
K. Rustan M. Leino.
Lecture note, Marktoberdorf 2008.
Rustan
PS. Unless you insist on particular formatting, you can print your array elements without using a loop if you first convert the array's element to a sequence:
print "a = ", a[..], "\n";
Using Z3's Horn clause solver:
If the answer is SAT, one can get a satisfying assignment to the unknown predicates (which, in most applications, correspond to inductive invariants of some kind of transition system or procedure call system).
If the answer is unsat, then this means the exists an unfolding of the Horn clauses and an assignment to the universally quantified variables in the Horn clauses such that at least one of the safety conditions (the clauses with a false head) is violated. This constitutes a concrete witness why the system had no solution.
I suspect that if Z3 can conclude unsat, then it has some form of such witness internally (and this anyway is the case in PDR, if I remember well). Is there a way to print it out?
Maybe I badly read the documentation, but I can't find a way. (get-proof) prints something unreadable, and, besides, (set-option :produce-proofs true) makes some problems intractable.
The refutation that Z3 produces for HORN logic problems is in the form of a tree of unit-resulting resolution steps. The counterexample you're looking for is hiding in the conclusions of the unit-resolution steps. These conclusions (the last arguments of the rules) are ground facts that correspond to program states (or procedure summaries or whatever) in the counterexample. The variable bindings that produce these facts can be found in "quant-inst" rules.
Obviously, this is not human readable, and actually is pretty hard to read by machine. For Boogie I implemented a more regular format, but it is currently only available with the duality engine and only for the fixedpoint format using "rule" and "query". You can get this using the following command.
(query :engine duality :print-certificate true)
As previously asked Z3 can not provide a model for recursive functions. However, is it possible to tell Z3 (preferably via the Java API) that a model without a definition for recursive functions is sufficient (or indeed choose the functions I am interested in, essentially I do not need a model for non-constant functions)? Obviously, that might lead to queries that return sat although some functions do not have a model. Basically, the user then has to ensure that these functions do have some model.
However, I would assume this is not really realizable the way Z3 or SMT solvers work, i.e., I would assume Z3 needs a (partial) model of recursive functions to evalutate expressions.
The MBQI implementation for quantifiers doesn't really work nicely with recursive functions.
There is one thing that might do the trick for you: replace recursive function definitions by bounded-recursive functions. You add an extra argument that counts the number of unfoldings you are willing to explore of the function. Whenever you apply the recursive function in the rest of the input, set the depth parameter. You can use either algebraic data-type Peano numbers or integers.
The symbolic automata toolkit uses this approach, for example.
I found one paper that explores the idea given in Nikolaj Bjorner's answer further: "Computing with an SMT solver" by Amin, Leino and Rompf (2014).
Furthermore, I found "Satisfiability Modulo Recursive Programs" by Suter, Köksal and Kuncak (2011) which unfolds calls to recursive functions successively until the satisfiability can be decided.
I have precise and validated descriptions of the behaviors of many X86 instructions in terms amenable to encoding in QF_ABV and solving directly with the standard solver (using no special solving strategies). I wrote an SMT-LIB script whose interface matches my ultimate goal perfectly:
X86State, a record sort describing x86 machine state (registers and flags as bitvectors, and memory as an array).
X86Instr, a record sort describing x86 instructions (enumerated mnemonics, operands as an ML-like discriminated union describing registers, memory expressions, etc.)
A function x86-translate taking an X86State and an X86Instr, and returning a new X86State. It decodes the X86Instr and produces a new X86State in terms of the symbolic effects of the given X86Instr on the input X86State.
It's great for prototyping: the user can write x86 easily and directly. After simplifying a formula built using the library, all functions and extraneous data types are eliminated, leaving a QF_ABV expression. I hoped that users could simply (set-logic QF_ABV) and #include my script (alas, neither the SMT-LIB standard nor Z3 support #include).
Unfortunately, by defining functions and types, the script requires theories such as uninterpreted functions, thus requiring a logic other than QF_ABV (or even QF_AUFBV due to the types). My experience with SMT solvers dictates that the lowest acceptable logic should be specified for best solving time. Also, it is unclear whether I can reuse my SMT-LIB script in a programmatic context (e.g. OCaml, Python, C) as I desire. Finally, the script is a bit verbose given the lack of higher-order functions, and my lack of access to par leading to code duplication.
Thus, despite having accomplished my technical goals, I think that SMT-LIB might be the wrong approach. Is there a more natural avenue for interacting with Z3 to implement my x86 instruction description / QF_ABV translation scheme? Is the SMT-LIB script re-usable at all in these avenues? For example, you can build "custom OCaml top-levels", i.e. interpreters with scripts "burned into them". Something like that could be nice. Or do I have to re-implement the functionality in another language, in a program that interacts with Z3 via a theory extension (C DLL)? What's the best option here?
Well, I don't think that people write .smt2 files by hand. These are usually generated automatically by some program.
I find the Z3 Python interface quite nice, so I guess you could give it a try. But you can always write a simple .smt2 dumper from any language.
BTW, do you plan releasing the specification you wrote for X86? I would be really interested!