Section: Scientific Foundations
Most of our research, and in particular controller synthesis and conformance testing, relies on the ability to solve some verification problems. A large part of these problems reduces to reachability and coreachability problems on a formal model (a state s is reachable from an initial state si if an execution starting from si can lead to s; s is coreachable from a final state sf if an execution starting from s can lead to sf ). These are important cases of verification problems, as they correspond to the verification of safety properties.
Verification in its full generality consists in checking that a system, which is specified in a formal model, satisfies a required property. When the state space of the system is finite and not too large, verification can be carried out by graph algorithms (model-checking). For large or infinite state spaces, we can perform approximate computations, either by computing a finite abstraction and resort to graph algorithms, or preferably by using more sophisticated abstract interpretation techniques. Another way to cope with large or infinite state systems is deductive verification, which, either alone or in combination with compositional and abstraction techniques, can deal with complex systems that are beyond the scope of fully automatic methods.
Abstract interpretation and Data Handling
The techniques described above, which are dedicated to the analysis of LTS , are already mature. It seems natural to extend them to IOSTS or data-flow applications that manipulate variables taking their values into possibly infinite data domains.
The techniques we develop for test generation or controller synthesis require to solve state reachability and state coreachability problems which can be solved by fixpoint computations (and also by deductive methods).
The big change induced by taking into account the data and not only the (finite) control of the systems under study is that the fixpoints become uncomputable. The undecidability is overcome by resorting to approximations, using the theoretical framework of Abstract Interpretation  .
Abstract Interpretation is a theory of approximate solving of fixpoint equations applied to program analysis. Most program analysis problems, among others reachability analysis, come down to solving a fixpoint equation
where C is a lattice. In the case of reachability analysis, if we denote by S the state space of the considered program, C is the lattice (S) of sets of states, ordered by inclusion, and F is roughly the ``successor states '' function defined by the program.
The exact computation of such an equation is generally not possible for undecidability (or complexity) reasons. The fundamental principles of Abstract Interpretation are:
to substitute to the concrete domain C a simpler abstract domain A (static approximation) and to transpose the fixpoint equation into the abstract domain, so that one has to solve an equation y = G(y), yA ;
to use a widening operator (dynamic approximation) to make the iterative computation of the least fixpoint of G converge after a finite number of steps to some upper-approximation (more precisely, a post-fixpoint).
Approximations are conservative so that the obtained result is an upper-approximation of the exact result. Those two principles are well illustrated by the Interval Analysis  , which consists in associating to each numerical variable of a program an interval representing an (upper) set of reachable values:
One substitutes to the concrete domain (Rn) induced by the numerical variables the abstract domain (IR)n , where IR denotes the set of intervals on real numbers; a set of values of a variable is then represented by the smallest interval containing it;
An iterative computation on this domain may not converge: it is indeed easy to generate an infinite sequence of intervals which is strictly growing. The ``standard'' widening operator extrapolates by + the upper bound of an interval if the upper bound does not stabilize within a given number of steps (and similarly for the lower bound).
In this example, the state space (Rn) that should be abstracted has a simple structure, but this may be more complicated when variables belong to different data types (Booleans, numerics, arrays) and when it is necessary to establish relations between the values of different types.
Programs performing dynamic allocation of objects in memory have an even more complex state space. Solutions have been devised to represent in an approximate way the memory heap and pointers between memory cells by graphs (shape analysis  ,  ). Values contained in memory cells are however generally ignored.
In the same way, programs with recursive procedure calls, parameter passing and local variables are more delicate to analyse with precision. The difficulty is to abstract the execution stacks which may have a complex structure, particularly when parameters passing by reference are allowed, as it induces aliasing on the stack  .
For verification we also use theorem proving and more particularly the pvs  and Coq  proof assistants. These are two general-purpose systems based on two different versions of higher-order logic. A verification task in such a proof assistant consists in encoding the system under verification and its properties into the logic of the proof assistant, together with verification rules that allow to prove the properties. Using the rules usually requires input from the user; for example, proving that a state predicate holds in every reachable state of the system (i.e., it is an invariant ) typically requires to provide a stronger, inductive invariant, which is preserved by every execution step of the system. Another type of verification problem is proving simulation between a concrete and an abstract semantics of a system. This too can be done by induction in a systematic manner, by showing that, in each reachable state of the system, each step of the concrete system is simulated by a corresponding step at the abstract level.