Why3 — Logic
The Why3 Platform
Why3 is targeted at deductive formal verification of algorithms and programs.
The most important conceptual components of the platform are the following:
-
WhyML, a functional-imperative programming language of the ML family
-
A logic language, which is used to write properties and annotations concerning the WhyML programs. These include preconditions, postconditions, loop invariants, variants, asserts …
-
A standard library containing many useful logical theories and data structures, including arithmetics, sets, lists, and maps (dictionaries).
The Why3 tool implements the following functionality:
-
Generation of verification conditions **(VCs): taking a program and a specification for it, the tool generates a set of first-order proof obligations that are sufficient to prove the correctness of the program: if all the VCs are valid then the program is guaranteed to be correct w.r.t its specification
-
Interaction with proof tools: Why3 has interfaces allowing it to use as background every popular first-order proof tool (including SMT solvers and interactive theorem provers). The tool will send proof obligations to any tool present in a given installation
-
Additionally, the Why3 IDE offers very useful functionality including syntax highlighting (very useful to associate VCs with the parts of the code from which they were generated), convenient access to proof transformations, and proof management (including storing and replaying proof sessions)
Note
Previously in this course the Alloy tool was also used for formal verification. However, in Alloy the word verification is used as a synonym for model checking (algorithmic state space exploration), whereas in Why3 it is based on actual deductive proofs. Moreover, Alloy targets systems specified at an abstract level, whereas Why3 is used to verify algorithms
Why3 as a Proof Tool
Although this was probably not the original intention, Why3 has become popular as a proof tool on its own (its logic functionality is also accessible through an API).
This is due to the extremely convenient interfacing with external proof tools, and also to the features of the logic language, which extends standard FOL with a set of features that are highly convenient for applications in computer science.
The logic language includes:
-
user-defined types, including algebraic (inductive), and polymorphic types
-
defined predicates and functions, including inductive and polymorphic definitions
-
inductive predicates, defined in a closed way by a set of inference rules
-
a rich logic library of theories, including (but not only) types that are particularly suited in the context of computer programming
It is possible, for instance, to define a type of binary trees and then define a recursive predicate stating when such a tree is a binary search tree (i.e. it is sorted inorder).
Example: Class Assignment (from Ficha 1)
Recall the assignment:
In a training course there are 5 consecutive classes and 3 teachers (Ana, Beatriz and Carlos), all capable of teaching any class. We want to allocate the teachers to different classes, subject to the following restrictions:
- Carlos can’t teach the first class
- If Beatriz teaches the first class, she cannot teach the last one
- Each class is assigned at least one teacher
- Each of the first four classes is taught by at most one teacher
- The last class can be taught by at most two teachers
- No teacher can teach 4 consecutive classes
The following is an encoding of this problem in the Why3 logic. The example illustrates:
- The use of enumerated (algebraic) types (for classes and teachers). An equality predicate is automatically made available
- The use of a declared predicate (teaches)
-
Axioms involving universal and existential quantifiers
module Classes
type class = ClassOne | ClassTwo | ClassThree | ClassFour | ClassFive type teacher = Ana | Beatriz | Carlos predicate teaches (teacher) (class) axiom A1 : not teaches Carlos ClassOne axiom A2 : teaches Beatriz ClassOne -> not teaches Beatriz ClassFive axiom A3 : forall c :class. teaches Ana c \/ teaches Beatriz c \/ teaches Carlos c axiom A4 : forall c :class, t1 t2 :teacher. c <> ClassFive /\ teaches t1 c /\ teaches t2 c -> t1 = t2 axiom A5 : forall t1 t2 t3 :teacher. teaches t1 ClassFive /\ teaches t2 ClassFive /\ teaches t3 ClassFive -> t3 = t2 \/ t3 = t1 axiom A6 : forall t :teacher. teaches t ClassTwo /\ teaches t ClassThree /\ teaches t ClassFour -> not teaches t ClassOne /\ not teaches t ClassFive goal g : teaches Beatriz ClassFive -> teaches Ana ClassOne goal gA3 : forall c :class. exists t :teacher. teaches t c goal SAT : false
end
[Try this example online here]
Unlike an SMT solver, Why3 works with validity rather than satisfiability. The above module contains two goals; Why3 will generate a proof obligation for each one of them, that will be encoded and dispatched to an external proof tool.
Proving that a goal follows from the axioms is a consequence problem; it will be encoded as a satisfiability problem if it is dispatched to an SMT solver.
**goal**
g : teaches Beatriz ClassFive -> teaches Ana ClassOne
states that it follows from the axioms that if Beatriz teaches ClassFive then it must be the case that Ana teaches ClassOne.
Why3 includes a number of automated strategies that will attempt to prove goals by performing simple proof transformations (such as splitting goals into smaller formulas) and sending the resulting proof obligations in turn to several SMT solvers, if more than one is available.
The line **goal**
SAT : false
may seem strange; its purpose is to try to establish that there exists at least one model for the theory defined by the previous axioms — if solvers fail to prove the goal and find a counterexample for it, then the theory is not inconsistent.
When solvers find them, Why3 allows for counter-examples to be displayed. In the above example, for instance the Z3 solver will find a counter-example, which corresponds to a model, i.e. an actual assignment of teachers to classes.
Underneath, what Z3 is doing is exactly what we did manually in a previous class, when we solved this puzzle by interacting with Z3 via its Python API.
The online version of Why3 contains a single SMT solver (Alt-Ergo). It allows the user to split goals and increase the time limit allowed to the solver for each goal. This web version does not allow for counter-examples to be inspected.
Example: Class Assignment — alternative encoding
Let us give a second encoding of the same puzzle to illustrate the use of logic functions and of a library theory for sets.
The idea is that the function teachers
associates to each class the set of teachers assigned to teach it; the axioms are then written in terms of these sets, using the operators mem
, inter
, is_empty
and cardinal
(note that the latter requires importing a specific library module, as well as [int.Int](https://why3.lri.fr/stdlib/int.html)
for integer numbers) .
module Classes_alt
use set.Set
use set.Cardinal
use int.Int
type class = ClassOne | ClassTwo | ClassThree | ClassFour | ClassFive
type teacher = Ana | Beatriz | Carlos
function teachers (class) : set teacher
axiom A1 : not mem Carlos (teachers ClassOne)
axiom A2 : not mem Beatriz (inter (teachers ClassOne) (teachers ClassFive))
axiom A3 : forall c :class. not is_empty (teachers c)
axiom A4 : forall c :class. c <> ClassFive -> cardinal (teachers c) <= 1
axiom A5 : cardinal (teachers ClassFive) <= 2
axiom A6 : forall t :teacher.
mem t (teachers ClassTwo) /\
mem t (teachers ClassThree) /\
mem t (teachers ClassFour) ->
not mem t (teachers ClassOne) /\ not mem t (teachers ClassFive)
goal SAT : false
goal g : mem Beatriz (teachers ClassFive) -> mem Ana (teachers ClassOne)
end
[Try this example online here]
Advanced Features of Why3
(things we will not be looking at)
- An important feature of Why3 is the interplay between the programming and logic languages. For instance,
- it is possible to define logic functions using programming constructs
- it is possible to write proof scripts using programming constructs (using lemma functions, very useful to conduct proofs by induction)
- It is possible to extract working programs (written in either OCaml or C) from verified WhyML programs