The overall aim of this thesis is the development of mathematically sound and practically e cient methods for automatically proving the correctness of computer software. More specifically, this thesis is grounded in the theory of Abstract Interpretation, a powerful mathematical framework for approximating the behavior of programs. In particular, this thesis focuses on proving program liveness properties, which represent requirements that must be eventually or repeatedly realized during program execution.

Program termination is the most prominent liveness property. This thesis designs new program approximations, in order to automatically infer sucient preconditions for program termination and synthesize so called piecewisedefined ranking functions, which provide upper bounds on the waiting time before termination. The approximations are parametric in the choice between the expressivity and the cost of the underlying approximations, which maintain information about the set of possible values of the program variables along with the possible numerical relationships between them. This thesis also contributes an abstract interpretation framework for proving liveness properties, which comes as a generalization of the framework proposed for termination. In particular, the framework is dedicated to liveness properties expressed in temporal logic, which are used to ensure that some desirable event happens once or infinitely many times during program execution. As for program termination, piecewise-defined ranking functions are used to infer su cient preconditions for these properties, and to provide upper bounds on the waiting time before a desirable event.

The results presented in this thesis have been implemented into a prototype analyzer. Experimental results show that it performs well on a wide variety of benchmarks, it is competitive with the state of the art, and is able to analyze programs that are out of the reach of existing methods.

Les résultats présentés dans cette thèse ont été mis en oeuvre dans un prototype d'analyseur. Les résultats expérimentaux montrent qu'il donne de bons résultats sur une grande variété de programmes, il est compétitif avec l'état de l'art, et il est capable d'analyser des programmes qui sont hors de la portée des méthodes existantes.

Résumé

L'objectif général de cette thèse est le développement de méthodes mathématiques correctes et e caces en pratique pour prouver automatiquement la correction de logiciels. Plus précisément, cette thèse est fondée sur la théorie de l'Interprétation Abstraite, un cadre mathématique puissant pour l'approximation du comportement des programmes. En particulier, cette thèse se concentre sur la preuve des propriétés de vivacité des programmes, qui représentent des conditions qui doivent être réalisés ultimement ou de manière répétée pendant l'exécution du programme.

La terminaison des programmes est la propriété de vivacité la plus fréquement considérée. Cette thèse conçoit des nouvelles approximations, afin de déduire automatiquement des conditions su santes pour la terminaison des programmes et synthétiser des fonctions de rang définies par morceaux, qui fournissent des bornes supérieures sur le temps d'attente avant la terminaison. Les approximations sont paramétriques dans le choix entre l'expressivité et le coût des approximations sous-jacentes, qui maintiennent des informations sur l'ensemble des valeurs possibles des variables du programme ainsi que les relations numériques possibles entre elles.

Cette thèse développe également un cadre d'interprétation abstraite pour prouver des propriétés de vivacité, qui vient comme une généralisation du cadre proposé pour la terminaison. En particulier, le cadre est dédié à des propriétés de vivacité exprimées dans la logique temporelle, qui sont utilisées pour s'assurer qu'un événement souhaitable se produit une fois ou une infinité de fois au cours de l'exécution du programme. Comme pour la terminaison, des fonctions de rang définies par morceaux sont utilisées pour déduire des préconditions su santes pour ces propriétés, et fournir des bornes supérieures sur le temps d'attente avant un événement souhaitable. In the last decades, software took a growing importance into all kinds of systems. As we rely more and more on software, the consequences of a bug are more and more dramatic, causing great financial and even human losses. A notorious example is the spectacular Ariane 5 failure 1 caused by an integer overflow, which resulted in more than $370 million loss. More recent examples are the Microsoft Zune Z2K bug 2 and the Microsoft Azure Storage service interruption 3 both due to non-termination, the Toyota unintended acceleration 4 caused by a stack overflow, and the Heartbleed security bug 5 .

Testing

The most widespread (and in many cases the only) method used to ensure the quality of software is testing. Many testing methods exist, ranging from blackbox and white-box testing to unit and integration testing. They all consist in executing parts or the whole of the program with selected or random inputs in a controlled environment, while monitoring its execution or its output. Achieving an acceptable level of confidence with testing is generally costly and, even then, testing cannot completely eliminate bugs. Therefore, while in some cases it is acceptable to ship potentially erroneous programs and rely on regular updates to correct them, this is not the case for mission critical software which cannot be corrected during missions.

Formal Methods

Formal methods, on the other hand, try to address these problems by providing rigorous mathematical guarantees that a program preserves certain properties. The idea of formally discussing about programs dates back from the early history of computer science: program proofs and invariants are attributed to Robert W. Floyd [START_REF] Floyd | Assigning Meanings to Programs[END_REF] and Tony Hoare [START_REF] Antony | An Axiomatic Basis for Computer Programming[END_REF] in the late 1960s, but may be latent in the work of Alan Turing in the late 1940s [START_REF] Turing | Checking a Large Routine[END_REF][START_REF] Morris | An Early Program Proof by Alan Turing[END_REF]. Current methods can be classified into three categories [START_REF] Cousot | A Gentle Introduction to Formal Verification of Computer Systems by Abstract Interpretation[END_REF]: deductive methods, model checking, and static analysis.

Formal deductive methods employ proof assistants such as Coq [START_REF] Bertot | Interactive Theorem Proving and Program Development[END_REF], or theorem provers such as PVS [START_REF] Owre | PVS: A Prototype Verification System[END_REF] to prove the correctness of programs. These methods rely on the user to provide the inductive arguments needed for the proof, and sometimes to interactively direct the proof itself.

Formal methods based on model checking [START_REF] Clarke | Design and Synthesis of Synchronization Skeletons using Branching-Time Temporal Logic[END_REF][START_REF] Queille | Specification and Verification of Concurrent Systems in CESAR[END_REF] explore exhaustively and automatically finite models of programs so as to determine whether undesirable error states are accessible. Various successful model checking algorithms based on SAT-solving, such as IC3 [START_REF] Bradley | SAT-Based Model Checking without Unrolling[END_REF], have been developed to complement the traditional model checking based on Binary Decision Diagrams [START_REF] Bryant | Graph-based Algorithms for Boolean Function Manipulation[END_REF]. A major di culty of this approach is to synthesize the model from the program and the property to check. In particular, the size of the model is critical for the checking phase to be practical.

Formal static analysis methods analyze directly and without user intervention the program source code at some level of abstraction. Due to decidability and e ciency concerns, the abstraction is incomplete and can result in false alarms or false positives (that is, correct programs may be reported as incorrect) but never false negatives. The programs that are reported as correct are indeed correct despite the approximation. The most prominent static analysis methods are based on Abstract Interpretation [START_REF] Cousot | Abstract Interpretation: a Unified Lattice Model for Static Analysis of Programs by Construction or Approximation of Fixpoints[END_REF].

Abstract Interpretation. Abstract Interpretation [START_REF] Cousot | Abstract Interpretation: a Unified Lattice Model for Static Analysis of Programs by Construction or Approximation of Fixpoints[END_REF] is a general theory for approximating the behavior of programs, developed by Patrick Cousot and Radhia Cousot in the late 1970s, as a unifying framework for static program analysis. It stems from the observation that, to reason about a particular program property, it is not necessary to consider all aspects and details of the program behavior. In fact, reasoning is facilitated by the design of a welladapted semantics, abstracting away from irrelevant details. Therefore, there 1.2. Program Properties is no universal general-purpose program semantics but rather a wide variety of special-purpose program semantics, each one of them dedicated to a particular class of program properties and reduced to essentials in order to ignore irrelevant details about program executions.

In the past decade, abstract interpretation-based static analyzers began to have an impact in real-world software development. This is the case, for instance, of the static analyzer Astrée [BCC + 10], which is used daily by industrial end-users in order to prove the absence of run-time errors in embedded synchronous C programs. In particular, by carefully designing the abstractions used for the analysis, Astrée has been successfully used to prove, with zero false alarm, the absence of run-time errors in the primary flight control software of the fly-by-wire systems of the Airbus A340 and A380 airplanes.

We provide a formal introduction to Abstract Interpretation in Chapter 2 and we recall the main results used in this thesis, which are later illustrated on a small idealized programming language in Chapter 3.

Program Properties

Leslie Lamport, in the late 1970s, suggested a classification of program properties into the classes of safety and liveness properties [START_REF] Lamport | Proving the Correctness of Multiprocess Programs[END_REF]. Each class encompasses properties of similar character, and every program property can be expressed as the intersection of a safety and a liveness property.

Safety Properties

The class of safety properties is informally characterized as the class of properties stating that "something bad never happens", that is, a program never reaches an unacceptable state.

Safety properties represent requirements that should be continuously maintained by the program. Indeed, in order to prove safety properties, an invariance principle [START_REF] Floyd | Assigning Meanings to Programs[END_REF] can be used. A counterexample to a safety property can always be witnessed by observing finite (prefixes of) program executions.

Examples of safety properties include program partial correctness, which guarantees that all terminating computations produce correct results, and mutual exclusion, which guarantees that no two concurrent processes enter their critical section at the same time.

1. Introduction

Liveness Properties

The class of liveness properties, on the other hand, is informally characterized as the class of properties stating that "something good eventually happens", that is, a program eventually reaches a desirable state.

Liveness properties typically represent requirements that need not hold continuously, but whose eventual or repeated realization must be guaranteed. They are usually proved by exhibiting a well-founded argument, often called ranking function, which provides a measure of the distance from the realization of the requirement [START_REF] Turing | Checking a Large Routine[END_REF][START_REF] Floyd | Assigning Meanings to Programs[END_REF]. Note that, a counterexample to a liveness property cannot be witnessed by observing finite program executions since these can always be extended in order to satisfy the liveness property.

Examples of liveness properties are program termination, which guarantees that all program computations are terminating, and starvation freedom, which guarantees that a process will eventually enter its critical section.

Termination

The halting problem, the problem of determining whether a given program will always finish to run or could potentially execute forever, rose to prominence before the invention of programs or computers, in the era of the Entscheidungsproblem posed by David Hilbert: the challenge to formalize all mathematics into logic and use mechanical means to determine the validity of mathematical statements. In hopes of either solving the challenge, or showing it impossible, logicians and mathematicians began to search for possible instances of undecidable problems. The undecidability of the halting problem, proved by Alan Turing [START_REF] Turing | On Computable Numbers, with An Application to the Entscheidungs Problem[END_REF], is the most famous of those findings. In Appendix A.1, we propose a proof of the undecidability of the halting problem reinterpreted by the linguist Geo↵rey K. Pullum.

However, relaxing the halting problem by asking for a sound but not necessarily complete solution, allows us to overcome the barrier of its undecidability. Indeed, in the recent past, termination analysis has benefited from many research advances and powerful termination provers have emerged over the years [BCF13, CPR06, GSKT06, HHLP13, [START_REF] Le | Termination and Non-Termination Specification Inference[END_REF]etc.]. This thesis stems from [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF], where Patrick Cousot and Radhia Cousot proposed a unifying point of view on the existing approaches for proving program termination, and introduced the idea of the inference of a ranking function by abstract interpretation. We recall and revise their work in Chapter 4.

Liveness Properties

Chapter 5 and Chapter 6 are devoted to the construction of new abstractions dedicated to program termination. More precisely, Chapter 5 presents abstractions based on piecewise-defined ranking functions, while Chapter 6 presents abstractions based on ordinal-valued ranking functions. Some of the results described in Chapter 5 and Chapter 6 have been the subject of publications in international workshops and conferences [Urb13a, Urb13b, UM14a, UM14c, UM14b] and are presented here with many extensions. In Chapter 7, we detail how these abstractions can be used for proving termination of recursive programs. The implementation of our prototype static analyzer [START_REF] Urban | FuncTion: An Abstract Domain Functor for Termination (Competition Contribution)[END_REF] and the most recent experimental evaluation [START_REF] Vijay | Conflict-Driven Abstract Interpretation for Conditional Termination[END_REF] are described in Chapter 8.

Liveness Properties

For reactive programs, which may never terminate, the spectrum of relevant and useful liveness properties is much richer than the single property of termination. For example, it also includes the guarantee that a certain event occurs infinitely many times.

In general, these liveness properties are satisfied only under fairness hypotheses, that is, a restriction on some infinite behavior according to eventual occurrence of some events. A common property of these fairness notions is that they all imply that, under certain conditions, each of a number of alternative or competing events occur infinitely often in every infinite behavior of the system considered. Nissim Francez distinguishes three main subclasses, depending on the condition guaranteeing the eventual occurrence [START_REF] Francez | Fairness[END_REF]: unconditional fairness guarantees that for each behavior each event occurs infinitely often without any further condition; weak fairness implies that an event will not be indefinitely postponed provided that it remains continuously enabled; and strong fairness guarantees eventual occurrence under the condition of being enabled infinitely often, but not necessarily continuously.

In Chapter 9, we generalize the abstract interpretation framework proposed for termination by Patrick Cousot and Radhia Cousot [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF], to other liveness properties. In particular, we focus on two classes of program properties proposed by Zohar Manna and Amir Pnueli [START_REF] Manna | A Hierarchy of Temporal Properties[END_REF]: the class of guarantee properties informally characterized as the class of properties stating that "something good happens at least once", and the class of recurrence properties informally characterized as the class of properties stating that "something good happens infinitely often". In order to e↵ectively prove these properties 1. Introduction we reuse the abstractions proposed in Chapter 5 and Chapter 6. The results described in Chapter 9 have been published in [START_REF] Urban | Proving Guarantee and Recurrence Temporal Properties by Abstract Interpretation[END_REF].

Note that the guarantee provided by liveness properties that something good will eventually happen is not enough for mission critical software, where some desirable event is required to occur within a certain time bound. Indeed, these real-time properties are considered safety properties, and there is a general consensus against the interest of proving liveness properties for mission critical software. However, specifying and verifying real-time properties can be cumbersome, while liveness properties provide a nice approximation, without distracting timing assumptions, of real-time properties. The well-founded measures used to prove these liveness properties can then be mapped back to a real-time duration. In particular, this is the premise of ongoing research work conducted at NASA Ames Research Center where some of the theoretical work presented in this thesis is being used for the verification of avionics software.

We envision further future directions in Chapter 10.

II Safety

Basic Notions and Notations

In the following, we briefly recall well-known mathematical concepts in order to establish the notation used throughout this thesis.

Sets. A set S is defined as an unordered collection of distinct elements. We write s 2 S (resp. s 6 2 S) when s is (resp. is not) an element of the set S. A set is expressed in extension when it is uniquely identified by its elements: we write {a, b, c} for the set of elements a, b and c. The empty set is denoted by ;. A set is expressed in comprehension when its elements are specified through a shared property: we write {x 2 S | P (x)} for the set of elements x of the set S for which P (x) is true. The cardinality of a set S is denoted by |S|.

A set S is a subset of a set S 0 , written S ✓ S 0 , if and only if every element of S is an element of S 0 . The empty set is a subset of every set. The power set P(S) of a set S is the set of all its subsets: P(S)

• • • ⇥ S n def = {hx 1 , . . . , x n i | x 1 2 S 1 ^• • • ^xn 2 S n } and S n def = {hx 1 , . . . , x n i | x 1 2 S ^• • • ^xn 2 S}
is the set of n-tuples of elements of S. A covering of a set S is a set P of non-empty subsets of S such that any element s 2 S belongs to a set in P: S = S P. A partition of a set S is a covering P such that any two sets in P are disjoint, that is, any element s 2 S belongs to a unique set in P: 8X, Y 2 P : X 6 = Y ) X \ Y = ;.

Relations. A binary relation R between two sets A and B is a subset of the cartesian product A ⇥ B. We often write x R y for hx, yi 2 R.

The following are some important properties which may hold for a binary relation R over a set S: 8x 2 S : x R x (reflexivity) 8x 2 S : ¬(x R x) ( i r r e fl e x i v i t y ) 8x, y 2 S : x R y ) y R x (symmetry) 8x, y 2 S : x R y ^y R x ) x = y (anti-symmetry) 8x, y, z 2 S : x R y ^y R z ) x R z (transitivity) 8x, y 2 S : x R y _ y R x (totality)

An equivalence relation is a binary relation which is reflexive, symmetric, and transitive. A binary relation which is reflexive (resp. irreflexive), antisymmetric, and transitive is called a partial order (resp. strict partial order ). A preorder is reflexive and transitive, but not necessarily anti-symmetric. A (strict) total order is a (strict) partial order which is total.

Ordered Sets. A partially ordered set or poset (resp. preordered set) hD, vi is a set D equipped with a partial order (resp. preorder) v. A finite partially ordered set hD, vi can be represented by a Hasse diagram such as the one in Figure 2.1: each element x 2 D is uniquely represented by a node of the diagram, and there is an edge from a node x 2 D to a node y 2 D if y covers x, that is, x  y and there exists no z 2 D such that x  z  y. Hasse diagrams are usually drawn placing the elements higher than the elements they cover.

Let hD, vi be a partially ordered set. The least element of the poset, when it exists, is denoted by ?: 8d 2 D : ? v d. Similarly, the greatest element of the poset, when it exists, is denoted by >: 8d 2 D : d v >. Note that any partially ordered set can always be equipped with a least (resp. greatest) element by adding a new element that is smaller (resp. greater) than every other element. Let X ✓ D. A maximal element of X is an element d 2 X such that, for each x 2 X , x v d. When X has a unique maximal element, it is called maximum and it is denoted by max X . Dually, a minimal element of X is an element d 2 X such that, for each x 2 X , d v x. When X has a unique minimal element, it is called minimum and it is denoted by min X . An upper bound of X is an element d 2 D (not necessarily belonging to X ) such that, for each x 2 X , x v d. The least upper bound (or lub, or supremum) of X is an upper bound d 2 D of X and such that, for every upper bound d 0 2 D of X , d v d 0 . When it exists, it is unique and denoted by F X (or sup X ). Dually, a lower bound of X is an element d 2 D such that, for each x 2 X , d v x. The greatest lower bound (or glb, or infimum) of X is a lower bound d 2 D of X such that, for every lower bound d 0 2 D of X , d 0 v d. When it exists, it is unique and denoted by d X (or inf X ). Note that, the notion of maximal element, maximum, and least upper bound (resp. minimal element, minimum, and greatest lower bound) are di↵erent, as illustrated by the following example. = {{a}, {b}, {c}, {a, b}, {a, c}, {b, c}}. The maximal elements of X are {a, b}, {a, c}, and {b, c}. Thus the maximum max X of X does not exist, while its least upper bound is sup X = {a, b, c}. Similarly, the minimal elements of X are {a}, {b}, and {c}. Thus, the minimum min X of X does not exist, while its greatest lower bound is inf X = ;.

A set equipped with a total order is a totally ordered set. A totally ordered subset C of a partially ordered set hD, vi is called a chain. A partially ordered set hD, vi satisfies the ascending chain condition (ACC) if and only if any infinite increasing chain

x 0 v x 1 v • • • v x n v • • • of elements of D is not strictly increasing, that is, 9k 0 : 8j k : x k = x j .
Dually, a partially ordered set hD, vi satisfies the descending chain condition (DCC) if and only if any infinite decreasing chain x 0 w x 1 w • • • w x n w • • • of elements of D is not strictly decreasing, that is, 9k 0 : 8j k : x k = x j . A complete partial order or cpo hD, vi is a poset where every chain C has a least upper bound F C, which is called the limit of the chain. Note that, since the empty set ; is a chain, a complete partial order has a least element ? = F ;. Thus, a partially ordered set that satisfies the ascending chain condition and that is equipped with a least element, is a complete partial order.

Lattices. A lattice hD, v, t, ui is a poset where each pair of elements x, y 2 D has a least upper bound, denoted by x t y, and a greatest lower bound, denoted by x u y. Any totally ordered set is a lattice. A complete lattice hD, v, t, u, ?, >i is a lattice where any subset X ✓ D has a least upper bound F X and a greatest lower bound d X . A complete lattice has both a least element ? Example 2.1.2

The power set hP(S), ✓, [, \, ;, Si of any set S is a complete lattice.

Functions. A partial function f from a set A to a set B, written f : A * B, is a binary relation between A and B that pairs each element x 2 A with no more than one element y 2 B. The set of all partial functions from a set A to a set B is denoted by A * B. We write f (x) = y if there exists an element y such that hx, yi 2 f , and we say that f (x) is defined, otherwise we say that f (x) is undefined. Given a partial function f : A * B, we define its domain as dom(f ) def = {x 2 A | 9y 2 B : f (x) = y}. The totally undefined function, denoted by ;, has the empty set as domain: dom( ;) = ;. The join of two partial functions f 1 : A * B and f 2 : A * B with disjoint domains, denoted by f 1 [ f 2 : A * B, is defined as follows:

f 1 [ f 2 def = x 2 A. 8 > < > : f 1 (x)
x 2 dom(f 1 ) f 2 (x)

x 2 dom(f 2 ) undefined otherwise where dom(f 1 ) \ dom(f 2 ) = ;.

A (total ) function f from a set A to a set B, written f : A ! B, is a partial function that pairs each x 2 A with exactly one element y 2 B. Equivalently, a (total) function f : A ! B is a partial function such that dom(f ) = A. The set of all functions from a set A to a set B is denoted by A ! B.

We sometimes denote functions using the lambda notation x 2 A. f(x), or more concisely x. f (x).

The composition of two functions f : A ! B and g : B ! C is another function g f : A ! C such that 8x 2 A : (g f )(x) = g(f (x)).

The following properties may hold for a function f : A ! B: 8x, y 2 A : f (x) = f (y) ) x = y (injectivity) 8y 2 B : 9x 2 A : f (x) = y (surjectivity)

A bijective function, also called isomorphism, is both injective and surjective. Two sets A and B are isomorphic if there exists a bijective function f : A ! B. The inverse of a bijective function f : A ! B is the bijective function

f 1 : B ! A defined as f 1 def = {hb, ai | ha, bi 2 f }.
Let hD 1 , v 1 i and hD 2 , v 2 i be partially ordered sets. A function f : D 1 ! D 2 is said to be monotonic when, for each x, y 2 D 1 , x v 1 y ) f (x) v 2 f (y). It is continuous (or Scott-continuous) when it preserves existing least upper bounds of chains, that is, for each chain

C ✓ D 1 , if F C exists then f ( F C) = F {f (x) | x 2 C}.
Dually, it is co-continuous when it preserves existing greatest lower bounds of chains, that is, if

d C exists then f ( d C) = d {f (x) | x 2 C}.
A complete t-morphism (resp. complete u-morphism) preserves existing least upper bounds (resp. greatest lower bounds) of arbitrary non-empty sets.

Pointwise Lifting. Given a complete lattice hD, v, t, u, ?, >i (resp. a lattice, a cpo, a poset) and a set S, the set S ! D of all functions from S to D inherits the complete lattice (resp. lattice, cpo, poset) structure of D: hS ! 2. Abstract Interpretation D, v, ṫ, u, ?, >i where the dotted operators are defined by pointwise lifting:

f v g def = 8s 2 S : f (s) v g(s) Ġ X def = s. G {f (s) | f 2 X } l X def = s. l {f (s) | f 2 X } ? def = s. ? > def = s. > (2.1.1)
Ordinals. The theory of ordinals was introduced by Georg Cantor as the core of his set theory [START_REF] Cantor | Beiträge zur Begründung der Transfiniten Mengenlehre[END_REF][START_REF] Cantor | Beiträge zur Begründung der Transfiniten Mengenlehre[END_REF].

A binary relation R over a set S is well-founded when every non-empty subset of S has a least element with respect to R. A well-founded total order is called a well-order (or a well-ordering). A well-ordered set hW, i is a set W equipped with a well-ordering . Every well-ordered set is associated with a so-called ordered type. Two well-ordered sets hA,  A i and hB,  B i are said to have the same order type if they are order-isomorphic, that is, if there exists a bijective function f : A ! B such that, for all elements x, y 2 A, x  A y if and only if f (x)  B f (y).

An ordinal is defined as the order type of a well-ordered set and it provides a canonical representative for all well-ordered sets that are order-isomorphic to that well-ordered set. We use lower case Greek letters to denote ordinals. In fact, a well-ordered set hW, i with order type ↵ is order-isomorphic to the well-ordered set {x 2 W | x < ↵} of all ordinals strictly smaller than the ordinal ↵ itself. In particular, as suggested by John von Neumann [vN23], this property permits to define each ordinal as the well-ordered set of all ordinals that precede it: the smallest ordinal is the empty set ;, denoted by 0. The successor of an ordinal ↵ is defined as ↵ [ {↵} and is denoted by ↵ + 1, or equivalently, by succ(↵). Thus, the first successor ordinal is {0}, denoted by 1. The next is {0, 1}, denoted by 2. Continuing in this manner, we obtain all natural numbers, that is, all finite ordinals. A limit ordinal is an ordinal number which is neither 0 nor a successor ordinal. The set N of all natural numbers, denoted by !, is the first limit ordinal and the first transfinite ordinal.

We use hO, i to denote the well-ordered set of ordinals. In the following, we will see that the theory of ordinals is the most general setting for proving program termination.

Fixpoints. Given a partially ordered set hD, vi and a function f : D ! D, a fixpoint of f is an element x 2 D such that f (x) = x. An element x 2 D such that x v f (x) is called a pre-fixpoint while, dually, a post-fixpoint is an element x 2 D such that f (x) v x. The least fixpoint of f , written lfp f , is a fixpoint of f such that, for every fixpoint x 2 D of f , lfp f v x. We write lfp d f for the least fixpoint of f which is greater than or equal to an element d 2 D. Dually, we define the greatest fixpoint of f , denoted by gfp f , and the greatest fixpoint of f smaller than or equal to d 2 D, denoted by gfp d f . When the order v is not clear from the context, we explicitly write lfp v f and gfp v f . We now recall a fundamental theorem due to Alfred Tarski [START_REF] Tarski | A lattice-theoretical fixpoint theorem and its applications[END_REF]:

Theorem 2.1.3 (Tarski's Fixpoint Theorem) The set of fixpoints of a monotonic function f : D ! D over a complete lattice is also a complete lattice.

Proof.

See [START_REF] Tarski | A lattice-theoretical fixpoint theorem and its applications[END_REF].

⌅

In particular, the theorem guarantees that f has a least fixpoint lfp f = d {x 2 D | f (x) v x} and a greatest fixpoint gfp f = F {x 2 D | x v f (x)}. However, such fixpoint characterizations are not constructive. An alternative constructive characterization is often attributed to Stephen Cole Kleene: Theorem 2.1.4 (Kleene's Fixpoint Theorem) Let hD, vi be a complete partial order and let f : D ! D be a Scott-continuous function. Then, f has a least fixpoint which is the least upper bound of the increasing chain ? v f (?) v f (f (?)) v f (f (f (?))) v . . . i.e., lfp f = F {f n (?) | n 2 N}.

In case of monotonic but not continuous functions, a theorem by Patrick Cousot and Radhia Cousot [START_REF] Cousot | Constructive Versions of Tarski's Fixed Point Theorems[END_REF] expresses fixpoints as limits of possibly transfinite iteration sequences: Theorem 2.1.5 Let f : D ! D be a monotonic function over a complete partial order and let d 2 D be a pre-fixpoint. Then, the iteration sequence:

f def = 8 > < > : d = 0 (zero case) f (f ↵ ) = ↵ + 1 (successor case) F {f ↵ | ↵ < } otherwise (limit case)
converges towards the least fixpoint lfp d f .

Transition Systems. The semantics of a program is a mathematical characterization of all possible behaviors of the program when executed for all possible input data. In order to be independent from the choice of a particular programming language, programs are often formalized as transition systems:

Definition 2.2.1 (Transition System) A transition system is a pair h⌃, ⌧ i where ⌃ is a (potentially infinite) set of states and the transition relation ⌧ ✓ ⌃ ⇥ ⌃ describes the possible transitions between states.

In a labelled transition system h⌃, A, ⌧ i, A is a set of actions that are used to label the transitions described by the transition relation ⌧ ✓ ⌃ ⇥ A ⇥ ⌃.

Note that this model allows representing programs with (possibly unbounded) non-determinism. In the following, in order to lighten the notation, a transition hs, s 0 i 2 ⌧ (resp. a labelled transition hs, a, s 0 i 2 ⌧ ) between a state s and another state s 0 is sometimes written as s ! s 0 (resp. s a ! s 0 ). In some cases, a set I ✓ ⌃ is designated as the set of initial states. The set of blocking or final states is ⌦ def = {s 2 ⌃ | 8s 0 2 ⌃ : hs, s 0 i 6 2 ⌧ }. We define the following functions to manipulate sets of program states. Definition 2.2.2 Given a transition system h⌃, ⌧ i, post : P(⌃) ! P(⌃) maps a set of program states X 2 P(⌃) to the set of their successors with respect to the program transition relation ⌧ :

post(X) def = {s 0 2 ⌃ | 9s 2 X : hs, s 0 i 2 ⌧ } (2.2.1)
Definition 2.2.3 Given a transition system h⌃, ⌧ i, pre : P(⌃) ! P(⌃) maps a set of program states X 2 P(⌃) to the set of their predecessors with respect to the program transition relation ⌧ :

pre(X) def = {s 2 ⌃ | 9s 0 2 X : hs, s 0 i 2 ⌧ } (2.2.2)
Definition 2.2.4 Given a transition system h⌃, ⌧ i, g post : P(⌃) ! P(⌃) maps a set of states X 2 P(⌃) to the set of states whose successors with respect to the program transition relation ⌧ are all in the set X:

g post(X) = ⌃\post(⌃\X) def = {s 0 2 ⌃ | 8s 2 ⌃ : hs, s 0 i 2 ⌧ ) s 2 X} (2.2.3)
Definition 2.2.5 Given a transition system h⌃, ⌧ i, f pre : P(⌃) ! P(⌃) maps a set of states X 2 P(⌃) to the set of states whose predecessors with respect to the program transition relation ⌧ are all in the set X:

f pre(X) = ⌃ \ pre(⌃ \ X) def = {s 2 ⌃ | 8s 0 2 ⌃ : hs, s 0 i 2 ⌧ ) s 0 2 X} (2.2.4)

Maximal Trace Semantics

The semantics generated by a transition system is the set of computations described by the transition system. We formally define this notion below.

Sequences. Given a set S, the set

S n def = {s 0 • • • s n 1 | 8i < n : s i 2
S} is the set of all sequences of exactly n elements from S. We write " to denote the empty sequence, i.e., S 0 , {"}.

In the following, let S ⇤ def = S n2N S n be the set of all finite sequences, S + def = S ⇤ \ S 0 be the set of all non-empty finite sequences, S ! be the set of all infinite sequences, S +1 def = S + [ S ! be the set of all non-empty finite or infinite sequences and S ⇤1 def = S ⇤ [ S ! be the set of all finite or infinite sequences of elements from S. In the following, in order to ease the notation, sequences of a single element s 2 S are often written omitting the curly brackets, e.g., we write s ! and s +1 instead of {s} ! and {s} +1 .

We write 0 (or • 0 ) for the concatenation of two sequences , 0 2 S +1 (with " = " = , and 0 = when 2 S ! ), T + def = T \ S + for the selection of the non-empty finite sequences of T ✓ S +1 , T ! def = T \ S ! for the selection of the infinite sequences of T ✓ S +1 and T ; T

0 def = { s 0 | s 2 S ^ s 2 T ^s 0 2 T 0 } [ T ! for the merging of sets of sequences T , T 0 ✓ S +1 .
Traces. Given a transition system h⌃, ⌧ i, a trace is a non-empty sequence of states in ⌃ determined by the transition relation ⌧ , that is, hs, s 0 i 2 ⌧ for each pair of consecutive states s, s 0 2 ⌃ in the sequence. Note that, the set of final states ⌦ and the transition relation ⌧ can be understood as a set of traces of length one and a set of traces of length two, respectively. The set of all traces generated by a transition system is called partial trace semantics: Definition 2.2.6 (Partial Trace Semantics) The partial trace semantics ⌧ +1 2 P(⌃ +1 ) generated by a transition system h⌃, ⌧ i is defined as follows:

⌧ +1 def = ⌧ + [ ⌧ !
where ⌧ + 2 P(⌃ + ) is the set of finite traces:

⌧ + def = [ n>0 {s 0 • • • s n 1 2 ⌃ n | 8i < n 1 : hs i , s i+1 i 2 ⌧ } and ⌧ ! 2 P(⌃ !
) is the set of infinte traces:

⌧ ! def = {s 0 s 1 • • • 2 ⌃ ! | 8i 2 N : hs i , s i+1 i 2 ⌧ } Example 2.2.7
Let ⌃ = {a, b} and ⌧ = {ha, ai, ha, bi}. The partial trace semantics generated by h⌃, ⌧ i is the set of traces a +1 [ a ⇤ b.

Maximal Trace Semantics. In practice, given a transition system h⌃, ⌧ i, and possibly a set of initial states I ✓ ⌃, the traces worth of consideration (start by an initial state in I and) either are infinite or terminate with a final state in ⌦. These traces define the maximal trace semantics ⌧ +1 2 P(⌃ +1 ) and represent infinite computations or completed finite computations:

Definition 2.2.8 (Maximal Trace Semantics) The maximal trace semantics ⌧ +1 2 P(⌃ +1 ) generated by a transition system h⌃, ⌧ i is defined as:

⌧ +1 def = ⌧ + [ ⌧ !
where ⌧ + 2 P(⌃ + ) is the set of finite traces terminating with a final state in ⌦:

⌧ + def = [ n>0 {s 0 • • • s n 1 2 ⌃ n | 8i < n 1 : hs i , s i+1 i 2 ⌧, s n 1 2 ⌦} Example 2.2.9
The maximal trace semantics generated by the transition system h⌃, ⌧ i of Example 2.2.7 is the set of traces a ! [ a ⇤ b. Note that, unlike the partial trace semantics of Example 2.2.7, the maximal trace semantics does not represent partial computations, i.e., finite sequences of a 2 ⌃.

In practice, in case a set of initial states I ✓ ⌃ is given, only the traces starting from an initial state s 2 I are considered:

{s 2 ⌧ +1 | s 2 I}.
Remark 2.2.10 It is worth mentioning that not all program semantics are directly generated by a transition system. For example, this is the case of the semantics of programs where the future evolution of a computation depends on the whole computation history.

Example 2.2.11 Let ⌃ = {a, b}. The set of fair traces a ⇤ b, where the event b eventually occurs, is an example of program semantics that cannot be generated by a transition system. As seen in Example 2.2.7 and Example 2.2.9, the transition relation ⌧ = {ha, ai, ha, bi} introduces spurious traces in a +1 .

In fact, transition systems can only describe computations whose future evolution depends entirely on their current state [START_REF] Cousot | Fondements des Méthodes de Preuve d'Invarian ce et de Fatalité de Programmes Parallèles[END_REF]. We will often come back to this remark throughout this thesis.

The following result provides a fixpoint definition of the maximal trace semantics within the complete lattice hP(⌃ +1 ), v, t, u, ⌃ ! , ⌃ + i, where the computational order is

T 1 v T 2 def = T + 1 ✓ T + 2 ^T ! 1 ◆ T ! 2 [Cou97]:
Theorem 2.2.12 (Maximal Trace Semantics) The maximal trace semantics ⌧ +1 2 P(⌃ +1 ) can be expressed as a least fixpoint in the complete lattice hP(⌃ +1 ), v, t, u, ⌃ ! , ⌃ + i as follows: In Figure 2.2, we propose an illustration of the fixpoint iterates. Intuitively, the traces belonging to the maximal trace semantics are built backwards by prepending transitions to them: the finite traces are built extending other finite traces from the set of final states ⌦, and the infinite traces are obtained selecting infinite sequences with increasingly longer prefixes forming traces. In particular, the ith iterate builds all finite traces of length i, and selects all infinite sequences whose prefixes of length i form traces. At the limit we obtain all infinite traces and all finite traces that terminate in ⌦.

⌧ +1 = lfp v +1 +1 (T ) def = ⌦ [ (⌧ ; T ) (2.2.5) Proof. See [Cou02]. ⌅ 22 2. Abstract Interpretation T 0 = ( ⌃ ! ) T 1 = ⇢ ⌦ [ ( ⌧ ⌃ ! ) T 2 = ⇢ ⌦ [ ⇢ ⌧ ⌦ [ ( ⌧ ⌧ ⌃ ! ) T 3 = ⇢ ⌦ [ ⇢ ⌧ ⌦ [ ⇢ ⌧ ⌧ ⌦ [ ( ⌧ ⌧ ⌧ ⌃ ! ) . . .

Galois Connections

The maximal trace semantics carries all information about a program. It is the most precise semantics and it fully describes the behavior of a program.

Then, usually another fixpoint semantics is designed that is minimal, sound and relatively complete for the program properties of interest.

Program Properties. Following [START_REF] Cousot | Abstract Interpretation: a Unified Lattice Model for Static Analysis of Programs by Construction or Approximation of Fixpoints[END_REF], a property is represented by the set of elements which have this property. By program property we mean a property of its executions, that is a property of its semantics. Since a program semantics is a set of traces, a program property is a set of set of traces.

The strongest property of a program with semantics S 2 P(⌃ +1 ) is the collecting semantics {S} 2 P(P(⌃ +1 )). This is the strongest property because any program with this property must have the same semantics.

We say that a program with semantics S 2 P(⌃ +1 ) satisfies a property Note that, not all program properties are trace properties. As an example, the non-interference policy is not a trace property, because whether a trace is allowed by the policy depends on whether another trace is also allowed [START_REF] Michael | Hyperproperties[END_REF].

P 2 P(P(⌃ +1 )) if
We prefer program semantics expressed in fixpoint form which directly lead, using David Park's fixpoint induction [START_REF] Park | Fixpoint Induction and Proofs of Program Properties[END_REF], to sound and complete proof methods for the correctness of a program with respect to a property: Theorem 2.2.14 (Park's Fixpoint Induction Principle) Let f : D ! D be a monotonic function over a complete lattice hD, v, t, u, ?, >i and let d 2 D be a pre-fixpoint. Then, given an element P 2 D, we have:

lfp d f v P , 9I 2 D : d v I ^f (I) v I ^I v P. (2.2.6)
Dually, we have:

P v gfp d f , 9I 2 D : I v d ^I v f (I) ^P v I. (2.2.7)
The element I 2 D is called inductive invariant.

Hierarchy of Semantics.

As mentioned, to reason about a particular program property, it is not necessary to consider all aspects and details of the program behavior. In fact, reasoning is facilitated by the design of a welladapted semantics, abstracting away from irrelevant matters. Therefore, there is no universal general-purpose program semantics but rather a wide variety of special-purpose program semantics, each one of them dedicated to a particular class of program properties and reduced to essentials in order to ignore irrelevant details about program executions. Abstract interpretation is a method for relating these semantics. In fact, they can be uniformly described as fixpoints of monotonic functions over ordered structures, and organized into a hierarchy of interrelated semantics specifying at various levels of detail the behavior of programs [START_REF] Cousot | Constructive Design of a Hierarchy of Semantics of a Transition System by Abstract Interpretation[END_REF][START_REF] Cousot | Constructive Design of a Hierarchy of Semantics of a Transition System by Abstract Interpretation[END_REF].

Galois Connections. The correspondence between the semantics in the hierarchy is established by Galois connections formalizing the loss of information: Definition 2.2.15 (Galois Connection) Let hD, vi and hD \ , v \ i be two partially ordered sets. A Galois connection hD, vi ! The orders v and v \ are called approximation orders. They dictate the relative precision of the elements in the concrete and abstract domain: if

↵ hD \ , v \ i is a pair of monotonic functions ↵ : D ! D \ and : D \ ! D such that: 8d 2 D, d \ 2 D \ : ↵(d) v \ d \ , d v (d \ ) (2.2.8) We write hD, vi ! ! ↵ hD \ , v \ i when ↵ is surjective (or, equivalently, is injective), hD, vi ! ↵ hD \ , v \ i when ↵ is injective (or,
↵(d) v \ d \ , then d \ is also a correct abstract approximation of the concrete element d, although less precise than ↵(d); if d v (d \ )
, then d \ is also a correct abstract approximation of the concrete element d, although the element d provides more accurate information about program executions than (d \ ).

Remark 2.2.16 Observe that, the computational order used to define fixpoints and the approximation order often coincide but, in the general case, they are distinct and totally unrelated. We will need to maintain this distinction throughout the rest of this thesis.

The function

↵ : D ! D is extensive, that is, 8d 2 D : d v ↵(d),
meaning that the loss of information in the abstraction process is sound. The function ↵

:

D \ ! D \ is reductive, that is, 8d \ 2 D \ : ↵ (d \ ) v \ d \
, meaning that the concretization introduces no loss of information.

Given a Galois connection hD, vi ! ↵ hD \ , v \ i, the abstraction function and the concretization function uniquely determine each other:

↵(d) def = l {d \ | d v (d \ )} (d \ ) def = G \ {d | ↵(d) v \ d \ }
For this reason, we often provide only the definition of the abstraction function or, indi↵erently, only the definition of the concretization function.

Another important property of Galois connections is that, given two Galois connections hD, vi !

↵ 1 1 hD # , v # i and hD # , v # i ! ↵ 2 2 hD \ , v \ i, their com- position hD, vi ! ↵ 2 ↵ 1 1 2 hD \
, v \ i is also a Galois connection. Hence, abstract interpretation has a constructive aspect, since program semantics can be systematically derived by successive abstractions of the maximal trace semantics, rather than just being derived by intuition and justified a posteriori.

Example 2.2.17

The function post 2 P(⌃) ! P(⌃) (cf. Definition 2.2.2) and the function f pre 2 P(⌃) ! P(⌃) (cf. Definition 2.2.5) form a Galois connection:

hP(⌃), ✓i ! post f pre hP(⌃), ✓i
↵ R (T ) def = I [ {s 2 ⌃ | 9s 0 2 I, 2 ⌃ ⇤ , 0 2 ⌃ ⇤1 : s 0 s 0 2 T } (2.2.9)
This abstraction, from now on, is called reachability abstraction.

Note that, the approximation order ✓ of the concrete domain hP(⌃ +1 ), ✓i di↵ers from the computational order v used to define the maximal trace semantics in the complete lattice hP(⌃ +1 ), v, t, u, ⌃ ! , ⌃ + i (cf. Equation 2.2.5).

The reachable state semantics is thus defined as:

⌧ R def = ↵ R (⌧ +1 )
It can be specified in fixpoint form as follows:

⌧ R = lfp ✓ R R (S) def = I [ post(S) (2.2.10)
In this case, the computational order ✓ used to define the semantics coincides with the approximation order of the abstract domain hP(⌃), ✓i.

Note that, while the traces belonging to the maximal trace semantics are built backwards, the states belonging to the reachable state semantics are build forward from the set of initial states I.

Remark 2.2.19 (Absence of Galois Connection) The use of Galois connections squares with an ideal situation where there is a best way to approximate any concrete property by an abstract property. However, imposing the existence of a Galois connection is sometimes too strong a requirement. In [START_REF] Cousot | Abstract Interpretation Frameworks[END_REF], Patrick Cousot and Radhia Cousot illustrate how to relax the Galois connection framework in order to work with only a concretization function or, dually, only an abstraction function. In practice, concretization-based abstract interpretations are much more used and will be frequently encountered throughout this thesis (cf. Section 3.4 and Chapter 5).

Fixpoint Transfer.

The following theorem provides guidelines for deriving an abstract fixpoint semantics S \ by abstraction of a concrete fixpoint semantics S, or dually, for deriving S by refinement of S \ .

Theorem 2.2.20 (Kleenian Fixpoint Transfer) Let hD, vi and hD \ , v \ i be complete partial orders, let : D ! D and \ : D \ ! D \ be monotonic functions, and let ↵ : D ! D \ be a Scott-continuous abstraction function that satisfies ↵(?) = ? \ and the commutation condition ↵ = \ ↵. Then, we have the fixpoint abstraction ↵(lfp v ) = lfp v \ \ . Dually, let : D \ ! D be a Scott-continuous concretization function that satisfies ? = (? \ ) and the commutation condition = \ . Then, we have the fixpoint derivation

lfp v = (lfp v \ \ ).
In particular, for the respective iterates of : D ! D and \ : D \ ! D \ from ? and ? \ (cf. Theorem 2.1.5) we have:

8 2 O : ↵( ) = \ .
Proof.

See [START_REF] Cousot | Constructive Design of a Hierarchy of Semantics of a Transition System by Abstract Interpretation[END_REF].

⌅

When the abstraction function is not Scott-continuous, but it preserves greatest lower bounds, we can rely on the following theorem.

Theorem 2.2.21 (Tarskian Fixpoint Transfer) Let hD, v, t, u, ?, >i and hD \ , v \ , t \ , u \ , ? \ , > \ i be complete lattices, let : D ! D and \ : D \ ! D \ be monotonic functions, and let ↵ : D ! D \ be an abstraction function that is a complete u-morphism and that satisfies

\ ↵ v \ ↵ and the post-fixpoint correspondence 8d \ 2 D \ : \ (d \ ) v \ d \ ) 9d 2 D : (d) v d ^↵(d) = d \ (i.e.
, each abstract post-fixpoint of \ is the abstraction by ↵ of some concrete post-fixpoint of ). Then, we have ↵(lfp v ) = lfp v \ .

Proof.

See [START_REF] Cousot | Constructive Design of a Hierarchy of Semantics of a Transition System by Abstract Interpretation[END_REF].

⌅

In the particular case when the abstraction function ↵ : D ! D \ is a complete t-morphism, there exists a unique concretization function :

D \ ! D such that hD, vi ! ↵ hD \ , v \ i is a Galois connection.
Fixpoint Approximation. In case no optimal fixpoint abstraction of a concrete semantics S can be defined, we settle for a sound abstraction, that is, an abstract semantics S \ such that ↵(S) v \ S \ , or equivalently S v (S \ ), for the approximation orders v and v \ .

Widening and Narrowing

We must now address the practical problem of e↵ectively computing these program semantics. In [START_REF] Cousot | Static Determination of Dynamic Properties of Programs[END_REF], Patrick Cousot and Radhia Cousot introduced the idea of using widening and narrowing operators in order to accelerate the convergence of increasing and decreasing iteration sequences to a fixpoint over-approximation. In [START_REF] Cousot | Méthodes Itératives de Construction et d'Appro ximation de Points Fixes d'Opérateurs Monotones sur un Treil lis, Analyse Sémantique de Programmes[END_REF], the dual operators are also considered.

Widening. The widening operator is used to enforce or accelerate the convergence of increasing iteration sequences over abstract domains with infinite or very long strictly ascending chains, or even over finite but very large abstract domains. It is defined as follows:

Definition 2.2.22 (Widening) Let hD, vi be a partially ordered set. A widening operator O : (D ⇥ D) ! D is such that:

(1) for all element x, y 2 D, we have x v x O y and y v x O y;

(2) for all increasing chains

x 0 v x 1 v • • • v x n v • • • , the increasing chain y 0 def = x 0 y n+1 def = y n O x n+1
is ultimately stationary, that is, 9l 0 : 8j l : y j = y l . Intuitively, given and abstract domain hD, vi and a function : D ! D, the widening uses two consecutive iterates y n and (y n ) in order to extrapolate the next iterate y

n+1 def = y n O (y n )
. This extrapolation should be an over-approximation for soundness, that is y n v y n+1 and (y n ) v y n+1 (cf. Definition 2.2.22(1)), and enforce convergence for termination (cf. Definition 2.2.22(2)). In this way, the widening allows computing in finite time an over-approximation of a Kleenian fixpoint: Theorem 2.2.23 (Fixpoint Approximation with Widening) Let hD, v i be a complete partial order, let : D ! D be a Scott-continuous function, let d 2 D be a pre-fixpoint, and let O : (D ⇥ D) ! D be a widening. Then, the following increasing chain:

y 0 def = d y n+1 def = y n O (y n
) is ultimately stationary and its limit, denoted by O , is such that lfp d v O . Proof. See [START_REF] Cousot | Comparing the Galois Connection and Widening/Narrowing Approaches to Abstract Interpretation[END_REF].

⌅

In [START_REF] Cousot | Comparing the Galois Connection and Widening/Narrowing Approaches to Abstract Interpretation[END_REF], Patrick Cousot and Radhia Cousot demonstrated that computing in an abstract domain with infinite ascending chains using a widening is strictly more powerful than any finite abstraction. Intuitively, the widening adds a dynamic dimension to the abstraction, which is more flexible than relying only on the static choice of an abstract domain.

Narrowing. The narrowing operator is used to enforce or accelerate the convergence of decreasing iteration sequences. It is defined as follows: (1) for all element x, y 2 D, if x w y we have x w (x 4 y) w y;

(2) for all decreasing chains

x 0 w x 1 w • • • w x n w • • • , the decreasing chain y 0 def = x 0 y n+1 def = y n 4 x n+1
is ultimately stationary, that is, 9l 0 : 8j l : y j = y l . It is often the case that the limit O of the iteration sequence with widening is a strict post-fixpoint of : ( O ) < O . Hence, the over-approximation O can be refined by a decreasing iteration without widening:

y 0 def = O y n+1 def =
(y n ) However, this decreasing sequence can be infinite. The narrowing operator is used to limit the refinement while enforcing termination (cf. Figure 2.3). Intuitively, the narrowing uses two consecutive iterates y n and (y n ) in order to compute the next iterate y

n+1 def = y n 4 (y n ).
This should be an interpolation for soundness, that is y n w y n+1 w (y n ) (cf. Definition 2.2.24(1)), and enforce convergence for termination (cf. Definition 2.2.24(2)). In this way, the narrowing allows refining in finite time an over-approximation of a fixpoint:

Abstract Interpretation

Theorem 2.2.25 (Fixpoint Refinement with Narrowing) Let hD, vi be a complete partial order, let : D ! D be a Scott-continuous function, let d 2 D be a pre-fixpoint and let a 2 D be a post-fixpoint such that d v a, and let 4 : (D ⇥ D) ! D be a narrowing. Then, the decreasing chain

y 0 def = a y n+1 def = y n 4 (y n
) is ultimately stationary and its limit, denoted by 4 , is such that lfp d v 4 . Proof. See [START_REF] Cousot | Comparing the Galois Connection and Widening/Narrowing Approaches to Abstract Interpretation[END_REF].

⌅

Dual Widening. The dual widening operator is used to enforce or accelerate the convergence of decreasing iterations sequences to a (greatest) fixpoint under-approximation. Its definition is the dual of Definition 2.2.22: Definition 2.2.26 (Dual Widening) Let hD, vi be a partially ordered set. A dual widening operator Ō : (D ⇥ D) ! D is such that:

(1) for all element x, y 2 D, we have x w x Ō y and y w x Ō y;

(2) for all decreasing chains

x 0 w x 1 w • • • w x n w • • • , the decreasing chain y 0 def = x 0 y n+1 def = y n Ō x n+1
is ultimately stationary, that is, 9l 0 : 8j l : y j = y l . The widening and the dual widening are extrapolators: they are used to find abstract elements outside the range of known abstract elements [START_REF] Cousot | Abstracting Induction by Extrapolation and Interpolation[END_REF].

Dual Narrowing. The dual narrowing operator is used to enforce or accelerate the convergence of increasing iterations sequences to a (greatest) fixpoint under-approximation. Its definition is the dual of Definition 2.2.24.

The narrowing and the dual narrowing are interpolators: they are used to find abstract elements inside the range of known abstract elements [START_REF] Cousot | Abstracting Induction by Extrapolation and Interpolation[END_REF].

In conclusion, a sound and fully automatic static analyzer can be designed by systematically approximating the semantics of programs, with an inevitable loss of information, from a concrete to a less precise abstract setting, until the resulting semantics is computable.

The formal treatment given in the previous chapter is language independent. In this chapter, we look back at the notions introduced in the context of a simple sequential programming language that will be used to illustrate our work throughout the rest of this thesis.

Le traitement formel donné dans le chapitre précédent est indépendant du langage. Dans ce chapitre, nous nous penchons sur les notions introduites dans le contexte d'un simple langage de programmation séquentiel qui sera utilisé pour illustrer notre travail dans le reste de cette thèse.

A Small Imperative Language

We consider a simple sequential non-deterministic programming language with no procedures, no pointers and no recursion. The variables are statically allocated and the only data type is the set Z of mathematical integers.

In Chapter 7 we will introduce procedures and recursion, while pointers and machine integers and floats will remain out of the scope of this work.

Language Syntax. In Figure 3.1, we define inductively the syntax of our programming language.

A program prog consists of an instruction followed by a unique label l 2 L. Another unique label appears within each instruction. An instruction stmt is either a skip instruction, a variable assignment, a conditional if statement, a while loop or a sequential composition of instructions.

Arithmetic expressions aexp involve variables X 2 X , numeric intervals [a, b] and the arithmetic operators +, , ⇤, / for addition, subtraction, multiplication, and division. Numeric intervals have constant and possibly infinite bounds, and denote a random choice of a number in the interval. This provides

aexp ::= X X 2 X | [i 1 , i 2 ] i 1 2 Z [ { 1}, i 2 2 Z [ {+1}, i 1  i 2 | aexp | aexp ⇧ aexp ⇧ 2 {+, , ⇤, /} bexp ::= ? | not bexp | bexp and bexp | bexp or bexp | aexp ./ aexpr ./ 2 {<, , =, 6 =} stmt ::= l skip | l X := aexp l 2 L, X 2 X | if l bexp then stmt else stmt fi l 2 L | while l bexp do stmt od l 2 L | stmt stmt prog ::= stmt l l 2 L Figure 3
.1: Syntax of our programming language.

a notion of non-determinism useful to model user input or to approximate arithmetic expressions that cannot be represented exactly in the language. Numeric constants are a particular case of numeric interval. In the following, we often write the constant c for the interval [c, c].

Boolean expressions bexp are built by comparing arithmetic expressions, and are combined using the boolean not, and, and or operators. The boolean expression ? represents a non-deterministic choice and is useful to provide a sequential encoding of concurrent programs by modeling a (possibly, but not necessarily, fair) scheduler. Whenever clear from the context, we frequently abuse notation and use the symbol ? to also denote the numeric interval [ 1, +1].

Maximal Trace Semantics

In the following, we instantiate the general definitions of transition system and maximal trace semantics of Section 2.2 with our small imperative language.

Expression Semantics. An environment ⇢ : X ! Z maps each program variable X 2 X to its value ⇢(X) 2 Z. Let E denote the set of all environments.

J X K⇢ def = { ⇢(X) } J [a, b] K⇢ def = { x | a  x  b } J aexp K⇢ def = { x | x 2 J aexp K⇢ } J aexp 1 + aexp 2 K⇢ def = { x + y | x 2 J aexp 1 K, y 2 J aexp 2 K⇢ } J aexp 1 aexp 2 K⇢ def = { x y | x 2 J aexp 1 K, y 2 J aexp 2 K⇢ } J aexp 1 ⇤ aexp 2 K⇢ def = { x ⇤ y | x 2 J aexp 1 K, y 2 J aexp 2 K⇢ } J aexp 1 / aexp 2 K⇢ def = { trnk(x / y) | x 2 J aexp 1 K, y 2 J aexp 2 K⇢, y 6 = 0 }
where trnk : R ! Z is defined as follows:

trnk(x) def = ( max{y 2 Z | y  x} x 0 min{y 2 Z | y x} x < 0 Figure 3.2: Semantics of arithmetic expressions aexp.
The semantics of an arithmetic expression aexp is a function JaexpK : E ! P(Z) mapping an environment ⇢ 2 E to the set of all possible values for the expression aexp in the environment. It is presented in Figure 3.2. Note that, the set of values for an expression may contain several elements because of the non-determinism embedded in the expressions. It might also be empty due to undefined results. In fact, this is the case of divisions by zero. The trnk function rounds the result of the division towards an integer.

Similarly, the semantics JbexpK : E ! P({true, false}) of boolean expressions bexp maps an environment ⇢ 2 E to the set of all possible truth values for the expression bexp in the environment. It is presented in Figure 3.3. In the following, we write true and false to represent a boolean expression that is always true and always false, respectively. Example 3.2.1 Let us consider the following program:

Transition Systems. A program state s 2 L ⇥ E is a
J ? K⇢ def = { true, false } J not bexp K⇢ def = { ¬x | x 2 J bexp K⇢ } J bexp 1 and bexp 2 K⇢ def = { x ^y | x 2 J bexp 1 K, y 2 J bexp 2 K⇢ } J bexp 1 or bexp 2 K⇢ def = { x _ y | x 2 J bexp 1 K, y 2 J bexp 2 K⇢ } J aexp 1 < aexp 2 K⇢ def = { x < y | x 2 J aexp 1 K, y 2 J aexp 2 K⇢ } J aexp 1  aexp 2 K⇢ def = { x  y | x 2 J aexp 1 K, y 2 J aexp 2 K⇢ } J aexp 1 = aexp 2 K⇢ def = { x = y | x 2 J aexp 1 K, y 2 J aexp 2 K⇢ } J aexp 1 6 = aexp 2 K⇢ def = { x 6 = y | x 2 J aexp 1 K, y 2 J aexp 2 K⇢ } Figure 3.3: Semantics of boolean expressions bexp. stmt ::= l skip iJ l skip K def = l | l X := aexp iJ l X := aexp K def = l | if l bexp then stmt 1 else stmt 2 fi iJ if l bexp then stmt 1 else stmt 2 fi K def = l | while l bexp do stmt 1 od iJ while l bexp do stmt 1 od K def = l | stmt 1 stmt 2 iJ stmt 1 stmt 2 K def = iJ stmt 1 K prog ::= stmt l iJ stmt l K def = iJ stmt K
1 x := ? while 2 (1 < x) do 3 x := x 1 od 4
We have the following final program control points:

f J 1 x := ? while 2 (1 < x) do 3 x := x 1 od 4 K = 4 f J 1 x := ? while 2 (1 < x) do 3 x := x 1 od K = 4 f J 1 x := ? K = 2 f J while 2 (1 < x) do 3 x := x 1 od K = 4 f J 3 x := x 1 K = 2
Note that, the final control point f J stmt K 2 L of an instruction stmt does not belong to the set of control points appearing in the instruction. A program execution starts at its initial program control point with any possible value for the program variables. Thus, the set of initial states of a program prog is

stmt ::= l skip f J l skip K def = f J stmt K | l X := aexp f J l X := aexp K def = f J stmt K | if l bexp then stmt 1 else stmt 2 fi f J if l bexp then stmt 1 else stmt 2 fi K def = f J stmt K f J stmt 1 K def = f J stmt K f J stmt 2 K def = f J stmt K | while l bexp do stmt 1 od f J while l bexp do stmt 1 od K def = f J stmt K f J stmt 1 K def = l | stmt 1 stmt 2 f J stmt 1 stmt 2 K def = f J stmt K f J stmt 1 K def = iJ stmt 2 K f J stmt 2 K def = f J stmt K prog ::= stmt l f J stmt l K def = l
I def = {hiJ prog K, ⇢i | ⇢ 2 E}.
It is sometimes useful to assume that a set E ✓ E of initial environments is given, in which case the program initial states correspond to the initial program control point paired with any initial environment:

I def = {hiJ prog K, ⇢i | ⇢ 2 E}. The set of final states of a program prog is Q def = {hf J prog K, ⇢i | ⇢ 2 E}.
Remark 3.2.2 In Section 2.2 we defined the final states to have no successors with respect to the transition relation, meaning that the program halts: ⌦ def = {s 2 ⌃ | 8s 0 2 ⌃ : hs, s 0 i 6 2 ⌧ }. This is the case when the program successfully terminates by reaching its final label, or when a run-time error occurs. For the sake of simplicity, the definition of program final states given in this section ignores possible run-time errors silently halting the program.

We now define the transition relation ⌧ 2 ⌃ ⇥ ⌃. In particular, in Figure 3.6, we define the transition semantics ⌧ J stmt K 2 ⌃ ⇥ ⌃ of each program instruction stmt. Given an environment ⇢ 2 E, a program variable X 2 X and a value v 2 Z, we denote by ⇢[X v] the environment obtained by writing the value v into the variable X in the environment ⇢:

⇢[X v](x) = ( v x= X ⇢(x) x 6 = X ⌧ J l skip K def = {hl, ⇢i ! hf J l skip K, ⇢i | ⇢ 2 E} ⌧ J l X := aexp K def = {hl, ⇢i ! hf J l X := aexp K, ⇢[X v]i | ⇢ 2 E, v 2 JaexpK⇢} ⌧ J if l bexp then stmt 1 else stmt 2 fi K def = {hl, ⇢i ! hiJ stmt 1 K, ⇢i | ⇢ 2 E, true 2 JbexpK⇢} [ ⌧ J stmt 1 K [ {hl, ⇢i ! hiJ stmt 2 K, ⇢i | ⇢ 2 E, false 2 JbexpK⇢} [ ⌧ J stmt 2 K ⌧ J while l bexp do stmt od K def = {hl, ⇢i ! hiJ stmt K, ⇢i | ⇢ 2 E, true 2 JbexpK⇢} [ ⌧ J stmt K [ {hl, ⇢i ! hf J while l bexp do stmt od K, ⇢i | ⇢ 2 E, false 2 JbexpK⇢} ⌧ J stmt 1 stmt 2 K def = ⌧ J stmt 1 K [ ⌧ J stmt 2 K Figure 3.6: Transition semantics of instructions stmt.
The semantics of a skip instruction simply moves control from the initial label of the instruction to its final label. The execution of a variable assignment l X := aexp moves control from the initial label of the instruction to its final label, and modifies the current environment in order to assign any of the possible values of aexp to the variable X. The semantics of a conditional statement if l bexp then stmt 1 else stmt 2 fi moves control from the initial label of the instruction to the initial label of stmt 1 , if true is a possible value for bexp, and to the initial label of stmt 2 , if false is a possible value for bexp; then, stmt 1 and stmt 2 are executed. Similarly, the execution of a while statement while l bexp do stmt od moves control from the initial label of the instruction to its final label, if false is a possible value for bexp, and to the initial label of stmt 1 , if true is a possible value for bexp; then stmt is executed. Note that, control moves from the end of stmt to the initial label l of the while loop, since l is the final label of stmt (cf. Figure 3.5). Finally, the semantics of the sequential combination of instructions stmt 1 stmt 2 executes stmt 1 and stmt 2 . Note that, control moves from the end of stmt 1 to the beginning of stmt 2 , since the final label of stmt 1 is the initial label of stmt 2 (cf. Figure 3.5).

The transition relation ⌧ 2 ⌃ ⇥ ⌃ of a program prog is defined by the semantics

⌧ J prog K 2 ⌃ ⇥ ⌃ of the program as ⌧ J prog K = ⌧ J stmt l K def = ⌧ J stmt K. Example 3.2.3
Let us consider again the program of Example 3.2.1:

1 x := ? while 2 (1 < x) do 3 x := x 1 od 4
The set of program environments E contains functions ⇢ : {x} ! Z mapping the program variable x to any possible value ⇢(x) 2 Z. The set of program states ⌃ def = {1, 2, 3, 4} ⇥ E consists of all pairs of labels and environments; the initial states are

I def = {h1, ⇢i | ⇢ 2 E}. The program transition relation ⌧ 2 ⌃ ⇥ ⌃ is defined as follows: ⌧ def = {h1, ⇢i ! h2, ⇢[x v]i | ⇢ 2 E ^v 2 Z} [ {h2, ⇢i ! h3, ⇢i | ⇢ 2 E ^true 2 J1 < xK⇢} [ {h3, ⇢i ! h2, ⇢[x ⇢(x) 1]i | ⇢ 2 E} [ {h2, ⇢i ! h4, ⇢i | ⇢ 2 E ^false 2 J1 < xK⇢}
The set of final states is

Q def = {h4, ⇢i | ⇢ 2 E}.
Note that, the definition of final states assumes all possible values for the program variable x although when executing the program we have x  1 on program exit.

Maximal Trace Semantics. In the following, we provide a structural definition of the fixpoint maximal trace semantics ⌧ +1 2 ⌃ +1 (Equation 2.2.5) by induction on the syntax of programs.

We recall that a program trace is a non-empty sequence of program states in ⌃ determined by the program transition relation ⌧ .

Example 3.2.4

Let us consider again the program of Example 3.2.3:

1 x := ? while 2 (1 < x) do 3 x := x 1 od 4
We write {hx, vi} to denote the environment ⇢ : {x} ! Z mapping the program variable x to the value v 2 Z. The following sequence of program states:

h1, {hx, 42i}ih2, {hx, 2i}ih3, {hx, 2i}ih2, {hx, 1i}ih4, {hx, 1i}i
is an example of program trace determined by the transition relation ⌧ .

We only consider program traces starting from the set I of initial states of a program prog. Accordingly, in Figure 3.7 we define the trace semantics ⌧ +1 J stmt K 2 P(⌃ +1 ) ! P(⌃ +1 ) of each program instruction stmt. Analogously to Equation 2.2.5, the program traces are built backwards: each function ⌧ +1 J stmt K 2 P(⌃ +1 ) ! P(⌃ +1 ) takes as input a set of traces starting with the final label of the instruction stmt and outputs a set of traces starting with the initial label of stmt.

⌧ +1 J l skip KT def = ⇢ hl, ⇢ihf J l skip K, ⇢i ⇢ 2 E, 2 ⌃ ⇤1 hf J l skip K, ⇢i 2 T ⌧ +1 J l X := aexp KT def = ⇢ hl, ⇢ihf J l X := aexp K, ⇢[X v]i ⇢ 2 E, v 2 JaexpK⇢, 2 ⌃ ⇤1 hf J l X := aexp K, ⇢[X v]i 2 T ⌧ +1 J if l bexp then stmt 1 else stmt 2 fi KT def = ⇢ hl, ⇢ihiJ stmt 1 K, ⇢i ⇢ 2 E, true 2 JbexpK⇢, 2 ⌃ ⇤1 hiJ stmt 1 K, ⇢i 2 ⌧ +1 J stmt 1 KT [ ⇢ hl, ⇢ihiJ stmt 2 K, ⇢i ⇢ 2 E, false 2 JbexpK⇢, 2 ⌃ ⇤1 hiJ stmt 2 K, ⇢i 2 ⌧ +1 J stmt 2 KT ⌧ +1 J while l bexp do stmt od KT def = lfp v +1 +1 (X) def = ⇢ hl, ⇢ihiJ stmt K, ⇢i ⇢ 2 E, true 2 JbexpK⇢, 2 ⌃ ⇤1 hiJ stmt K, ⇢i 2 ⌧ +1 J stmt KX [ ⇢ hl, ⇢ihf J while • • • od K, ⇢i ⇢ 2 E, false 2 JbexpK⇢, 2 ⌃ ⇤1 hf J while • • • od K, ⇢i 2 T ⌧ +1 J stmt 1 stmt 2 KT def = ⌧ +1 J stmt 1 K(⌧ +1 J stmt 2 KT )
The trace semantics of a skip instruction takes as input a set T 2 P(⌃ +1 ) of traces starting with environments paired with the final label of the instruction and, according to the transition relation semantics of the instruction, it prepends to them the same environments paired with its initial label.

The trace semantics of a variable assignment l X := aexp takes as input a set T 2 P(⌃ +1 ) of traces starting with the final label of the instruction and it prepends to them all program states with its initial label that are allowed by the transition relation semantics of the instruction (cf. Figure 3.6).

Similarly, given a conditional instruction if l bexp then stmt 1 else stmt 2 fi, its trace semantics prepends all program states with its initial label that are allowed by its transition relation semantics to the traces starting with the initial labels of stmt 1 and stmt 2 ; these are obtained by means of the trace semantics of stmt 2 and stmt 1 taking as input a set T 2 P(⌃ +1 ) of traces starting with the final label of the conditional instruction.

The trace semantics of a loop instruction while l bexp do stmt od is defined as the least fixpoint of the function +1 : P(⌃ +1 ) ! P(⌃ +1 ) within the complete lattice hP(⌃ +1 ), v, t, u, ⌃ ! , ⌃ + i, analogously to Equation 2.2.5. The iteration sequence, starting from all infinite sequences ⌃ ! 2 P(⌃ +1 ), builds the set of program traces that consist of an infinite number of iterations within the loop, and it prepends a finite number of iterations within the loop to an input set T 2 P(⌃ +1 ) of traces starting with the final label of the loop instruction. In Figure 3.7, we have shortened f J while l bexp do stmt od K by means of f J while • • • od K. In particular, the function +1 : P(⌃ +1 ) ! P(⌃ +1 ) takes as input a set X 2 P(⌃ +1 ) of traces: initially, X is the set of all infinite sequences ⌃ ! and, at each iteration, the function prepends all program states whose label is the initial label of the loop instruction, to the traces belonging to the input set T , and to the traces that are obtained by means of the trace semantics of the loop body stmt from the set X. In this way, after the ith iteration, the set X contains the program traces starting at the initial label of the loop instruction whose prefix consist of from zero up to i 1 iterations within the loop and whose su x is a trace in T , and the sequences whose prefix are program traces which consist of i 1 iterations within the loop. With a slight abuse of notation, we depict the fixpoints iterates in Figure 3.8.

X 0 = ( ⌃ ! ) X 1 = ( ¬bexp T ) [ ( bexp stmt ⌃ ! ) X 2 = ( ¬bexp T ) [ ( bexp stmt ¬bexp T ) [ ( bexp stmt bexp stmt ⌃ ! ) . . .
Finally, the trace semantics of the sequential combination of instructions stmt 1 stmt 2 takes as input a set T 2 P(⌃ +1 ) of traces starting with the final label of stmt 2 , determines from T the set of traces ⌧ +1 J stmt 2 KT belonging to the trace semantics of stmt 2 , and outputs the set of traces determined by the trace semantics of stmt 1 from ⌧ +1 J stmt 2 KT .

The maximal trace semantics ⌧ +1 J prog K 2 P(⌃ +1 ) of a program prog is the maximal trace semantics ⌧ +1 2 P(⌃ +1 ) defined in Equation 2.2.5 restricted to the traces starting from the program initial states I, and it is defined taking as input the set of program final states Q: Definition 3.2.5 (Maximal Trace Semantics) The maximal trace semantics ⌧ +1 J prog K 2 P(⌃ +1 ) of a program prog is:

⌧ +1 J prog K = ⌧ +1 J stmt l K def = ⌧ +1 J stmt KQ (3.2.1)
where the trace semantics ⌧ +1 J stmt K 2 P(⌃ +1 ) ! P(⌃ +1 ) of each program instruction stmt is defined in Figure 3.7.

Note that, as pointed out in Remark 3.2.2, possible run-time errors are ignored.

More specifically, all traces containing run-time errors are discarded and do not belong to the maximal trace semantics of a program prog.

In the following, we often simply write ⌧ +1 instead of ⌧ +1 J prog K.

Invariance Semantics

The reachable state semantics ⌧ R 2 P(⌃) introduced by Example 2.2.18 abstracts the maximal trace semantics ⌧ +1 2 P(⌃ +1 ) by collecting the possible values of the program variables at each program point and disregarding other information. In the following, we provide an isomorphic invariance semantics defined by induction on the syntax of our small language. Note that the complete lattice hP(⌃), ✓, [, \, ;, ⌃i on which the reachable state semantics is defined is isomorphic by partitioning with respect to the program control points and by pointwise lifting (cf. Equation 2.1.1) to hL ! P(E), ✓, [, \, l. ;, l. Ei. This can be formalized as a Galois connection

↵ I (R) def = l 2 L. {⇢ 2 E | hl, ⇢i 2 R} I (I) def = {hl, ⇢i 2 ⌃ | ⇢ 2 I(l)} (3.3.1)
This abstraction, from now on, is called invariance abstraction. In this form, the reachable state semantics ⌧ R 2 P(⌃) becomes an invariance semantics ⌧ I 2 L ! P(E) associating to each program control point l 2 L an invariant E 2 P(E) which collects the set of possible program environments for each

3.3. Invariance Semantics ⌧ post J l skip KE def = E ⌧ post J l X := aexp KE def = {⇢[X v] 2 E | ⇢ 2 E, v 2 JaexpK⇢} ⌧ post J if l bexp then stmt 1 else stmt 2 fi KE def = ⌧ post Jstmt 1 K{⇢ 2 E | true 2 JbexpK⇢} [ ⌧ post Jstmt 2 K{⇢ 2 E | false 2 JbexpK⇢} ⌧ post J while l bexp do stmt od KE def = {⇢ 2 lfp post | false 2 JbexpK⇢} post (X) def = E [ ⌧ post JstmtK{⇢ 2 X | true 2 JbexpK⇢} ⌧ post J stmt 1 stmt 2 KE def = ⌧ post J stmt 2 K(⌧ post J stmt 1 KE)
Figure 3.9: Invariance semantics of instructions stmt.

time the program execution reaches that program control point. We can now define the invariance semantics pointwise within the power set of environments.

In Figure 3.9, for each program instruction stmt, we define its postcondition semantics ⌧ post J stmt K : P(E) ! P(E). Analogously to the states belonging to the reachable state semantics in Example 2.2.18, the environment belonging to the postcondition semantics are built forward : each function ⌧ post J stmt K : P(E) ! P(E) takes as input a set of environments and outputs the set of possible environments at the final control point of the instruction.

The postcondition semantics ⌧ post J prog K 2 P(E) of a program prog outputs the set of possible program environments at the final program control point f J prog K 2 L. It is defined from the set of all program environments E as: Definition 3.3.1 (Postcondition Semantics) Given a program prog, its postcondition semantics ⌧ post J prog K 2 P(E) is:

⌧ post J prog K = ⌧ post J stmt l K def = ⌧ post J stmt KE (3.3.2)
where the postcondition semantics ⌧ post J stmt K 2 P(E) ! P(E) of each program instruction stmt is defined in Figure 3.9.

In this way, we can collect the set of possible program environments at each program control point. At the initial control point, the possible environments are all program environments:

⌧ I (iJ prog K) def = E.
Then, for each program instruction stmt, the set ⌧ I (f J stmt K) 2 P(E) of possible environments at its final control point is defined by the postcondition semantics (cf. Figure 3.9), taking as input the set E 2 P(E) of possible environments at the final control point of the instruction preceding stmt (or all program environments in case stmt is the first instruction of the program):

⌧ I (f J stmt K) def = ⌧ post J stmt KE.
In case of a while loop instruction, the set ⌧ I (iJ while l bexp do stmt od K) 2 P(E) of possible environments at its initial control point is defined as the least fixpoint greater than the input set E of the function post : P(E) ! P(E) defined in Figure 3.9:

⌧ I (iJ while l bexp do stmt od K) def = lfp E post
At each iteration, the function post : P(E) ! P(E) accumulates the possible environments after another loop iteration from a given set of environments X 2 P(E). The set ⌧ I (iJ stmt K) 2 P(E) of possible environments at the initial control point of the loop body is the set of possible environments at the initial control point of the loop that satisfy the boolean expression bexp:

⌧ I (iJ stmt K) def = {⇢ 2 ⌧ I (iJ while l bexp do stmt od K) | true 2 JbexpK⇢} Example 3.3.2
Let us consider again the program of Example 3.2.4:

1 x := ? while 2 (1 < x) do 3 x := x 1 od 4
The following are the set of possible program environments collected by the invariance semantics at each program control point:

⌧ I (1) = E ⌧ I (2) = lfp ⌧postJ 1 x:=? K⌧ I (1) post = E ⌧ I (3) = {⇢ 2 ⌧ I (2) | true 2 J1 < xK⇢} = {⇢ 2 E | 2  ⇢(x)} ⌧ I (4) = {⇢ 2 ⌧ I (2) | false 2 J1 < xK⇢} = {⇢ 2 E | ⇢(x)  1} where post (X) = X [ ⌧ post J 3 x := x 1 K{⇢ 2 X | true 2 J1 < xK⇢}.
In the next section, we present further abstractions of the invariance semantics by means of numerical abstract domains.

Numerical Abstract Domains

We consider concretization-based abstractions of the following form:

hP(E), ✓i D hD, v D i
which provide, for each program control point l 2 L, a sound decidable abstraction ⌧ \ I (l) 2 D of the invariance semantics ⌧ I (l) 2 P(E) (cf. Section 3.3). We have ⌧ I (l) ✓ D (⌧ \ I (l)), meaning that the abstract invariance semantics • a set D whose elements are computer-representable;

⌧ \ I (l)
• a partial order v D together with an e↵ective algorithm to implement it;

• a concretization-based abstraction hP(E), ✓i D hD, v D i or, when possible, a Galois connection hP(E), ✓i !

↵ D D hD, v D i;
• a least element ? D 2 D such that D (? D ) = ;;

• a greatest element > D 2 D such that D (> D ) = E; • a sound binary operator t D such that D (d 1 ) [ D (d 2 ) ✓ D (d 1 t D d 2 ); • a sound binary operator u D such that D (d 1 ) \ D (d 2 ) ✓ D (d 1 u D d 2 );
• a sound unary operator ASSIGN D J X := aexp K : D ! D, together with an e↵ective algorithm to handle a variable assignment l X := aexp, such that

⌧ I J l X := aexp K D (d) ✓ D (ASSIGN D J X := aexp Kd); • a sound backward operator B-ASSIGN D J X := aexp K : D ! D ! D, to-
gether with an e↵ective algorithm to refine an element d 2 D given the result r 2 D of the assignment l X := aexp, such that

{⇢ 2 D (d) | ⌧ I J l X := aexp K{⇢} ✓ D (r)} ✓ D ((B-ASSIGN D J X := aexp Kd)(r)) ✓ D (d);
• a sound unary operator FILTER D J bexp K : D ! D, together with an effective algorithm to handle a boolean expression bexp, such that {⇢ 2

D (d) | true 2 JbexpK⇢} ✓ D (FILTER D J bexp Kd);
• a sound widening operator O D , when hD, v D i does not satisfy the ACC;

• a sound narrowing operator O D , when hD, v D i does not satisfy the DCC;

The backward assignment operator B-ASSIGN D J X := aexp K : D ! D ! D, is not directly used to abstract the invariance semantics. However, it usually defined in order to allow the combination of forward and backward analyses [START_REF] Cousot | Abstract Interpretation and Application to Logic Programs[END_REF]. It will also be useful in Chapter 5.

Abstract Invariance Semantics. The operators of the numerical abstract domains can now be used to define the abstract invariance semantics.

In Figure 3.10 we define, for each program instruction stmt, its abstract postcondition semantics ⌧ D J stmt K : D ! D. Each function ⌧ D J stmt K : D ! D takes as input a numerical abstraction and outputs the possible numerical abstraction at the final control point of the instruction. For a while loop, O D is the limit of the following increasing chain (cf. Theorem 2.2.23):

y 0 def = d y n+1 def = y n O D D (y n )
The abstract postcondition semantics ⌧ D J prog K 2 D of a program prog outputs the possible numerical abstraction at the final program control point f J prog K 2 L. It is defined taking as input the element > D as:

⌧ D J l skip Kd def = d ⌧ D J l X := aexp Kd def = ASSIGN D J X := aexp Kd ⌧ D J if l bexp then stmt 1 else stmt 2 fi Kd def = F 1 (d) t D F 2 (d) F 1 (d) def = ⌧ D J stmt 1 K(FILTER D J bexp Kd) F 2 (d) def = ⌧ D J stmt 2 K(FILTER D J not bexp Kd) ⌧ D J while l bexp do stmt od Kd def = FILTER D J not bexp K O D D (x) def = d t D ⌧ D J stmt K(FILTER D J bexp Kx) ⌧ D J stmt 1 stmt 2 Kd def = ⌧ D J stmt 2 K(⌧ D J stmt 1 Kd)
⌧ D J prog K = ⌧ D J stmt l K def = ⌧ D J stmt K> D (3.4.1)
where the abstract postcondition semantics ⌧ D J stmt K 2 D ! D of each program instruction stmt is defined in Figure 3.10.

The following result proves the soundness of ⌧ D J prog K 2 D with respect to the postcondition semantics ⌧ post J prog K 2 D (cf. Definition 3.3.1):

Theorem 3.4.3 ⌧ post J prog K ✓ D (⌧ D J prog K) Proof (Sketch).
The proof follows from the soundness of the operators of the numerical abstract domain (cf. Definition 3.4.1) used for the definition of ⌧ D J prog K 2 D.

⌅

In this way, we can collect the possible numerical abstractions at each program control point. At the initial control point, the possible numerical abstraction is the element > D :

⌧ \ I (iJ prog K) def = > D .
Then, for each instruction stmt, the numerical abstraction ⌧ \ I (f J stmt K) 2 D at its final control point is defined by the abstract postcondition semantics (cf. Figure 3.10), taking as input the numerical abstraction d 2 D at the final control point of the instruction preceding stmt (or the element > D in case stmt is the first instruction of the program):

⌧ \ I (f J stmt K) def = ⌧ D J stmt Kd.
For a while loop, the numerical abstraction ⌧ \ I (iJ while l bexp do stmt od K) 2 D at its initial control point is defined as the limit O D of the increasing chain

y 0 def = d, y n+1 def = y n O D D (y n )
, where d is the input numerical abstraction and the function D : D ! D is defined in Figure 3.10:

⌧ \ I (iJ while l bexp do stmt od K) def = O D
The numerical abstraction ⌧ \ I (iJ stmt K) 2 D at the initial control point of the loop body is the numerical abstraction at the initial control point of the loop filtered by the boolean expression bexp:

⌧ \ I (iJ stmt K) def = FILTER D J bexp K⌧ \ I (iJ while l bexp do stmt od K)
The following result proves, for each program control point l 2 L, the soundness of the abstract invariance semantics ⌧ \ I 2 D with respect to the invariance semantics ⌧ I (l) 2 P(E) proposed in Section 3.3:

Theorem 3.4.4 8l 2 L : ⌧ I (l) ✓ D (⌧ \ I (l))
Proof (Sketch).

The proof follows from the definition of ⌧ I (l) 2 P(E) (cf. Section 3.3) and ⌧ \ I 2 D, and from Theorem 3.4.3.

⌅

Various numerical abstract domains have been proposed in the literature. We refer to [START_REF] Miné | Weakly Relational Numerical Abstract Domains[END_REF] for an overview. In the following, we briefly recall the well-known numerical abstract domains of intervals [START_REF] Cousot | Static Determination of Dynamic Properties of Programs[END_REF], convex polyhedra [START_REF] Cousot | Automatic Discovery of Linear Restraints Among Variables of a Program[END_REF], and octagons [START_REF] Miné | The Octagon Abstract Domain[END_REF]. They are the foundation upon which we develop new abstract domains in Chapter 5 and Chapter 6.

Intervals Abstract Domain

The intervals abstract domain is a non-relational numerical abstract domain. Non-relational abstract domains abstract each program variable independently, thus forgetting any relationship between variables. They are an abstraction of the power set of environments given by the Galois connection hP(E), ✓ i !

↵ C C
hX ! P(Z), ✓i where the abstraction ↵ C : P(E) ! (X ! P(Z)) and the concretization C : (X ! P(Z)) ! P(E) are defined as follows:

↵ C (E) def = X 2 X . {⇢(X) 2 Z | ⇢ 2 E} C (f ) def = {⇢ 2 E | 8X 2 X : ⇢(X) 2 f (X)} (3.4.2)
This abstraction, from now on, is called cartesian abstraction. Specifically, the interval abstract domain maintains an upper bound and a lower bound on the possible values of each program variable. It was introduced by Patrick Cousot and Radhia Cousot [START_REF] Cousot | Static Determination of Dynamic Properties of Programs[END_REF] and it is still widely used as it is e cient and yet able to provide valuable information crucial to prove the absence of various run-time errors.

In the following, the intervals abstract domain is denoted by hB, v B i. The abstraction is formalized by a Galois connection hX ! P(Z), ✓i !

↵ B B hB, v B i.
Most operators of the domain rely on well-known interval arithmetics [START_REF] Moore | Interval Analysis[END_REF]. We do not discuss the details here and we refer instead to [START_REF] Miné | Weakly Relational Numerical Abstract Domains[END_REF].

Polyhedra Abstract Domain

The polyhedra abstract domain, introduced by Patrick Cousot and Nicolas Halbwachs [START_REF] Cousot | Automatic Discovery of Linear Restraints Among Variables of a Program[END_REF], is a relational numerical abstract domain. Relational abstract domains are more precise than non-relational ones since they are able to preserve some of the relationships between the program variables. Specifically, the polyhedra abstract domain allows inferring a ne inequalities

c 1 X 1 + . . . + c k X k + c
k+1 0 between the program variables. In the following, the polyhedra abstract domain is denoted by hP, v P i. The abstraction is formalized as a concretization-based abstraction hP(E), ✓i P hP, v P i. We again omit the details and we refer to [START_REF] Cousot | Automatic Discovery of Linear Restraints Among Variables of a Program[END_REF][START_REF] Miné | Weakly Relational Numerical Abstract Domains[END_REF].

Octagons Abstract Domain

The octagons abstract domain is a weakly-relational abstract domain. It was introduced by Antoine Miné [START_REF] Miné | The Octagon Abstract Domain[END_REF] to answer the need for a trade-o↵ between non-relational abstract domains, that are very cheap but quite imprecise, and relational abstract domains, that are very expressive but quite costly.

The octagons abstract domain, in the following denoted by hO, v O i, allows inferring inequalities of the form ±X i ±X j c between the program variables. It is based on the e cient Di↵erence Bound Matrix data structure [START_REF] Kim Guldstrand Larsen | E cient Verification of Real-Time Systems: Compact Data Structure and State-Space Reduction[END_REF].

The abstraction, since our program variables have integer values (cf. Section 3.1), is formalized by a Galois connection hP(E), ✓i !

↵ O O hO, v O i.
We refer to [START_REF] Miné | Weakly Relational Numerical Abstract Domains[END_REF][START_REF] Miné | The Octagon Abstract Domain[END_REF] for a more detailed discussion.

Note that, the intervals [START_REF] Cousot | Static Determination of Dynamic Properties of Programs[END_REF], convex polyhedra [START_REF] Cousot | Automatic Discovery of Linear Restraints Among Variables of a Program[END_REF], and octagons [START_REF] Miné | The Octagon Abstract Domain[END_REF] numerical abstract domains maintain information about the set of possible values of the program variables along with the possible numerical relationships between them using convex sets consisting of conjunctions of linear constraints. The convexity of these abstract domains makes the analysis scalable. On the other hand, it might lead to too harsh approximations and imprecisions in the analysis, ultimately yielding false alarms and a failure of the analyzer to prove the desired program property.

The key for an adequate cost versus precision trade-o↵ is handling disjunctions arising during the analysis (e.g., from program tests and loops). In practice, numerical abstract domains are usually refined by adding weak forms of disjunctions to increase the expressivity while minimizing the cost of the analysis [CCM10, GR98, GC10a, SISG06, etc.].

An Abstract Interpretation Framework for Termination

In this chapter, we recall and revise the abstract interpretation framework for potential and definite termination proposed by Patrick Cousot and Radhia Cousot [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF]. In particular, we recall their fixpoint semantics for definite termination, which is at the basis of our work. For potential termination, we choose a di↵erent fixpoint semantics. Then, we provide the definition of the semantics for definite termination for our small language of Chapter 2.

Dans ce chapitre, nous rappelons et révisons le cadre de l'interprétation abstraite de terminaison et de terminaison potentielle proposé par Patrick Cousot et Radhia Cousot [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF]. En particulier, nous rappelons leur sémantique de point fixe pour la terminaison, qui est à la base de notre travail. Pour la terminaison potentielle, nous choisissons une sémantique de point fixe di↵érente. Ensuite, nous fournissons la définition de la sémantique de terminaison pour notre petit langage du Chapitre 2.

Ranking Functions

The traditional method for proving program termination dates back to Alan Turing [START_REF] Turing | Checking a Large Routine[END_REF] and Robert W. Floyd [START_REF] Floyd | Assigning Meanings to Programs[END_REF]. It consists in inferring ranking functions, namely functions from program states to elements of a well-ordered set whose value decreases during program execution. Definition 4.1.1 (Ranking Function) Given a transition system h⌃, ⌧ i, a ranking function is a partial function f : ⌃ * W from the set of states ⌃ into a well-ordered set hW, i whose value decreases through transitions between states, that is 8s, s 0 2 dom(f ) : hs, s 0 i 2 ⌧ ) f (s 0 ) < f(s).

The best known well-ordered sets are the natural numbers hN, i and the ordinals hO, i, and the most obvious ranking function maps each program state to the number of program execution steps until termination, or some well-chosen upper bound on this number.

while 2 (1 < x) do 3 x := x 1 od 4
The loop terminates whatever the initial value of the variable x. In order to prove it, we define a ranking function f : ⌃ ! N whose domain coincides with the set of program states and whose value is an upper bound on the number of state transitions until termination. We have defined the program transition relation ⌧ 2 ⌃⇥⌃ in Example 3.2.3. In particular, as in Section 3.3, we partition with respect to the program control points, and we define the ranking function f : L ! (E ! N):

f (2) def = ⇢.
(

⇢(x)  1 2⇢(x) 1 1 < ⇢(x) f (3) def = ⇢. ( 2 ⇢(x)  2 2⇢(x) 2 2 < ⇢(x) f (4) def = 1
⇢. 0 Note that, at the final program control point 4, the program is terminated and thus no transitions are needed.

At the program control point 2 and 3, the value of the ranking function depends on the value of the program variable x in the current environment ⇢. As an example, given the state h2, {hx, 2i}i, the transitions needed to reach termination are h2, {hx, 2i}i ! h3, {hx, 2i}i, h3, {hx, 2i}i ! h2, {hx, 1i}i, and h2, {hx, 1i}i ! h4, {hx, 1i}i (cf. Example 3.2.4). Indeed, f (2){hx, 2i} = 3, . . . Thus, in order to prove that the program terminates, we define a ranking function f : ⌃ ! O mapping the program states to ordinals:

f (3){hx, 2i} = 2,
f (1) def =
⇢. ! where f (2), f (3), and f (4) are defined as above. Note that, the value ! does not provide an upper bound on the number of transitions until termination that depends on the value of the program variable x but simply testifies that this number is finite, meaning that the program always terminates. Indeed, even when starting from !, a strictly decreasing function cannot decrease forever since ordinals are a well-ordered set.

In the following, we also consider a weaker notion of ranking function, called potential ranking function. The value of a potential ranking function decreases at least along one transition during program execution.

Definition 4.1.3 (Potential Ranking Function) Given a transition system h⌃, ⌧ i, a potential ranking function is a partial function f : ⌃ * W from ⌃ to a well-ordered set hW, i whose value decreases through at least one transition from each state, that is 8s 2 dom(f ) : (9s 0 2 dom(f ) : hs, s 0 i 2 ⌧ ) ) 9s 0 2 dom(f ) : hs, s 0 i 2 ⌧ ^f (s 0 ) < f(s).

Termination Semantics

In [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF], Patrick Cousot and Radhia Cousot prove the existence of a most precise program ranking function that can be derived by abstract interpreta-tion of the program maximal trace semantics. In the following, we recall from [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF] the results that are most relevant to our work.

Potential and Definite Termination. In presence of non-determinism, we distinguish between potential termination or may-terminate properties and definite termination or must-terminate properties. The property of potential termination requires a program to have at least one finite execution trace. Definition 4.2.1 (Potential Termination) A program with trace semantics S 2 P(⌃ +1 ) may terminate if and only if S \ ⌃ + 6 = ;.

The property of definite termination requires all execution traces of a program to be finite (cf. also Example 2.2.13).

Definition 4.2.2 (Definite Termination) A program with trace semantics S 2 P(⌃ +1 ) must terminate if and only if S ✓ ⌃ + .

In the following, when clear from the context, we will refer to the property of definite termination simply as property of termination.

Termination Trace Semantics

We present a first abstraction of the program maximal trace semantics (cf. Definition 2.2.8 and Equation 2.2.5, and Definition 3.2.5) into a potential termination trace semantics and a definite termination trace semantics.

The definite (resp. potential) termination trace semantics eliminates the program execution traces that are not starting with a state from which the program execution must (resp. may) terminate.

I def = {1} ⇥ E. The program transition relation ⌧ 2 ⌃ ⇥ ⌃ is ⌧ def = {h1, ⇢i ! h2, ⇢i | ⇢ 2 E} [ {h2, ⇢i ! h1, ⇢i | ⇢ 2 E} [ {h1, ⇢i ! h3, ⇢i | ⇢ 2 E}.
The maximal trace semantics ⌧ +1 2 P(⌃ +1 ) of the program (cf. Definition 3.2.5) contains the execution traces starting from the initial states I that enter the while loop a non-deterministic number of times:

⌧ +1 def = {h1, ⇢i(h2, ⇢i) ⇤ h3, ⇢i | ⇢ 2 E} [ {h1, ⇢i(h2, ⇢i) ! | ⇢ 2 E}.
↵ m (T ) def = T \ ⌃ + m (T ) def = T [ ⌃ ! (4.2.1)
This abstraction, from now on, is called potential termination abstraction. It forgets about non-terminating program executions.

Example 4.2.4

Let T = {ab, aba, ba, bb, ba ! }. Then, the potential termination abstraction of

T is ↵ m (T ) = {ab, aba, ba, bb}.
Definition 4.2.5 (Potential Termination Trace Semantics) The potential termination trace semantics ⌧ m 2 P(⌃ + ) is defined as follows:

⌧ m def = ↵ m (⌧ +1 )
where ⌧ +1 2 P(⌃ +1 ) is the maximal trace semantics (cf. Definition 2.2.8).

The following result provides, by Kleenian fixpoint transfer (cf. Theorem 2.2.20) from the fixpoint maximal trace semantics (cf. Equation 2.2.5), a fixpoint definition of the potential termination trace semantics within the complete lattice hP(⌃ + ), ✓, [, \, ;, ⌃ + i: Theorem 4.2.6 (Potential Termination Trace Semantics) The potential termination trace semantics ⌧ m 2 P(⌃ + ) can be expressed as a least fixpoint in the complete lattice hP(⌃ + ), ✓, [, \, ;, ⌃ + i as follows:

⌧ m = lfp ✓ m m (T ) def = ⌦ [ (⌧ ; T ) (4.2.2)
In this case, the abstraction function ↵ m : P(⌃ +1 ) ! P(⌃ + ) is a complete [-morphism and thus there also exists a Galois connection hP(

⌃ +1 ), v i ! ! ↵ m ¯ m hP(⌃ + ), ✓i, where the concretization function ¯ m 2 P(⌃ + ) ! P(⌃ +1 ) is defined as ¯ m (T ) def = T .
Note that, because of the distinction between the approximation order ✓ and the computational order v, such Galois connection is di↵erent from the potential termination abstraction presented above (cf. Equation 4.2.1).

Example 4.2.7

Let us consider again the program of Example 4.2.3:

while 1 ( ? ) do 2 skip od 3 Its potential termination trace semantics is ⌧ m def = {h1, ⇢i(h2, ⇢i) ⇤ h3, ⇢i | ⇢ 2 E}
since an execution trace starting from the state h1, ⇢i may terminate (by choosing a transition to the state h3, ⇢i).

Definite Termination Trace Semantics. The definite termination trace semantics ⌧ M 2 P(⌃ + ) eliminates all program execution traces potentially branching, through local non-determinism, to non-termination.

We define the neighborhood of a sequence 2 ⌃ +1 in a set of sequences T ✓ ⌃ +1 as the set of sequences 0 2 T with a common prefix with :

nbhd( , T ) def = { 0 2 T | pf( ) \ pf( 0 ) 6 = ;} (4.2.3)
where pf 2 ⌃ +1 ! P(⌃ +1 ) yields the set of prefixes of a sequence 2 ⌃ +1 : pf( )

def = { 0 2 ⌃ +1 | 9 00 2 ⌃ ⇤1 : = 0 00 }. ( 4

.2.4)

A program execution trace belongs to the definite termination trace semantics if and only if it is finite and its neighborhood in the program semantics consists only of finite traces. The corresponding definite termination abstraction

↵ M : P(⌃ +1 ) ! P(⌃ +
) is defined as follows:

↵ M (T ) def = { 2 T + | nhbd( , T ! ) = ;}. (4.2.5)
where

T + def = T \ ⌃ + and T ! def = T \ ⌃ ! .
Example 4.2.8 Let T = {ab, aba, ba, bb, ba ! }. Then, ↵ M (T ) = {ab, aba} since pf(ab) \ pf(ba ! ) = ; and pf(aba) \ pf(ba ! ) = ;, while pf(ba) \ pf(ba ! ) = {ba} 6 = ; and pf(bb) \ pf(ba ! ) = {b} 6 = ;.

Definition 4.2.9 (Definite Termination Trace Semantics) The definite termination trace semantics ⌧ M 2 P(⌃ + ) is defined as follows:

⌧ M def = ↵ M (⌧ +1 )
where ⌧ +1 2 P(⌃ +1 ) is the maximal trace semantics (cf. Definition 2.2.8).

The following result provides, by Tarskian fixpoint transfer (cf. Theorem 2.2.21) from the fixpoint maximal trace semantics (cf. Equation 2.2.5), a fixpoint definition of the definite termination trace semantics within the complete lattice hP(⌃ + ), ✓, [, \, ;, ⌃ + i: Theorem 4.2.10 (Definite Termination Trace Semantics) The definite termination trace semantics ⌧ M 2 P(⌃ + ) can be expressed as a least fixpoint in the complete lattice hP(⌃ + ), ✓, [, \, ;, ⌃ + i:

⌧ M = lfp ✓ M M (T ) def = ⌦ [ ((⌧ ; T ) \ ¬(⌧ ; ¬T )) (4.2.6)
where ¬(⌧ ; ¬T ) stands for ⌃ + \ (⌧ ; (⌃ + \ T )): the term ¬(⌧ ; ¬T ) eliminates potential transition towards non-terminating executions.

Example 4.2.11

Let us consider again the program of Example 4.2.3:

while 1 ( ? ) do 2 skip od 3
Its definite termination trace semantics is ⌧ M def = ; since for any execution trace starting from the state h1, ⇢i there is a possibility of non-termination (by always choosing a transition to the state h2, ⇢i).

Termination Semantics

We now further abstract the definite (resp. potential) termination trace semantics into a definite (resp. potential ) termination semantics, which is the most precise ranking function (resp. potential ranking function) that can be derived by abstract interpretation of the program maximal trace semantics.

Proposition 4.2.12 A program, whose maximal trace semantics is generated by a transition system h⌃, ⌧ i, terminates if and only if the program transition relation ⌧ 2 ⌃ ⇥ ⌃ is well-founded.

When considering a given set I ✓ ⌃ of initial states, the program execution traces starting from an initial state are terminating if and only if the program transition relation is well-founded when restricted to reachable states:

⌧ ✓ ↵ R (⌧ +1 ) ⇥ ↵ R (⌧ +1 ), where ↵ R : P(⌃ +1 ) ! P(⌃) is the reachability abstraction defined in Example 2.2.18.
In the case when the program semantics is not generated by a transition system (cf. Remark 2.2.10), we might consider its transition abstraction given by the Galois connection hP(⌃ +1 ), ✓i !

↵ (T ) def = {hs, s 0 i | 9 2 ⌃ ⇤ , 0 2 ⌃ ⇤1 : ss 0 0 2 T }. (4.2.7)
Note, however, that in this case the condition of Proposition 4.2.12 is su cient but not necessary (i.e., the program execution traces starting from an initial states are terminating if the program transition relation is well-founded when restricted to reachable states), as shown by the following counterexample.

Counterexample 4.2.13 Let ⌃ = {a, b}. The program whose semantics T is the set of fair traces a ⇤ b is terminating but the transition abstraction ! ↵ (T ) = {ha, ai, ha, bi} generates the infinite trace a ! (cf. also Remark 2.2.10). Thus, the transition relation restricted to the reachable states is not well-founded.

An over-approximation R ◆ ↵ R (⌧ +1 ) of the reachable states can be computed by abstract interpretation, as we have seen in Section 3.4. The program transition relation restricted to the reachable states

⌧ ✓ ↵ R (⌧ +1 ) ⇥ ↵ R (⌧ +1 ) is well-founded if its over-approximation r ✓ R ⇥ R is well-founded. More- over, r ✓ R ⇥ R is well-founded if
and only if there exists a ranking function f : ⌃ * W into a well-ordered set hW, i whose domain is R: dom(f ) = R. Thus, for programs whose maximal trace semantics is generated by a transition system, (potential) termination can be proved by exhibiting a (potential) ranking function mapping invariant states to elements of a well-ordered set.

In the following, we consider the set of partial functions from the program states ⌃ into the well-ordered set of ordinals hO, i.

Potential Termination Semantics. The potential termination semantics is the most precise potential ranking function ⌧ mt 2 ⌃ * O for a program. It is defined starting from the final states in ⌦, where the function has value zero, and retracing the program backwards while mapping each program state in ⌃ potentially leading to a final state (i.e., a program state such that there exists a terminating program execution trace to which it belongs) to an ordinal in O representing the minimum number of program execution steps remaining to termination. The domain dom(⌧ mt ) of ⌧ mt is the set of states from which the program execution may terminate: at least one trace branching from a state s 2 dom(⌧ mt ) terminates in at least ⌧ mt (s) execution steps, while all traces branching from a state s 6 2 dom(⌧ mt ) do not terminate.

Intuitively, a potential ranking function f 1 is more precise than another potential ranking function f 2 when it is defined over a smaller set of program states, that is, it can disprove termination for more program states, and when its value is always smaller, that is, the minimum number of program execution steps required for termination is lower. The approximation order is then:

f 1 v f 2 () dom(f 1 ) ✓ dom(f 2 ) ^8x 2 dom(f 1 ) : f 1 (x)  f 2 (x).
⌧ mt def = ↵ mrk (↵ m (⌧ +1 )) = ↵ mrk (⌧ m ) (4.2.9)
where the potential ranking abstraction ↵ mrk :

P(⌃ + ) ! (⌃ * O) is: ↵ mrk (T ) def = ↵ mv ( ! ↵ (T )) (4.2.10)
where the function ↵ mv : P(⌃ ⇥ ⌃) ! (⌃ * O) provides the rank of the elements in the domain of a relation r ✓ ⌃ ⇥ ⌃:

↵ mv (;) def = ; ↵ mv (r)s def = 8 > < > : 0 8s 0 2 ⌃ : hs, s 0 i 6 2 r inf ( ↵ mv (r)s 0 + 1 s 0 2 dom(↵ mv (r)) ^hs, s 0 i 2 r ) otherwise
The following result provides, by Kleenian fixpoint transfer (cf. Theorem 2.2.20) from the fixpoint potential termination trace semantics (cf. Equation 4.2.2), a fixpoint definition of the potential termination semantics within the partially ordered set h⌃ * O, vi, where the computational order coincides with the approximation order defined in Equation 4

⌧ mt = lfp v ; mt mt (f ) def = s. 8 > < > : 0 s 2 ⌦ inf {f (s 0 ) + 1 | hs, s 0 i 2 ⌧ } s 2 pre(dom(f )) undefined otherwise (4.2.11) Example 4.2.16
Let us consider the following trace semantics:

The fixpoint iterates of the potential termination semantics ⌧ mt 2 ⌃ * O are:

0 0 1 1 0 0 2 1 1 0 0 2 1 1 0 0
where unlabelled states are outside the domain of the function.

Note that our definition of the potential termination semantics ⌧ mt 2 ⌃ * O di↵ers from [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF]: the value of the ranking function for a state is the greatest lower bound (instead of the least upper bound ) of the value plus one of the ranking function for its successors. In fact, the following example shows that the definition of [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF] does not guarantee the existence of a least fixed point.

Example 4.2.17 Let us consider again the program of Example 4.2.7:

while 1 ( ? ) do 2 skip od 3
The iterates of the potential termination semantics ⌧ mt 2 ⌃ * O with respect to the program control points are the following:

f 0 (1) def = ; f 0 (2) def = ; f 0 (3) def = ; f 1 (1) def = ; f 1 (2) def = ; f 1 (3) def = ⇢. 0 f 2 (1) def = ⇢. 1 f 2 (2) def = ; f 2 (3) def = ⇢. 0 f 3 (1) def = ⇢. 1 f 3 (2) def = ⇢. 2 f 3 (3) def = ⇢. 0 f 4 (1) def = ⇢. 1 f 4 (2) def = ⇢. 2 f 4 (3) def =
⇢. 0 Instead, the iterates of the potential termination semantics of [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF] are:

f 0 (1) def = ; f 0 (2) def = ; f 0 (3) def = ; f 1 (1) def = ; f 1 (2) def = ; f 1 (3) def = ⇢. 0 f 2 (1) def = ⇢. 1 f 2 (2) def = ; f 2 (3) def = ⇢. 0 f 3 (1) def = ⇢. 1 f 3 (2) def = ⇢. 2 f 3 (3) def = ⇢. 0 f 4 (1) def = ⇢. 3 f 4 (2) def = ⇢. 2 f 4 (3) def = ⇢. 0 f 5 (1) def = ⇢. 3 f 5 (2) def = ⇢. 4 f 5 (3) def = ⇢. 0 f 6 (1) def = ⇢. 5 f 6 (2) def = ⇢. 4 f 6 (3) def = ⇢. 0 . . . f ! (1) def = ⇢. ! f ! (2) def = ⇢. ! f ! (3) def = ⇢. 0 f !+1 (1) def = ⇢. ! + 1 f !+1 (2) def = ⇢. ! + 1 f !+1 (3) def = ⇢. 0 . . .
In particular, note that the value of the potential termination semantics at the program control points 1 and 2 is always increasing.

The potential termination semantics is sound and complete for proving potential termination of a program for a given set of initial states I ✓ ⌃: Theorem 4.2.18 A program may terminate for execution traces starting from a given set of initial states I if and only if I ✓ dom(⌧ mt ).

Proof. See Appendix A.2.

⌅ Definite Termination Semantics. The definite termination semantics is the most precise ranking function ⌧ Mt 2 ⌃ * O for a program. It is defined starting from the final states in ⌦, where the function has value zero, and retracing the program backwards while mapping each program state in ⌃ definitely leading to a final state (i.e., a program state such that all program execution traces to which it belongs are terminating) to an ordinal in O representing an upper bound on the number of program execution steps remaining to termination. The domain dom(⌧ Mt ) of ⌧ Mt is the set of states from which the program execution must terminate: all traces branching from a state s 2 dom(⌧ Mt ) terminate in at most ⌧ Mt (s) execution steps, while at least one trace branching from a state s 6 2 dom(⌧ Mt ) does not terminate.

Intuitively, a ranking function f 1 is more precise than another ranking function f 2 when it is defined over a larger set of program states, that is, it can prove termination for more program states, and when its value is always smaller, that is, the maximum number of program execution steps required for termination is smaller. The approximation order is then:

f 1 4 f 2 () dom(f 1 ) ◆ dom(f 2 ) ^8x 2 dom(f 2 ) : f 1 (x)  f 2 (x).
⌧ Mt def = ↵ Mrk (↵ M (⌧ +1 )) = ↵ Mrk (⌧ M ) (4.2.13)
where the ranking abstraction ↵ Mrk :

P(⌃ + ) ! (⌃ * O) is: ↵ Mrk (T ) def = ↵ Mv ( ! ↵ (T )) (4.2.14)
where the function ↵ Mv : P(⌃ ⇥ ⌃) ! (⌃ * O) provides the rank of the elements in the domain of a relation r ✓ ⌃ ⇥ ⌃:

↵ Mv (r)s def = 8 > < > : 0 8s 0 2 ⌃ : hs, s 0 i 6 2 r sup ( ↵ Mv (r)s 0 + 1 s 0 2 dom(↵ Mv (r)) ^hs, s 0 i 2 r ) otherwise
The following result provides a fixpoint definition of the definite termination semantics within the partially ordered set h⌃ * O, vi, where the computational order is defined as: Note that, the approximation order 4 and the computational order v coincide when the ranking functions have the same domain:

f 1 v f 2 () dom(f 1 ) ✓ dom(f 2 ) ^8x 2 dom(f 1 ) : f 1 (x)  f 2 (x).
⌧ Mt = lfp v ; Mt Mt (f ) def = s. 8 > < > : 0 s 2 ⌦ sup {f (s 0 ) + 1 | hs, s 0 i 2 ⌧ } s 2 f pre(dom(f )) undefined otherwise
Lemma 4.2.22 dom(f 1 ) = dom(f 2 ) ) (f 1 4 f 2 () f 1 v f 2 ) Proof.
The proof is immediate from Equation 4.2.12 and Equation 4.2.15.

⌅

The definite termination semantics is sound and complete for proving definite termination of a program for a given set of initial states I ✓ ⌃: Theorem 4.2.23 A program must terminate for execution traces starting from a given set of initial states I if and only if I ✓ dom(⌧ Mt ).

Proof.

See [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF].

Denotational Definite Termination Semantics

In this work, we are mostly interested in proving program definite termination.

In the following, we provide a structural definition of the fixpoint definite termination semantics ⌧ Mt 2 ⌃ * O (cf. Equation 4.2.16) by induction on the syntax of programs written in the small language presented in Chapter 3.

In Section 3.3 we partitioned the reachable state semantics ⌧ R (cf. Equation 2.2.10) into an invariance semantics ⌧ I 2 L ! P(E). Similarly, we partition ⌧ Mt with respect to the program control points:

⌧ Mt 2 L ! (E * O).
⌧ Mt J stmt K : (E * O) ! (E * O).
The termination semantics

⌧ Mt J stmt K : (E * O) ! (E * O)
of each program instruction stmt outputs a ranking function whose domain represents the terminating environments at the initial label of stmt, which is determined taking as input a ranking function whose domain represents the terminating environments at the final label of stmt, and whose value represents an upper bound on the number of program execution steps remaining to termination.

The termination semantics of a skip instruction takes as input a ranking function f : E * O whose domain represents the terminating environments at the final label of the instruction, and increases its value by one to take into account that from the environments at the initial label of the instruction another program execution step is necessary before termination:

⌧ Mt J l skip Kf def = ⇢ 2 dom(f ). f(⇢) + 1 (4.3.1)
Similarly, the termination semantics of a variable assignment l X := aexp takes as input a ranking function f : E * O whose domain represent the terminating environments at the final label of the instruction. The resulting ranking function is defined over the environments that when subject to the variable assignment always belong to the domain of the input ranking function. The value of the input ranking function for these environments is increased by one, to take into account another execution step before termination, and the value of the resulting ranking function is the least upper bound of these values:

⌧ Mt J l X := aexp Kf def = ⇢. 8 > > > > < > > > > : sup{f (⇢[X v]) + 1 | v 2 JaexpK⇢} 9v 2 JaexpK⇢ 8v 2 JaexpK⇢ : ⇢[X v] 2 dom(f ) undefined otherwise (4.3.2)
Note that, all environments yielding a run-time error due to a division by zero do not belong to the domain of the termination semantics of the assignment.

Example 4.3.1 Let X def = {x}. We consider the following ranking function f : E * O:

f (⇢) def = 8 > < > : 2 ⇢(x) = 1 3 ⇢(x) = 2 undefined otherwise
and the backward assignment x := x + [1, 2]. The termination semantics of the assignment, given the ranking function, is:

⌧ Mt J x := x + [1, 2] Kf (⇢) def = ( 4 ⇢(x) = 0 undefined otherwise
In particular, note that the function is only defined when ⇢(x) = 0. In fact, when

⇢(x) = 1, we have Jx + [1, 2]K⇢ = {0, 1} and ⇢[x 0] 6 2 dom(f ). Similarly, when ⇢(x) = 1, we have Jx+[1, 2]K⇢ = {2, 3} and ⇢[x 3] 6 2 dom(f ).
Given a conditional instruction if l bexp then stmt 1 else stmt 2 fi, its termination semantics takes as input a ranking function f : E * O and derives the termination semantics ⌧ Mt J stmt 1 Kf of stmt 1 , in the following denoted by S 1 , and the termination semantics ⌧ Mt J stmt 2 Kf of stmt 2 , in the following denoted by S 2 . Then, the termination semantics of the conditional instruction is defined by means of the ranking function F [f ] : E * O whose domain is the set of environments that belong to the domain of S 1 and to the domain of S 2 , and that due to non-determinism may both satisfy and do not satisfy the boolean expression bexp:

F [f ] def = ⇢ 2 dom(S 1 ) \ dom(S 2 ). 8 > < > : sup{S 1 (⇢) + 1, S 2 (⇢) + 1} JbexpK⇢ = {true, false} undefined otherwise
and the ranking function F 1 [f ] : E * O whose domain is the set of environments ⇢ 2 E that belong to the domain of S 1 and that must satisfy bexp:

F 1 [f ] def = ⇢ 2 dom(S 1 ). ( S 1 (⇢) + 1 JbexpK⇢ = {true} undefined otherwise
and the ranking function F 2 [f ] : E * O whose domain is the set of environments that belong to the domain of S 2 and that cannot satisfy bexp:

F 2 [f ] def = ⇢ 2 dom(S 2 ). ( S 2 (⇢) + 1 JbexpK⇢ = {false} undefined otherwise
The resulting ranking function is defined joining

F [f ], F 1 [f ],
and F [f ]:

⌧ Mt J if l bexp then stmt 1 else stmt 2 fi Kf def = F [f ] [ F 1 [f ] [ F 2 [f ] (4.3.3) Example 4.3.2 Let X def = {x}.
We consider the termination semantics of the conditional statement if bexp then stmt 1 else stmt 2 fi. We assume, given a ranking function f : E * O, that the termination semantics of stmt 1 is defined as:

⌧ Mt J stmt 1 Kf (⇢) def = ( 1 ⇢(x)  0 undefined otherwise
and that the termination semantics of stmt 2 is defined as

⌧ Mt J stmt 2 Kf (⇢) def = ( 3 0 ⇢(x) undefined otherwise
Then, when the boolean expression bexp is for example x  3, the termination semantics of the conditional statement is:

⌧ Mt J if l bexp then stmt 1 else stmt 2 fi Kf (⇢) def = 8 > < > : 2 ⇢(x)  0 4 3< ⇢(x) undefined otherwise
Instead, when bexp is for example the non-deterministic choice ?, we have:

⌧ Mt J if l bexp then stmt 1 else stmt 2 fi Kf (⇢) def = ( 4 ⇢(x) = 0 undefined otherwise
The termination semantics of a loop instruction while l bexp do stmt od takes as input a ranking function f : E * O the domain of which represents the terminating environments at the final label of the instruction, and outputs the ranking function which is defined as a least fixpoint of the function Mt : (E * O) ! (E * O) within hE * O, vi, analogously to Equation 4.2.16:

⌧ Mt J while l bexp do stmt od Kf def = lfp v ; Mt (4.3.4)
where the computational order is defined as in Equation 4.2.15:

f 1 v f 2 () dom(f 1 ) ✓ dom(f 2 ) ^8x 2 dom(f 1 ) : f 1 (x)  f 2 (x).
The function Mt : (E * O) ! (E * O) takes as input a ranking function

x : E * O and adds to its domain the environments for which one more loop iteration is needed before termination. In the following, the termination semantics ⌧ Mt J stmt Kx of the loop body is denoted by S. The function Mt is defined by means of the ranking function F [x] : E * O whose domain is the set of environments that belong to the domain of S and to the domain of the input function f , and that may both satisfy and not satisfy the boolean expression bexp:

F [x] def = ⇢ 2 dom(S) \ dom(f ). 8 > < > : sup{S(⇢) + 1, f(⇢) + 1} JbexpK⇢ = {true, false} undefined otherwise
and the ranking function F 1 [x] : E * O whose domain is the set of environments ⇢ 2 E that belong to the domain of S and that must satisfy bexp:

F 1 [x] def = ⇢ 2 dom(S).
( S(⇢) + 1 JbexpK⇢ = {true} undefined otherwise and the ranking function F 2 [f ] : E * O whose domain is the set of environments that belong to the domain of the input function f and that cannot satisfy bexp:

F 2 [f ] def = ⇢ 2 dom(f ). ( f (⇢) + 1 JbexpK⇢ = {false} undefined otherwise
The resulting ranking function is defined joining

F [x], F 1 [x], and F 2 [f ]: Mt (x) def = F [x] [ F 1 [x] [ F 2 [f ] (4.3.5)
Finally, the termination semantics of the sequential combination of instructions stmt 1 stmt 2 , takes as input a ranking function f : E * O, determines from f the termination semantics ⌧ Mt J stmt 2 Kf of stmt 2 , and outputs the ranking function determined by the termination semantics of stmt 1 from ⌧ Mt J stmt 2 Kf :

⌧ Mt J stmt 1 stmt 2 Kf def = ⌧ Mt J stmt 1 K(⌧ Mt J stmt 2 Kf ) (4.3.6)
The termination semantics ⌧ Mt J prog K 2 E * O of a program prog is a ranking function whose domain represents the terminating environments, which is determined taking as input the zero function:

Definition 4.3.3 (Termination Semantics) The termination semantics ⌧ Mt J prog K 2 E * O of a program prog is: ⌧ Mt J prog K = ⌧ Mt J stmt l K def = ⌧ Mt J stmt K( ⇢. 0) (4.3.7)
where the function

⌧ Mt J stmt K : (E * O) ! (E * O) is the termination se- mantics of each program instruction stmt.
Note that, as pointed out in Remark 3.2.2 and accordingly to Definition 3.2.5, possible run-time errors silently halting the program are ignored. More specifically, all environments leading to run-time errors are discarded and do not belong to the domain of the termination semantics of a program prog.

The termination semantics ⌧ Mt J prog K 2 E * O is usually not computable. In the next Chapter 5 and Chapter 6, we present sound decidable abstractions of ⌧ Mt J prog K by means of piecewise-defined functions. The soundness is related to the same approximation order defined in Equation 4.2.12 as:

f 1 4 f 2 () dom(f 1 ) ◆ dom(f 2 ) ^8x 2 dom(f 2 ) : f 1 (x)  f 2 (x).

Piecewise-Defined Ranking Functions

In this chapter, we present a parameterized numerical abstract domain for e↵ectively proving program termination by abstract interpretation of the definite termination semantics presented in Section 4.3. The domain is used to automatically synthesize piecewise-defined ranking functions and infer sucient preconditions for program termination. The elements of the abstract domain are piecewise-defined partial functions represented by decision trees, where the decision nodes are labeled with linear constraints, and the leaf nodes belong to an auxiliary abstract domain for functions. The abstract domain is parametric in the choice between the expressivity and the cost of the numerical abstract domain which underlies the linear constraints labeling the decision nodes, and the choice of the auxiliary abstract domain for the leaf nodes. We describe various instances based on the numerical abstract domains presented in Section 3.4 for the decision nodes, and a ne functions for the leaf nodes.

Dans ce chapitre, nous présentons un domaine abstrait numérique paramétré pour prouver e↵ectivement la terminaison de programmes par interprétation abstraite de la sémantique de terminaison présentée dans la Section 4.3. Le domaine est utilisé pour synthétiser automatiquement des fonctions de rang définies par morceaux et en déduire des conditions su santes pour la terminaison de programmes. Les éléments du domaine abstrait sont des fonctions partielles définies par morceaux représentées par des arbres de décision, où les noeuds de décision sont étiquetés avec des contraintes linéaires et les feuilles appartiennent à un domaine abstrait auxiliaire pour fonctions.

Le domaine abstrait est paramétrique dans le choix entre l'expressivité et le coût du domaine abstrait numérique qui sous-tend les contraintes linéaires étiquetant les noeuds de décision, et le choix du domaine abstrait auxiliaire pour les feuilles. Nous décrivons di↵érentes instances sur la base des domaines numériques abstraits présentés dans la Section 3.4 pour les noeuds de décision, et les fonctions a nes pour les noeuds feuilles.

Piecewise-Defined Ranking Functions

In order to abstract the termination semantics presented in Section 4.3, we consider the following concretization-based abstraction:

hE * O, 4i T hT , 4 T i which provides a sound decidable abstraction ⌧ \ Mt J prog K 2 T of the termina- tion semantics of programs ⌧ Mt J prog K 2 E * O with
respect to the approximation order defined in Equation 4.2.12:

f 1 4 f 2 def = dom(f 1 ) ◆ dom(f 2 ) ^8x 2 dom(f 2 ) : f 1 (x)  f 2 (x).
We have ⌧ Mt J prog K 4 T (⌧ \ Mt J prog K), meaning that the abstract termination semantics ⌧ \ Mt J prog K over-approximates the value of the ranking function ⌧ Mt J prog K and under-approximates its domain of definition dom(⌧ Mt J prog K). In this way, an abstraction provides su cient preconditions for program termination: if the abstract ranking function is defined on a program state, then all program execution traces branching from that state are terminating.

By pointwise lifting (cf. Equation 2.1.1) we obtain the following: The partitioning is dynamic: during the analysis, partitions (resp. decision nodes and constraints) are split (resp. added) by tests, modified by assignments and joined (resp. removed) when merging control flows. In order to minimize the cost of the analysis, a widening limits the height of the decision trees and the number of maintained disjunctions.

hL ! (E * O), 4i ˙ T hL ! T , 4T i
The abstract domain is parametric in the choice between the expressivity and the cost of the numerical abstract domain which underlies the linear constraints labeling the decision nodes, and the choice of the auxiliary abstract domain for the leaf nodes. In this chapter, we propose various instances based on the numerical abstract domains presented in Section 3.4 for the decision nodes, and a ne functions for the leaf nodes.

The following examples motivate the choice and illustrate the potential of piecewise-defined ranking functions.

Example 5.1.1 Let us consider the following program from [START_REF] Podelski | A Complete Method for the Synthesis of Linear Ranking Functions[END_REF]:

while 1 (x 0) do 2 x := 2x + 10 od 3
The program is terminating since our program variables have integer values (cf. Section 3.1). In case we admitted non-integer values, the program would not terminate for x = 10 3 . However, the program does not have a linear ranking function (cf. [START_REF] Podelski | A Complete Method for the Synthesis of Linear Ranking Functions[END_REF]). As a result, well-known methods to synthesize ranking functions like [START_REF] Podelski | A Complete Method for the Synthesis of Linear Ranking Functions[END_REF][START_REF] Bradley | The Polyranking Principle[END_REF], are not capable to guarantee its termination.

On the other hand, our method is not impaired from the fact that the program does not have a linear ranking function. The decision tree t 2 T inferred at the initial program control point is depicted in Figure 5.1a. It represents the following piecewise-defined ranking function T (t) : E * O, which proves that the program is terminating in at most nine program execution steps independently from the initial value for the program variable: 5. Piecewise-Defined Ranking Functions

x 6 0

x. 3

x 4 0

x. 7

x 3 0

x. 9 x 0

x. 5

x. 1 The leaves of the tree represent partial functions whose domain is determined by the constraints satisfied along the path to the leaf node.

T (t) def = ⇢. 8 > > > > > > < > > > > > > : 1 ⇢(x)  1 5 0  ⇢(x)  2 9 ⇢(x) = 3 7 4  ⇢(x)  5 3 6  ⇢(x)
The graphical representation of the ranking function is shown in

T (t) def = ⇢. 8 > < > : 1 ⇢(r) 1 3r + 1 0  ⇢(r) ^⇢(x) < ⇢(y) undefined otherwise
which proves that the program is terminating in at most 3r + 1 program execution steps if the initial value of the program variable x is smaller than the initial value of the program variable y. Note that the constraint x < y does not explicitly appear in the program.

The fully detailed analysis of the program proposed in Example 5.1.2 uses polyhedral constraints based on the polyhedra abstract domain (cf. Section 3.4.2) for the decision nodes.

We emphasize that, as shown by the previous example, the partitioning induced by the decision trees is semantic-based rather than syntactic-based: the linear constraints labeling the decision nodes are automatically inferred by the analysis and do not necessarily appear in the program.

Decision Trees Abstract Domain

In the following, we give a more formal presentation of the decision trees abstract domain. To this end, we introduce the family of abstract domains T(D, C, F), parameterized by a family C of auxiliary abstract domains for the linear constraints labeling the decision nodes, and a family F of auxiliary abstract domains for the leaf nodes, both parameterized by a numerical abstract domain D from Section 3.4. Adopting an OCaml terminology, each T is an abstract domain functor : a function mapping the parameter abstract domains D, C and F into a new abstract domain T(D, C, F). T can be applied to various implementations of D, C and F yielding the corresponding implementations of T(D, C, F), with no need for further programming e↵ort. We first formally define the families C, F and T. Then, we present all abstract operators needed to manipulate decision nodes, leaf nodes, and decision trees.

Decision Trees

We first dive into some details on the families of auxiliary abstract domains C and F. Then, we formally define the family of abstract domains T.

Linear Constraints Auxiliary Abstract Domain. The family of auxiliary abstract domains C is itself a functor parameterized by D, where D is any of the numerical abstract domains hD, v D i. introduced in Section 3.4.

In the following, let X def = {X 1 , . . . , X k } be the set of program variables. The elements of the numerical abstract domains of Section 3.4 are equivalently represented as sets (i.e., conjunctions) of linear constraints of the form:

±X i c (intervals abstract domain) ±X i ± X j c (octagons abstract domain) c 1 X 1 + . . . + c k X k + c k+1 0 (polyhedra abstract domain) where c, c 1 , . . . , c k , c k+1 2 Z. In the following, C B def = {±X i c | X i 2 X , c 2 Z} denotes the set of interval constraints, C O def = {±X i ± X j c | X i , X j 2 X , c 2
Z} denotes the set of octagonal constraints, and

C P def = {c 1 X 1 + . . . + c k X k + c k+1 0 | X 1 , . . . , X n 2 X , c 1 , . . . , c k , c
k+1 2 Z} denotes the set of polyhedral constraints. Let C be any of these sets of constraints. We have

C B ✓ C O ✓ C P . In particular, any interval constraint ±X i c is equiva- lent to the polyhedral constraint 0X 1 + . . . ± X i + . . . + 0X k c 0, and any octagonal constraint ±X i ± X j c is equivalent to the polyhedral constraint 0X 1 + . . . ± X i + . . . ± X j + . . . 0X k c 0.
C def = 8 < : c 1 X 1 + . . . + c k X k + c k+1 0 X 1 , . . . , X k 2 X , c 1 , . . . , c k , c k+1 2 Z gcd(|c 1 |, . . . , |c k |, |c k+1 |) = 1 9 = ;
(5.2.1) We can easily formalize the correspondence between the elements of the numerical abstract domains of Section 3.4 and sets of linear constraints as a Galois connection hP(C), v D i ! The decision tree abstract domain is parametric in the choice between the expressivity and the cost of the set C of linear constraints chosen for labeling the decision nodes, which depends on the corresponding underlying numerical abstract domain hD, v D i. As for boolean decision trees, where an ordering is imposed on all decision variables, we assume the set of program variables X to be totally ordered and we impose a total order < C on C. As an example, we define < C to be the lexicographic order on the coe cients c 1 , . . . , c n and constant c k+1 of the linear constraints c 1 X 1 + . . .

↵ C C hD, v D i,
+ c k X k + c k+1 0: a 1 X 1 + . . . + a k X k + a k+1 0 < C b 1 X 1 + . . . + b k X k + b k+1 0 () 9j > 0 : 8i < j : (a i = b i ) ^(a j < b j ) (5.2.2)
Thus, any set C equipped with < C forms a totally ordered set hC, < C i.

We define the negation ¬c of a linear constraint c as follows:

¬(c 1 X 1 + . . . + c k X k + c k+1 0) def = c 1 X 1 . . . c k X k c k+1 1 0 (5.2.
3) Note that, we decrement the value of the constant of the negated linear constraint because our program variables have integer values (cf. Section 3.1).

Example 5.2.1 Let X def = {x} and let us consider the linear constraint x 2 0. Its negation ¬(x 2 0) is the linear constraint x + 1 0 (i.e., x  1).

In order to ensure a canonical representation of the decision trees, we forbid a linear constraint c and its negation ¬c from simultaneously appearing in a decision tree. As an example, between c and ¬c, we keep only the largest constraint with respect to the total order < C . We define the following equivalence relation between a linear constraint and its negation:

c 1 ⌘ C c 2 def = c 1 = ¬c 2 ^c2 = ¬c 1 (5.2.4)
Let C denote any totally ordered set hC/ ⌘ C , < C i.

Functions Auxiliary Abstract Domain. The family of abstract domains F is also a functor parameterized by any of the numerical abstract domains D introduced in Section 3.4. It is dedicated to the manipulation of the leaf nodes of a decision tree with respect to the set of linear constraints satisfied along their paths from the root of the decision tree.

The elements of these abstract domains belong to the following set:

F def = {? F } [ ⇣ Z |X | ! N ⌘ [ {> F }.
(5.2.5) which consists of natural-valued functions of the program variables, plus the element ? F and the element > F , whose meaning will be explained shortly.

In the following, the leaf nodes belonging to F \ {? F , > F } and {? F , > F } are referred to as defined and undefined leaf nodes, respectively. Moreover, the undefined leaf nodes belonging to {? F } are called ? F -leaves and those belonging to {> F } are called > F -leaves.

As an instance, in the following we consider a ne functions:

F A def = n f : Z |X | ! N f (X 1 , . . . , X k ) = m 1 X 1 + . . . + m k X k + q o [ {? F ,> F }.
(5.2.6) We now define a computational order v F and an approximation order 4 F where ? F -leaves and > F -leaves are comparable and incomparable, respectively. These orders are parameterized by a numerical abstract domain element D 2 D, which represents the linear constraints satisfied along the path to the compared leaf nodes. Intuitively, these orders abstract the computational order v defined in Equation 4.2.15 and the approximation order 4 defined in Equation 4.2.12, respectively. We have observed in Lemma 4.2.22 that v and 4 coincide when the ranking functions have the same domain. Analogously, the approximation order 4 F and the computational order v F between defined leaf nodes are identical and defined as follows:

f : Z |X | ! N ? F > F (a) > F f : Z |X | ! N ? F (b)
f 1 4 F [D] f 2 () 8⇢ 2 D (D) : f 1 (⇢(x 1 ), . . . , ⇢(x k ))  f 2 (⇢(x 1 ), . . . , ⇢(x k )) (5.2.7) f 1 v F [D] f 2 () 8⇢ 2 D (D) : f 1 (⇢(x 1 ), . . . , ⇢(x k ))  f 2 (⇢(x 1 ), . . . , ⇢(x k )). (5.2.8)
Instead, when one or both leaf nodes are undefined, the approximation and computational order are defined by the Hasse diagrams in Figure 5.3a and Figure 5.3b, respectively. Note that, as we mentioned, in the approximation order ? F -leaves and > F -leaves are incomparable.

A leaf node, together with its path from the root of the decision tree, represents a (piece of a) partial ordinal-valued functions of environments. We define the following concretization-based abstraction:

hE * O, 4i F [D] hF, 4 F i
where D 2 D represents the path to the leaf node. The concretization function

F : D ! F ! (E * O)
is defined as follows:

F [D]? F def = ; F [D]f def = ⇢ 2 D (D) : f (⇢(x 1 ), . . . , ⇢(x k )) F [D]> F def = ;
(5.2.9)

Note that, both F and > F represent the totally undefined function.

The following result proves that, given D 2 D, F [D] is monotonic:

Lemma 5.2.2 8f 1 , f 2 2 F : f 1 4 F [D] f 2 ) F [D]f 1 4 F [D]f 2 .
Proof. See Appendix A.3.

⌅

Note that, for now, we are approximating ordinal-valued functions by means of natural-valued functions. The next Chapter 6, will be dedicated to abstractions based on ordinal-valued functions.

Decision Trees Abstract Domain. We can now use the families of domains D, C and F to build the decision trees abstract domains T(D, C, F).

The elements of these abstract domains belong to the following set:

T def = {LEAF : f | f 2 F} [ {NODE{c} : t 1 ; t 2 | c 2 C, t 1 , t 2 2 T } (5.2.10)
where F is defined in Equation 5.2.5 and C is defined in Equation 5.2.1. A decision tree t 2 T is either a leaf node LEAF : f , with f an element of F (in the following denoted by t.f ), or a decision node NODE{c} : t 1 ; t 2 , such that c is a linear constraint in C (in the following denoted by t.c) and the left subtree t 1 and the right subtree t 2 (in the following denoted by t.l and t.r, respectively) belong to T . In addition, given a decision tree NODE{c} : t 1 ; t 2 , we impose that the linear constraint c 2 C is always the largest constraint, with respect to < C , appearing in the tree. In the following, let ? T def = LEAF : ? F .

A decision tree represents a partial ordinal-valued function of environments. We define the following concretization-based abstraction:

hE * O, 4i T [D] hT , 4 T i
where D 2 D represent an over-approximation of the reachable environments.

The concretization function T : D ! T ! (E * O) is defined as follows:

T [D]t def = ¯ T [ C (D)]t (5.2.11) where ¯ T : D ! T ! (E * O). The function ¯ T : D ! T ! (E * O) accu- mulates into a set C 2 P(C) (initially equal to C (D)
) the linear constraints satisfied along the paths of the decision tree up to a leaf node, where the concretization function F : D ! F ! (E * O) (cf. Equation 5.2.9) returns a partially defined function over D (↵ C (C)):

¯ T [C]LEAF : f def = F [↵ C (C)]f ¯ T [C]NODE{c} : t 1 ; t 2 def = ¯ T [C [ {c}]t 1 [ ¯ T [C [ {¬c}]t 2
The approximation order 4 T will be formally defined in the next section.

Binary Operators

In the following, we define the decision tree computational and approximation ordering. Moreover, we define binary operators for the computational and approximation join, and for the meet of decision trees.

The binary operators manipulate elements belonging to the following set:

T NIL def = {NIL} [ {LEAF : f | f 2 F} [ {NODE{c} : t 1 ; t 2 | c 2 C, t 1 , t 2 2 T NIL }
(5.2.12) A partial decision tree t 2 T NIL is either an empty tree NIL, or a leaf node leaf node LEAF : f , with f an element of F, or a decision node NODE{c} : t 1 ; t 2 , such that c is a linear constraint in C and the left subtree t 1 and the right subtree t 2 belong to T NIL . Note that T ✓ T NIL . Intuitively, the special element NIL represent the absence of information regarding some partition of the domain of the ranking function. Note that, an empty tree NIL is di↵erent from an undefined leaf node LEAF : ? F or LEAF : > F , since an undefined leaf node provides the information that the ranking function is undefined. The NIL nodes serve an algorithmic purpose. They allow carving out parts of decision trees and stitching them up on disjoint domains. In particular, NIL nodes are only temporary. They are inserted in intermediate trees during computations but disappear before the abstract operators return.

Tree Unification. The decision tree orderings and binary operators are based on Algorithm 1 for tree unification: the main function unification, given an over-approximation D 2 D of the reachable environments and two decision trees t 1 , t 2 2 T NIL , calls the auxiliary unification-aux to find a common refinement for the trees.

The function unification-aux accumulates into a set C 2 P(C) (initially equal to C (D), cf. Line 36) the linear constraints encountered along the paths of the decision trees (cf. Lines 12-13, Lines 21-22, Lines 31-32), possibly adding decision nodes (cf. Line 14, Line 23) or removing constraints that are redundant (cf. Line 7, Line 16, Line 26) or whose negation is redundant (cf. Line 9, Line 18, Line 28) with respect to C.

The redundancy check is performed by the function isRedundant which, given a linear constraint c 2 C and a set of linear constraints C 2 P(C), tests the inclusion of the corresponding numerical abstract domain elements

↵ C (C) 2 D and ↵ C ({c}) 2 D (cf. Line 2).

Piecewise-Defined Ranking Functions

Algorithm 1 : Tree Unification return unification-aux(t 1 , t 2 , C (D))

1: function isRedundant(c, C) . c 2 C, C 2 P(C) 2: return ↵ C (C) v D ↵ C ({c}) 3: 4: function unification-aux(t 1 , t 2 , C) . t 1 ,
x + 1 0

x.x + 4 NIL (a)
x 0

NIL (b)
x 0

x.x + 4

x + 1 0 Note that the tree unification does not loose any information. Then, the binary operations are carried out "leaf-wise" on the unified decision trees. Ordering. The decision tree ordering is implemented by Algorithm 2: the function order is parameterized by the choice of the ordering E between leaf nodes and, given a sound over-approximation D 2 D of the reachable environments and two decision trees t 1 , t 2 2 T , calls the function unification for tree unification (cf. Line 11) and then calls the auxiliary function orderaux. The function order-aux accumulates into a set C 2 P(C) (initially 82 5. Piecewise-Defined Ranking Functions Algorithm 2 : Tree Order

x.x + 4 NIL (c) x 0 NIL x + 1 0 (d)
1: function order-aux(E, t 1 , t 2 , C) . t 1 , t 2 2 T , C 2 P(C), E 2 {4 F , v F } 2:
if isLeaf(t 1 ) ^isLeaf(t 2 ) then 3: return order-aux(E, t 1 , t 2 , C (D))

return LEAF : t 1 .f E [↵ C (C)] t 2 .
Algorithm 3 : Tree Approximation Order 1: function a-order(D, t 1 , t 2 ) . D 2 D, t 1 , t 2 2 T 2:
return order(4 F , D, t 1 , t 2 ) equal to C (D), cf. Line 12) the linear constraints encountered along the paths of the decision trees (cf. Lines 6-7) up to the leaf nodes, which are compared by means of the chosen ordering E (cf. Line 3).

In particular, the approximation ordering 4 T and the computational ordering v T are implemented by Algorithm 3 and Algorithm 4, respectively: the functions a-order of Algorithm 3 and c-order of Algorithm 4 call the function order of Algorithm 2 choosing respectively the approximation order 4 F (cf. Equation 5.2.7 and Figure 5.3a) and the computational order v F (cf. Equation 5.2.8 and Figure 5.3b).

The following result proves that, given D 2 D, the concretization function

T [D] is monotonic with respect to the approximation order 4 T [D]: Lemma 5.2.4 8t 1 , t 2 2 T : t 1 4 T [D] t 2 ) T [D]f 1 4 T [D]f 2 . Proof. See Appendix A.3. ⌅ Join.
return LEAF : t 1 .f [↵ C (C)] t 2 .f 6:
else if isNode(t 1 ) ^isNode(t 2 ) then 7:

c t 1 .c 8: (l 1 , l 2 ) join-aux(t 1 .l, t 2 .l, C [ {c}) 9: (r 1 , r 2 ) join-aux(t 1 .r, t 2 .r, C [ {¬c}) 10:
return (NODE{c} : l 1 ; r 1 , NODE{c} : l 2 ; r 2 ) 11:

12: function join( , D, t 1 , t 2 ) . D 2 D, t 1 , t 2 2 T NIL , 2 {g F , t F } 13: (t 1 , t 2 ) unification(D, t 1 , t 2 ) 14: return join-aux( , t 1 , t 2 , C (D))
join is parameterized by the choice of the join between leaf nodes, which will be presented shortly. Given a sound over-approximation D 2 D of the reachable environments and two partial decision trees t 1 , t 2 2 T NIL , join first calls unification (cf. Line 13) and then calls the auxiliary function join-aux. The latter collects the set C 2 P(C) (initially equal to C (D), cf. Line 14) of linear constraints encountered up to the leaf nodes (cf. Lines 8-9), which are joined by the chosen operator (cf. Line 5). In case it encounters an empty tree, join-aux favors the possibly non-empty one (cf. Lines 2-3).

We define the approximation join operator g F and the computational join operator t F between leaf nodes. The approximation join is the least upper bound for the approximation order (cf. Figure 5.3a and Equation 5.2.7), and the computational join is the least upper bound for the computational order (cf. Figure 5.3b and Equation 5.2.8). These operators are parameterized by a numerical abstraction D 2 D, which represents the linear constraints satisfied along the path to the leaf nodes (cf. Line 5 of Algorithm 5).

The approximation and computational join di↵er when joining defined and 84 5. Piecewise-Defined Ranking Functions undefined leaf nodes. In this case, the approximation join is defined as follows:

? F g F [D] f def = ? F f 2 F \ {> F } f g F [D] ? F def = ? F f 2 F \ {> F } > F g F [D] f def = > F f 2 F \ {? F } f g F [D] > F def = > F f 2 F \ {? F } (5.2.13)
and the computational join is defined as follows:

? F t F [D] f def = f f2 F f t F [D] ? F def = f f2 F > F t F [D] f def = > F f 2 F f t F [D] > F def = > F f 2 F (5.2.14)
In particular, note that the approximation join is undefined when joining ? Fleaves and > F -leaves and always favors the undefined leaf nodes. Instead, given two defined leaf nodes

f 1 , f 2 2 F \ {? F , > F }, their approx- imation join f 1 g F [D] f 2 and their computational join f 1 t F [D] f 2 coincide
and they are defined as their least upper bound f 2 F \ {? F , > F } or, when such least upper bound does not exist, > F :

f 1 g F [D] f 2 def = ( f f 2 F \ {? F , > F } > F otherwise
(5.2.15)

f 1 t F [D] f 2 def = ( f f 2 F \ {? F , > F } > F otherwise (5.2.16)
where

f def = ⇢ 2 D (D). max{f 1 (⇢(X 1 ), . . . , ⇢(X k )), f 2 (⇢(X 1 ), . . . , ⇢(X k ))}.
As an instance, let us consider two a ne functions f 1 , f 2 2 F A \ {? F , > F }. Let V 6 2 X be a special variable not appearing in any program. We define the hypograph of a given a ne function

f 2 F A \{? F , > F } within a given numerical abstraction D 2 D as f [D]# def = {(X 1 , . . . , X k , V ) | C (D), V  f (X 1 , . . . , X k )}. The approximation join f 1 g F [D] f 2 and computational join f 1 t F [D] f 2 of
f 1 and f 2 are identical and defined as the a ne function f 2

F A \ {? F , > F }, whose hypograph f [D]# is the convex-hull of the hypographs f 1 [D]# and f 2 [D]#
of f 1 and f 2 , respectively; when such function does not exist, the result is > F :

f 1 g F [D] f 2 def = ( f f[D]# = convex-hull{f 1 [D]#, f 2 [D]#} > F otherwise
(5.2.17)

x 1 5 (a) x 1 5 (b) x 1 5 (c) x 1 5 (d) x 1 5 (e) x 1 5 (f)
f 1 t F [D] f 2 def = ( f f[D]# = convex-hull{f 1 [D]#, f 2 [D]#} > F otherwise (5.2.18)
To clarify, let us consider the following example: x be two a ne functions, whose domain of definition D 2 D is represented by the empty set of linear constraints C def = C (D) = ;. Then, since there is no a ne function which is

Example 5.2.5 Two a ne functions f 1 , f 2 2 F A \ {? F , > F }
x 1 x 2 4 4 (a)
x 1

x 2 4 4

(b)
x 1

x 2 4 4 (c) Algorithm 6 : Tree Approximation Join

1: function a-join(D, t 1 , t 2 ) . D 2 D, t 1 , t 2 2 T NIL 2: return join(g F , D, t 1 , t 2 )
the least upper bound of f 1 and f 2 , the result of the join is > F .

Another example of join of a ne functions is proposed in Figure 5.6.

The approximation join g T and the computational join t T of decision trees are implemented by Algorithm 6 and Algorithm 7, respectively: the functions a-join of Algorithm 6 and c-join of Algorithm 7 call the function join of Algorithm 5 choosing respectively the approximation join g F and the computational join t F between leaf nodes.

Example 5.2.7 Let X def = {x}, let D be the intervals abstract domain hB, v B i, let C be the interval constraints auxiliary abstract domain hC B / ⌘ C , < C i, and let F be the a ne functions auxiliary abstract domain hF A , 4 F i. We consider the decision trees t 1 2 T represented in Algorithm 7 : Tree Computational Join

1: function c-join(D, t 1 , t 2 ) . D 2 D, t 1 , t 2 2 T NIL 2:
return join(t F , D, t 1 , t 2 )

x 0

x. x + 4 x + 1 0 Meet. The meet of decision trees represents a ranking function defined over the intersection of their partitions. It is implemented by Algorithm 8: the function meet, given a sound over-approximation D 2 D of the reachable environments and two partial decision trees t 1 , t 2 2 T NIL , calls unification (cf. Line 12) and then calls the auxiliary function join-aux. The latter collects the set C 2 P(C) (initially equal to C (D), cf. Line 13) of linear constraints encountered up to the leaf nodes (cf. Lines 8-9), which are joined by the approximation join operator g F (cf. Line 4). However, unlike Algorithm 6, meet-aux favors empty trees over non-empty trees (cf. Line 2).

( x. x + 4) g F

Unary Operators

We now define the unary operators for handling skip instructions, backward variable assignments and program tests on decision trees.

Skip. The step operator STEP T : T ! T for handling skip instructions is implemented by Algorithm 9: the function step, given a decision tree t 2 T , descends along the paths of the decision tree (cf. Line 5) up to a leaf node, where the leaves step operator STEP F is invoked (cf. Line 3). The operator STEP F : F ! F, given a function f 2 F \ {? F , > F }, simply increments its constant to take into account that one more execution step is needed before termination; undefined leaf nodes are left unaltered: return NODE{t.c} : step(t.l); step(t.r)

STEP F (? F ) def = ? F STEP F (f ) def = X 1 , . . . , X k . f(X 1 , . . . , X k ) + 1 STEP F (> F ) def = > F (5.
The following result proves that for a skip instruction l skip, given a sound over-approximation R 2 D of ⌧ I (l) and a sound over-approximation D 2 D of ⌧ I (f J l skip K), the step operator STEP T is a sound over-approximation of the termination semantics ⌧ Mt J l skip K defined in Equation 4.3.1:

Lemma 5.2.8 ⌧ Mt J l skip K T [D]t 4 T [R]STEP T (t).
Proof. See Appendix A.3.

⌅

Tree Pruning. The remaining decision tree unary operators rely on Algorithm 10 for pruning a decision tree with respect to a given set of linear constraints. Only the subtrees whose paths from the root of the decision tree satisfy these constraints are preserved, while the other subtrees are pruned and substituted with empty trees. The function prune takes as input a decision tree t 2 T , a set C 2 P(C) of linear constraints representing an overapproximation of the reachable environments, and a set J 2 P(C) of linear constraints that need to be added to the decision tree in order to prune it. When J is empty (cf. Line 2), prune accumulates in C the linear constraints encountered along the paths (cf. Lines 8-9) up to a leaf node (cf. Line 3), possibly removing constraints that are redundant (cf. Line 5) or whose negation is redundant (cf. Line 6) with respect to C. When J is not empty (cf. Line 11), the linear constraints J are added to the decision tree in descending order with respect to < C . Note that not all constraints in J are in canonical form, that is, J 6 2 P(C/ ⌘ C ): at each iteration a linear constraint j 2 C is extracted from J (cf. Line 12), which is the largest constraint in J with respect to the constraints in canonical form.

Example 5.2.9 Let J def = {x 1 0, x + 5 0}. Note that, x + 5 0 is not in canonical form, since its negation x 6 0 is larger with respect to < C . However, when comparing x 1 0 and x + 5 0, their canonical forms are compared and thus max J is the linear constraint x + 5 0.

Then, the function prune possibly adds a decision node for the linear constraint j or its negation ¬j (cf. Lines 13-19), or continues the descent along the paths of the decision tree (cf. Lines 20-34). In the first case, prune tests j and ¬j for redundancy with respect to C (cf. Lines 14-15): when ¬j is redundant with respect to C the whole decision tree is pruned (cf. Line 15); otherwise, prune adds a decision node for j while pruning its right subtree (cf. Line 17), if j is already in canonical form (cf. Line 16), or it adds a decision node for for ¬j while pruning its left subtree (cf. Line 19), if ¬j is the canonical form of j (cf. Line 18). In the second case, prune accumulates in C the encountered linear constraints (cf. Lines 24-25), possibly removing redundant decision nodes (cf. Lines 21-22) and pruning the decision tree when the encountered linear constraints coincide with those appearing in J (cf. Lines 27-30) or their negations (cf. Lines 31-34).

Example 5.2.10 Let X def = {x}, let D be the intervals abstract domain hB, v B i, let C be the interval constraints auxiliary abstract domain hC B / ⌘ C , < C i, and let F be the a ne functions auxiliary abstract domain hF A , 4 F i. We consider the decision tree represented in Figure 5.7 from Example 5.2.7, and the set of constraints The function prune adds a decision node for the negation x 2 0 of

J def = { x + 1 0}. Let d def = > B and let C def = C (d) = ;. x 2 0 NIL x 0 x. x + 4 x + 1 0 ( x. x + 4) g F
x + 1 0, since x + 1 0 is not in canonical form (cf. Line 18), and prunes the left subtree (cf. Line 19). Then, it continues the descent along the paths of the decision tree, without removing decision nodes. The result is the decision tree represented in Figure 5.8.

Assignments.

A variable assignment might impact some linear constraints within the decision nodes as well as some functions within the leaf nodes.

We define the operator B-ASSIGN C to handle backward variable assignments by manipulating linear constraints within the decision nodes by means of the underlying numerical abstract domain hD, v D i:

B-ASSIGN C J X := aexp KD def = c. ↵ C (B-ASSIGN D J X := aexp KD( C ({c})))
(5.2.20)

The operator B-ASSIGN C J X := aexp K : D ! C ! P(C) takes as input a numerical abstraction D 2 D of the reachable environments at the initial control point of the instruction and a linear constraint c 2 C, and produces a set C 2 P(C) of linear constraints that need to be substituted to c in the decision tree. It is often the case that the set C contains a single linear constraint. However, when variable assignments and program tests cannot be exactly represented in the numerical abstract domain, the output set C contains multiple linear constraints, as shown by the following example. We now define the operator B-ASSIGN F to handle backward variable assignments within the leaf nodes of a decision tree. The operator B-ASSIGN F J X := aexp K : D ! D ! F ! F, given a numerical abstraction d 2 D of the reachable environments at the initial control point of the instructions, a numerical abstraction D 2 D of the linear constraints accumulated along the path to the leaf node, and a function f 2 F \ {? F , > F }, substitutes the arithmetic expression aexp to the variable X with the function, and increments the constant of the resulting function to take into account that one more program execution step is needed before termination; when such function does not exist, the result is > F ; undefined leaf nodes are left unaltered:

B-ASSIGN F J X := aexp Kd[D]? F def = ? F B-ASSIGN F J X := aexp Kd[D]f def = ( F F 2 F \ {? F , > F } > F otherwise B-ASSIGN F J X := aexp Kd[D]> F def = > F (5.2.21) where F (X 1 , . . . , X, . . . , X k ) def = max{f (⇢(X 1 ), . . . , v, . . . , ⇢(X k )) + 1 | ⇢ 2 D (R), v 2 J aexp K⇢} and R def = B-ASSIGN D J X := aexp Kd(D).
Note that, all possible outcomes of the backward assignment are taken into account when substituting the arithmetic expression aexp to the variable X.

As an instance, given an a ne function f 2 F A \ {? F , > F }, the result of the backward assignment is the a ne function

f 0 2 F A \ {? F , > F } whose hypograph f 0 [R]# within R is the convex-hull of the hypograph F [R]# of F ; when such a ne function does not exist, the result is > F : B-ASSIGN F J X := aexp Kd[D]f def = ( f 0 f 0 [R]# = convex-hull{F [R]#} > F otherwise
(5.2.22) To clarify, consider the following example: if isLeaf(t) then 3:

return LEAF : b-assign F J X := aexp KD[↵ D (C)]t.f 4:
else if isNode(t) then if isEmpty(I) ^isEmpty(J) then return assign-auxJ X := aexp K(D, t, C (D))

Example 5.2.12 Let X def = {x} and let D be the intervals abstract domain hB, v B i. We consider the a ne function f 2 F A \ {? F , > F } defined as f (x) function assignJ X := aexp K, given a sound over-approximation D 2 D of the reachable environments before the assignment and a decision tree t 2 T , calls the auxiliary function assign-auxJ X := aexp K, which performs the assignment on each linear constraint along the paths in the decision tree (cf. Lines 4-21), and accumulates the encountered constraints into a set C 2 P(C) (initially equal to C (D), cf. Line 24), up to the leaf nodes, where the assignment is performed by the operator B-ASSIGN F defined in Equation 5.2.21 (cf. Line 3).

In particular, for each linear constraint c 2 C appearing in the decision trees, the auxiliary function assign-auxJ X := aexp K performs the assignment on both c and its negation ¬c (cf. Lines 5-6) by means of the backward assignment operator B-ASSIGN C defined in Equation 5.2.20. Then, assign-auxJ X := aexp K possibly (cf. Line 15) calls prune to add the resulting sets of constraints I 2 P(C) and J 2 P(C) to the decision tree (cf. Lines 17-19). In case both I and J are empty (cf. Line 7), it means that neither c nor ¬c exist anymore and thus the subtrees of the decision tree are joined by the approximation join A-JOIN (cf. Line 10). Note that, the function prune introduces empty trees. However, they disappear when the subtrees are joined. Indeed, since I and J are sets of constraints resulting from the assignment on complementary linear constraints, they identify adjacent (or, due to non-determinism, overlapping) partitions. In case I is empty and J is an unsatisfiable set of constraints (cf. Line 11), it means that ¬c is no longer satisfiable and thus only the left subtree of the decision tree is kept (cf. Line 12). Similarly, in case I is an unsatisfiable set of constraints and J is empty (cf. Line 13), it means that c is no longer satisfiable and thus only the right subtree of the decision tree is kept (cf. Line 14). When both I and J are unsatisfiable sets of constraints, an error is raised (cf. Line 21).

Example 5.2.13 Let X def = {x}, let D be the intervals abstract domain hB, v B i, let C be the interval constraints auxiliary abstract domain hC B / ⌘ C , < C i, and let F be the a ne functions auxiliary abstract domain hF A , 4 F i. We consider the decision tree represented in Figure 5.9a, where ↵, 2 T are leaf nodes, and the backward assignment

x := x + [1, 2]. Let d def = > B .
The function assign-aux collects the set C def = { x + 2 0, x 1 0} of encountered linear constraints up to the leaf node LEAF : x.x + 1, where B-ASSIGN F performs the assignment (cf. Line 3). From Example 5.2.12, the result of the assignment is the leaf node LEAF : x.x + 4. Similarly, let and be the results of the assignment to ↵ and , respectively. Then, the function assign-aux performs the assignment on x 1 0 and its negation x 0 (cf. Lines 5-6) yielding the sets of constraints

x 3 0 ↵ x 1 0 x. x + 1 (a)
x 2 0

x 1 0

g F ( x. x + 4) x 0 ( x. x + 4) g F (b)
Figure 5.9: Tree assignment on the decision tree (a) of Example 5.2.13. The resulting decision tree is represented in (b).

I def = {x + 1 0} and J def = { x 1 0}
, respectively. Note that, because of non-determinism within the variable assignment, the partitions identified by I and J overlap when x = 1. The leaf node LEAF : x.x + 4 is pruned with I (cf. Line 17) and the leaf node is pruned with J (cf. Line 19); the resulting decision trees respectively represented in Figure 5.4a and Figure 5.4b are joined by the approximation join (cf. Line 20) yielding the decision tree represented in Figure 5.7 (cf. Example 5.2.7).

Finally, assign-aux performs the assignment on x 3 0 and its negation x+2 0 yielding the sets of constraints I def = {x 1 0} and J def = { x+1 0}, respectively. Note that, because of non-determinism, the partitions identified by I and J overlap when x = 1. The leaf node is pruned with I and the decision tree represented in Figure 5.7 is pruned with J; the resulting decision trees NODE{x 1 0} : ; NIL and Figure 5.8 (cf. Example 5.2.10) are joined by the approximation join yielding the decision tree represented in Figure 5.9.

In absence of run-time errors, the following result proves that for a variable assignment l X := aexp, given a sound over-approximation R 2 D of ⌧ I (l) and a sound over-approximation D 2 D of ⌧ I (f J l X := aexp K), the backward assignment operator B-ASSIGN T J X := aexp K is a sound over-approximation of return prune(step(t), C (D), J)

⌧ Mt J l X := aexp K defined in Equation 4.3.2: Lemma 5.2.14 ⌧ Mt J l X := aexp K D [D]t 4 T [R]((B-ASSIGN T J X := aexp KR)(t)
Tests. In case of a program test, all paths that are feasible in the decision tree are preserved, while all paths that for sure can never be followed according to the tested condition are discarded. We define the operator FILTER C J bexp K : D ! P(C) which takes as input a numerical abstraction D 2 D and, by means of the underlying numerical abstract domain hD, v D i, produces a set C 2 P(C) of linear constraints that need to be added to prune the decision tree:

FILTER C J bexp KD def = ↵ C (FILTER D J bexp KD) (5.2.23)
The operator FILTER T J bexp K : D ! T ! T for handling tests within decision trees is implemented by Algorithm 12: the function filterJ bexp K, given a sound over-approximation D 2 D of the reachable environments before the test and a decision tree t 2 T , reasons by induction on the structure of the boolean expression bexp. In particular, when bexp is a conjunction of two boolean expression bexp 1 and bexp 2 (cf. Line 6), the resulting decision trees are merged by the function MEET defined in Algorithm 8 (cf. Line 7). Similarly, when bexp is a disjunction of two boolean expression bexp 1 and bexp 2 (cf. Line 7), the resulting decision trees are merged by the approximation join A-JOIN defined in Algorithm 6 (cf. Line 9). Instead, when bexp is a comparison of arithmetic expressions aexp 1 ./ aexp 2 (cf. Line 10), the function step (cf. Algorithm 9) is invoked (cf. Line 12). Then, the resulting decision tree is pruned (cf. Line 12) with the set of constraints J (cf. Line 11) produced by the operator FILTER C defined in Equation 5.2.23.

In absence of run-time errors, the following result provides a sound overapproximation of ⌧ Mt J if l bexp then stmt 1 else stmt 2 fi K defined in Equation 4.3.3, given a sound over-approximation R 2 D of ⌧ I (l) and a sound over-approximation D 2 D of ⌧ I (f J if l bexp then stmt 1 else stmt 2 fi K):

Lemma 5.2.15 Let F \ 1 [t] def = (FILTER T J bexp KR)(⌧ \ Mt J stmt 1 Kt) and F \ 2 [t] def = (FILTER T J not bexp KR)(⌧ \ Mt J stmt 2 Kt).
Then, for all t 2 T , we have:

⌧ Mt J if l bexp then stmt 1 else stmt 2 fi K T [D]t 4 T [R](F \ 1 [t] g T [R] F \ 2 [t])
Proof. See Appendix A.3.

⌅

Note that, FILTER T introduces empty trees. However, they disappear when the decision trees

F \ 1 [t] and F \ 2 [t] are joined. Indeed, F \ 1 [t] and F \ 2 [t] are obtained from complementary boolean expressions.
Similarly, the next result provides, for a loop while l bexp do stmt od, a sound over-approximation \ Mt of Mt defined in Equation 4.3.5, given sound over-approximations R 2 D of ⌧ I (l) and D 2 D of ⌧ I (f J while l bexp do stmt od K):

Lemma 5.2.16 Let F \ 1 [x] def = (FILTER T J bexp KR)(⌧ \ Mt J stmt Kx) and F \ 2 [t] def = (FILTER T J not bexp KR)(t).
Then, given t 2 T , for all x 2 T we have:

Mt ( D [R]x) 4 T [R]( \ Mt (x))
where \ Mt (x)

def = F \ 1 [x] g T [R] F \ 2 [t].
Proof. See Appendix A.3. ⌅

Widening

The widening operator O T requires a more thorough discussion. The widening is allowed more freedom than the other operators, in the sense that it is temporary allowed to under-approximate the value of the termination semantics ⌧ Mt (cf. Section 4.3) or over-approximate its domain of definition, or both -in contrast with the approximation order 4 (cf. Equation 4.2.12). This is necessary in order to extrapolate a ranking function over the environments on which it is not yet defined. The only requirement is that, when the iteration sequence with widening is stable for the computational order, its limit is a sound abstraction of the termination semantics with respect to the approximation order. In the following, we discuss in detail how the widening guarantees the soundness of the analysis.

As running example, let us consider Figure 5.10. In Figure 5.10a we depict a transition system and the value of the termination semantics for the well-founded part of its transition relation. In Figure 5.10b we represent the concretization of a possible iterate of the analysis: we assume that the first iterate has individuated the states marked with value zero, the second iterate has individuated the states marked with value one, and the widening at the third iterate has extrapolated the ranking function over the states marked with value two. In this case the abstraction both under-approximates the value of the termination semantics (on the second state from the left -case B) and over-approximates its domain of definition (including the first and the last state from the left -case A and C, respectively). In case A, the nonterminating loop is outside the domain of definition of the unsound abstract function, while in case C the loop is inside. The analysis continues iterating until all these discrepancies are solved and, in the following, we explain and justify why this works in general.

For a loop while l bexp do stmt od, given a sound over-approximation R 2 D of ⌧ I (l), we define the iteration sequence with widening as follows:

y 0 def = ? T y n+1 def = ( y n \ Mt (y n ) v T [R] y n ^ \ Mt (y n ) 4 T [R] y n y n O T \ Mt (y n ) otherwise
(5.2.24) if isLeaf(t 1 ) ^isLeaf(t 2 ) then 3: return caseA-aux(t 1 , t 2 , C (D))

if t 1 .f v F [↵ C (C)] t 2 .f
In the following, its limit is denoted by lfp \ \ Mt . Note that, the usual condition for halting the iterations \ Mt (y

n ) v T [R] y n has been strengthened to \ Mt (y n ) v T [R] y n ^ \ Mt (y n ) 4 T [R]
y n in order to force the iterations to continue in case of discrepancies as in Figure 5.10b. Indeed, in situations like case A and case B, the usual halting condition \ Mt (y n ) v T [R] y n can be satisfied but the iteration sequence should not halt.

The widening O T is implemented by Algorithm 13: the function widen, given a given a sound over-approximation D 2 D of the reachable environments and two decision trees t 1 , t 2 2 T , calls in order the functions caseA (cf. Line 2), left-unification (cf. Line 3), caseBorC (cf. Line 4), and widen-aux (cf. Line 4). In the following, we detail all these functions. Check for Case A. First, the widening O T has to detect situations like case A in Figure 5.10b, where at some iterate y i in Equation 5.2.24 the domain of the termination semantics has been over-approximated including environments from which a non-terminating loop is reachable.

The following result proves in situations like case A that, given t 2 T , 100 5. Piecewise-Defined Ranking Functions a sound over-approximations R 2 D of ⌧ I (l) and a sound-overapproximation D 2 D of ⌧ I (f J while l bexp do stmt od K), an additional iterate of \ Mt removes (a subset of) the incriminated environments from the abstraction: Lemma 5.2.17 Let w def = ⌧ Mt J while l bexp do stmt od K T [D]t and, for some iterate y i , let dom( T [R]y i ) \ dom(w) 6 = ;. Then, in case A of Figure 5.10b, we have dom(

T [R] \ Mt (y i )) \ dom(w) ⇢ dom( T [R]y i ) \ dom(w). Proof.

Let dom( T [R]y

i ) \ dom(w) 6 = ;, for some iterate y i . It means that there exists at least an environment ⇢ 2 dom( T [R]y i ) such that the state hl, ⇢i 2 ⌃ belongs to a non-terminating program execution trace 2 ⌃ ! . We assumed to be in case A of Figure 5.10b. Thus, let hl 0 , ⇢ 0 i 2 ⌃ where ⇢ 0 6 2 dom( T [R]y i ) be a state reachable from hl, ⇢i on . Without loss of generality, we can assume that hl 0 , ⇢ 0 i is the immediate successor of hl, ⇢i: hhl, ⇢i, hl 0 , ⇢ 0 ii 2 ⌧ . Thus, by definition of (cf. Equation 4.3.5), we have ⇢ 6 2 dom( ( T [R]y i )) and, by Lemma 5.2.16 and by definition of the approximaiton order 4 (cf. Equation 4.2.12), we have dom(

T [R] \ Mt (y i )) ✓ dom( ( T [R]y i )) which im- plies ⇢ 6 2 dom( T [R] \ Mt (y i ))
. This concludes the proof, for case A, that dom(

T [R] \ Mt (y i )) \ dom(w) ⇢ dom( T [R]y i ) \ dom(w).
⌅ Therefore note that, in situations like case A, the iterate \ Mt (y i ) is a decision tree with more undefined leaf nodes than y i , that is y i 4 T [R] \ Mt (y i ). Moreover, when the newly added undefined leaf nodes are ? F -leaves, we have

\ Mt (y i ) v T [R] y i .
Thus, the widening O T has to detect whether some defined leaf node in y i has become a ? F -leaf in \ Mt (y i ) and, in case, turn it into a > F -leaf in order to have y i v T [R] \ Mt (y i ) but also to prevent successive iterates from mistakenly including again the same environment in their domain. This check is implemented by Algorithm 14: the main function caseA, given a sound over-approximation D 2 D of the reachable environments and two decision trees t 1 , t 2 2 T , calls unification for tree unification (cf. Line 11) and then calls the auxiliary function caseA-aux. The latter collects the set C 2 P(C) (initially equal to C (D), cf. Line 12) of the linear constraints encountered up to the leaf nodes (cf. Lines 6-7), which are compared by the computational order v F [↵ C (C)] defined in Equation 5.2.8 and Figure 5.3b (cf. Line 3) and, in case, turned into a > F -leaf (cf. Line 4). Domain Widening -Left Unification. In order to ensure convergence, the widening O T uses Algorithm 15 to limit the size of the decision trees, and thus avoid infinite sequences of partition refinements. Algorithm 15 is a slight modification of Algorithm 1: the main function left-unificaiton is parameterized by the choice of the join between leaf nodes and, given a sound over-approximation D 2 D of the reachable environments and two decision trees t 1 , t 2 2 T , calls the auxiliary function left-unification-aux in order to force the structure of t 1 on t 2 . Note that in this way, unlike Algorithm 1, Algorithm 15 might loose information.

The function left-unification-aux accumulates into a set C 2 P(C) (initially equal to C (D), cf. Line 33) the linear constraints encountered along the paths in the first decision trees (cf. Lines 17-18, Lines 27-28), possibly adding decision nodes to the second tree (cf. Line 19) or removing decision nodes from the second tree (cf. Line 10), or removing constraints that are redundant (cf. Line 5, Line 12, Line 22) or whose negation is redundant (cf. Line 7, Line 14, Line 24) with respect to C. When removing a decision node from the second tree, the left and right subtree are joined by means of join (cf. Line 10): in order to extrapolate the domain of the ranking function over environments on which it is not yet defined, the widening O T invokes leftunification choosing the computational join t F (cf. Line 3 of Algorithm 13). For this reason, since ? F -leaves might disappear when joining subtrees, it is important to check for situations like case A before the left unification.

Remark 5.2.18 Note that, in order to limit the loss of precision, it is possible to adapt the idea presented in [START_REF] Cousot | Comparing the Galois Connection and Widening/Narrowing Approaches to Abstract Interpretation[END_REF] to design a domain widening parametric in a finite set of thresholds. Is is also possible to integrate the state-of-the-art precise widening operators proposed in [START_REF] Bagnara | Precise Widening Operators for Convex Polyhedra[END_REF]. In [START_REF] Vijay | Conflict-Driven Abstract Interpretation for Conditional Termination[END_REF], we used conflictdriven learning to obtain an improvement of the precision that is similar in spirit to using a more precise domain widening. We plan to investigate further possibilities for the domain widening as part of our future work.

Check for Case B and C. Next, the widening O T has to detect situations like case B in Figure 5.10b, where at some iterate y i the value of the termination semantics has been under-approximated, and situations like case C in Figure 5.10b, where the domain of the termination semantics has been over-approximating including a non-terminating loop.

The following result proves in situations like case B that, given t 2 T , a sound over-approximations R 2 D of ⌧ I (l) and a sound-overapproximation D 2 D of ⌧ I (f J while l bexp do stmt od K), an additional iterate of \ Mt strictly increases the value of the abstraction for the incriminated environments:

Decision Trees

i , let T [R]y i (⇢) < w(⇢), for some ⇢ 2 dom(w) \ dom( T [R]y i ). For all ⇢ 2 dom( T [R] \ Mt (y i )) \ dom(w), we have T [R]y i (⇢) < T [R] \ Mt (y i )(⇢).

Proof.

For some iterate y i , let T [R]y i (⇢) < w(⇢), for some environment ⇢ 2 dom(w) \ dom( T [R]y i ). It means that the state hl, ⇢i 2 ⌃ belongs to a program execution trace 2 ⌃ + whose length from hl, ⇢i is greater than T [R]y i (⇢). Let hl 0 , ⇢ 0 i 2 ⌃ where ⇢ 0 2 dom(w) \ dom( T [R]y i ) and w(⇢ 0 )  T [R]y i (⇢ 0 ), be a state reachable from hl, ⇢i on . Without loss of generality, we can assume that from hl, ⇢i is the longest program execution trace from hl, ⇢i and that hl 0 , ⇢ 0 i is the immediate successor of hl, ⇢i: hhl, ⇢i, hl 0 , ⇢ 0 ii 2 ⌧ . Thus, by definition of (cf. Equation 4.3.5), by Lemma 5.2.16 and by definition of 4 (cf. Equation 4.2.12), we have w(⇢)

 ( T [R]y i )(⇢)  T [R] \ Mt (y i )(⇢). This concludes the proof that T [R]y i (⇢) < T [R] \ Mt (y i )(⇢).

⌅

The following result proves in situations like case C that, given t 2 T , a sound over-approximation R 2 D of ⌧ I (l) and a sound-overapproximation D 2 D of ⌧ I (f J while l bexp do stmt od K), an additional iterate of \ Mt strictly increases the value of the abstraction for the incriminated environments: Lemma 5.2.20 Let w def = ⌧ Mt J while l bexp do stmt od K T [D]t and, for some iterate y i , let dom( T [R]y i )\dom(w) 6 = ;. Then, for all ⇢ 2 dom( Proof.

T [R] \ Mt (y i ))\ dom(w) in case C of Figure 5.10b, we have T [R]y i (⇢) < T [R] \ Mt (y i )(⇢).
Let dom( T [R]y i ) \ dom(w) 6 = ;, for some iterate y i . It means that there exists at least an environment ⇢ 2 dom( T [R]y i ) such that the state hl, ⇢i 2 ⌃ belongs to a non-terminating program execution trace 2 ⌃ ! . We assume to be in case C of Figure 5.10b. For all ⇢ 2 dom( T [R]y i ) \ dom(w) 6 = ;, by definition of (cf. Equation 4.3.5), by Lemma 5.2.16, and by definition of 4 (cf. Equation 4.2.12), we have

T [R]y i (⇢) < ( T [R]y i )(⇢)  T [R] \ Mt (y i )(⇢)
. This concludes the proof, for case C.

⌅

Note that, an additional iterate of \

Mt is not able to distinguish between an under-approximation of the value of the termination semantics as in case B, and an over-approximation of its domain of definition as in case C.

Therefore, the widening O T has to detect whether the value of some defined leaf node in y i has increased in \ Mt (y i ) and, in such case, turn it into a > F -leaf in order to prevent an indefinite growth. This check is implemented by Algorithm 16: the main function caseBorC, given a sound over-approximation D 2 D of the reachable environments and two decision trees t 1 , t 2 2 T , calls the auxiliary function caseBorC-aux, which collects into a set C 2 P(C) (initially equal to C (D), cf. Line 12) the linear constraints encountered along the paths up to the leaf nodes (cf. Lines 7-8), which are compared (cf. Line 3) and, in case, turned into a > F -leaf (cf. Line 4).

Remark 5.2.21 Note that, it is also possible to allow the ranking function to increase using a finite set of thresholds instead of returning directly > F . In this way, in situations like case C, it simply delays the iteration that must return > F . However, in situations like case B, it may discover the correct ranking function and avoid losing precision.

Value Widening Finally, the widening O T extrapolates the value of the ranking function over the environments on which it was not defined before the domain widening. The heuristic that we chose consists in widening leaf nodes with respect to their adjacent leaf nodes. The rationale being that programs often loop over consecutive values of a variable, to infer the shape of the ranking function over the environments on which it was not defined we use the information available in adjacent partitions of its domain of definition.

We define an extrapolation operator H F [D 1 , D 2 ] between two defined leaf nodes f 1 , f 2 2 F \ {? F , > F }, given the numerical abstractions D 1 2 D and D 2 2 D representing their path from the root of the decision tree.

In particular, given two a ne functions f 1 , f 2 2 F A \ {? F , > F }, the operator extrapolates the a ne function f 2 F A \ {? F , > F }, whose hypograph

f [D 2 ]# within D 2 is the convex-hull of the hypographs f 0 [D 2 ]# of the a ne functions f 0 2 F A \ {? F , > F } lying on the boundaries of convex-hull{f 1 [D 1 ]#, f 2 [D 2 ]
#}; when such a ne function does not exist, the result is > F :

f 1 H F [D 1 , D 2 ] f 2 def = ( f f[D 2 ]# = convex-hull{f 0 [D 2 ]# | f 0 2 F } > F otherwise
(5.2.25) where

F def = {f 2 F A \ {? F , > F } | f [D 1 t D D 2 ]#◆ convex-hull{f 1 [D 1 ]#, f 2 [D 2 ]# }} is the minimal set of a ne functions whose hypographs within D 1 t D D 2 determine convex-hull{f 1 [D 1 ]#, f 2 [D 2 ]#}, that is, 8f 2 F :6 9f 0 2 F : f [D 1 t D D 2 ]# f 0 [D 1 t D D 2 ]#◆ convex-hull{f 1 [D 1 ]#, f 2 [D 2 ]#} and T f 2F f [D 1 t D D 2 ]#= convex-hull{f 1 [D 1 ]#, f 2 [D 2 ]#}.
To clarify, let us consider the following example: The heuristic for widening adjacent leaf nodes within decision trees is implemented by Algorithm 17: the function widen-aux in Algorithm 17 is given as input two decision trees t 1 , t 2 2 T , a copy t 2 T of t 1 and a set C 2 P(C) initially equal to C (D), where D 2 D is a sound over-approximation of the reachable environments (cf. Line 5 of Algorithm 13). It accumulates into C the linear constraints accumulated along the paths up to the leaf nodes (cf. Lines 36-37). The leaf nodes defined in t 2 and undefined in t 1 (cf. Line 29) are extrapolated with respect to their adjacent defined leaf nodes (cf. Line 31) by means of the extrapolation operator H F (cf. Line 32).

Example 5.2.22 Two a ne functions f 1 , f 2 2 F A \ {? F , > F }
The adjacent leaf nodes are determined by the function adjacent (cf. Line 31). Note that, not all linear constraints appearing in a decision tree necessarily appear along a path in the decision tree. For this reason, given a decision tree t 2 T and a set C 2 P(C) of linear constraints encountered along the path to a leaf node, the function adds to a set K 2 P(C) (initially equal to C, cf. Line 17) all the redundant constraints (cf. Lines 20-21) that appear in the decision tree (cf. Line 18) but are missing from the path represented by C (cf. Line 19). Then, the adjacent leaf nodes are sought negating one by one in K the linear constraint in C, and are collected into a set A (cf. Line 23).

f (f 1 H F [d 1 , ↵ C (C)] t 2 .f ) t F [↵ C (C)]
The search for a leaf node determined by a set of constraints J 2 P(C) is conducted by the function leaf: the function extracts from J the linear constraints in decreasing order (cf. Line 11) and uses them to choose a path in the decision tree while accumulating into an initial empty set C 2 P(C) the linear constraints e↵ectively encountered (cf. Lines 12-14). In case the path leads to a defined leaf node, the function returns a set containing the leaf node together with the numerical abstract domain ↵ C (C) 2 D representing its path (cf. Line 8). Otherwise, the function returns an empty set (cf. Line 9).

The linear constraints appearing in a decision tree are determined by the function constraints by visiting in-order the decision tree (cf. Line 4).

Remark 5.2.23 Note that, besides establishing relationships between adjacent leaf nodes, other value widening heuristics are possible. An example would be establishing relationships between leaf nodes based on the parity of some variable, or based on numerical relationships between variables. We plan to investigate these possibilities as part of our future work.

The following result provides, for a loop while l bexp do stmt od, a sound over-approximation of ⌧ Mt J while l bexp do stmt od K defined in Equation 4.3.4, given a decision tree t 2 T , a sound over-approximation R 2 D of ⌧ I (l), and a sound over-approximation D 2 D of ⌧ I (f J while l bexp do stmt od K):

Lemma 5.2.24 Let \ Mt (x) def = F \ 1 [x] g T [R] F \ 2 [t]
as defined in Lemma 5.2.16 for any given t 2 T . Then, we have:

⌧ Mt J while l bexp do stmt od K T [D]t 4 T [R](lfp \ \ Mt )
where lfp \ \ Mt is the limit of the iteration sequence with widening:

y 0 def = ? T , y n+1 def = y n O \ Mt (y n ) (cf. Equation 5.2.24).

Proof.

See Appendix A.3. ⌅

Abstract Definite Termination Semantics

The operators of the decision trees abstract domains can now be used to define the abstract definite termination semantics. Note that, pure backward analysis is blind with respect to the program initial states. For this reason, in the following, we assume to have, for each program control point l 2 L, a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (l) 2 P(E): ⌧ I (l) ✓ D (R) (cf. Section 3.4).

In Figure 5.12 we define the semantics ⌧ \ Mt J stmt K : T ! T , for each program instruction stmt. Each function ⌧ \ Mt J stmt K : T ! T takes as input a decision tree over-approximating the ranking function corresponding to the final control point of the instruction, and outputs a decision tree defined over a subset of the reachable environments at iJ stmt K, which over-approximates the ranking function corresponding to the initial control point of the instruction.

The abstract termination semantics ⌧ \ Mt J prog K 2 T of a program prog outputs the decision tree over-approximating the ranking function corresponding

⌧ \ Mt J l skip Kt def = STEP T (t) ⌧ \ Mt J l X := aexp Kt def = (B-ASSIGN T J X := aexp KR)(t) ⌧ \ Mt J if l bexp then stmt 1 else stmt 2 fi Kt def = F \ 1 [t] g T [R] F \ 2 [f ] F \ 1 [t] def = (FILTER T J bexp KR)(⌧ \ Mt J stmt 1 Kt) F \ 2 [t] def = (FILTER T J not bexp KR)(⌧ \ Mt J stmt 2 Kt) ⌧ \ Mt J while l bexp do stmt od Kt def = lfp \ \ Mt \ Mt (x) def = F \ [x] g T [R] (FILTER T J not bexp KR)(t) F \ [x] def = (FILTER T J bexp KR)(⌧ \ Mt J stmt Kx) ⌧ \ Mt J stmt 1 stmt 2 Kt def = ⌧ \ Mt J stmt 1 K(⌧ \ Mt J stmt 2 Kt)
Figure 5.12: Abstract termination semantics of instructions stmt.

to the initial program control point iJ prog K 2 L. It is defined taking as input the leaf node LEAF : X 1 , . . . , X k . 0 as: Definition 5.3.1 (Abstract Termination Semantics) The abstract termination semantics ⌧ \ Mt J prog K 2 T of a program prog is:

⌧ \ Mt J prog K = ⌧ \ Mt J stmt l K def = ⌧ \ Mt J stmt KLEAF : X 1 , . . . , X k . 0 (5.3.1)
where the abstract termination semantics ⌧ \ Mt J stmt K 2 T ! T of each program instruction stmt is defined in Figure 5.12.

The following result proves the soundness of the abstract termination semantics ⌧ \ Mt J prog K 2 T with respect to the termination semantics ⌧ Mt J prog K 2 E * O, given a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (iJ prog K):

Theorem 5.3.2 ⌧ Mt J prog K 4 T [R]⌧ \ Mt J prog K Proof (Sketch).
The proof follows from the soundness of the operators of the decision trees abstract domain (cf. Lemma 5.2.8, Lemma 5.2.14, Lemma 5.2.15, Lemma 5.2.16, and Lemma 5.2.24) used for the definition of ⌧ \ Mt J prog K 2 T .

⌅

In particular, the abstract termination semantics provides su cient preconditions for ensuring definite termination of a program for a given overapproximation R 2 D of the set of initial states I ✓ ⌃:

Corollary 5.3.3 A program must terminate for execution traces starting from a given set of initial states

D (R) if D (R) ✓ dom( T [R]⌧ \ Mt J prog K).
Examples. In the following, we recall the examples introduced at the beginning of the chapter and we present the fully detailed analyses of the program using the abstract domain of decision trees. We present the analysis of the program using interval constraints based on the intervals abstract domain (cf. Section 3.4.1) for the decision nodes, and a ne functions for the leaf nodes (cf. Equation 5.2.6).

The starting point is the zero function at the program final control point:

3 : LEAF : x. 0
The ranking function is then propagated backwards towards the program initial control point taking the loop into account:

1 : NODE{x 0} : (LEAF : ? F ); (LEAF : x. 1)
The first iterate of the loop is able to conclude that the program terminates in at most one program step if the loop condition x 0 is not satisfied. Then, at program control point 2, the operator ASSIGN T replaces the program variable

x with the expression 2x + 10 within the decision tree: 2 : NODE{x 6 0} : (LEAF : x. 2); (LEAF : ? F ) Note that, ASSIGN T has also increased the value of the ranking function in order to count one more program execution step to termination. The second iterate of the loop concludes that the program terminates in at most three execution steps, when x 6 and thus the loop is executed only once, and in at most one program step, when the loop is not entered:

1 : NODE{x 6 0} : LEAF : x. 3; NODE{x 0} : (LEAF : ? F ); (LEAF : x. 1)
In this particular case, there is no need for convergence acceleration and the analysis is rather precise: at the sixth iteration, a fixpoint is reached providing the decision tree shown in Figure 5.1.

:

NODE{r 1 0} : NODE{x y + r 1 0} :

NODE{2x 2y +r 1 0} : (LEAF : ? F ); (LEAF : x. y. r. 7); LEAF : x. y. r. 4 LEAF : x. y. r. 1

The widening that we defined in Section 5.2.4 extrapolates the ranking function on the partitions over which it is not yet defined:

1 : NODE{r 1 0} :
NODE{x y+r 1 0} : (LEAF : x. y. r. 7); (LEAF : x. y. r. 4); LEAF : x. y. r. 1 Note, in particular, that the ranking function is now temporarily defined even when x y and the program does not terminate. Indeed, the fourth iterate of the while loop identifies a situation like case C in Figure 5.10b: The fixpoint represents the following piecewise-defined ranking function:

⇢. 8 > < > : 1 ⇢(r) 1 4
0 ⇢(r) ^⇢(r)  ⇢(y) ⇢(x) undefined otherwise which proves that the program is terminating in at most 4 program execution steps if the initial value of the program variable r is smaller than or equal to the di↵erence between the initial value of the program variable y and the initial value of the program variable x.

In Remark 5.2.18, we mentioned various possibilities to improve the precision of the widening operator. In particular, an adaptation of the domain widening using the evolving rays technique proposed in [START_REF] Bagnara | Precise Widening Operators for Convex Polyhedra[END_REF] yields the more precise decision tree shown in Figure 5.2. The same result can be obtained using conflict-driven learning [START_REF] Vijay | Conflict-Driven Abstract Interpretation for Conditional Termination[END_REF].

Related Work

We conclude the chapter with a discussion of the most relevant related work.

Decision Trees. The use of (binary) decision trees (Binary Decision Diagrams [START_REF] Bryant | Graph-based Algorithms for Boolean Function Manipulation[END_REF], in particular) for verification has been devoted a large body of work, especially in the area of timed-systems and hybrid-system verification [Jea02, LPWY99, MLAH99, etc.].

In this thesis, we focus on common program analysis applications and, in this sense, our decision trees abstract domain is mostly related to the ones presented in [CCM10, GC10a]: both ours and these abstract domains are based on decision trees extended with linear constraints. However, the abstract domains proposed in [START_REF] Cousot | A Scalable Segmented Decision Tree Abstract Domain[END_REF][START_REF] Gurfinkel | BOXES: A Symbolic Abstract Domain of Boxes[END_REF] are designed for the disjunctive refinement of numerical abstract domains, while our abstract domain is designed specifically in order manipulate ranking functions. Moreover, while our abstract domain is based on binary decision trees, in [START_REF] Cousot | A Scalable Segmented Decision Tree Abstract Domain[END_REF] the choices at the decision nodes may di↵er at each node and their number is not bounded a priori.

In general, despite all the available alternatives [BCC + 10, CCM10, GR98, GC10a, GC10b, SISG06, etc.], it seems to us that in the literature there is no disjunctive abstract domain well-suited for program termination. A first (minor) reason is the fact that most of the existing disjunctive abstract domains are designed specifically for forward analyses while ranking functions are inferred through backward analysis (cf. Section 5.3). However, the main reason is that adapting existing widening operators to ranking functions is not obvious due to the coexistence of an approximation and computational ordering in the termination semantics domain (cf. Section 4.3 and Section 5.2.4).

Termination. In the recent past, termination analysis has benefited from many research advances and powerful termination provers have emerged over the years [BCF13, CPR06, GSKT06, HHLP13, LQC15].

Many results in this area [BCC + 07, CPR06, etc.] are based on the transition invariants method introduced in [START_REF] Podelski | Transition Invariants[END_REF]. In particular, the Terminator prover [START_REF] Cook | Terminator: Beyond Safety[END_REF] is based on an algorithm for the iterative construction of transition invariants. This algorithm searches within a program for single paths representing potential counterexamples to termination, computes a ranking function for each one of them individually (as in [START_REF] Podelski | A Complete Method for the Synthesis of Linear Ranking Functions[END_REF]), and combines the obtained ranking functions into a single termination argument. Our approach di↵ers in that it aims at proving termination for all program paths at the same time, without resorting to counterexample-guided analysis. In particular, we emphasize that our approach is able to deal with arbitrary control structures, and thus it is not limited to simple loops as [START_REF] Podelski | A Complete Method for the Synthesis of Linear Ranking Functions[END_REF] or to nonnested loops as [START_REF] Bradley | Linear Ranking with Reachability[END_REF]. Moreover, it avoids the cost of explicit checking for the well-foundedness of the termination argument. The approach presented in [START_REF] Tsitovich | Loop Summarization and Termination Analysis[END_REF] shares similar motivations, but prefers loop summarization to iterative fixpoint computation with widening, as considered in this thesis.

The majority of the literature is based on the indirect use of invariants for proving termination [ADFG10, BCC + 07, BCF13, CS02, LORCR13, etc.]. On the other hand, our approach infers and manipulates ranking functions directly as invariants associated to program control points. In this sense, [START_REF] Alias | Multi-Dimensional Rankings, Program Termination, and Complexity Bounds of Flowchart Programs[END_REF] is the closest approach to ours: the invariants are pre-computed, but each program point is assigned with a ranking function (that also provides information on the execution time in terms of execution steps), as in our approach.

The strength of our approach is being an abstract interpretation of a complete semantics for termination. For any given terminating program, it is always possible to design an abstraction able to prove its termination. In particular, this is stronger than fixing a priori an incomplete reasoning method that can miss terminating programs. For example, various methods to synthesize ranking functions based on linear programming [ADFG10, CS01, PR04a, etc.] are complete for programs with rational -valued variables, but not with integer-valued variables. Indeed, as we have seen in Example 5.1.1 at the beginning of the chapter, there are programs that terminate over the integers but do not terminate over the rationals.

Finally, in the literature, we found only few works that have addressed the problem of automatically inferring preconditions for program termination. In [CGLA + 08], the authors proposed a method based on preconditions generating ranking functions from potential ranking functions, while our preconditions are inherently obtained from the inferred ranking functions as the set of programs state for which the ranking function is defined. Thus, our preconditions are derived by under-approximation of the set of terminating states as opposed to the approaches presented in [START_REF] Ganty | Proving Termination Starting from the End[END_REF][START_REF] Massé | Policy Iteration-based Conditional Termination and Ranking Functions[END_REF] where the preconditions are derived by (complementing an) over-approximation of the non-terminating states.

The abstract domain that we have presented in this chapter has been instantiated only with a ne functions, while several methods in the literature use more powerful lexicographic ranking functions. This limitation will be addressed in the next chapter Chapter 6 using ordinal-valued ranking functions. We postpone the comparison between our work and related work based on lexicographic ranking functions to the end of the next chapter.

Ordinal-Valued Ranking Functions

In this chapter, we address the limitation to natural-valued functions of the decision trees abstract domain presented in Chapter 5. In particular, we propose a functions auxiliary abstract domain based on ordinal-valued functions. More specifically, these functions are polynomials in !, where the polynomial coefficients are natural-valued functions of the program variables. The abstract domain is parametric in the choice of the maximum degree of the polynomials, and the types of functions used as polynomial coe cients.

Dans ce chapitre, nous levons la limitation à des fonctions à valeur naturelle du domaine abstrait d'arbres de décision présentés au Chapitre 5. En particulier, nous proposons un domaine abstrait auxiliaire de fonctions basé sur des fonctions à valeurs dans les ordinaux. Plus précisément, ces fonctions sont basées sur des polynômes en !, où les coe cients des polynômes sont des fonctions à valeur naturelle des variables du programme. Le domaine est paramétrique dans le choix du degré maximum des polynômes, et des types de fonctions utilisées comme coe cients des polynômes.

Ordinal-Valued Ranking Functions

In many cases, a single natural-valued ranking function is not su cient. In particular, this is the case in the presence of unbounded non-determinism, as we have seen in Example 4.1.2. In order to further motivate the need for ordinal-valued ranking functions, we propose the following example. x  0 y  0 0 Each loop iteration, either decrements the value of y, or decrements the value of x and resets the value of y, until either program variable becomes less than or equal to zero. There is a non-deterministic choice between the branches of the conditional if instruction at program control point 2, and the value of the variable y is chosen non-deterministically at program control point 4. The program always terminates, whatever the initial values for x and y, and whatever the non-deterministic choices during execution.

x  0 y = 1 0 x  0 y = 2 0 . . . x  0 y = n 0 . . . x = 1 y  0 0 x = 1 y = 1 1 x = 1 y = 2 2 . . . x = 1 y = n n . . . x = 2 y  0 0 x = 2 y = 1 ! x = 2 y = 2 ! + 1 . . . x = 2 y = n ! + n 1 . . . . . . . . . . . . . . . . . . . . . x = n y  0 0 x = n y = 1 ! • (n 1) x = n y = 2 ! • (n 1) + 1 . . . x = n y = n ! • (n 1) + n 1 . . .
In the graph of Figure 6.1, each node represents a possible state of the program at program control point 1, and each edge represents a loop iteration.

The nodes with a double outline are blocking states with no successor. We define a ranking function for the program following the intuition behind the definite termination semantics of Section 4.2.2: we start from the blocking states, where we assign value 0 to the function; then, we follow the edges backwards, and for each state that we encounter (whose successors belong to the domain of the function) we define the value of the ranking function as the maximum of all values of the function plus 1 for all successors of the state. Hence, we need a transfinite value whenever we encounter a state leading through unbounded non-determinism to program executions of arbitrary length. In particular, in this case, we need ordinal numbers for all states where x > 1 and y > 0

The analysis of the program using our decision trees abstract domain extended with ordinal-valued functions is proposed in Example 6.4.4 Lexicographic Ranking Functions. It is also possible to prove the termination of the program of Example 6.1.1 using a lexicographic ranking function (x, y). Indeed, a lexicographic tuple (f n , . . . , f 1 , f 0 ) of natural numbers is an isomorphic representation of the ordinal

! n • f n + • • • + ! • f 1 + f 0 [MP96]
. However, reasoning directly with lexicographic ranking functions, poses the additional di culty of finding an appropriate lexicographic order. Existing methods [BMS05a, CSZ13, etc.] use heuristics to explore the space of possible orders, which grows very large with the number of program variables. Instead, the coe cients f n , . . . , f 1 , f 0 (and thus their order) of our ordinal-valued ranking functions are automatically inferred by the analysis. Moreover, there exist programs for which there does not exist a lexicographic ranking function but there is a piecewise-defined ordinal-valued ranking function as considered in this chapter, and we will provide an example in Example 6.4.5. We refer to Section 6.5 at end of the chapter for further discussion on the comparison between lexicographic and ordinal-valued ranking functions.

Ordinal Arithmetic

The theory of ordinals was introduced by Georg Cantor as the core of his set theory [START_REF] Cantor | Beiträge zur Begründung der Transfiniten Mengenlehre[END_REF][START_REF] Cantor | Beiträge zur Begründung der Transfiniten Mengenlehre[END_REF]. We recall from Chapter 2 that the smallest ordinal is denoted by 0. The successor of an ordinal ↵ is denoted by ↵+1, or equivalently, by succ(↵). A limit ordinal is an ordinal which is neither 0 nor a successor ordinal. In the following, we provide the definition and some properties of addition, multiplication and exponentiation on ordinals [START_REF] Kunen | Set Theory: An Introduction to Independence Proofs[END_REF]. Addition. Ordinal addition is defined by transfinite induction:

↵ + 0 def = ↵ (zero case) ↵ + ( + 1) def = (↵ + ) + 1 (successor case) ↵ + def = [ < (↵ + ) (limit case) (6.2.1)
Ordinal addition generalizes the addition of natural numbers. It is associative, i.e. (↵ + ) + = ↵ + ( + ), but not commutative, e.g. 1

+ ! = ! 6 = ! + 1.
Multiplication. Ordinal multiplication is also defined inductively: Exponentiation. We define ordinal exponentiation by transfinite induction:

↵ • 0 def = 0 (zero case) ↵ • ( + 1) def = (↵ • ) + ↵ (successor case) ↵ • def = [ < (↵ • ) (limit case) (6.
↵ 0 def = 1 (zero case) ↵ +1 def = (↵ ) • ↵ (successor case) ↵ def = [ < (↵ ) (limit case) (6.2.3)
Cantor Normal Form. Using ordinal arithmetic, we can build all ordinals up to " 0 (i.e. the smallest ordinal such that " 0 = ! " 0 ):

0, 1, 2, . . . , !, ! + 1, ! + 2, . . . , ! • 2, ! • 2 + 1, ! • 2 + 2, . . . , ! 2 , . . . , ! 3 , . . . , ! ! , .
. . In the following, we use the representation of ordinals based on Cantor Normal Form [START_REF] Kunen | Set Theory: An Introduction to Independence Proofs[END_REF], i.e. every ordinal ↵ > 0 can be uniquely written as

! 1 • n 1 + • • • + ! k • n k
where k is a natural number, the coe cients n 1 , . . . , n k are positive integers and the exponents 1 > 2 > • • • > k 0 are ordinal numbers. Throughout the rest of the thesis we will consider ordinal numbers only up to ! ! .

Decision Trees Abstract Domain

In the previous Chapter 5 we have presented the decision trees abstract domain T(D, C, F), parameterized by a numerical abstract domain D, an auxiliary abstract domain C for the decision nodes, and an auxiliary abstract domain F based on natural-valued functions for the leaf nodes (cf. Section 5.2). In the following, we address the limitations of F by means of auxiliary abstract domain W(F) based on ordinal-valued functions. Thus, the decision trees abstract domain T(D, C, F) is lifted to T(D, C, W(F)).

Decision Trees

We now formally define the family of auxiliary abstract domains W. Then, we illustrate its integration within the family of abstract domains T.

Ordinal-Valued Functions Auxiliary Abstract Domain. The family of abstract domains W is a functor which lifts any auxiliary abstract domain F introduced in Section 5.2 to ordinal-valued functions. As F, it is dedicated to the manipulation of the leaf nodes of a decision tree with respect to the linear constraints satisfied along their paths from the root of the decision tree.

Let X def = {X 1 , . . . , X k } be the set of program variables. The elements of these abstract domains belong to the following set:

W def = {? W } [ ( X i ! i • f i f i 2 F \ {? F , > F } ) [ {> W } (6.3.1)
where F is defined in Equation 5.2.5, which consists of ordinal-valued functions of the program variables, plus the counterparts ? W and > W of ? F and > F , respectively. More specifically, the ordinal-valued functions are polynomials in ! (that is, ordinals in Cantor Normal Form), where the coe cients are natural-valued functions of the program variables belonging to F \ {? F , > F }.

The maximum degree of the polynomials, in the following denoted by M , is another parameter of the abstract domain. The computational order v W and the approximation order 4 W are parameterized by a numerical abstract domain element D 2 D, which represents the linear constraints satisfied along the path to the leaf nodes. According to Lemma 4.2.22, they coincide when the compared leaf nodes are both defined :

X i ! i • f i 1 4 W [D] X i ! i • f i 2 () 8⇢ 2 D (D) : X i ! i • f i 1 (⇢(X 1 ), . . . , ⇢(X k ))  X i ! i • f i 2 (⇢(X 1 ), . . . , ⇢(X k )) (6.3.2) 120 6. Ordinal-Valued Ranking Functions p : Z |X | ! O ? F > F (a) > F p : Z |X | ! O ? F (b)
X i ! i • f i 1 v W [D] X i ! i • f i 2 () 8⇢ 2 D (D) : X i ! i • f i 1 (⇢(X 1 ), . . . , ⇢(X k ))  X i ! i • f i 2 (⇢(X 1 ), . . . , ⇢(X k )) (6.3.3)
Instead, when one or both leaf nodes are undefined, the approximation and computational orders are defined by the Hasse diagrams in Figure 6.2a and Figure 6.2b, respectively. Note that, as in Figure 5.3a and Figure 5.3b, ? Wleaves and > W -leaves are incomparable and comparable, respectively.

We define the following concretization-based abstraction:

hE * O, 4i W [D] hW, 4 W i
where D 2 D represents the path to the leaf node. The concretization function

W : D ! W ! (E * O) is defined as follows: W [D]? W def = ; W [D] X i ! i • f i def = ⇢ 2 D (D) : X i ! i • f i (⇢(X 1 ), . . . , ⇢(X k )) W [D]> W def = ; (6.3.4)
As in Equation 5.2.9, ? W and > W represent the totally undefined function.

The following result proves that, given D 2 D, W [D] is monotonic:

Lemma 6.3.1 8p 1 , p 2 2 W : p 1 4 W [D] p 2 ) W [D]p 1 4 W [D]p 2 .

Proof.

See Appendix A.4. Specifically, the decision trees now belong to the following set:

T def = {LEAF : p | p 2 W} [ {NODE{c} : t 1 ; t 2 | c 2 C, t 1 , t 2 2 T } (6.3.5)
where W is defined in Equation 6.3.1 and C is defined in Equation 5.2.1.

In the following, we lift to ordinal-valued functions all the abstract domain operators, focusing on the operators used to manipulate leaf nodes.

Binary Operators

The need for ordinals arising from non-deterministic boolean expressions (cf. Example 6.1.1) gets reflected into the binary operator for the computational and approximation join of decision tree.

Join. The join of decision trees is parameterized by the choice of the join between leaf nodes and yields a ranking function defined over the union of their partitions (cf. Algorithm 5). We lift Algorithm 5 to ordinal-valued functions by simply defining the join between ordinal-valued leaf nodes.

The approximation join g W and the computational join t W are parameterized by a numerical abstraction D 2 D, which represents the linear constraints satisfied along the path to both leaf nodes, after the decision tree unification (cf. Line 5 of Algorithm 5). They di↵er when joining defined and undefined leaf nodes. Specifically, the approximation join is defined as follows:

? W g W [D] p def = ? W p 2 W \ {> W } p g W [D] ? W def = ? W p 2 W \ {> W } > F g W [D] f def = > W p 2 W \ {? W } p g W [D] > W def = > W p 2 W \ {? W } (6.3.6)
and the computational join is defined as follows: .

? W t W [D] p def = p p2 W p t W [D] ? W def = p p2 W > W t W [D] p def = > F p 2 W p t W [D] > W def = > F p 2
D 2 D, p 1 , p 2 2 W \ {? W , > W }, 2 {g F , t F } 3: r P i ! i • ( X 1 , . . . , X k . 0) 4: i 0 5: carry false 6:
while i < M do . join carried out in ascending powers of ! 7: return > W

f p 1 [i] [D] p 2 [i] 8: if f = > F
In particular, as in Equation 5.2.13, the approximation join is undefined when joining ? W -leaves and > W -leaves and always favors the undefined leaf nodes.

Instead, the approximation and computational join between defined leaf nodes coincide. Algorithm 18 is a generic implementation parameterized by the choice of the join between natural-valued leaf nodes. Given an ordinal valued function

p def = P i ! i • f i 2 W \ {? W , > W }, we write p[i] to denote the coe cient f i .
The join of two given ordinal-valued functions p 1 , p 2 2 W \ {? W , > W } is carried out in ascending powers of !, joining the coe cients of terms with the same power of ! (cf. Line 7), up to the maximum degree M (cf. Line 6). In case the join of natural-valued leaf nodes yields > F (cf. Line 8), the function w-join sets the coe cient to equal the zero function (cf. Line 3) and propagates a carry of one execution step (cf. Line 9 and Lines 12) to the unification of terms with next higher degree; unless the maximum degree M has been reached, in which case w-join returns > W (cf. Line 20).

To clarify, let us consider the following example: = y. However, there does not exists a natural-valued a ne function which is the least upper bound of f 1 0 and f 2 0 within D. Thus, we force their join to equal zero and we carry one to the join of f 1 1 def = x 1 and f 2 1 def = x which becomes x + 1 (i.e., x after the join and x + 1 after propagating the carry). Thus, the result of the join of p 1 and p 2 is r def = ! • (x + 1).

Intuitively, whenever natural-valued functions are not su cient, w-join naturally resorts to ordinal numbers: given two terms ! k •f 1 and ! k •f 2 , forcing their join to equal zero and carrying one to the terms with next higher degree is equivalent to considering their join to be equal to ! and applying the limit case of ordinal multiplication (cf. Equation 6.2.2):

! k • ! = ! k+1 • 1 + ! k • 0 = ! k+1 .
The approximation join g W and the computational join t W between defined leaf nodes are implemented by Algorithm 19 and Algorithm 20, respectively: the functions a-w-join of Algorithm 19 and c-w-join of Algorithm 20 call the function w-join of Algorithm 18 choosing respectively the approximation join g F and the computational join t F between natural-valued leaf nodes.

Unary Operators

In the following, we lift to ordinal-valued functions the unary operators for handling skip instructions and backward variable assignments. In particular, the assignment operator reflects the need for ordinals arising from nondeterministic assignments (cf. Example 4.1.2 and Example 6.1.1). . d, D 2 D, p 2 W \ {? W , > W } 3: return > W Skip. We lift the step operator for handling skip instructions (cf. Algorithm 9) defining the step operator STEP W for ordinal-valued leaves. The operator STEP W : W ! W, given an ordinal-valued function p 2 W \ {? W , > W }, simply invokes the step operator STEP F for natural-valued leaves on the constant term of the polynomial; undefined leaf nodes are unaltered:

r P M i=1 ! i • ( X 1 , . . . ,
STEP W (? W ) def = ? F STEP W ( X i ! i • f i ) def = STEP F (f 0 ) + X i>0 ! i • f i = ( X i ! i • f i ) + 1 STEP W (> W ) def = > F (6.3.8)
Assignments. We now define the operator B-ASSIGN W to handle backward assignments within ordinal-valued leaf nodes, in order to lift the operator B-ASSIGN T (cf. Algorithm 11) to ordinal-valued functions.

The operator B-ASSIGN W J X := aexp K : D ! D ! W ! W is implemented by Algorithm 21. The assignment, given a numerical abstraction d 2 D of the reachable environments at the initial control point of the instruction, a numerical abstraction D 2 D of the linear constraints accumulated along the path to the leaf node, is carried out in ascending powers of !, invoking the B-ASSIGN F operators on the coe cients (cf. Line 7), up to the maximum degree M (cf. Line 6). In case the assignment of natural-valued leaf nodes yields > F (cf. Line 8), the function w-assign lets the coe cient to equal the zero function (cf. Line 3) and carries one execution step (cf. Line 9 and Line 12) to the term with next higher degree; unless the maximum degree M has been reached, in which case w-assign returns > W (cf. Line 20). The operator STEP W is invoked before returning (cf. Line 18) to take into account that one more program execution step is needed before termination.

To clarify, let us consider the following example: x is reset to zero and carries one to the term with next higher degree ! 2 . In fact, the non-deterministic assignment x := ? allows x (and consequently f 1 ) to take any value, but there does not exists a natural-valued a ne function that properly abstracts all possible outcomes of the assignment. The resulting ordinal-valued function, after the invocation of STEP W , is r def = ! 2 • 1 + (y + 1).

Widening

The widening operator, unlike the join and assignment operators, is not allowed to introduce ordinals of higher degree to avoid missing cases like case B and case C in Figure 5.10b, where the value of the abstract ranking function increases between iterates. We lift Algorithm 13 to ordinal-valued functions defining an extrapolation operator H W between ordinal-valued leaf nodes.

The extrapolation operator H

W [D 1 , D 2 ] is implemented by Algorithm 22.
The extrapolation, given the numerical abstractions D 1 2 D and D 2 2 D representing the path to the leaf nodes from the root of the decision tree, is carried out in ascending powers of ! invoking the extrapolation operator H F [D 1 , D 2 ] on the coe cients (cf. Line 6), up to the maximum degree M (cf. .

D 1 , D 2 2 D, p 1 , p 2 2 W \ {? W , > W } 3: r P M i=1 ! i • ( X 1 , . . . , X k . 0) 4: i 0 5:
while i < M do . widening carried out in ascending powers of ! 6:

f p 1 [i] H F [D 1 , D 2 ] p 2 [i] 7: if f = > F then 8:
return > W 9: else 10:

r[i] f 11: i i + 1 12:
return r Line 5). In case the extrapolation of natural leaf nodes yields > F (cf. Line 7), the function w-widen returns > W (cf. Line 8).

Abstract Definite Termination Semantics

The lifted operators of the decision trees abstract domain can now lift to ordinal-valued functions the abstract termination semantics of a program instruction stmt, defined in Figure 5.12, and the abstract termination semantics of a program prog, defined in Definition 5.3.1.

The following result proves, for program instruction stmt, the soundness of the abstract termination semantics ⌧ \ Mt J stmt K with respect to the termination semantics ⌧ Mt J stmt K defined in Section 4.3, given sound over-approximations

R 2 D of ⌧ I (iJ stmt K) and D 2 D of ⌧ I (f J stmt K): Lemma 6.4.1 ⌧ Mt J stmt K( T [D]t) 4 T [R](⌧ \ Mt J stmt Kt).

Proof.

See Appendix A.4.

⌅

Similarly, the following result proves the soundness of the abstract termination semantics ⌧ \ Mt J prog K 2 T with respect to the termination semantics ⌧ Mt J prog K 2 E * O, given a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (iJ prog K) at the initial program control point:

Theorem 6.4.2 ⌧ Mt J prog K 4 T [R]⌧ \ Mt J prog K Proof (Sketch).
The proof follows from the soundness of the operators of the decision trees abstract domain (cf. Lemma 6.4.1) used for the definition of

⌧ \ Mt J prog K 2 T .⌅
In particular, the abstract termination semantics provides su cient preconditions for ensuring definite termination of a program for a given overapproximation R 2 D of the set of initial states I ✓ ⌃: Corollary 6.4.3 A program must terminate for execution traces starting from a given set of initial states

D (R) if D (R) ✓ dom( T [R]⌧ \ Mt J prog K).
Examples. In the following, we recall the example introduced at the beginning of the chapter and we describe in some detail the analysis of the program using the abstract domain of decision trees. Then, we propose further examples to illustrate the expressiveness of the abstract domain. We present the analysis of the program using interval constraints based on the intervals abstract domain (cf. Section 3.4.1) for the decision nodes, and ordinal-valued functions for the leaf nodes (cf. Equation 6.3.1).

The starting point is the zero function at the program final control point:

6 : LEAF : x. y. 0
The ranking function is then propagated backwards towards the program initial control iterating through the while loop. We use a widening delay of three iterations. At the fourth iteration, the decision tree at program control point 1 represents the following piecewise-defined ranking function:

> <

> :

1 ⇢(x)  0 _ ⇢(y)  0 3y + 2 ⇢(x) = 1 undefined otherwise
where 3y + 2 is the result of the widening between adjacent leaf nodes with consecutive values for y (i.e., between LEAF : x. y. 5 within ⇢(x) = 1 ⇢(y) = 1 and LEAF : x. y. 8 within ⇢(x) = 1 ^⇢(y) = 2). Ordinals appear for the first time at program control point 4 due to the non-deterministic assignment to y:

⇢. 8 > < > : 2 ⇢(x)  0 ! + 9 ⇢(x) = 1 undefined otherwise
In the first case the value of the function is simply increased to count one more program step before termination, but (since y can now have any value) its domain is modified forgetting all constraints on y (i.e. y  0). In the second case, 3y + 2 becomes ! + 9 due to the non-deterministic assignment.

At the seventh iteration, the decision tree associated with program control point 1, represents the following ranking function:

⇢. 8 > > > > < > > > > : 1 ⇢(x)  0 _ ⇢(y)  0 3y + 2 ⇢(x) = 1 ! + (3y + 9) ⇢(x) = 2 undefined otherwise
where ! + (3y + 9) is the result of the widening between LEAF : x. y. ! + 12 within ⇢(x) = 2 ^⇢(y) = 1 and LEAF : x. y. ! +15 within ⇢(x) = 2 ^⇢(y) = 2. The widening is carried out in ascending powers of !: from the constants 12 and 15, the widening infers the value 3y + 9; then, since the coe cients of ! are equal to one, the inferred coe cient is again one. Thus, the result of the widening is ! + (3x + 9) within ⇢(x) = 2. Finally, at the eleventh iteration, the analysis reaches a fixpoint:

⇢. 8 > > > > < > > > > : 1 ⇢(x)  0 _ ⇢(y)  0 3y + 2 ⇢(x) = 1 ! + (3y + 9) ⇢(x) = 2 ! • (x 1) + (7x + 3y 5) otherwise
where 3y + 2 and ! + (3y + 9) are particular cases (within ⇢(x) = 1 and ⇢(x) = 2, respectively) of ! • (x 1) + (7x + 3y 5) and are explicitly listed only due to the amount of widening delay we used. The ranking function proves that the program is always terminating, whatever the initial values for

x and y, and whatever the non-deterministic choices during execution. The reason why we obtain a di↵erent and more complex ranking function with respect to Figure 6.1 is because we count the number of program execution steps whereas, for convenience of presentation, in Figure 6.1 we simply count the number of loop iterations.

Example 6.4.5 Let us consider the following program: x is positive, either decrements the value of x, or decrements the value of x and resets the value of y; when x is negative, either increments the value of x, or decrements the value of y and resets the value of x to any value (possibly positive). The loop exits when x is equal to zero or y is less than zero.

while 1 (x 6 = 0 ^0 < y) do if 2 (0 < x) then if 3 ( ? ) then
Note that, there does not exist a lexicographic ranking function for the loop. In fact, the variables x and y can be alternatively reset to any value at each loop iteration: the value of y is reset at the program control point 5, while the value of x is reset at the control point 10. 130 6. Ordinal-Valued Ranking Functions There is an edge from any node where x has value k > 0 (and y > 0) to all nodes where x has value k 1 (and y has any value); there is also an edge from any node where y has value h > 0 (and x < 0) to all nodes where y has value h 1 (and x has any value). In every node we indicate the maximum number of loop iterations needed to reach a blocking state: the highlighted nodes require ordinals greater than ! 2 .

x  y  0 x  0 y = 1 0 x  0 y = 2 0 . . . x  0 y = n 0 . . . x = y  0 x = 1 y = 1 1 x = 1 y = 2 2 . . . x = 1 y = n n . . . x = y  0 x = 1 y = 1 1 x = 1 y = 2 ! 2 . . . x = 1 y = n ! 2 + ! • (n 1) . . . x = y  0 x = 2 y = 1 ! x = 2 y = 2 ! + 1 . . . x = 2 y = n ! + n 1 . . . x = y  0 x = 2 y = 1 2 x = 2 y = 2 ! 2 + 1 . . . x = 2 y = n ! 2 + ! • (n 1) + 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x = n y  0 x = n y = 1 ! • (n 1) x = n y = 2 ! • (n 1) + 1 . . . x = n y = n ! • (n 1) + n 1 . . . x = n y  0 x = n y = 1 n x = n y = 2 ! 2 + n 1 . . . x = n y = n ! 2 + ! • (n 1) + n 1 . . .
Nonetheless, the program always terminates, regardless of the initial values for x and y, and regardless of the non-deterministic choices taken during execution. Let us consider the graph in Figure 6.3. Whenever y is reset to any value, we move towards the blocking states decreasing the value of x, and whenever x is reset to any value, we move towards the blocking states decreasing the value of y. Moreover, whenever x is reset to a positive value, its value will only decrease until it reaches zero (or y is reset to a value less than zero).

The analysis of the program using interval constraints based on the intervals abstract domain (cf. Section 3.4.1) for the decision nodes, ordinal-valued functions for the leaf nodes (cf. Equation 6.3.1), yields the following piecewisedefined ranking function at program control point 1:

⇢. 8 > < > : ! 2 + ! • (y 1) + ( 4x + 9y 2) ⇢(x)  0 _ 0 < ⇢(y) 1 ⇢(x) = 0 _ y  0 ! • (x 1) + (9x + 4y 7) 0 < ⇢(x) _ 0  ⇢(y)
In Figure 6.3, we justify the need for ! 2 . Indeed, from any state where x < 0 and y = h > 0, whenever x is reset at program control point 10, it is possible to jump to any state where y = h 1. In particular, for example from the state where x = 1 and y = 2, it is possible to jump through unbounded nondeterminism to states with value of the most precise ranking function equal to an arbitrary ordinal number between ! and ! 2 , which requires ! 2 as upper bound of the maximum number of loop iterations needed to reach a final state. Finally, note the expressions identified as coe cients of !: where x < 0, the coe cient of ! is an expression in y (since y guides the progress towards the blocking states), and where 0 < x, the coe cient of ! is an expression in x (because x rules the progress towards termination). The expressions are automatically inferred by the analysis without any assistance from the user.

Related Work

Interestingly, ordinal-valued ranking functions already appeared in the work of Alan Turing in the late 1940s [START_REF] Turing | Checking a Large Routine[END_REF][START_REF] Morris | An Early Program Proof by Alan Turing[END_REF]. To the best of our knowledge, the automatic inference of ordinal-valued ranking functions for proving termination of imperative programs is unique to our work.

The approach presented in this chapter is mostly related to [ADFG10]: both techniques handle programs with arbitrary structure and infer ranking functions (that also provide information on the program computational complexity in terms of executions steps) attached to program control points. In [START_REF] Alias | Multi-Dimensional Rankings, Program Termination, and Complexity Bounds of Flowchart Programs[END_REF], lexicographic ranking functions are obtained by a greedy algorithm based on Farkas lemma that, analogously to the operators of our abstract domain, constructs the ranking functions by adding one dimension at a time. However, the method proposed in [START_REF] Alias | Multi-Dimensional Rankings, Program Termination, and Complexity Bounds of Flowchart Programs[END_REF], although complete for programs with rational-valued variables, is incomplete for integer-valued variables. In contrast, there is no completeness limitation to our method, only a choice of relevant abstract domains. In [START_REF] Gonnord | Synthesis of Ranking Functions using Extremal Counterexamples[END_REF], the authors improve over [START_REF] Alias | Multi-Dimensional Rankings, Program Termination, and Complexity Bounds of Flowchart Programs[END_REF] and present an SMT-based method for the inference of lexicographic ranking functions. However, both [START_REF] Alias | Multi-Dimensional Rankings, Program Termination, and Complexity Bounds of Flowchart Programs[END_REF] and [START_REF] Gonnord | Synthesis of Ranking Functions using Extremal Counterexamples[END_REF] remain focused only on proving termination for all program input, while our work naturally deals with proving conditional termination as well.

In a di↵erent context, a large amount of research followed the introduction of size-change termination [START_REF] Chin | The Size-Change Principle for Program Termination[END_REF]. The size-change termination approach consists in collecting a set of size-change graphs (representing function calls) and combining them into multipaths (representing program executions) in such a way that at least one variable is guaranteed to decrease. Compared to sizechange termination, our approach avoids the exploration of the combinatorial space of multipaths with the explicit manipulation of ordinals. In [START_REF] Soon | Ranking Functions for Size-Change Termination[END_REF][START_REF] Amir | Ranking Functions for Size-Change Termination II[END_REF], algorithms are provided to derive explicit ranking functions from size-change graphs, but these ranking functions have a shape quite di↵erent from ours which makes it di cult for us to compare their expressiveness. For example, the derived ranking functions use lexicographic orders on variables while our polynomial coe cients are arbitrary linear combinations of variables. In general, an in-depth comparison between such fairly di↵erent methods is an open research topic (e.g., see [START_REF] Heizmann | Size-Change Termination and Transition Invariants[END_REF] for the comparison of the transition invariants and the size-change termination methods).

Finally, we have seen that there exist programs for which there does not exist a lexicographic ranking function (cf. Example 6.4.5). In [START_REF] Cook | Ramsey vs. Lexicographic Termination Proving[END_REF] the authors discuss the problem and propose some heuristics to circumvent it. Interestingly these heuristics rediscover exactly the need for piecewise-defined ranking functions, even if implicitly and in a roundabout way.

Recursive Programs

In the small programming language introduced in Chapter 3 only loops present a challenge when proving termination. In this chapter, we illustrate a simple extension of the language with recursive procedures. We revisit the definition of its maximal trace semantics (cf. Section 3.2) and its definite termination semantics (cf. Section 4.3). Moreover, we propose a sound decidable abstraction for proving termination of recursive programs based the piecewise-defined ranking functions introduced in Chapter 5 and Chapter 6.

Dans le petit langage de programmation introduit dans le Chapitre 3 seules les boucles présentent un défi pour prouver la terminaison. Dans ce chapitre, nous montrons une simple extension du language avec des procédures récursives. Nous reviendrons sur la définition de sa sémantique de traces maximales (cf. Section 3.2) et sa sémantique de terminaison (cf. Section 4.3). De plus, nous proposons une abstraction décidable correcte pour prouver la terminaison des programmes récursifs basée sur les fonctions de rang définies par morceaux introduites au Chapitre 5 et au Chapitre 6.

A Small Procedural Language

In Figure 7.1, the syntax of our programming language proposed in Figure 3.1 is extended with possibly recursive procedures.

A program prog consists of a procedure declaration followed by a unique label l 2 L. A procedure declaration mthd is either a main procedure declaration or a sequential composition of declarations. The main procedure is always declared last. A procedure consists in an instruction statement labelled by a unique procedure name M 2 M [ {main}.

The set of language instructions is extended with call and return statements: a call statement branches to the initial control point of the called procedure; the return statement branches back to the control point after the call statement. With the exception of the main procedure, the last instruction of all procedures is a return statement. For simplicity, we assume that any mutual recursion is reduced into a single recursive procedure [START_REF] Owen Kaser | On the Conversion of Indirect to Direct Recursion[END_REF]. Note that, this extension of the language allows us to also encode programs containing functions with arguments and return values, thanks to variables. Therefore, we do not explicitly introduce such features in the language.

Maximal Trace Semantics

We now define the transition semantics of our extended language. In particular, since a procedure might be called during the execution of another procedure, we introduce a stack to recover the right calling control point: the procedure call statement pushes the calling control point onto the stack, whereas the procedure return statement pops the last calling control point from the top of the stack and branches to this control point. Then, we define the maximal trace semantics of the language by induction on its extended syntax.

Transition Systems. A stack k 2 L ⇤ is a possibly empty sequence of program control points. Let K denote the set of all stacks.

The set of all program states ⌃ def = L ⇥ E is extended to pairs K ⇥ ⌃ consisting of a stack k 2 K and a program state s 2 ⌃, which in turn consists of a program control point l 2 L paired with an environment ⇢ 2 E.

In Figure 7.2 we define the initial control point of a program prog, a call instruction stmt and a return instruction ret. The initial control point of a program prog is the initial control point of the main procedure. The initial stmt ::= . . .

| l call M i J l call M K def = l ret ::= l return iJ l return K def = l mthd ::= main: stmt iJ main : stmt K def = iJ stmt K | M : stmt ret mthd 1 iJ M : stmt ret mthd 1 K def = iJ mthd 1 K prog ::= mthd l iJ mthd l K def = iJ mthd K Figure 7
.2: Initial control point of stmt, ret, and prog.

stmt ::= . . . call instruction stmt. The final control point f J l return K of a return instruction ret cannot be defined statically; it is a dynamic information depending on the calling control point on the stack during execution. The final control point of other instructions stmt is unchanged from Figure 3.5.

| l call M fJ l call M K def = f J stmt K prog ::= mthd l f J mthd l K def = l
In the following, the function i : M ! L maps procedure names to their initial control point: given a declaration M : stmt ret, i(M

) def = iJ stmt K. The set of initial states is extended to {"} ⇥ I def = {h", hiJ prog K, ⇢ii | ⇢ 2 E} and the set of final states is extended to {"} ⇥ Q def = {h", hf J prog K, ⇢ii | ⇢ 2 E}.
We now redefine the transition relation ⌧ 2 (K⇥⌃)⇥(K⇥⌃). In particular, in Figure 7.4, we define the transition semantics

⌧ J stmt K 2 (K ⇥ ⌃) ⇥ (K ⇥ ⌃) and ⌧ J ret K 2 (K ⇥ ⌃) ⇥ (K ⇥ ⌃) of
a call instruction and a return instruction, respectively. The semantics of other instructions stmt is defined analogously to Figure 3.6, extending the states with a stack, which is left unchanged by the instruction. The execution of a call instruction pushes the final control point of the instruction onto the stack and branches to the initial control point of the called procedure. The function ⌧ : M ! L maps procedure names to their transition semantics: given a declaration M : stmt ret,

⌧ (M ) def = ⌧ J stmt K [ ⌧ J ret K.
The execution of a return instruction branches to the control point popped from the top of the stack.

⌧ J l call M K def = {hk, hl, ⇢ii ! hf J l call M K • k, hi(M ), ⇢ii | k 2 K, ⇢ 2 E} [ ⌧ (M ) ⌧ J l return K def = {hr • k, hl, ⇢ii ! hk, hr, ⇢ii | r 2 L, k 2 K, ⇢ 2 E}
The transition relation ⌧ 2 (K ⇥ ⌃) ⇥ (K ⇥ ⌃) of a program prog is defined by the semantics ⌧ J prog K 2 (K ⇥ ⌃) ⇥ (K ⇥ ⌃)
of the program as follows:

⌧ J prog K = ⌧ J mthd l K def = ⌧ J mthd K where ⌧ J main : stmt K def = ⌧ J stmt K and ⌧ J M : stmt ret mthd K def = ⌧ J mthd K.
In other words, the semantics ⌧ J prog K of a program prog is defined by the semantics ⌧ J main : stmt K 2 (K ⇥ ⌃) ⇥ (K ⇥ ⌃) of the main procedure.

def = {h", h6, ⇢ii | ⇢ 2 E}. The program transition relation ⌧ 2 (K ⇥ ⌃) ⇥ (K ⇥ ⌃) is defined as follows: ⌧ def = {h", h6, ⇢ii ! h", h7, ⇢[x v]ii | ⇢ 2 E ^v 2 Z} [ {h", h7, ⇢ii ! h8 • ", h1, ⇢ii | ⇢ 2 E} [ {hk, h1, ⇢ii ! hk, h2, ⇢ii | k 2 K, ⇢ 2 E ^true 2 J1 < xK⇢} [ {hk, h2, ⇢ii ! hk, h3, ⇢[x ⇢(x) 1]ii | k 2 K, ⇢ 2 E} [ {hk, h3, ⇢ii ! h5 • k, h1, ⇢ii | k 2 K, ⇢ 2 E} [ {hk, h1, ⇢ii ! hk, h4, ⇢ii | k 2 K, ⇢ 2 E ^false 2 J1 < xK⇢} [ {hk, h4, ⇢ii ! hk, h5, ⇢ii | k 2 K, ⇢ 2 E} [ {h5 • k, h5, ⇢ii ! hk, h5, ⇢ii | k 2 K, ⇢ 2 E} [ {h8 • ", h5, ⇢ii ! h", h8, ⇢ii | ⇢ 2 E} The extended set of final states is {"} ⇥ Q def = {h", h8, ⇢ii | ⇢ 2 E}.
Maximal Trace Semantics. The maximal trace semantics ⌧ +1 2 P((K ⇥ ⌃) +1 ) of our extended language is generated by the extended transition system hK ⇥ ⌃, ⌧ i as in Section 3.2. In particular, the following result restates Theorem 2.2.12 and defines the maximal trace semantics in fixpoint form: Theorem 7.2.2 (Maximal Trace Semantics) The maximal trace semantics ⌧ +1 2 P((K ⇥ ⌃) +1 ) can be expressed as a least fixpoint in the complete lattice hP((K ⇥ ⌃) +1 ), v, t, u, (K ⇥ ⌃) ! , (K ⇥ ⌃) + i as follows:

⌧ +1 = lfp v +1 +1 (T ) def = ({"} ⇥ Q) [ (⌧ ; T ) (7.2.1)
In the following, we provide a structural definition of the maximal trace semantics by induction on the extended syntax of programs.

Remark 7.2.3 From now on, we assume that procedures have a single recursive call. We plan to generalize the framework as part of our future work.

We do not explicitly represent the stack. Instead, we use least fixpoints as denotations of recursive procedures. Thus, we have ⌧ +1 2 P(⌃ +1 ).

In Figure 7.5, for any procedure P, we define the semantics ⌧ +1 J stmt K P S : P(⌃ +1 ) ! P(⌃ +1 ) and ⌧ +1 J ret K P S : P(⌃ +1 ) ! P(⌃ +1 ) of a call instruction and a return instruction, respectively. The traces are built backwards: each function ⌧ +1 J stmt K P S (resp. ⌧ +1 J ret K P S) takes as input a set of traces starting with the final label of the instruction stmt (resp. ret) and outputs a set of traces starting with the initial label of stmt (resp. ret). The parameter set of traces S 2 P(⌃ +1 ) is used to handle recursive calls.

The trace semantics of a recursive call instruction, when the called procedure coincides with the caller, is parameterized by a set of traces S representing

⌧ +1 J l call M K M S(T ) def = ⇢ hl, ⇢ihi(M ), ⇢i ⇢ 2 E, 2 ⌃ ⇤1 hi(M ), ⇢i 2 S ; T ⌧ +1 J l call M K P S(T ) def = ⇢ hl, ⇢ihi(M ), ⇢i ⇢ 2 E, 2 ⌃ ⇤1 hi(M ), ⇢i 2 C P 6 = M C def = lfp v ⌃ ! ( S. ⌧ +1 (M )S(T )) ⌧ +1 J l return K P S(T ) def = {hl, ⇢ihr, ⇢i | r 2 L, ⇢ 2 E, 2 ⌃ ⇤1 , hr, ⇢i 2 T } Figure 7
.5: Maximal trace semantics of instructions stmt and ret.

the trace semantics of the following recursive calls, followed by a set of traces T starting with the final label of the instruction. The traces belonging to S ; T start with environments paired with the initial control point of the procedure. Thus, the trace semantics of the instruction simply prepends to them the same environments paired with the initial label of the instruction.

The trace semantics of a non-recursive call instruction, when the called procedure M is di↵erent from the caller P , takes as input a set of traces T starting with the final label of the instruction, determines from T the trace semantics C of the callee, and prepends to the initial states of the traces belonging to C the same environments paired with the initial label of the instruction. The called procedure M can be a recursive procedure. Thus, its trace semantics is defined as the least fixpoint of S. ⌧ +1 (M )S(T ) within the complete lattice hP(⌃ +1 ), v, t, u, ⌃ ! , ⌃ + i, analogously to Equation 2.2.5. Note that, we assumed that mutual recursion is reduced into a single recursive procedure. The function ⌧ +1 : M ! (P(⌃ +1 ) ! P(⌃ +1 ) ! P(⌃ +1 )) maps procedure names to their maximal trace semantics: given a declaration M : stmt ret, ⌧ +1 (M )S(T ) def = ⌧ +1 J stmt K M S(⌧ +1 J ret K M S(T )). The iteration sequence, starting from all infinite sequences ⌃ ! , builds the set of program traces that consist of an infinite number of recursive calls, and it prepends a finite number of recursive calls to an input set T 2 P(⌃ +1 ) of traces starting with the final label of the call instruction.

Finally, the semantics of a return instruction takes as input a set of traces starting from the calling control point, and prepends to them the same initial environments paired with the initial control point of the instruction.

The trace semantics ⌧ +1 J stmt K P S : P(⌃ +1 ) ! P(⌃ +1 ) of other instructions stmt is defined as follows:

⌧ +1 J stmt K P S def = ⌧ +1 J stmt K (7.2.2)
where ⌧ +1 J stmt K : P(⌃ +1 ) ! P(⌃ +1 ) is defined in Figure 3.7.

The maximal trace semantics ⌧ +1 J prog K 2 P(⌃ +1 ) of a program prog is defined by the maximal trace semantics of the main procedure taking as input the infinite sequences ⌃ ! and the final states Q: Definition 7.2.4 (Maximal Trace Semantics) The maximal trace semantics ⌧ +1 J prog K 2 P(⌃ +1 ) of a program prog is:

⌧ +1 J prog K = ⌧ +1 J mthd l K def = ⌧ +1 J mthd K⌃ ! (Q) (7.2.3)
where ⌧ +1 J main : stmt

K def = ⌧ +1 J stmt K main and ⌧ +1 J M : stmt ret mthd K def = ⌧ +1 J mthd K,
Q def = {6} ⇥ E.
The maximal trace semantics of the program is defined by the maximal trace semantics of the main procedure: ⌧ +1 main J 5 call f K⌃ ! (Q) (cf. Definition 3.2.5). The semantics of the call statement determines the maximal trace semantics of the procedure f (cf. Figure 7.5). The fixpoint iterates are depicted in Figure 7.6. Thus, the maximal trace semantics of the program contains the traces that starting from the initial states I call the procedure f a nondeterminist number of times: {h5, ⇢i(h1, ⇢ih3, ⇢i

) ⇤ h1, ⇢ih2, ⇢ih4, ⇢ih8, ⇢i | ⇢ 2 E} [ {h5, ⇢i(h1, ⇢ih3, ⇢i) ! | ⇢ 2 E} S 0 = ( ⌃ ! ) S 1 = ( ? skip return ) [ ( ? call f ⌃ ! ) S 2 = ( ? skip return ) [ ( ? call f ? skip return ) [ ( ? call f ? call f ⌃ ! ) . . .

Definite Termination Semantics

We now extend the structural definition given in Section 4.3 of the fixpoint definite termination semantics ⌧ Mt 2 ⌃ * O (cf. Equation 4.2.16). Then, we propose a sound decidable abstraction of ⌧ Mt based on piecewise-defined ranking functions (cf. Chapter 5 and Chapter 6).

Definite Termination Semantics

We partition the definite termination semantics ⌧ Mt with respect to the program control points:

⌧ Mt 2 L ! (E * O).
In this way, to each program control point l 2 L corresponds a partial function f : E * O, and, for any procedure P, to each program instruction stmt and ret corresponds a termination semantics

⌧ Mt J stmt K P : (E * O) ! (E * O) and ⌧ Mt J ret K P : (E * O) ! (E * O).
Each function ⌧ Mt J stmt K P F and ⌧ Mt J ret K P F takes as input a ranking function whose domain represents the terminating environments at the final label of the instruction and outputs a ranking function whose domain represents the terminating environments at the initial label of the instruction, and whose value is an upper bound on the number of program execution steps remaining to termination. The parameter F 2 E * O is used to handle recursive calls.

The termination semantics of a recursive call, when the called procedure coincides with the caller, is parameterized by a ranking function F : E * O representing the termination semantics of the following recursive calls, and takes as input a ranking function f : E * O whose domain represents the terminating environments at the final label of the instruction. The domain of termination semantics of the instruction is the intersection of the domains of f and F , and its value is the sum of the value of f and F plus one, to take into account that from the environments at the initial label of the instruction another program execution step is necessary before termination:

(⌧ Mt J l call M K M F )(f ) def = ⇢ 2 dom(f ) \ dom(F ). f(⇢) + F (⇢) + 1 (7.3.1)
The termination semantics of a non-recursive call, when the called procedure M is di↵erent from the caller P , takes as input a ranking function f : E * O, determines from f the termination semantics I : E * O of the callee, and increases its value to account of another program execution step:

(⌧ Mt J l call M K P F )(f ) def = ⇢ 2 dom(I). I(⇢) + 1 P 6 = M I def = lfp v ; ( F. (⌧ Mt (M )F )(f )) (7.3.2)
The termination semantics of the possibly recursive called procedure M is defined as the least fixpoint of F. (⌧ Mt (M )F )(f ) within the partially ordered set hE * O, vi, analogously to Equation 4.2.16. The rationale being that the call from P to M may be a call to a sequence of recursive calls to M , which are collected by the fixpoint. The function

⌧ Mt : M ! ((E * O) ! (E * O) ! (E * O))
maps procedure names to their termination semantics: given a procedure declaration M : stmt ret, we have (⌧

Mt (M )F )(f ) def = (⌧ Mt J stmt K M F )((⌧ Mt J ret K M F )(f )
). The iteration sequence, starting from the totally undefined function ;, builds the ranking function whose domain is the set of environments from which a finite number of recursive calls is made.

Finally, the termination semantics of a return instruction takes as input a ranking function whose domain represents the terminating environments at the calling control point and increases its value to take into account another program execution step before termination:

(⌧ Mt J l return K P F )(f ) def = ⇢ 2 dom(f ). f(⇢) + 1 (7.3.3)
The termination semantics ⌧ Mt J stmt K P F : (E * O) ! (E * O) of other instructions stmt is defined as follows:

⌧ Mt J stmt K P F def = ⌧ Mt J stmt K (7.3.4)
where

⌧ Mt J stmt K : (E * O) ! (E * O)
is defined in Section 4.3. For a conditional statement if l bexp then stmt 1 else stmt 2 fi, F has to be passed to the termination semantics of stmt 1 and stmt 2 . For a loop while l bexp do stmt od, F has to be passed to the termination semantics of the loop body stmt. For a sequential composition of instructions stmt 1 stmt 2 , F has to be passed to the termination semantics of the components stmt 1 and stmt 2 .

The termination semantics ⌧ Mt J prog K 2 E * O of a program prog is a ranking function whose domain represents the terminating environments, which is determined by the termination semantics of the main procedure taking as input the totally undefined function and the zero function: Definition 7.3.1 (Termination Semantics) The termination semantics

⌧ Mt J prog K 2 E * O of a program prog is: ⌧ Mt J prog K = ⌧ Mt J mthd l K def = (⌧ Mt J mthd K ;)( ⇢. 0) (7.3.5)
where ⌧ Mt J main : stmt

K def = ⌧ Mt J stmt K main and ⌧ Mt J M : stmt ret mthd K def = ⌧ Mt J mthd K,
and where the function

⌧ Mt J stmt K P F : (E * O) ! (E * O)
is the termination semantics of each program instruction stmt.

Abstract Definite Termination Semantics

We propose a sound decidable abstraction of the definite termination semantics ⌧ Mt J prog K 2 E * O based on piecewise-defined ranking functions.

In particular, we supplement the set of operators of the decision trees abstract domain (cf. Chapter 5 and Chapter 6) with a sum operator + T .

Sum. The sum operator + T is implemented by Algorithm 23: the function sum, given a sound over-approximation D 2 D of the reachable environments and two decision trees t 1 , t 2 2 T , first calls unification (cf. Line 10) for tree unification and then calls the auxiliary function sum-aux (cf. Line 11). The latter descends along the paths of the decision trees (cf. Lines 5-6), up to the leaf nodes where the leaves sum operator + F is invoked.

The sum + F between defined and undefined leaf nodes is analogous to the leaves approximation join g F (cf. Equation 5.2.13): if isLeaf(t 1 ) ^isLeaf(t 2 ) then 3:

? F + F f def = ? F f 2 F \ {> F } f + F ? F def = ? F f 2 F \ {> F } > F + F f def = > F f 2 F \ {? F } f + F > F def = > F f 2 F \ {? F } (
return LEAF : t 1 .f + F t 2 .f 4:
else if isNode(t 1 ) ^isNode(t 2 ) then 5:

(l 1 , l 2 ) sum-aux(t 1 .l, t 2 .l)

6:

(r 1 , r 2 ) sum-aux(t 1 .r, t 2 .r)

7:
return (NODE{c} : l 1 ; r 1 , NODE{c} : l 2 ; r 2 ) 8:

9: function sum(D, t 1 , t 2 ) . D 2 D, t 1 , t 2 2 T 10: (t 1 , t 2 ) unification(D, t 1 , t 2 ) 11: return sum-aux(t 1 , t 2 ) (⌧ \ Mt J l call M K M T )(t) def = STEP T (t + T T ) (⌧ \ Mt J l call M K P T )(t) def = STEP T (I) P 6 = M I def = lfp \ ( T. (⌧ \ Mt (M )T )(t)) (⌧ \ Mt J l return K P T )(t) def = STEP T (t)
Figure 7.7: Abstract termination semantics of instructions stmt.

In particular, the sum is undefined between ? F -leaves and > F -leaves and always favors the undefined leaf nodes. Instead, given two defined leaf nodes f 1 , f 2 2 F \ {? F , > F }, their sum f 1 + F f 2 is defined as expected:

f 1 + F f 2 def = f 1 + f 2 (7.3.7) Example 7.3.2 Let X = {x}, and let f 1 def = x.
x and f 2 def = x. x+5 be two a ne functions. Then, their sum is the a ne function

f 1 + F f 2 def = x. x x + 5 = x. 5.
Abstract Definite Termination Semantics. In the following, as in Section 5.3, we assume to have, for each program control point l 2 L, a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (l) 2 P(E):

⌧ I (l) ✓ D (R) (cf. Section 3.4).
In Figure 7.7, for any procedure P, we define ⌧ \ Mt J stmt K P T : T ! T and ⌧ \ Mt J ret K P T : T ! T for a call instruction stmt and a return instruction ret, respectively. Each function ⌧ \ Mt J stmt K P and ⌧ \ Mt J ret K P takes as input a decision tree over-approximating the ranking function corresponding to the final control point of the instruction, and outputs a decision tree defined over a subset of the reachable environments R 2 D, which over-approximates the ranking function corresponding to the initial control point of the instruction. The parameter T 2 T is used to handle recursive calls. In particular, the decision tree T abstracts the termination semantics F : E * O of the following recursive calls (cf. Equation 7.3.1). Then, the semantics of a recursive call instruction invokes STEP T (cf. Algorithm 9) on the sum + T (cf. Algorithm 23) between T and the input decision tree t 2 T .

The following result proves that for a recursive call instruction l call M , given sound over-approximations R 2 D of ⌧ I (l), S 2 D of ⌧ I (i(M )), and

D 2 D of ⌧ I (f J l call M K), the abstract semantics ⌧ \ Mt J l call M K M is a sound over-approximation of ⌧ Mt J l call M K M defined in Equation 7.3.1: Lemma 7.3.3 (⌧ Mt J l call M K M T [S]T )( T [D]t) 4 T [R](STEP T (t + T T )).
Proof. See Appendix A.5.

⌅

The semantics of a non-recursive call, when the called procedure M is di↵erent from the caller P , invokes the STEP T operator on the semantics I 2 T of the callee. The semantics of the called procedure M is defined as the limit of the iteration sequence with widening (cf. Equation 5.2.24) of T. ⌧ \ Mt (M )T (t). The function ⌧ \ Mt : M ! (T ! T ! T ) maps procedure names to their semantics: given a procedure declaration M : stmt ret, we have

⌧ \ Mt (M )T (t) def = ⌧ \ Mt J stmt K M T (⌧ \ Mt J ret K M T (t)). The abstract semantics ⌧ \ Mt J l call M K P of a non-recursive call instruc- tion l call M , given sound over-approximations R 2 D of ⌧ I (l), S 2 D of ⌧ I (i(M )), and D 2 D of ⌧ I (f J l call M K)
, is a sound over-approximation of the termination semantics ⌧ Mt J l call M K P defined in Equation 7.3.2:

Lemma 7.3.4 (⌧ Mt J l call M K P T [S]T )( T [D]t) 4 T [R](STEP T (I))
, where

I def = lfp \ ( T. (⌧ \ Mt (M )T )(t)).
Proof. See Appendix A.5.

⌅

Finally, the semantics of a return instruction simply invokes the STEP T operator on the given input decision tree.

The following result proves, given sound over-approximations R 2 D of ⌧ I (l) and D 2 D of ⌧ I (f J l return K), the soundness of the abstract semantics ⌧ \ Mt J l return K P with respect to ⌧ Mt J l return K P defined in Equation 7.3.3:

Lemma 7.3.5 (⌧ Mt J l return K P T [D]T )( T [D]t) 4 T [R](STEP T (t)). Proof. See Appendix A.5.

⌅

The semantics ⌧ \ Mt J stmt K P T : T ! T of other instructions stmt is:

⌧ \ Mt J stmt K P T def = ⌧ \ Mt J stmt K (7.3.8)
where ⌧ \ Mt J stmt K : T ! T is defined in Figure 5.12. For a conditional statement if l bexp then stmt 1 else stmt 2 fi, T has to be passed to the termination semantics of stmt 1 and stmt 2 . For a loop while l bexp do stmt od, T has to be passed to the termination semantics of the loop body stmt. For a sequential composition of instructions stmt 1 stmt 2 , T has to be passed to the termination semantics of the components stmt 1 and stmt 2 . Given sound overapproximations R 2 D of ⌧ I (iJ stmt K) and D 2 D of ⌧ I (f J stmt K), ⌧ \ Mt J stmt K P is a sound over-approximation of ⌧ Mt J stmt K P defined in Equation 7.3.4:

Lemma 7.3.6 (⌧ Mt J stmt K P T [D]T )( T [D]t) 4 T [R]((⌧ \ Mt J stmt K P T )(t)).
Proof (Sketch).

The proof follows from Equation 7.3.4 and Equation 7.3.8 and from the soundness of ⌧ \ Mt J stmt K defined in Figure 5.12 with respect to ⌧ Mt J stmt K defined in Section 4.3 (cf. Lemma 5.2.8, Lemma 5.2.14, Lemma 5.2.15, Lemma 5.2.16, Lemma 5.2.24, and Lemma 6.4.1).

⌅

The abstract termination semantics ⌧ \ Mt J prog K 2 T of a program prog outputs the decision tree over-approximating the ranking function corresponding to the initial program control point iJ prog K 2 L. It is defined by means of the abstract termination semantics of the main procedure taking as input ? T and the leaf node LEAF : X 1 , . . . , X k . 0: Definition 7.3.7 (Abstract Termination Semantics) The abstract termination semantics ⌧ \ Mt J prog K 2 T of a program prog is:

⌧ \ Mt J prog K = ⌧ \ Mt J mthd l K def = (⌧ \ Mt J mthd K? T )(LEAF : X 1 , . . . , X k . 0) (7.3.9)
where ⌧ \ Mt J main : stmt

K def = ⌧ \ Mt J stmt K main and ⌧ \ Mt J M : stmt ret mthd K def = ⌧ \ Mt J mthd K,
and where the abstract semantics ⌧ \ Mt J stmt K P T : T ! T of each program instruction stmt is defined in Figure 7.7 and Equation 7.3.8.

The following result proves the soundness of the abstract termination semantics ⌧ \ Mt J prog K 2 T with respect to the termination semantics ⌧ Mt J prog K 2 E * O, given a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (iJ prog K) at the initial program control point:

Theorem 7.3.8 ⌧ Mt J prog K 4 T [R]⌧ \ Mt J prog K Proof (Sketch).
The proof follows from the soundness of the operators of the decision trees abstract domain (Lemma 7.3.3, Lemma 7.3.4, Lemma 7.3.5, and Lemma 7.3.6) used for the definition of ⌧ \ Mt J prog K 2 T .

⌅

In particular, the abstract termination semantics provides su cient preconditions for ensuring definite termination of a program for a given overapproximation R 2 D of the set of initial states I ✓ ⌃: Corollary 7.3.9 A program must terminate for execution traces starting from a given set of initial states

D (R) if D (R) ✓ dom( T [R]⌧ \ Mt J prog K).
Example. In the following, we recall the example introduced at the beginning of the chapter and we present the fully detailed analysis of the program using the abstract domain of decision trees.

Example 7.3.10 Let us consider again the recursive program of Example 7.2.1: Similarly, the third iterate of the call to f concludes that the procedure terminates in at most eleven execution steps, when it calls itself recursively twice, in at most seven execution steps, when it calls itself recursively only once, and in at most three program steps when 1 < x is not satisfied:

f : if 1 (1 < x) then 2 x := x 1 3 call f else
1 : NODE{x 4 0} : LEAF : ? F ; NODE{x 3 0} : LEAF : LEAF : x. 11; NODE{x 2 0} : (LEAF : x. 7); (LEAF : x. 3)
Then, the widening extrapolates the ranking function on the partitions over which it is not yet defined:

1 : NODE{x 3 0} : LEAF : x. 4x 1;
NODE{x 2 0} : (LEAF : x. 7); (LEAF : x. 3) yielding a fixpoint for the call to f within the main procedure.

The ranking function associated with program control point 7 is:

7 : NODE{x 3 0} : LEAF : x. 4x; NODE{x 2 0} : (LEAF : x. 8); (LEAF : x. 4)
Finally, the non-deterministic assignment at program control point 6 yields:

6 : LEAF : x. ! + 8.
which proves that the program is always terminating, whatever the initial value of the program variable x.

The results presented in this chapter are only preliminary, more general results being necessary to cover all practical cases.

Implementation

This chapter presents our prototype static analyzer FuncTion which is based on piecewise-defined ranking functions. We also propose the most recent experimental evaluation.

Ce chapitre présente notre prototype d'analyseur statique FuncTion qui est basé sur des fonctions de rang définies par morceaux. Nous présentons aussi l'évaluation expérimentale la plus récente.

FuncTion

We have implemented a prototype static analyzer FuncTion based on the decision trees abstract domain presented in Chapter 5. It is available online: http://www.di.ens.fr/ ~urban/FuncTion.html. The prototype accepts programs written in a (subset of) C, without struct and union types. It provides only a limited support for arrays and pointers. The only basic data type are mathematical integers, deviating from the standard semantics of C. The prototype is written in OCaml and, at the time of writing, the available numerical abstractions for handling linear constraints within the decision nodes are based on the intervals abstract domain [START_REF] Cousot | Static Determination of Dynamic Properties of Programs[END_REF] (cf. Section 3.4.1), the convex polyhedra abstract domain [START_REF] Cousot | Automatic Discovery of Linear Restraints Among Variables of a Program[END_REF] (cf. Section 3.4.2), and the octagons abstract domain [START_REF] Miné | The Octagon Abstract Domain[END_REF] (cf. Section 3.4.3), and the available abstraction for handling functions within the leaf nodes are based on a ne functions. The numerical abstract domains are provided by the APRON library [START_REF] Jeannet | Apron: A Library of Numerical Abstract Domains for Static Analysis[END_REF]. It is also possible to activate the extension to ordinalvalued ranking functions presented in Chapter 6, and tune the precision of the analysis by adjusting the widening delay.

To improve precision, we avoid trying to compute a ranking function for the non-reachable states: FuncTion runs a forward analysis to over-approximate the reachable states using a numerical abstract domain (cf. Section 3.4). Then, it runs the backward analysis to infer a ranking function, intersecting its domain at each step with the states identified by the previous analysis.

The analysis proceeds by structural induction on the program syntax, iterating loops and recursive procedures (cf. Chapter 7) until an abstract fixpoint is reached. In case of nested loops, a fixpoint on the inner loop is computed for each iteration of the outer loop, following [START_REF] Bourdoncle | E cient Chaotic Iteration Strategies with Widenings[END_REF][START_REF] Muthukumar | Compiletime Derivation of Variable Dependency Using Abstract Interpretation[END_REF]. It is also possible to activate the extension of FuncTion with conflict-driven learning [START_REF] Vijay | Conflict-Driven Abstract Interpretation for Conditional Termination[END_REF].

Experimental Evaluation

We evaluated our prototype implementation FuncTion against 288 terminating C programs collected from the termination category of the 4th International Competition on Software Verification (SV-COMP 2015). FuncTion provides only a limited support for arrays and ponters. Therefore, we were not able to analyze 17% of the SV-COMP 2015 benchmark test cases.

The experiments were performed on a system with a 1.30GHz 64-bit Dual-Core CPU (Intel i5-4250U) and 4GB of RAM, and running Ubuntu 14.04.

In Figure 8.1, we compared di↵erent parameterizations of FuncTion. The results match the expectations: FuncTion parameterized with interval constraints based on the intervals abstract domains (cf. Section 3.4.1) and a widening delay of two iterations is the fastest but least precise, and Func-Tion parameterized with polyhedral constraints based on the polyhedra abstract domain (cf. Section 3.4.2) and a widening delay of three iterations is the slowest but most precise. We observed that delaying the widening further marginally improves precision but significantly increases running times.

We also compared FuncTion to the other tools that participated to the termination category of SV-COMP 2015 : AProVE [SAF + 15], the preliminary version of FuncTion [Urb15], HIPTnT+ [START_REF] Le | Termination and Non-Termination Specification Inference[END_REF], and Ultimate [HDL + 15]. FuncTion, with respect to its preliminary version, has been extended with conflict-driven learning [START_REF] Vijay | Conflict-Driven Abstract Interpretation for Conditional Termination[END_REF]. In the comparison, we implemented FuncTion to use interval constraints and a two iteration widening delay, and respond to failure to prove a program terminating by using polyhedral constraints with three iterations widening delay. The reported execution times are for the entire run, which may involve trying both parameterizations. It was not possible to run all the tools on the same system because we did not have access to the competition versions of AProVE, HIPTnT+ and Ultimate. For these tools, we used the results of SV-COMP 2015 1 even though the competition was conducted on more powerful systems with a 3.40GHz 64-bit Quad-Core CPU (Intel i7-4770) and 33GB of RAM.

Figure 8.2 summarizes our experimental evaluation and Figure 8.3 shows a detailed comparison of FuncTion against each other tool. In Figure 8.2a, the first column reports the total number of programs that each tool could prove terminating, the second column reports the average running time in seconds for the programs where the tool proved termination, and the last column reports the number of time outs. We used a time limit of 180 seconds for each program test case. In Figure 8.2b, the first column (⌅) lists the total number of programs that the tool was not able to prove termination for and that FuncTion could prove terminating, the second column (N) reports the total number of programs that FuncTion was not able to prove termination for and that the tool could prove terminating, and the last two columns report the total number of programs that both the tool and FuncTion were able (⇥) or unable (#) to prove terminating. The same symbols are used in Figure 8.3.

Figure 8.2a shows that FucTion improves by around 9% the result of its preliminary version. The increase in the execution time is not evenly distributed, and about 2% of the program test cases require more than 20 seconds to be proved terminating by FuncTion (cf. also Figure 8.3a). The reason for this overhead is the heuristic that we have chosen to guide the conflictdriven analysis, which appears to be unfortunate in these cases [START_REF] Vijay | Conflict-Driven Abstract Interpretation for Conditional Termination[END_REF] Figure 8.3a it also emerges that, as expected, the previous version of Func-Tion gives up earlier when unable to prove termination. Instead, FuncTion persists in the analysis and times out slightly more frequently.

In Figure 8.3b and Figure 8.3d we clearly notice that, despite the fact that AProVE and Ultimate were run on the more powerful machines of SV-COMP 2015, FuncTion is generally faster but able to prove termination of respectively 19% and 9% fewer program test cases (cf. also Figure 8.2a).

HIPTnT+ is able to prove termination of 16% more programs than Func-Tion (cf. Figure 8.2a), but FuncTion can prove termination of 52% of the programs that HIPTnT+ is not able to prove terminating (8% of the total program test cases, cf. Figure 8.2b). Note that, when performing the experiments with the previous version of FuncTion [START_REF] Urban | FuncTion: An Abstract Domain Functor for Termination (Competition Contribution)[END_REF] we observed that the SV-COMP 2015 machines provided a 2x speedup. Thus, the comparison of the execution times of FuncTion and HIPTnT+ is currently inconclusive.

Finally, we noticed that 1% of the SV-COMP 2015 program test cases could be proved terminating only by FuncTion (2.7% only by AProVE, 1% only by HIPTnT+, and 1.7% only by Ultimate). None of the tools was able to prove termination for 0.7% of the programs.

In the following, we further detail our experimental evaluation. In particular, we further discuss the comparison of our prototype implementation FuncTion with each of the other tools that participated to the termination category of SV-COMP 2015.

The SV-COMP 2015 program test cases for termination are arranged into four verification tasks, according to the characteristics of the programs: crafted (programs manually crafted by the participants to the competition), crafted-lit (programs collected from the literature), memory-alloca (programs with dynamic memory allocation), and numeric (programs implementing numerical algorithms). For each verification task, a dedicated overview of the experimental evaluation is shown in Figure 8. 8.2a, the first column of the tables reports the total number of programs that each tool was able to prove termination for, the second column reports the average running time in seconds for the programs where the tool proved termination, and the last column reports the number of time outs. We used a time limit of 180 seconds for each program test case. As in Figure 8.2b, the first column (⌅) of the tables reports the total number of programs that FuncTion was able to prove terminating and that the tool was not, the second column (N) reports the total number of programs that the tool was able to prove terminating and that FuncTion was not, and the last two columns report the total number of programs that both the tool and FuncTion were able (⇥) or unable (#) to prove terminating. The same Figure 8.5 shows, for each verification task, a detailed comparison of Func-Tion against AProVE [SAF + 15]. In the crafted verification task, the tool are able to prove the termination of the same number of programs (cf. also Figure 8.4a), while in the crafted-lit verification task, AProVE performs much better than FuncTion (cf. also Figure 8.6a). In all verification tasks, Func-Tion is faster despite running on a less powerful machine than AProVE. In particular, we observe that AProVE times out on most of the programs that only FuncTion is able to prove terminating.

In Figure 8.7, we observe a comparison of FuncTion against its previous version [Urb15]. The numeric verification task is where FuncTion improves the most the result of its previous version (around 17%, cf. also Figure 8.10a). In the crafted-lit verification task, we clearly see that, as expected, Func-Tion spends more execution time and often times out when unable to prove termination (cf. also Figure 8.6a).

The comparison of FuncTion against HIPTnT+ is shown in Figure 8.9. In the crafted-lit verification task HIPTnT+ performs better than FuncTion (cf. also Figure 8.6a), while FuncTion performs better than HIPTnT+ in the memory-alloca verification task (cf. also Figure 8.8a). Note that, as mentioned, when performing the experiments with the previous version of Func-Tion [START_REF] Urban | FuncTion: An Abstract Domain Functor for Termination (Competition Contribution)[END_REF] we observed that the more powerful SV-COMP 2015 machines provided a 2x speedup in the execution time. Nonetheless, in the crafted verification task FuncTion is faster than HIPTnT+ (cf. also Figure 8.4a), and in the numeric verification task the execution time of the tools is at least comparable (cf. also Figure 8.10a). Finally, the programs that could be proved terminating only by Func-Tion were 4% of the programs for the crafted verification task (4% only by Ultimate), 0.7% of the programs for the crafted-lit verification task (1.5% only by AProVE and HIPTnT+, and 3.1% only by Ultimate), and 1.7% of the programs for the numeric verification task (1.7% only by AProVE). For the memory-alloca, 6.5% and 1.3% of the programs could be proved terminating only by AProVE and HIPTnT+, respectively. All the programs that none of the tools could prove terminating belong to the crafted-lit verification task.

IV

Liveness

A Hierarchy of Temporal Properties

In this chapter, we generalize the abstract interpretation framework proposed for termination by Patrick Cousot and Radhia Cousot [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF] and presented in Chapter 4, to other liveness properties. In particular, with reference to the hierarchy of temporal properties proposed by Zohar Manna and Amir Pnueli [MP90], we focus on guarantee ("something good occurs at least once") and recurrence ("something good occurs infinitely often") temporal properties. Specifically, static analyses of guarantee and recurrence temporal properties are systematically derived by abstract interpretation of the program maximal trace semantics presented in Chapter 2 and Chapter 3. These methods automatically infer su cient preconditions for the temporal properties by leveraging the abstract domains based on piecewise-defined ranking functions presented in Chapter 5 and Chapter 6. We augment these abstract domains with new operators including a dual widening.

Finally, we describe the implementation of the static analysis methods for guarantee and recurrence temporal properties into our prototype static analyzer FuncTion described in Chapter 8.

Dans ce chapitre, nous généralisons le cadre de l'interprétation abstraite proposé pour la terminaison par Patrick Cousot et Radhia Cousot [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF] et présenté dans le Chapitre 4, à d'autres propriétés de vivacité. En particulier, en référence à la hiérarchie des propriétés temporelles proposée par Zohar Manna et Amir Pnueli [START_REF] Manna | A Hierarchy of Temporal Properties[END_REF], nous nous concentrons sur les propriétés temporelles de garantie ("quelque bon chose se produit au moins une fois") et de récurrence ("quelque bon chose se produit infiniment souvent").

Plus précisément, les analyses statiques pour les propriétés temporelles de garantie et de récurrence sont dérivées systématiquement par interprétation abstraite de la sémantique de traces maximales des programmes présentée dans le Chapitre 2 et le Chapitre 3. Ces méthodes déduisent automatiquement des conditions su santes pour les propriétés temporelles en s'appuyant sur les domaines abstraits basés sur des fonctions de rang définies par morceaux présentées dans le Chapitre 5 et le Chapitre 6. Nous enrichissons ces domaines abstraits avec de nouveaux opérateurs, dont un élargissement dual.

Enfin, nous décrivons la mise en oeuvre des méthodes d'analyse statique pour les propriétés temporelles de garantie et de récurrence dans notre prototype d'analyseur statique FuncTion décrit dans le Chapitre 8.

A Hierarchy of Temporal Properties

Leslie Lamport, in the late 1970s, suggested a classification of program properties into the classes of safety and liveness properties [START_REF] Lamport | Proving the Correctness of Multiprocess Programs[END_REF]. The class of safety properties is informally characterized as the class of properties stating that "something bad never happens", that is, a program never reaches an unacceptable state. The class of liveness properties is informally characterized as the class of properties stating that "something good eventually happens", that is, a program eventually reaches a desirable state (cf. Section 1.2).

Zohar Manna and Amir Pnueli, in the late 1980s, suggested an alternative classification of program properties into a hierarchy [START_REF] Manna | A Hierarchy of Temporal Properties[END_REF], which distinguishes four basic classes making di↵erent claims about the frequency or occurrence of "something good" mentioned in the informal characterizations of the classes proposed by Leslie Lamport: safety properties, guarantee properties, recurrence properties, and persistence properties.

In the following, we only consider program properties expressible by temporal logic. To this end, we assume an underlying specification language, which is used to describe properties of program states.

For instance, for the small imperative language presented in Chapter 3, we define inductively the syntax of the state properties as follows:

' ::= bexp | l : bexp | ' ^' | ' _ ' l 2 L (9.1.1)
where bexp is a boolean expression (cf. Figure 3 x := x + 1 then

6 x := x fi od 7
The first loop is an infinite loop for the values of the variable x greater than or equal to zero: at each iteration the value of x is increased by one. The second loop is an infinite loop for any value of the variable x: at each iteration, the value of x is increased by one or negated when it becomes greater than ten.

The set of program environments E contains functions ⇢ : {x} ! Z mapping the program variable x to any possible value ⇢(x) 2 Z. The set of program states ⌃ def = {1, 2, 3, 4, 5, 6, 7} ⇥ E consists of all pairs of numerical labels and environments; the initial states are

I def = {h1, ⇢i | ⇢ 2 E}.
An example of state property allowed by the specification language defined in Equation 9.1.1 is the property x = 3. The set of states that satisfy this property is {1, 2, 3, 4, 5, 6, 7} ⇥ {hx, 3i}. Note however, that the states h6, {hx, 3i}i and h7, {hx, 3i}i are not reachable from the initial states.

Another examples of state property allowed by the specification language is 7 : x = 3, which is only satisfied by the unreachable state h7, {hx, 3i}i.

The program properties within the hierarchy are then defined by means of the temporal operators always 2 and eventually 3.

Safety Properties

The class of safety properties is informally characterized as the class of properties stating that "something good alway happens", that is, a program never reaches an unacceptable state. The safety properties that we consider are expressible by a temporal formula of the following form:

2'

where ' is a state property. The temporal formula expresses that all program states in every program trace satisfy the state property '.

In general, these safety properties are used to express invariance of some program state property over all computations.

A typical safety property is program partial correctness, which guarantees that all terminating computations produce correct results, and which is expressible by the following temporal formula: 2(l e : ) where l e 2 L denotes the program final control point and the formula specifies the postcondition of the program.

Another typical safety property is mutual exclusion, which guarantees that no two concurrent processes can enter their critical section at the same time, and which is expressible by the following temporal formula:

2(l 1 : false _ l 2 : false)
where l 1 2 L and l 2 2 L denote the program control points representing the critical section of the first and second process, respectively. The class of safety properties that we consider are closed under conjunction.

In fact, any temporal formula of the form 2' 1 ^2' 2 is equivalent to the safety property formula 2(' 1 ^'2 ).

Guarantee Properties

The class of guarantee properties is informally characterized as the class of properties stating that "something good happens at least once", that is, a program eventually reaches a desirable state. The guarantee properties that we consider are expressible by a temporal formula of the following form:

3'

where ' is a state property. The temporal formula expresses that at least one program state in every program trace satisfies the property ', but it does not promise any repetition.

In general, these guarantee properties are used to ensure that some event happens once during a program execution.

A typical guarantee property is program termination, which ensures that all computations are finite, expressible by the following temporal formula:

3(l e : true)
where l e 2 L denotes the program final control point. Another typical guarantee property is program total correctness, which ensures that all computations starting in a '-state terminate in a -state, expressible by the following temporal formula: An example of guarantee property is the formula 3(x = 3), which is satisfied when the program initial states are limited to the set {h1, ⇢i 2 ⌃ | ⇢(x)  3}. In particular, note that when the program initial state are limited to {h1, ⇢i 2 ⌃ | 0  ⇢(x)  3}, the guarantee property is satisfied within the first while loop. Instead, when the program initial states are limited to {h1, ⇢i 2 ⌃ | ⇢(x) < 0}, the guarantee property is satisfied within the second while loop.

Another example of guarantee property is the formula 3(3  x), which is always satisfied by the program whatever its initial states.

The class of guarantee properties that we considered are closed under disjunction. In fact, any temporal formula of the form 3' 1 _ 3' 2 is equivalent to the guarantee property formula 3(' 1 _ ' 2 ).

The classes of safety and guarantee properties that we consider are not closed under negation. On the other hand, the negation of a safety property formula 2' is a guarantee property formula 3¬'. Similarly, the negation of a guarantee property formula 3' is a safety property formula 2¬'.

Obligation Properties

The program properties that cannot be expressed by either a safety or a guarantee property formula belong to the compound class of obligation properties, which contains program properties expressible as a boolean combination of a safety property formula and guarantee property formula. The obligation properties that we consider are represented by a temporal formula of the form:

2' _ 3
where ' and are state properties.

Recurrence Properties

The class of recurrence properties is informally characterized as the class of properties stating that "something good happens infinitely often", that is, a program reaches a desirable state infinitely often. The recurrence properties that we consider are expressible by a temporal formula of the following form:

23'

where ' is a state property. The temporal formula expresses that infinitely many program states in every program trace satisfy the property '.

In general, these recurrence properties are used to ensure that some event happens infinitely many times during a program execution.

A typical recurrence property is program starvation freedom, which ensures that a process will eventually enter its critical section, and which is expressible by the following temporal formula: The recurrence property represented by the formula 23x = 3 is satisfied when the program initial states are limited to the set {h1, ⇢i 2 ⌃ | ⇢(x) < 0}. In particular, note that the recurrence property is satisfied only within the second while loop. Instead, the recurrence property 233  x is always satisfied by the program whatever its initial states.

The class of recurrence properties that we consider are closed under disjunction. In fact, any temporal formula of the form 23' 1 _ 23' 2 is equivalent to the recurrence property formula 23(' 1 _ ' 2 ).

Persistence Properties

The class of persistence properties is informally characterized as the class of properties stating that "something good eventually happens continuously", that is, a program eventually reaches a desirable state and continues to stay in a desirable state. The persistence properties that we consider are expressible by a temporal formula of the following form:

32'

where ' is a state property. The temporal formula expresses that all but finitely many program states (and, in particular, all program states from a certain point on) in every program trace satisfy the property '.

In general, these persistence properties are used to ensure the eventual stabilization of the program into a state. They allow an arbitrary delay until the stabilization, but require that once it occurs it is continuously maintained. An example of persistence property is the formula 32x = 3, which is never satisfied by the program. Instead, the persistence property represented by the formula 323  x is satisfied when the program initial states are limited to the set {h1, ⇢i 2 ⌃ | 0  ⇢(x)}. In particular, note that the persistence property is satisfied only within the first while loop.

The class of persistence properties that we consider are closed under conjunction. In fact, any temporal formula of the form 32' 1 ^32' 2 is equivalent to the persistence property formula 32(' 1 ^'2 ).

The classes of recurrence and persistence properties that we consider are not closed under negation but, analogously to the classes of safety and guarantee properties, the negation of a formula in one of the classes belongs to the other. The negation of a recurrence property formula 23' is a persistence property formula 32¬'. Similarly, the negation of a persistence property formula 32' is a recurrence property formula 23¬'.

Reactivity Properties

The program properties that cannot be expressed by either a recurrence or a persistence property formula belong to the compound class of reactivity prop-erties, which contains program properties expressible as a boolean combination of a recurrence property formula and a persistence property formula. The reactivity properties that we consider are represented by a temporal formula of the following form:

23' _ 32

where ' and are state properties.

Guarantee Semantics

In the following, we generalize Section 4.2 and Section 4.3 from definite termination to guarantee properties. We define a sound and complete semantics for proving guarantee temporal properties by abstract interpretation of the program maximal trace semantics (cf. Equation 2.2.5). The generalization is straightforward but provides a building block for the next Section 9.3. Then, we propose a sound decidable abstraction based on piecewise-defined ranking functions (cf. Chapter 5 and Chapter 6).

Guarantee Semantics

The guarantee semantics, given a set of desirable states S ✓ ⌃, is a ranking function ⌧ g [S] 2 ⌃ * O defined starting from the states in S, where the function has value zero, and retracing the program backwards while mapping every state in ⌃ definitely leading to a state in S (i.e., a state such that all the traces to which it belongs eventually reach a state in S) to an ordinal in O representing an upper bound on the number of program execution steps remaining to S. The domain dom(⌧ g [S]) of ⌧ g [S] is the set of states definitely leading to a desirable state in S: all traces branching from a state s 2 dom(⌧ g [S]) reach a state in S in at most ⌧ g [S]s execution steps, while at least one trace branching from a state s 6 2 dom(⌧ g [S]) never reaches S.

Note that the program traces that satisfy a guarantee property can also be infinite traces. In particular, guarantee properties are satisfied by finite subsequences of possibly infinite traces. Thus, in order to reason about subsequences, we define the function sq : P(⌃ +1 ) ! P(⌃ + ), which extracts the finite subsequences of a set of sequences T ✓ ⌃ +1 : sq(T )

def = { 2 ⌃ + | 9 0 2 ⌃ ⇤
, 00 2 ⌃ ⇤1 : 0 00 2 T } (9.2.1)

We recall that the neighborhood of a sequence 2 ⌃ +1 in a set of sequences , d ! }. Then, we have ↵ g [S]T = {c, bc}. In fact, let us consider the trace (abcd) ! : the subsequences of (abcd) ! that are terminating with c and never encounter c before are {c, bc, abc, dabc}; for abc, we have pf(ab) \ pf(a ! ) = {a} 6 = ; and, for dabc, we have pf(dab) \ pf(d ! ) = {d} 6 = ;. Similarly, let us consider (cd) ! : the subsequences of (cd) ! that are terminating with c and never encounter c before are {c, dc}; for dc, we have pf(d) \ pf(d ! ) = {d} 6 = ;.

We can now define the guarantee semantics ⌧ g [S] 2 ⌃ * O: Definition 9.2.2 (Guarantee Semantics) Given a desirable set of states S ✓ ⌃, the guarantee semantics ⌧ g [S] 2 ⌃ * O is an abstract interpretation of the maximal trace semantics ⌧ +1 2 P(⌃ +1 ) (cf. Equation 2.2.5):

⌧ g [S] def = ↵ Mrk (↵ g [S](⌧ +1 )) (9.2.4)
where the abstraction ↵ Mrk : P(⌃ + ) ! (⌃ * O) is the same ranking abstraction defined in Equation 4.2.14.

The following result provides a fixpoint definition of the guarantee semantics within the partially ordered set h⌃ * O, vi, where the computational order is defined as in Equation 4.2.15 as:

f 1 v f 2 () dom(f 1 ) ✓ dom(f 2 ) ^8x 2 dom(f 1 ) : f 1 (x)  f 2 (x).

Guarantee Semantics

Theorem 9.2.3 (Guarantee Semantics) Given a desirable set of states S ✓ ⌃, the guarantee semantics ⌧ g [S] 2 ⌃ * O can be expressed as a least fixpoint in the partially ordered set h⌃ * O, vi: Note that, when the set of desirable states S is the set of final states ⌦, unsurprisingly we rediscover the definite termination semantics presented in Section 4.2, since g [⌦] = Mt (cf. Equation 4.2.16).

⌧ g [S] = lfp v ; g [S] g [S]f def = s. 8 > < > : 0 s 2 S sup {f (s 0 ) + 1 | hs, s 0 i 2 ⌧ } s 6 2 S ^s 2 f pre(dom(f )) undefined otherwise ( 9
Let ' be a state property. The '-guarantee semantics ⌧ ' g 2 ⌃ * O:

⌧ ' g def = ⌧ g ['] (9.2.6)
is sound and complete for proving a guarantee property 3': The guarantee semantics of a skip instruction resets the value of the input ranking function f : E * O for the environments that satisfy ', and otherwise it increases its value to take into account another program execution step to reach ' from the environments at the initial label of the instruction:

⌧ ' g J l skip Kf def = ⇢. 8 > < > : 0 hl, ⇢i |= ' f (⇢) + 1 hl, ⇢i 6 |= ' ^⇢ 2 dom(f ) undefined otherwise (9.2.7)
Similarly, the guarantee semantics of a variable assignment l X := aexp resets the value of the input ranking function f : E * O for the environments that satisfy '; otherwise, the resulting ranking function is defined over the environments that, when subject to the variable assignment, always belong to the domain of the input ranking function. The value of the input ranking function for these environments is increased by one, to take into account another execution step, and the value of the resulting ranking function is the least upper bound of these values:

⌧ ' g J l X := aexp Kf def = ⇢. 8 > > > > > > < > > > > > > : 0 hl, ⇢i |= ' sup{f (⇢[X v]) + 1 | v 2 JaexpK⇢} hl, ⇢i 6 |= ' ^9v 2 JaexpK⇢ 8v 2 JaexpK⇢ : ⇢[X v] 2 dom(f ) undefined otherwise (9.2.8)
Note that all environments yielding a run-time error due to a division by zero do not belong to the domain of the termination semantics of the assignment.

Example 9.2.6 Let X def = {x}. We consider the following ranking function f : E * O:

f (⇢) def = 8 > < > : 2 ⇢(x) = 1 3 ⇢(x) = 2 undefined otherwise
the backward assignment x := x + [1, 2] and the guarantee property 3(x = 3).

The guarantee semantics of the assignment, given the ranking function, is:

⌧ x=3 g J x := x + [1, 2] Kf (⇢) def = 8 > < > : 4 ⇢(x) = 0 0 ⇢(x) = 3 undefined otherwise
In particular, note that unlike Example 4.3.1, the function is also defined when ⇢(x) = 3, since the environment satisfies the property x = 3. Given a conditional instruction if l bexp then stmt 1 else stmt 2 fi, its guarantee semantics takes as input a ranking function f : E * O and derives the guarantee semantics ⌧ ' g J stmt 1 Kf of stmt 1 , in the following denoted by S 1 , and the guarantee semantics ⌧ ' g J stmt 2 Kf of stmt 2 , in the following denoted by S 2 . Then, the guarantee semantics of the conditional instruction is defined by means of the ranking function F [f ] : E * O whose domain is the set of environments that belong to the domain of S 1 and to the domain of S 2 , and that may both satisfy and not satisfy the boolean expression bexp:

F [f ] def = ⇢ 2 dom(S 1 ) \ dom(S 2 ). 8 > < > : sup{S 1 (⇢) + 1, S 2 (⇢) + 1} JbexpK⇢ = {true, false} undefined otherwise
and the ranking function F 1 [f ] : E * O whose domain is the set of environments ⇢ 2 E that belong to the domain of S 1 and that must satisfy bexp:

F 1 [f ] def = ⇢ 2 dom(S 1 ).
( S 1 (⇢) + 1 JbexpK⇢ = {true} undefined otherwise and the ranking function F 2 [f ] : E * O whose domain is the set of environments that belong to the domain of S 2 and that cannot satisfy bexp:

F 2 [f ] def = ⇢ 2 dom(S 2 ). ( S 2 (⇢) + 1 JbexpK⇢ = {false} undefined otherwise
The resulting ranking function is defined by joining

F [f ], F 1 [f ], and F 2 [f ],
and resetting the value of the function for the environments that satisfy ':

⌧ ' g J if l bexp then stmt 1 else stmt 2 fi Kf def = ⇢. 8 > > > > < > > > > : 0 hl, ⇢i |= ' G(⇢) hl, ⇢i 6 |= ' ⇢ 2 dom(G) undefined otherwise (9.2.9) where G def = F [f ] [ F 1 [f ] [ F 2 [f ].
Example 9.2.7 Let X def = {x}. We consider the guarantee property 3(x = 3) and the guaran- tee semantics of the conditional statement if bexp then stmt 1 else stmt 2 fi. We assume, given a ranking function f : E * O, that the guarantee semantics of stmt 1 is defined as:

⌧ x=3 g J stmt 1 Kf (⇢) def = 8 > < > : 1 ⇢(x)  0 0 ⇢(x) = 3 undefined otherwise
and that the guarantee semantics of stmt 2 is defined as

⌧ x=3 g J stmt 2 Kf (⇢) def = 8 > > > > < > > > > : 3 0 ⇢(x) < 3 0 ⇢(x) = 3 3 3< ⇢(x) undefined otherwise
Then, when the boolean expression bexp is for example x  3, the guarantee semantics of the conditional statement is:

⌧ x=3 g J if l bexp then stmt 1 else stmt 2 fi Kf (⇢) def = 8 > > > > < > > > > : 2 ⇢(x)  0 0 ⇢(x) = 3 4 3< ⇢(x) undefined otherwise
Instead, when bexp is for example the non-deterministic choice ?, we have:

⌧ x=3 g J if l bexp then stmt 1 else stmt 2 fi Kf (⇢) def = 8 > < > : 4 ⇢(x) = 0 0 ⇢(x) = 3 undefined otherwise
Note that, unlike Example 4.3.2, both functions are also defined when ⇢(x) = 3, since the environment satisfies the property x = 3.

The guarantee semantics of a loop instruction while l bexp do stmt od takes as input a ranking function f : E * O whose domain represents the environments leading to ' from the final label of the instruction, and outputs the ranking function which is defined as the least fixpoint of the function

⌧ ' g J while l bexp do stmt od Kf def = lfp v ; ' g (9.2.10)
where the computational order is defined as in Equation 4.2.15:

f 1 v f 2 () dom(f 1 ) ✓ dom(f 2 ) ^8x 2 dom(f 1 ) : f 1 (x)  f 2 (x).
The function ' g : (E * O) ! (E * O) takes as input a ranking function

x : E * O, resets its value for the environments that satisfy ', and adds to its domain the environments for which one more loop iteration is needed before '. In the following, the guarantee semantics ⌧ ' g J stmt Kx of the loop body is denoted by S. The function ' g is defined by means of the ranking function F [x] : E * O whose domain is the set of environments that belong to the domain of S and to the domain of the input function f , and that may both satisfy and not satisfy the boolean expression bexp:

F [x] def = ⇢ 2 dom(S) \ dom(f ). 8 > < > : sup{S(⇢) + 1, f(⇢) + 1} JbexpK⇢ = {true, false} undefined otherwise
and the ranking function F 1 [x] : E * O whose domain is the set of environments ⇢ 2 E that belong to the domain of S and that must satisfy bexp:

F 1 [x] def = ⇢ 2 dom(S).
( S(⇢) + 1 JbexpK⇢ = {true} undefined otherwise and the ranking function F 2 [f ] : E * O whose domain is the set of environments that belong to the domain of the input function f and that cannot satisfy bexp:

F 2 [f ] def = ⇢ 2 dom(f ). ( f (⇢) + 1 JbexpK⇢ = {false} undefined otherwise
The resulting ranking function is defined by joining F [x], F 1 [x], and F 2 [f ], and resetting the value of the function for the environments that satisfy ':

' g (x) def = ⇢. 8 > < > : 0 hl, ⇢i |= ' G(⇢) hl, ⇢i 6 |= ' ^⇢ 2 dom(G) undefined otherwise (9.2.11)
where

G def = F [x] [ F 1 [x] [ F 2 [f ].
Finally, the guarantee semantics of the sequential combination of instructions stmt 1 stmt 2 , takes as input a ranking function f : E * O, determines from f the guarantee semantics ⌧ ' g J stmt 2 Kf of stmt 2 , and outputs the ranking function determined by the guarantee semantics of stmt 1 from ⌧ ' g J stmt 2 Kf :

⌧ ' g J stmt 1 stmt 2 Kf def = ⌧ ' g J stmt 1 K(⌧ ' g J stmt 2 Kf ) (9.2.12)
The guarantee semantics ⌧ ' g J prog K 2 E * O of a program prog is a ranking function whose domain represents the environments always leading to ', which is determined by taking as input the constant function equal to zero for the environments that satisfy ', and undefined otherwise: Definition 9.2.8 (Guarantee Semantics) The guarantee semantics Note that, as pointed out in Remark 3.2.2, possible run-time errors are ignored. Thus, all environments leading to run-time errors do not belong to the domain of the guarantee semantics of a program prog.

⌧ ' g J prog K 2 E * O of a program prog is: ⌧ ' g J prog K = ⌧ ' g J stmt l K def = ⌧ ' g J stmt K ⇢. ( 0

Abstract Guarantee Semantics

In the following, we propose a sound decidable abstraction of the guarantee semantics ⌧ ' g J prog K 2 E * O, which is based on the piecewise-defined ranking functions presented in Chapter 5 and Chapter 6. The abstraction is sound with respect to the same approximation order defined in Equation 4.2.12 as:

f 1 4 f 2 () dom(f 1 ) ◆ dom(f 2 ) ^8x 2 dom(f 2 ) : f 1 (x)  f 2 (x).
In particular, we complement the operators of the decision trees abstract domain presented in Chapter 5 with a new unary operator RESET T J ' K, which resets the leaves of a decision tree that satisfy a given property '.

Reset. The operator RESET T J ' K : L ! D ! T ! T for the reset of decision trees is implemented by Algorithm 24: the function reset, given a program control point p 2 L, a sound over-approximation d 2 D of the reachable environments, and a decision tree t 2 T , reasons by induction on the structure of the property '. In particular, when ' specifies the property at a particular program control point l 2 L (cf. Line 55), the decision tree is reset only if l coincides with p (cf. Line 57). Instead, when ' is a conjunction of two properties ' 1 and ' 2 (cf. Line 58), or a conjunction of two boolean expressions bexp 1 and bexp 2 (cf. Line 44), the resulting decision trees are merged by the function MEET defined in Algorithm 8 (cf. Line 59 and Line 47). Similarly, when ' is a disjunction of two properties ' 1 and ' 2 (cf. Line 60), or a disjunction of two boolean expressions bexp 1 and bexp 2 (cf. Line 48), the resulting decision trees are merged by the approximation join A-JOIN defined in Algorithm 6 (cf. Line 61 and Line 51). Finally, when ' is a comparison of arithmetic expressions aexp 1 ./ aexp 2 (cf. Line 52), a set of constraints J is produced by the operator FILTER C defined in Equation 5.2.23 (cf. Line 53), which is used by the auxiliary function reset-aux (cf. Line 54).

The function reset-aux augments a decision tree with a given set of linear constraints. Then, only the subtrees whose paths from the root of the decision tree satisfy these constraints are reset. In particular, the function reset-aux takes as input a decision tree t 2 T , a set C 2 P(C) of linear constraints representing an over-approximation of the reachable environments, and a set J 2 P(C) of linear constraints that need to be added to the decision tree. When J is not empty (cf. Line 12), the linear constraints J are added to the decision tree in descending order with respect to < C : at each iteration a linear constraint j 2 C is extracted from J (cf. Line 13), which is the largest constraint in J with respect to the constraints in canonical form. Then, the function reset-aux possibly adds a decision node for the linear constraint j

⌧ '\ g J l skip Kt def = RESET T J ' K(l, R, STEP T (t)) ⌧ '\ g J l X := aexp Kt def = RESET T J ' K(l, R, (B-ASSIGN T J X := aexp KR)(t)) ⌧ '\ g J if l bexp then stmt 1 else stmt 2 fi Kt def = RESET T J ' K(l, R, F \ 1 [t] g T [R] F \ 2 [f ]) F \ 1 [t] def = (FILTER T J bexp KR)(⌧ '\ g J stmt 1 Kt) F \ 2 [t] def = (FILTER T J not bexp KR)(⌧ '\ g J stmt 2 Kt) ⌧ '\ g J while l bexp do stmt od Kt def = lfp \ '\ g '\ g (x) def = RESET T J ' K(l, R, F \ [x] g T [R] (FILTER T J not bexp KR)(t)) F \ [x] def = (FILTER T J bexp KR)(⌧ '\ g J stmt Kx) ⌧ '\ g J stmt 1 stmt 2 Kt def = ⌧ '\ g J stmt 1 K(⌧ '\ g J stmt 2 Kt)
Figure 9.1: Abstract guarantee semantics of instructions stmt.

or left decision subtree unmodified when the encountered linear constraints coincide with those appearing in J (cf. Lines 29-32) or their negations (cf. Lines 33-36). When J is empty (cf. Line 2), reset-aux accumulates in C the linear constraints encountered along the paths (cf. Lines 9-10) up to a leaf node, possibly removing constraints that are redundant (cf. Line 5) or whose negation is redundant (cf. Line 6) with respect to C. Once reached a leaf node, the operator RESET F J ' K : F ! F is invoked (cf. Line 3): given a function f 2 F, it simply resets its value to zero:

RESET F (f ) def = X 1 , . . . , X k . 0 (9.2.14)
Abstract Guarantee Semantics. The operators of the decision trees abstract domain can now be used to define the abstract guarantee semantics.

In the following, as in Section 5.3 we assume to have, for each program control point l 2 L, a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (l) 2 P(E): ⌧ I (l) ✓ D (R) (cf. Section 3.4).

In Figure 9.1 we define the semantics ⌧ '\ g J stmt K : T ! T , for each program instruction stmt. Each function ⌧ '\ g J stmt K : T ! T takes as input a decision tree over-approximating the ranking function corresponding to the final control point of the instruction, and outputs a decision tree defined over a subset of the reachable environments R 2 D, which over-approximates the ranking function corresponding to the initial control point of the instruction. Note that each function ⌧ '\ g J stmt K invokes the reset operator RESET T . For a while loop, lfp \ '\ g is the limit of the iteration sequence with widening:

y 0 def = ? T y n+1 def = ( y n '\ g (y n ) v T [R] y n ^ '\ g (y n ) 4 T [R] y n y n O T '\ g (y n ) otherwise (9.2.15)
In absence of run-time errors, the abstract semantics ⌧ '\ g J stmt K, given sound over-approximations R 2 D of ⌧ I (iJ stmt K) and D 2 D of ⌧ I (f J stmt K), is a sound over-approximation of the semantics ⌧ ' g J stmt K defined in Section 9.2.2:

Lemma 9.2.9 ⌧ ' g J stmt K T [D]t 4 T [R]⌧ '\ g J stmt Kt.

Proof.

See Appendix A.6.

⌅

The abstract guarantee semantics ⌧ '\ g J prog K 2 T of a program prog outputs the decision tree over-approximating the ranking function corresponding to the initial program control point iJ prog K 2 L. It is defined by taking as input the leaf node LEAF : ? F as: Definition 9.2.10 (Abstract Guarantee Semantics) The abstract guarantee semantics ⌧ '\ g J prog K 2 T of a program prog is:

⌧ '\ g J prog K = ⌧ '\ g J stmt l K def = ⌧ '\ g J stmt KRESET T J ' K(l, R, LEAF : ? F ) (9.2.16
) where the abstract guarantee semantics ⌧ '\ g J stmt K : T ! T of each program instruction stmt is defined in Figure 9.1.

In absence of run-time errors, the following result proves the soundness of the abstract guarantee semantics ⌧ '\ g J prog K 2 T with respect to the guarantee semantics ⌧ ' g J prog K 2 E * O, given a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (iJ prog K):

Theorem 9.2.11 ⌧ ' g J prog K 4 T [R]⌧ '\ g J prog K Proof (Sketch).
The proof follows from the soundness of the operators of the decision trees abstract domain (cf. Lemma 9.2.9) used for the definition of ⌧ '\ g J prog K 2 T .⌅

In particular, the abstract guarantee semantics provides su cient preconditions for ensuring a guarantee property 3' for a given over-approximation R 2 D of the set of initial states I ✓ ⌃:

Corollary 9.2.12 A program satisfies a guarantee property 3' for execution traces starting from a set of states

D (R) if D (R) ✓ dom( T [R]⌧ '\ g J prog K).

Recurrence Semantics

In the following, along the same approach used in the previous Section 9.2 for guarantee properties, we define a sound and complete semantics for proving recurrence temporal properties by abstract interpretation of the program maximal trace semantics (cf. Equation 2.2.5). Then, we propose a sound decidable abstraction based on piecewise-defined ranking functions. ) never reaches S.

Recurrence Semantics

In particular, the recurrence semantics reuses the guarantee semantics of Section 9.2 as a building block: from the guarantee that some desirable event happens once during program execution, the recurrence semantics ensures that the event happens infinitely often. A finite subsequence of a program trace satisfies a recurrence property if and only if it terminates in the desirable set of states, and its neighborhood in the subsequences of the program semantics consists only of sequences that are terminating in the desirable set of states, and that are prefixes of traces in the program semantics that reach infinitely often the desirable set of states. The corresponding recurrence abstraction ↵ r [S] : P(⌃ +1 ) ! P(⌃ + ) is parameterized by a set of desirable states S ✓ ⌃ and it is defined as follows:

↵ r [S]T def = gfp ✓ ↵ g [S]T r [T, S] r [T, S]T 0 , def = ↵ g [ f pre[T ]T 0 \ S]T (9.3.1) where f pre[T ]T 0 def = {s 2 ⌃ | 8 2 ⌃ ⇤ , 0 2 ⌃ ⇤1 : s 0 2 T ) pf( 0 ) \ T 0 6
= ;} is the set of states whose successors all belong to a given set of subsequences, and ↵ g [S] : P(⌃ +1 ) ! P(⌃ + ) is the guarantee abstraction of Equation 9.2.2.

To explain intuitively Equation 9.3.1, we use the dual of Kleene's Fixpoint Theorem (cf. Theorem 2.1.4) to rephrase ↵ r [S] as follows:

↵ r [S]T = \ i2N T i+1 T i+1 def = [ r [T, S]] i (↵ g [S]T )
Then, for i = 0, we get the set T 1 = ↵ g [S]T of subsequences of T that guarantee S at least once. For i = 1, starting from T 1 , we derive the set of states S 1 = f pre[T ]T 1 \ S (i.e., S 1 ✓ S) whose successors all belong to the subsequences in T 1 , and we get the set T 2 = ↵ g [S 1 ]T of subsequences of T that guarantee S 1 at least once and thus guarantee S at least twice. Note that all the subsequences in T 2 terminate with a state s 2 S 1 and therefore are prefixes of subsequence of T that reach S at least twice. More generally, for each i 2 N, we get the set T i+1 of subsequences which are prefixes of subsequences of T that reach S at least i + 1 times, i.e., the subsequences that guarantee S at least i + 1 times. The greatest fixpoint thus guarantees S infinitely often.

= ↵ Mrk (↵ r [S](⌧ +1 )) (9.3.2)
where the abstraction ↵ Mrk : P(⌃ + ) ! (⌃ * O) is the same ranking abstraction defined in Equation 4.2.14.

The following result provides a fixpoint definition of the recurrence semantics within the partially ordered set h⌃ * O, vi, where the computational order is defined as in Equation 4.2.15 as:

f 1 v f 2 () dom(f 1 ) ✓ dom(f 2 ) ^8x 2 dom(f 1 ) : f 1 (x)  f 2 (x).
Theorem 9.3.3 (Recurrence Semantics) Given a desirable set of states S ✓ ⌃, the recurrence semantics ⌧ r [S] 2 ⌃ * O can be expressed as a greatest fixpoint in the partially ordered set h⌃ * O, vi:

⌧ r [S] = gfp v ⌧g[S] r [S] r [S]f def = s. ( f (s) s 2 dom(⌧ g [ f pre(dom(f )) \ S]) undefined otherwise (9.3.3)
Note that, the recurrence semantics can be equivalently simplified as:

⌧ r [S] = gfp v ⌧g[S] r [S] r [S]f def = s. ( f (

Proof.

See Appendix A.6. ⌅

Denotational Recurrence Semantics

We now provide a structural definition of the '-recurrence semantics ⌧ ' r 2 ⌃ * O by induction on the syntax of our idealized imperative language.

We partition ⌧ ' r with respect to the program control points:

⌧ ' r 2 L ! (E * O).
⌧ ' r J stmt K 2 (E * O) ! (E *
O) behaves as described in Section 9.2.2 and also ensures that each time ' is satisfied, it will be satisfied again in the future: the value of the input ranking function is reset for the environments that satisfy ' only if all their successors by means of the instruction stmt belong to the domain of the input ranking function.

The recurrence semantics of a skip instruction resets the value of the input ranking function f : E * O for the environments that belong to its domain and satisfy ', and otherwise it increases its value to take into account another program execution step from the initial label of the instruction:

⌧ ' r J l skip Kf def = ⇢. 8 > < > : 0 hl, ⇢i |= ' ^⇢ 2 dom(f ) f (⇢) + 1 hl, ⇢i 6 |= ' ^⇢ 2 dom(f ) undefined otherwise (9.3.6)
Similarly, the recurrence semantics of a variable assignment l X := aexp is defined over the environments that when subject to the assignment always belong to the domain of the input ranking function f : E * O. The value of the input ranking function for these environments is reset when they satisfy '; otherwise, it is increased by one to account for another execution step, and the value of the resulting ranking function is the least upper bound of these values:

⌧ ' r J l X := aexp Kf def = ⇢. 8 > > > > > > > > > < > > > > > > > > > : 0 hl, ⇢i |= ' ^9v 2 JaexpK⇢ 8v 2 JaexpK⇢ : ⇢[X v] 2 dom(f ) sup{f (⇢[X v]) + 1 | v 2 JaexpK⇢} hl, ⇢i 6 |= ' ^9v 2 JaexpK⇢ 8v 2 JaexpK⇢ : ⇢[X v] 2 dom(f ) undefined otherwise ( 9
⌧ x=3 r J x := x + [1, 2] Kf (⇢) def = ( 4 ⇢(x) = 0 undefined otherwise
In particular, note that unlike Example 9.2.6, the function is not defined when ⇢(x) = 3, since the environment satisfies the property x = 3 but Jx + [1, 2]K⇢ = {4, 5} and ⇢[x 4] 6 2 dom(f ) and ⇢[x 5] 6 2 dom(f ).

Given a conditional instruction if l bexp then stmt 1 else stmt 2 fi, its recurrence semantics takes as input a ranking function f : E * O and derives the recurrence semantics ⌧ ' r J stmt 1 Kf of stmt 1 , in the following denoted by S 1 , and the recurrence semantics ⌧ ' r J stmt 2 Kf of stmt 2 , in the following denoted by S 2 . Then, the recurrence semantics of the conditional instruction is defined by means of the ranking function F [f ] : E * O whose domain is the set of environments that belong to the domain of S 1 and to the domain of S 2 , and that may both satisfy and not satisfy the boolean expression bexp:

F [f ] def = ⇢ 2 dom(S 1 ) \ dom(S 2 ). 8 > < > : sup{S 1 (⇢) + 1, S 2 (⇢) + 1} JbexpK⇢ = {true, false} undefined otherwise
and the ranking function F 1 [f ] : E * O whose domain is the set of environments ⇢ 2 E that belong to the domain of S 1 and that must satisfy bexp:

F 1 [f ] def = ⇢ 2 dom(S 1 ). ( S 1 (⇢) + 1 JbexpK⇢ = {true} undefined otherwise
and the ranking function F 2 [f ] : E * O whose domain is the set of environments that belong to the domain of S 2 and that cannot satisfy bexp:

F 2 [f ] def = ⇢ 2 dom(S 2 ). ( S 2 (⇢) + 1 JbexpK⇢ = {false} undefined otherwise
The resulting ranking function is defined by joining

F [f ], F 1 [f ], and F 2 [f ],
and resetting the value of the function for the environments that belong to its domain and satisfy ':

⌧ ' r J if l bexp then stmt 1 else stmt 2 fi Kf def = ⇢. 8 > > > > > > < > > > > > > : 0 hl, ⇢i |= ' ⇢ 2 dom(R) R(⇢) hl, ⇢i 6 |= ' ⇢ 2 dom(R) undefined otherwise (9.3.8) where R def = F [f ] [ F 1 [f ] [ F 2 [f ].
Example 9.3.7 Let X def = {x}. We consider the recurrence property 23(x = 3) and the recur- rence semantics of the conditional statement if bexp then stmt 1 else stmt 2 fi.

We assume, given a ranking function f : E * O, that the recurrence semantics of stmt 1 is defined as:

⌧ x=3 r J stmt 1 Kf (⇢) def = ( 1 ⇢(x)  0 undefined otherwise
and that the recurrence semantics of stmt 2 is defined as

⌧ x=3 r J stmt 2 Kf (⇢) def = 8 > > > > < > > > > : 3 0 ⇢(x) < 3 0 ⇢(x) = 3 3 3< ⇢(x) undefined otherwise
Then, when the boolean expression bexp is for example x  3, the recurrence semantics of the conditional statement is:

⌧ x=3 r J if l bexp then stmt 1 else stmt 2 fi Kf (⇢) def = 8 > < > : 2 ⇢(x)  0 4 3< ⇢(x) undefined otherwise
Instead, when bexp is for example the non-deterministic choice ?, we have:

⌧ x=3 r J if l bexp then stmt 1 else stmt 2 fi Kf (⇢) def = ( 4 ⇢(x) = 0 undefined otherwise
Note that, like Example 4.3.2 and unlike Example 9.2.7, both functions are undefined when ⇢(x) = 3, even though the property x = 3 is satisfied. In fact, the ranking function for the then branch of the if is undefined when ⇢(x) = 3.

The recurrence semantics of a loop instruction while l bexp do stmt od takes as input a ranking function f : E * O whose domain represents the environments leading infinitely often to ' from the final label of the instruction, and outputs the ranking function which is defined as a greatest fixpoint of the function

' r : (E * O) ! (E * O) within hE * O, vi: ⌧ ' r J while l bexp do stmt od Kf def = gfp v G ' r (9.3.9)
where G def = ⌧ ' g J while l bexp do stmt od Kf is the guarantee semantics of the loop instruction defined in Equation 9.2.10, and the computational order is defined as in Equation 4.2.15:

f 1 v f 2 () dom(f 1 ) ✓ dom(f 2 ) ^8x 2 dom(f 1 ) : f 1 (x)  f 2 (x).
In essence, from the guarantee that some desirable event eventually happens, the recurrence semantics ensures that the event happens infinitely often. The function ' r : (E * O) ! (E * O) takes as input a ranking function x : E * O, resets its value for the environments that belong to its domain and that satisfy ', and adds to its domain the environments for which one more loop iteration is needed before the next occurrence of '. In the following, the recurrence semantics ⌧ ' r J stmt Kx of the loop body is denoted by S. The function ' r is defined by means of the ranking function F [x] : E * O whose domain is the set of environments that belong to the domain of S and to the domain of the input function f , and that may both satisfy and not satisfy the boolean expression bexp: As pointed out in Remark 3.2.2, possible run-time errors are ignored. Thus, all environments leading to run-time errors are discarded and do not belong to the domain of the recurrence semantics of a program prog.

F [x]

Abstract Recurrence Semantics

We now propose a sound decidable abstraction of the recurrence semantics ⌧ ' r J prog K 2 E * O, based on the piecewise-defined ranking functions presented in Chapter 5 and Chapter 6. The abstraction is sound with respect to the usual approximation order defined in Equation 4.2.12:

f 1 4 f 2 () dom(f 1 ) ◆ dom(f 2 ) ^8x 2 dom(f 2 ) : f 1 (x)  f 2 (x).
In particular, we revisit the definition of the unary operator RESET T J ' K and we introduce a dual widening operator ŌT .

Reset. The operator RESET T J ' K : T ! T should reset the leaves of a decision tree that not only satisfy a given property ' but also guarantee that the property will be satisfied again in the future. To this end, we redefine the operator RESET F J ' K : F ! F invoked when Algorithm 24 reaches a leaf node (cf. Line 3): given a function f 2 F \ {? F , > F }, RESET F J ' K simply resets its value to zero; undefined leaf nodes are instead left unaltered: return dual-widen-aux(t 1 , t 2 , C (d))

RESET F (? F ) def = ? F RESET F (f ) def = X 1 , .
. value widening Dual Widening. The recurrence semantics of a while loop instruction, as defined in Equation 9.3.9, involves a greatest fixpoint. Greatest fixpoints are solved by iterations using a new dual widening operator ŌT . The dual widening ŌT is implemented by Algorithm 25: the function dual-widen, given a given a sound over-approximation d 2 D of the reachable environments and two decision trees t 1 , t 2 2 T , calls the function leftunification (cf. Line 11) to limit the size of the decision trees in order to ensure convergence. Unlike Algorithm 13, Algorithm 25 invokes leftunification choosing the approximation join g F . Then, Algorithm 25 calls the auxiliary function dual-widen-aux, which collects into a set C 2 P(C) (initially equal to C (d), cf. Line 12) the linear constraints encountered along the paths up to the leaf nodes (cf. Lines 6-7), which are compared (cf. Line 3) and, in case, turned into a ? F -leaf (cf. Line 4).

In Figure 9.2 we depict an example of dual widening. In essence, the dual widening maintains the value of a piecewise-defined ranking function only on the pieces where it stays defined between two iterate, and if a piece where it is defined shrinks, we remove it entirely.

Abstract Recurrence Semantics. In the following, we assume to have, for each program control point l 2 L, a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (l) 2 P(E): ⌧ I (l) ✓ D (R) (cf. Section 3.4).

In Figure 9.3 we define the semantics ⌧ '\ r J stmt K : T ! T , for each program instruction stmt. Each function ⌧ '\ r J stmt K : T ! T takes as input a decision tree over-approximating the ranking function corresponding to the ⌧ '\ r J l skip Kt def = RESET T J ' K(l, R, STEP T (t))

⌧ '\ r J l X := aexp Kt def = RESET T J ' K(l, R, (B-ASSIGN T J X := aexp KR)(t)) final control point of the instruction, and outputs a decision tree defined over a subset of the reachable environments R 2 D, which over-approximates the ranking function corresponding to the initial control point of the instruction. Each function ⌧ '\ r J stmt K invokes the redefined reset operator RESET T . For a while loop, gfp \ '\ r is the limit of the iteration sequence with dual widening: where G is the guarantee semantics of the loop (cf. Figure 9.1).

⌧ '\ r J if l bexp then stmt 1 else stmt 2 fi Kt def = RESET T J ' K(l, R, F \ 1 [t] g T [R] F \ 2 [f ]) F \ 1 [t] def = (FILTER T J bexp KR)(⌧ '\ r J stmt 1 Kt) F \ 2 [t]
y 0 def = G(t)
In absence of run-time errors, the abstract semantics ⌧ '\ r J stmt K, given sound over-approximations R 2 D of ⌧ I (iJ stmt K) and D 2 D of ⌧ I (f J stmt K), is a sound over-approximation of the semantics ⌧ ' r J stmt K defined in Section 9.3.2:

Lemma 9.3.9 ⌧ ' r J stmt K T [D]t 4 T [R]⌧ '\ r J stmt Kt.

Proof.

See Appendix A.6.

⌅

The abstract recurrence semantics ⌧ '\ r J prog K 2 T of a program prog outputs the decision tree over-approximating the ranking function corresponding to the initial program control point iJ prog K 2 L. It is defined by taking as input the leaf node LEAF : ? F as: Definition 9.3.10 (Abstract Recurrence Semantics) The abstract recurrence semantics ⌧ '\ r J prog K 2 T of a program prog is:

⌧ '\ r J prog K = ⌧ '\ r J stmt l K def = ⌧ '\ r J stmt KRESET T J ' K(l,

Implementation

We have incorporated the static analysis methods for guarantee and recurrence temporal properties that we have presented in this chapter into our prototype static analyzer FuncTion that we have presented in Chapter 8. The prototype, when the guarantee or recurrence analysis methods are selected, accepts state properties written as C-like pure expressions.

The following examples illustrate the potential and e↵ectiveness of our new static analysis methods. and the guarantee property 3(x = 3). FuncTion, using interval constraints based on the intervals abstract domain (cf. Section 3.4.1) for the decision nodes and a ne functions for the leaf nodes (cf. Equation 5.2.6), infers the following ranking function associated with program control point 1:

x.

> < > :

3x + 10 x < 0 2x + 6 0  x ^x  3 undefined otherwise which bounds the wait (from the program control point 1) for the desirable state x = 3 by 3x + 10 program execution steps when x < 0, and by 2x + 6 execution steps when 0  x ^x  3. The analysis is inconclusive when 3 < x. In this case, when 3 < x, the guarantee property is never satisfied (cf. Example 9.1.3). Thus, the precondition x  3 induced by the domain of the ranking function is the weakest precondition for 3(x = 3).

Let us consider now the recurrence property 23(x = 3). FuncTion infers the following ranking function associated with program control point 1:

x.

( 3x + 10 x < 0 undefined otherwise which induces the precondition x < 0 for 23(x = 3). Indeed, when 0  x x  3, the desirable state x = 3 does not occur infinitely often but only once. Again x < 0 is the weakest precondition for 23(x = 3).

Instead, for both 3(x = 3) and 23(x = 3), FuncTion infers the follow- ing ranking function associated with program control point 3:

x.

> <

> :

3x + 9

x  3 3x + 72 3 < x  10 3x + 12 10 < x which bounds the wait (from the program control point 3) for the next occurrence of x = 3 by 3x + 9 execution steps when x  3, by 3x + 72 execution steps when 3 < x  10, and by 3x + 12 execution steps when 10 < x. Each iteration of the outer loop, assigns to the program variable x the value of some counter c, which initially has value one; then, the inner loop decreases the value of x and increases the value of the counter c until the value of x becomes less than or equal to zero.

FuncTion, using interval constraints based on the intervals abstract domain (cf. Section 3.4.1) for the decision nodes and a ne functions for the leaf nodes (cf. Equation 5.2.6), is able to prove that the recurrence property 23(x = 0) is always satisfied by the program. The piecewise-defined rank- ing function inferred at program control point 1 bounds the wait for the next occurrence of the desirable state x = 0 by five program execution steps (i.e., executing the variable assignment c := 1, testing the outer loop condition, executing the assignment x := c, testing the inner loop condition and executing the assignment x := x 1). The analysis infers a more interesting raking function associated to program control point 4:

x. c. 8 > > > > > > < > > > > > > : 3c + 2 x < 0 ^0 < c 3 x < 0 ^c = 0 1 x = 0 ^0  c 3x 1 (x = 1 ^ 1  c) _ (2  x ^ 2  c) undefined otherwise
The function bounds the wait for the next occurrence of x = 0 by 3c + 2 execution steps when x < 0 ^0 < c, by 3 execution steps when x < 0 ^c = 0 (i.e., testing the inner loop condition, testing the outer loop condition and executing the assignment x := c), by 1 execution step when x = 0 ^0  c (i.e., testing the inner loop condition) and by 3x 1 execution steps when (x = 1 ^ 1  c) _ (2  x ^ 2  c). In the last case there is a precision loss due to a lack of expressiveness of the intervals abstract domain: if x is strictly positive at program control point 4, the weakest precondition ensuring infinitely many occurrences of the desirable state x = 0 is x  c, which is not representable by the intervals abstract domain. However, because of the non-deterministic assignment x := ?, the number of execution steps between two occurrences of the desirable state x = 0 is unbounded. FuncTion is able to prove that the property is satisfied using interval constraints based on the intervals abstract domain (cf. Section 3.4.1) for the decision nodes and ordinal-valued functions for the leaf nodes (cf. Chapter 6). The inferred ranking function at program control point 1:

x. ! + 8 means that, whatever the value of the variable x, the number of execution steps between two occurrences of x = 0 is unbounded but finite. Note that weak fairness assumptions are required to guarantee bounded bypass (i.e., a process cannot be bypassed by any other process in entering the critical section for more than a finite number of times. At the moment our prototype FuncTion is not able to directly analyze concurrent programs. Thus, we have modeled the algorithm as a fair non-deterministic sequential program which interleaves execution steps from both processes while enforcing 1-bounded bypass (i.e., a process cannot be bypassed by any other process in entering the critical section for more than once). FuncTion, using interval constraints based on the intervals abstract domain (cf. Section 3.4.1) for the decision nodes and a ne functions for the leaf nodes (cf. Equation 5.2.6), is able to prove the recurrence property 23(8 : true), meaning that both processes are allowed to enter their critical section infinitely often.

Related Work

In the recent past, a large body of work has been devoted to proving liveness properties of (concurrent) programs.

A successful approach for proving liveness properties is based on a transformation from model checking of liveness properties to model checking of safety properties [START_REF] Biere | Liveness Checking as Safety Checking[END_REF]. The approach looks for and exploits lasso-shaped counterexamples. A similar search for lasso-shaped counterexamples has been used to generalize the model checking algorithm IC3 to deal with liveness properties [START_REF] Bradley | An Incremental Approach to Model Checking Progress Properties[END_REF]. However, in general, counterexamples to liveness properties in infinite-state systems are not necessarily lasso-shaped. Our approach is not counterexample-based and is meant for proving liveness properties directly, without reduction to safety properties.

In [START_REF] Podelski | Transition Predicate Abstraction and Fair Termination[END_REF], Andreas Podelski and Andrey Rybalchenko present a method for the verification of liveness properties based on transition invariants [START_REF] Podelski | Transition Invariants[END_REF]. The approach, as in [START_REF] Vardi | Verification of Concurrent Programs: The Automata-Theoretic Framework[END_REF], reduces the proof of a liveness property to the proof of fair termination by means of a program transformation. It is at the basis of the industrial-scale tool Terminator [CGP + 07]. By contrast, our method is meant for proving liveness properties directly, without reduction to termination. Moreover, it avoids the cost of explicit checking for the wellfoundedness of the transition invariants.

A distinguishing aspect of our work is the use of infinite height abstract domains, equipped with (dual) widening. We are aware of only one other such work: in [START_REF] Massé | Property Checking Driven Abstract Interpretation-Based Static Analysis[END_REF], Damien Massé proposes a method for proving arbitrary temporal properties based on abstract domains for lower closure operators. A small analyzer is presented in [START_REF] Massé | Abstract Domains for Property Checking Driven Analysis of Temporal Properties[END_REF] but the approach remains mainly theoretical. We believe that our framework, albeit less general, is more straightforward and of practical use.

An emerging trend focuses on proving existential temporal properties (e.g., proving that there exists a particular execution trace). The most recent approaches [START_REF] Beyene | Solving Existentially Quantified Horn Clauses[END_REF][START_REF] Cook | Reasoning About Nondeterminism in Programs[END_REF] are based on counterexample-guided abstraction refinement [CGJ + 03]. Our work is designed for proving universal temporal properties (i.e., valid for all program execution traces). We leave proving existential temporal properties as part of our future work.

Finally, to our knowledge, the inference of su cient preconditions for guarantee and recurrence properties, and the ability to provide upper bounds on the time before a program reaches a desirable state, is unique to our work.

V

Conclusion

Future Directions

With this thesis, we have proposed new abstract interpretation-based methods for proving termination and other liveness properties of programs.

In particular, our first contribution is the design of new abstract domains suitable for the abstract interpretation framework for termination proposed by Patrick Cousot and Radhia Cousot [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF]. These abstract domains automatically infer su cient preconditions for program termination, and synthesize piecewise-defined ranking functions through backward analysis (cf. Chapter 5 and Chapter 6). The ranking functions provide upper bounds on the program execution time in terms of execution steps. The abstract domains are parametric in the choice between the expressivity and the cost of the underlying numerical abstract domain (cf. Section 3.4). They are shown to be e↵ective for proving termination of recursive programs in Chapter 7.

Our second contribution is an abstract interpretation framework for liveness properties, which comes as a generalization of the framework proposed for termination [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF]. In particular, we have proposed new abstract interpretation-based methods for proving guarantee and recurrence properties (cf. Chapter 9). We have also reused the abstract domains based on piecewise-defined ranking functions (cf. Chapter 5 and Chapter 6) to e↵ectively infer su cient preconditions for these properties, and to provide upper bounds on the time before a program reaches a desirable state.

Our last contribution is a prototype implementation of a static analyzer based on piecewise-defined ranking functions (cf. Chapter 8). The earlier versions of the prototype participated in the 3rd International Competition on Software Verification (SV-COMP 2014), which featured a category for termination for the first time, and in the 4th International Competition on Software Verification (SV-COMP 2015). We conclude with some perspectives for future research.

Potential Termination and Non-Termination. In Chapter 4 we have introduced the definite and potential termination semantics for a program [START_REF] Cousot | An Abstract Interpretation Framework for Termination[END_REF]. Then, throughout the rest of the thesis we have focused our attention only on the definite termination semantics, and proposed decidable abstractions in Chapter 5 and Chapter 6. As part of our future work, we plan to do a similar work for the potential termination semantics.

We plan to use the same domains based on piecewise-defined ranking functions (cf. Chapter 5 and Chapter 6) but adapt their operators in order to automatically infer necessary preconditions for program termination, which are not very interesting per se but provide complementary su cient preconditions for non-termination. In this way, we could complement our analysis method for proving program termination with an analysis method for proving program non-termination. In particular, we envision to run the analyses simultaneously in order to improve precision. Abstract Domains. In Chapter 5 we have proposed the decision trees abstract domain, which we have designed to be parameterized by a convex numerical abstract domain, such as intervals [START_REF] Cousot | Static Determination of Dynamic Properties of Programs[END_REF], convex polyhedra [START_REF] Cousot | Automatic Discovery of Linear Restraints Among Variables of a Program[END_REF], and octagons [START_REF] Miné | The Octagon Abstract Domain[END_REF]. In the future, we would like to also allow non-convex abstract domain, such as congruences [START_REF] Granger | Static Analysis of Arithmetic Congruences[END_REF].

Moreover, the decision tree abstract domain has been instantiated with a ne functions, in Chapter 5, and ordinal-valued functions, in Chapter 6. It remains for future work to support non-linear functions, such as polynomials [START_REF] Bradley | The Polyranking Principle[END_REF] or exponentials [START_REF] Feret | The Arithmetic-Geometric Progression Abstract Domain[END_REF]. Non-linear functions would provide more precise upper bounds on the program execution time for programs with non-linear computational complexity. On this account, we plan to explore further the possible potential of our approach in the termination-related field of automatic cost analysis [DLH90, SLH14, Weg75].

In Chapter 5, we also mentioned various ideas for improving the widening of decision trees, by introducing thresholds [START_REF] Cousot | Comparing the Galois Connection and Widening/Narrowing Approaches to Abstract Interpretation[END_REF] and integrating state-ofthe-art precise widening operators [START_REF] Bagnara | Precise Widening Operators for Convex Polyhedra[END_REF]. We plan to investigate these and further possibilities.

The decision trees abstract domain could also o↵er an alternative disjunctive refinement of numerical abstract domains [CCM10, GR98, GC10a, SISG06, etc.]. We would also like to explore its potential to be adapted to other program semantics and for proving other program properties.

Fairness and Liveness Properties. In Chapter 9, we have proposed an abstract interpretation framework for guarantee and recurrence temporal properties [START_REF] Manna | A Hierarchy of Temporal Properties[END_REF]. The verification of liveness properties is a di cult problem, with not many satisfying solutions. We have made a first step that shows how Abstract Interpretation can also be used for proving liveness properties and that, we believe, opens many possibilities.

We mentioned in Chapter 1 that some of the theoretical work presented in this thesis is being used as part of ongoing research work aimed at the verification of real-time properties of avionics software.

It remains for future work the integration of fairness properties [START_REF] Francez | Fairness[END_REF]. We also plan to extend the present framework to the full hierarchy of temporal properties [START_REF] Manna | A Hierarchy of Temporal Properties[END_REF], and more generally to arbitrary (universal and existential [START_REF] Beyene | Solving Existentially Quantified Horn Clauses[END_REF][START_REF] Cook | Reasoning About Nondeterminism in Programs[END_REF]) liveness properties.

Machine Integers and Floats

In this thesis we have only considered programs that operate over mathematical integers. The reality is that most programs operate over variables that range over fixed-width numbers, such as 32-bit integers or 64-bit floating-point numbers, with the possibility of overflow or underflow. In particular, we cannot ignore the fixed-width semantics, as overflow and underflow can for example cause non-termination in programs that would otherwise terminate. We plan, as part of our future work, to make the decision trees abstract domain aware of the low-level memory representation of data-types.

Heap-Manipulating Programs. We also plan to prove termination and liveness properties of more complex programs, such as heap-manipulating programs. We would like to investigate the adaptability of existing methods [START_REF] Berdine | Automatic Termination Proofs for Programs with Shape-Shifting Heaps[END_REF] and existing abstract domains for shape analysis [START_REF] Bor-Yuh | Modular construction of shape-numeric analyzers[END_REF], and possibly design new techniques.

Concurrent Programs. Finally, in this thesis we have developed methods for proving termination and liveness properties of sequential programs. A natural future direction is considering concurrent programs. When analyzing concurrent programs, it is necessary to consider all possible interactions between concurrently executing threads. The usual method for proving concurrent programs correct is based on rely-guarantee or assume-guarantee style of reasoning, which considers every thread in isolation under assumptions on its environment and thus avoids reasoning about thread interactions directly [START_REF] Gotsman | Proving that Non-Blocking Algorithms Don't Block[END_REF][START_REF] Miné | Relational Thread-Modular Static Value Analysis by Abstract Interpretation[END_REF]. We plan to extend these strategies to liveness properties. J aexp K⇢}. Moreover, by definition of B-ASSIGN T (cf. Algorithm 11), we have sup{( T [D]t)(⇢[X ! v]) + 1 | v 2 J aexp K⇢}  A(⇢). In fact, Algorithm 11 invokes B-ASSIGN F , which after the assignment increases the value of the defined leaf nodes of a decision tree (cf. Equation 5.2.21). Thus, C(⇢)  A(⇢), which is absurd. Therefore, we conclude that 8⇢ 2 dom(A) : C(⇢)  A(⇢).

This concludes the proof.

⌧ Mt J if l bexp then stmt 1 else stmt 2 fi K T [D]t 4 T [R](F \ 1 [t] g T [R] F \ 2 [t])
Proof of Lemma 5.2.15.

We have ⌧ I J if l bexp then stmt 1 else stmt 2 fi K D (R) ✓ D (D), given that R 2 D is a sound over-approximation of ⌧ I (l) and D 2 D is a sound overapproximations of ⌧ I (f J if l bexp then stmt 1 else stmt 2 fi K). Let us assume, by absurd, that dom(C) ⇢ dom(A). Then, there exists an environment ⇢ 2 E such that ⇢ 2 dom(A) and ⇢ 6 2 dom(C). Since ⇢ 2 dom(A), by definition of 4 T [D] (cf. Algorithm 6) and FILTER T (cf. Algorithm 12), we have ⇢ 2 dom( T [R](⌧ \ Mt J stmt 1 Kt)) or ⇢ 2 dom( T [R](⌧ \ Mt J stmt 2 Kt)), or both. In fact, Algorithm 12 prunes a decision tree (cf. Line 12) and Algorithm 6 favors undefined leaf nodes over defined leaf nodes (cf. Equation 5.2.13). Thus, by structural induction, we have ⇢ 2 dom(⌧ Mt J stmt 1 K T [D]t) or ⇢ 2 dom(⌧ Mt J stmt 2 K T [D]t), or both. In absence of run-time errors, by definition of ⌧ Mt J if l bexp then stmt 1 else stmt 2 fi K (cf. Equation 4.3.3), we have ⇢ 2 dom(C) which is absurd. Therefore, we conclude that dom(C) ◆ dom(A).

Let us assume now, by absurd, that 9⇢ 2 dom(A) : C(⇢) > A(⇢). Let We have, by structural induction, S 1 (⇢) < A(⇢) or S 2 (⇢) < A(⇢) or sup{S 1 (⇢) + 1, S 2 (⇢) + 1} < A(⇢). In fact, Algorithm 12 invokes step which increases the value of the defined leaf nodes of a decision tree (cf. Algorithm 9. Thus, C(⇢)  A(⇢), which is absurd. Therefore, we conclude that 8⇢ 2 dom(A) : C(⇢)  A(⇢).

This concludes the proof. def = (FILTER T J not bexp KR)(t). Then, given t 2 T , for all x 2 T we have:

Mt ( D [R]x) 4 T [R]( \ Mt (x))
where \ Mt (x)

def = F \ 1 [x] g T [R] F \ 2 [t].
Proof of Lemma 5. Mt J stmt Kx). We have, by structural induction, S 1 (⇢) < A(⇢) or ( T [D]t)(⇢) < A(⇢) or sup{S 1 (⇢) + 1, ( T [D]t)(⇢) + 1} < A(⇢). In fact, Algorithm 12 invokes step which increases the value of the defined leaf nodes of a decision tree (cf. Algorithm 9. Thus, C(⇢)  A(⇢), which is absurd. Therefore, we conclude that 8⇢ 2 dom(A) : C(⇢)  A(⇢).

This concludes the proof.

⌅ Lemma 5.2.24 Let \ Mt (x) def = F \ 1 [x] g T [R] F \ 2 [t]
as defined in Lemma 5.2.16 for any given t 2 T . Then, we have:

⌧ Mt J while l bexp do stmt od K T [D]t 4 T [R](lfp \ \ Mt )
where lfp \ \ Mt is the limit of the iteration sequence with widening: y 0

def=

  {S 0 | S 0 ✓ S}. The union of two sets A and B, written A [ B, is the set of all elements of A and all elements of B: A [ B def = {x | x 2 A _ x 2 B}. More generally, the union of a set of sets S, is denoted by S S: S S def = S S 0 2S S 0 = {x | 9S 0 2 S : x 2 S 0 }. The intersection A \ B of two sets A and B is the set of all elements that are elements of both A and B: A \ B def = {x | x 2 A ^x 2 B}. More generally, the intersection of a set of sets S is denoted by T S: T S def = T S 0 2S S 0 = {x | 8S 0 2 S : x 2 S 0 }. The relative complement of a set B in a set A, denoted by A \ B, is the set of all elements of A that are not elements of B: A \ B def = {x | x 2 A ^x 6 2 B}. When B ✓ A and the set A is clear from the context, we simply write ¬B for A \ B and we call it complement of B. The cartesian product of two sets A and B, denoted by A ⇥ B, is the set of all pairs where the first component is an element of A and the second component is an element of B: A ⇥ B def = {hx, yi | x 2 A ^y 2 B}. More generally, S 1 ⇥

Figure 2

 2 Figure 2.1: Hasse diagrams for the partially ordered set hP({a, b, c}), ✓i.

  Let us consider the partially ordered set hP({a, b, c}), ✓i represented in Figure 2.1 and the subset X def

Figure 2 . 2 :

 22 Figure 2.2: Fixpoint iterates of the maximal trace semantics.

  equivalently, is surjective), and hD, vi ! ! ↵ hD \ , v \ i when both ↵ and are bijective. The posets hD, vi and hD \ , v \ i are called the concrete domain and the abstract domain, respectively. The function ↵ : D ! D \ is the abstraction function, which provides the abstract approximation ↵(d) of a concrete element d 2 D, and : D \ ! D is the concretization function, which provides the concrete element (d \ ) corresponding to the abstract description d \ 2 D \ . Note that, the notion of Galois connection can also be defined on preordered sets.

Figure 2 . 3 :

 23 Figure 2.3: Example of increasing iteration with widening ( O O O !) followed by

  pair consisting of a label l 2 L and an environment ⇢ 2 E, where the environment defines the values of the program variables at the program control point designated by the label. Let ⌃ denote the set of all program states. The initial control point iJ stmt K 2 L (resp. iJ prog K 2 L) of an instruction stmt (resp. a program prog) defines where the execution of the instruction (resp. program) starts, and the final control point f J stmt K 2 L (resp. f J prog K 2 L) defines where the execution of the instruction stmt (resp. program prog) ends. The formal definitions are in Figure 3.4 and Figure 3.5.

Figure 3 . 4 :

 34 Figure 3.4: Initial control point of instructions stmt and programs prog.

Figure 3 . 5 :

 35 Figure 3.5: Final control point of instructions stmt and programs prog.

Figure 3 . 7 :

 37 Figure 3.7: Maximal trace semantics of instructions stmt.

Figure 3 . 8 :

 38 Figure 3.8: Fixpoint iterates of the trace semantics of a loop instruction.

  (E), ✓i where the abstraction ↵ I : P(⌃) ! (L ! P(E)) and the concretization I : (L ! P(E)) ! P(⌃) are defined as follows:

Figure 3 .

 3 Figure 3.10: Abstract invariance semantics of instructions stmt.

  Let us consider again the loop within the program of Example 3.3.2:

  Example 4.2.3 Let us consider the following non-deterministic program: while 1 ( ? ) do 2 skip od 3 The program has no variables: X def = ;. Thus, the set of program environments E only contains the totally undefined function ⇢ : ; ! Z. The set of program states is ⌃ def = {1, 2, 3} ⇥ E, and the set of initial states is

  In the following, we abstract such maximal trace semantics into a definite termination trace semantics and a potential termination trace semantics. Potential Termination Trace Semantics. The potential termination trace semantics ⌧ m 2 P(⌃ + ) eliminates all program infinite traces. It can be derived by abstract interpretation of the maximal trace semantics ⌧ +1 2 P(⌃ +1 ) by means of the Galois connection hP(⌃ +1 ), ✓i ! ! ↵ m m hP(⌃ + ), ✓i, where the abstraction function ↵ m : P(⌃ +1 ) ! P(⌃ + ) and the concretization function m : P(⌃ + ) ! P(⌃ +1 ) are defined as follows:

  ⇥ ⌃), ✓i where the abstraction function ! ↵ : P(⌃ +1 ) ! P(⌃ ⇥ ⌃) extracts from a set of sequences T ✓ ⌃ +1 the smallest transition relation r ✓ ⌃ ⇥ ⌃ that generates T : !

  (4.2.8) Definition 4.2.14 (Potential Termination Semantics) The potential termination semantics ⌧ mt 2 ⌃ * O is derived by abstract interpretation of the maximal trace semantics ⌧ +1 2 P(⌃ +1 ):

  (4.2.12) Definition 4.2.19 (Definite Termination Semantics) The definite termination semantics ⌧ Mt 2 ⌃ * O is derived by abstract interpretation of the maximal trace semantics ⌧ +1 2 P(⌃ +1 ):

  (4.2.15) Theorem 4.2.20 (Definite Termination Semantics) The definite termination semantics ⌧ Mt 2 ⌃ * O can be expressed as a least fixpoint in the partially ordered set h⌃ * O, vi:

  Example 4.2.21 Let us consider again the trace semantics of Example 4.2.16: The fixpoint iterates of the definite termination semantics ⌧ Mt 2 ⌃ * O are: are outside the domain of the function.

⌅ 4 .

 4 An Abstract Interpretation Framework for Termination

  In this way, to each program control point l 2 L corresponds a partial function f : E * O, and to each program instruction stmt corresponds a termination semantics

  which provides a concretization-based abstraction of the definite termination semantics ⌧ Mt 2 L ! (E * O) by partitioning with respect to the program control points. No approximation is made on L. On the other hand, each program control point l 2 L is associated with an element t 2 T .Piecewise-Defined Ranking Functions. The elements of the abstract domain hT , 4 T i are piecewise-defined partial functions.Their internal representation is inspired by the space partitioning trees[START_REF] Fuchs | On Visible Surface Generation by a Priori Tree Structures[END_REF] developed in the context of 3D computer graphics and the use of decision trees in program analysis and verification [BCC + 10, Jea02]: the piecewisedefined partial functions are represented by decision trees, where the decision nodes are labeled with linear constraints, and the leaf nodes belong to an auxiliary abstract domain for functions. The decision trees recursively partition the space of possible values of the program variables inducing disjunctions into the auxiliary domain. The elements of the auxiliary domain are functions of the program variables, which provide upper bounds on the computational complexity of the program in terms of execution steps.

Figure 5

 5 Figure 5.1: Decision tree representation (a) of the piecewise-defined ranking function (b) for the program of Example 5.1.1. The linear constraints are satisfied by their left subtree, while their right subtree satisfies their negation. The leaves of the tree represent partial functions whose domain is determined by the constraints satisfied along the path to the leaf node.

  Figure 5.2: Decision tree representation of the piecewise-defined ranking function for the program of Example 5.1.2. The leaf with value ? explicitly represents the undefined piece of the ranking function determined by the constraints satisfied along the path to the leaf node.

  where the abstraction function ↵ C : P(C) ! D maps a set of interval (resp. octagonal, polyhedral) constraints to an interval (resp. an octagon, a polyhedron), and the concretization function C : D ! P(C) maps an interval (resp. an octagon, a polyhedron) to a set of interval (resp. octagonal, polyhedral) constraints. In particular, we define C (> D ) def = ; and C (? D ) def = {? C }, where ? C represents the unsatisfiable linear constraint 1 0.

Figure 5

 5 Figure 5.3: Hasse diagrams defining the approximation order 4 F [D] (a) and the computational order v F [D] (b) of the functions abstract domain.

Figure 5 . 4 :

 54 Figure 5.4: Tree unification of the decision trees (a) and (b) of Example 5.2.3. The resulting decision trees are represented in (c) and (d), respectively.

  Example 5.2.3 Let X def = {x}, let D be the intervals abstract domain hB, v B i, let C be the interval constraints auxiliary abstract domain hC B / ⌘ C , < C i, and let F be the a ne functions auxiliary abstract domain hF A , 4 F i. We consider the decision trees t 1 2 T NIL represented in Figure 5.4a and t 2 2 T NIL represented in Figure 5.4b, where 2 T is a leaf node. Let d def = > B and let C def = C (d) = ;. The function unification-aux adds a decision node for x 0 to t 1 (cf. Line 14) and removes the redundant constraint x+1 0 from the resulting left subtree (cf. Line 8). Moreover, unification-aux adds a decision node for x+ 1 0 to the right subtree of t 2 (cf. Line 23). The result of the tree unification are the decision trees represented in Figure 5.4c and Figure 5.4d, respectively.

Figure 5 . 5 :

 55 Figure 5.5: Example of join of two a ne functions of one variable, shown in (a) and (b), respectively. The result is shown in (c). In (d), (e), and (f) are respectively shown the hypographs of (a), (b), and (c).

  are shown in Figure 5.5a and Figure 5.5b, respectively. Their domain of definition D 2 D is represented by the set of linear constraints C def = C (D) = {x 1 0, x + 5 0}. In Figure 5.5d and Figure 5.5e are represented the hypographs f 1 [D]# and f 2 [D]# of f 1 and f 2 , respectively. Their convex-hull is shown in Figure 5.5e, and the result of the join is the a ne function f 2 F A \{? F , > F } shown in Figure 5.5c. Example 5.2.6 Let X = {x}, and let f 1 def = x. x and f 2 def = x.

Figure 5

 5 Figure 5.6: Example of join of two a ne functions of two variables, shown in (a) and (b), respectively. The result is shown in (c).

  Figure 5.4a and t 2 2 T represented in Figure 5.4b, where 2 T is a leaf node. Let d def = > B and let C def = C (d) = ;. From Example 5.2.3, the result of the tree unification are the decision trees represented in Figure 5.4c and Figure 5.4d, respectively. The decision tree returned by the function a-join-aux is represented in Figure 5.7.

Figure 5

 5 Figure 5.7: Tree approximation join of Figure 5.4a and Figure 5.4b.

Figure 5

 5 Figure 5.8: Tree pruning of Figure 5.7 with respect to { x + 2 0}.

=

  {x, y}. We consider, as numerical abstract domain D, the intervals abstract domain hB, v B i. Let c 2 C B be the linear constraint x 0 and let 92 5. Piecewise-Defined Ranking Functions D 2 B be the interval hy, [0, +1]i, which is isomorphic to the set of constraints {y 0}. The backward assignment x := x y produces the set of linear constraints C def = B-ASSIGN C J x := x y KD(c) = {x 0, y 0}, since the linear constraint x y 0, obtained by replacing x with x y in c, cannot be exactly represented in the intervals abstract domain.

5. 2 .

 2 Decision Trees Abstract Domain 93 Algorithm 11 : Tree Assignment 1: function assign-auxJ X := aexp K(D, t, C) . D 2 D, t 2 T , C 2 P(C) 2:

  C J X := aexp Kd(t.c) 6: J b-assign C J X := aexp Kd(¬t.c) 7:

  def = x + 1 and the backward assignment x := x + [1, 2]. Let D 2 B be the interval hx, [1, 2]i and let d 2 B be defined as d def = > B . The backward assignment produces the interval R def = hx, [ 1, 1]i and the a ne function f 0 2 F A \ {? F , > F } defined as f 0 (x) def = x + 4, since substituting the expression x + [1, 2] to the variable x within f gives f (x+[1, 2])+1 = x+[1, 2]+1+1 = x+[3, 4] and max{3, 4} = 4. The operator B-ASSIGN T J X := aexp K : D ! T ! T for handling backward assignments within decision trees is implemented by Algorithm 11: the 94 5. Piecewise-Defined Ranking Functions

Figure 5 .

 5 Figure 5.10: Unsound abstraction (b) of a most precise ranking function (a).

  are shown in Figure 5.11a and Figure 5.11b, respectively. Their domains of definition D 1 2 D and D 2 2 D are represented by the set of linear constraints C 1 def = C (D 1 ) = {x 6 0, x + 10 0} and C 2 def = C (D 2 ) = { x + 5 0}. In Figure 5.11d and Figure 5.11e are represented the hypographs f 1 [D 1 ]# and f 2 [D 2 ]# of f 1 and f 2 , respectively. Their convex-hull is shown in Figure 5.11e, and the result of the extrapolation is the a ne function f 2 F A \ {? F , > F } shown in Figure 5.11c.

Figure 5

 5 Figure 5.11: Example of extrapolation between two a ne functions of one variable, shown in (a) and (b), respectively. The hypographs of (a) and (b) are respectively shown in (d) and (e). Their convex-hull is shown in (f) together with the a ne functions lying on its boundaries. The result of the extrapolation is shown in (c).

Example 5.3. 4

 4 Let us consider again the program of Example 5.1.1 [PR04a]: while 1 (x 0) do 2 x := 2x + 10 od 3

  NODE{x y+r 1 0} : (LEAF : x. y. r. 10); (LEAF : x. y. r. 4); LEAF : x. y. r. 1 and the widening corrects the ranking function yielding a fixpoint: NODE{x y + r 1 0} : (LEAF : > F ); (LEAF : x. y. r. 4); LEAF : x. y. r. 1

Figure 6 . 1 :x

 61 Figure 6.1: Transitions between states at program control point 1 for the program of Example 6.1.1. There is an edge from any node where y has value k > 0 (and y > 0) to all nodes where y has value k 1 (and y has any value).In every node we indicate the maximum number of loop iterations needed to reach a blocking state with no successors.

  2.2) Ordinal multiplication generalizes the multiplication of natural numbers. It is associative, i.e. (↵ • ) • = ↵ • ( • ), and left distributive, i.e. ↵ • ( + ) = (↵ • ) + (↵ • ). However, commutativity does not hold, e.g. 2 • ! = ! 6 = ! • 2, and neither does right distributivity, e.g. (! + 1) • ! = ! • ! 6 = ! • ! + !.

Figure 6 . 2 :

 62 Figure 6.2: Hasse diagrams for approximation order 4 F [D] (a) and computational order v F [D] (b) of the ordinal-valued functions abstract domain.

  Domain. We can now use the family of abstract domains W to lift the decision trees abstract domain to T(D, C, W(F)).

6. 3 .

 3 Decision Trees Abstract Domain 123 Algorithm 19 : Ordinal-Valued Function Approximation Join 1: function a-w-join(D, p 1 , p 2 ) . D 2 D, p 1 , p 2 2 W \ {? W , > W } 2: return w-join(g F , D, p 1 , p 2 ) Algorithm 20 : Ordinal-Valued Function Computational Join 1: function c-w-join(D, p 1 , p 2 ) . D 2 D, p 1 , p 2 2 W \ {? W , > W } 2: return w-join(t F , p 1 , p 2 , C) Example 6.3.2 Let X def = {x, y}, let D be the intervals abstract domain hB, v B i, and let F be the a ne functions auxiliary abstract domain hF A , 4 F i. We consider the ordinal-valued functions p 1 def = ! • x + y and p 2def = ! • (x 1) y and we assume that their domain of definition D 2 D is defined as D def = > B . The join of p 1 and p 2 is carried out in ascending powers of ! starting from the coe cients f 1 0 def = y and f 2 0 def

124 6 .

 6 Ordinal-Valued Ranking Functions Algorithm 21 : Ordinal-Valued Function Assignment 1: function w-assignJ X := aexp K(d, D, p) 2:

=

  {x, y}, let D be the intervals abstract domain hB, v B i, and let F be the a ne functions auxiliary abstract domain hF A , 4 F i. We consider the ordinal-valued functions p def = ! • x + y and the non-deterministic assignment x := ?. We assume that the domain of definition D 2 D and d 2 B are defined as D def = > B and d def = > B . The assignment is carried out in ascending powers of ! starting from the coe cient f 0 def = y, which remains unchanged since the assignment only involves the variable x, whereas the coe cient f 1 def =

126 6 .

 6 Ordinal-Valued Ranking Functions Algorithm 22 : Ordinal-Valued Function Extrapolation 1: function w-widen(D 1 , D 2 , p 1 , p 2 ) 2:

Example 6.4. 4

 4 Let us consider again the program from[START_REF] Cook | Proving Program Termination[END_REF]:while 1 (0 < x ^0 < y) do if 2 ( ? )

  is an involved variation of Example 6.1.1. Each loop iteration, when

Figure 6 . 3 :

 63 Figure 6.3: Transitions between states at control point 1 for the program in Figure 6.4.5. There is an edge from any node where x has value k > 0 (and

  Figure 7.1: Syntax of our programming language extended with procedures.

Figure 7 . 3 :

 73 Figure 7.3: Final control point of stmt and prog.

Figure 7 . 4 :

 74 Figure 7.4: Transition semantics of stmt and ret.

8

  Let us consider the recursive version of the program of Example 4.1.2: The set of program environments E contains the functions ⇢ : {x} ! Z mapping the program variable x to any possible value ⇢(x) 2 Z. The set of program states ⌃ def = {1, 2, 3, 4, 5, 6, 7, 8}⇥E consists of all pairs of numerical labels and environments; the extended initial states are {"} ⇥ I

6

  and where the semantics ⌧ +1 J stmt K P S : P(⌃ +1 ) ! P(⌃ +1 ) of each program instruction stmt is defined in Figure7.5. Example 7.2.5 Let us consider the recursive version of the program of Example 4.2.3: The set of program environments E only contains the totally undefined function ⇢ : ; ! Z, since the program has no variables. The set of all program states is ⌃ def = {1, 2, 3, 4, 5, 6} ⇥ E, while the set of initial states is I def = {5} ⇥ E, and the set of final states is

Figure 7 . 6 :

 76 Figure 7.6: Fixpoint iterates of the maximal trace semantics for Example 7.2.5.

  NODE{x 3 0} : LEAF : ? F ; NODE{x 2 0} : (LEAF : x. 7); (LEAF : x. 3)

Figure 8 . 1 :

 81 Figure 8.1: Comparison of di↵erent parameterizations of FuncTion.

Figure 8 . 2 :

 82 Figure 8.2: Overview of the experimental evaluation.

1

  http://sv-comp.sosy-lab.org/2015/results/Termination.table.html

Figure 8

 8 Figure 8.3: Detailed comparison of our prototype FuncTion against its previous version [Urb15] (a), AProVE [SAF + 15] (b), HIPTnT+ [LQC15] (c), and Ultimate [HDL + 15] (d).

FuncTionFigure 8

 8 Figure 8.4: crafted: overview of the experimental evaluation.

Figure 8

 8 Figure 8.5: Detailed comparison of FuncTion against AProVE [SAF + 15].

Figure 8

 8 Figure 8.6: crafted-lit: overview of the experimental evaluation.

Figure 8 .Figure 8

 88 Figure 8.7: Detailed comparison of FuncTion against its previous version [Urb15].

Figure 8

 8 Figure 8.8: memory-alloca: overview of the experimental evaluation.

Figure 8 . 9 :

 89 Figure 8.9: Detailed comparison of FuncTion against HIPTnT+ [LQC15].

Figure 8 .

 8 Figure 8.10: numeric: overview of the experimental evaluation.

Figure 8 .

 8 Figure 8.11: Detailed comparison of FuncTion against Ultimate Automizer [HDL + 15].

  Let us consider again the program of Example 9.1.1:while 1 (x 0) do 2 x := x + 1 od while 3 ( true ) do if 4 (x  10) then 5 x := x + 1 then 6 x := x fi od 7An example of safety property is the formula 2(x = 3), which is never satisfied by the program. Instead, since the first while loop increases the value of the variable x at each iteration, the safety property 2(3  x) is satisfied when the program initial states are limited to the set {h1, ⇢i 2 ⌃ | 3  ⇢(x)}.

  e 2 L respectively denote the initial and final program control point. Example 9.1.3 Let us consider again the program of Example 9.1.1:while 1 (x 0) do 2 x := x + 1 od while 3 ( true ) do if 4 (x  10)

c

  : true) where l c 2 L is the program control point representing the critical section. Example 9.1.4 Let us consider again the program of Example 9.1.1: while 1 (x 0) do 2 x := x + 1 od while 3 ( true ) do if 4 (x  10) then 5 x := x + 1 then 6 x := x fi od 7

  Let us consider again the program of Example 9.1.1:while 1 (x 0) do 2 x := x + 1 od while 3 ( true ) do if 4 (x  10) then 5 x := x + 1 then 6 x := x fi od 7

  .2.5) Example 9.2.4 Let us consider the following trace semantics: where the highlighted states are the set S of desirable states. The fixpoint iterates of the guarantee semantics ⌧ g [S] 2 ⌃ * O are: are outside the domain of the function.

'

  g : (E * O) ! (E * O) within hE * O, vi, analogously to Equation 9.2.5:

  where the function ⌧ ' g J stmt K : (E * O) ! (E * O) is the guarantee semantics of each program instruction stmt.

  Example 9.3.1 Let T def = {(cd) !, ca ! , d(be) ! } and let S def = {b, c, d}. For i = 0, we haveT 1 = ↵ g [S]T = {b, eb, c, d}. For i = 1, we derive S 1 = {b, d}, since c(dc) ! 2 T and pf((dc) ! ) \ T 1 = {d} 6 = ; but ca ! 2 T and pf(a ! ) \ T 1 = ;. We getT 2 = ↵ g [S 1 ]T = {b, eb, d}. For i = 2, we derive S 2 = {b}, since d(be) ! 2 T and pf((be) ! ) \ T 1 = {b} 6 = ; but d(cd) ! 2 T and pf((cd) ! ) \ T 2 = ;. We getT 3 = ↵ g [S 2 ]T = {b,eb} which is the greatest fixpoint: the only subsequences of sequences in T that guarantee S infinitely often start with b or eb. We can now define the recurrence semantics ⌧ r [S] 2 ⌃ * O: Definition 9.3.2 (Recurrence Semantics) Given a desirable set of states S ✓ ⌃, the recurrence semantics ⌧ r [S] 2 ⌃ * O is an abstract interpretation of the maximal trace semantics ⌧ +1 2 P(⌃ +1 ) (cf. Equation 2.2.5): ⌧ r [S]

  def

  is not need to redefine ⌧ g [S] at each iterate since the various subsequences of a program traces manipulated by the recurrence abstraction (cf. Equation 9.3.1) have been abstracted into program states. The rest of the chapter refers to this simplified version of the recurrence semantics. Example 9.3.4 Let us consider the following trace semantics: where the highlighted states are the set S of desirable states. The fixpoint iterates of the recurrence semantics ⌧ r [S] 2 ⌃ * O are: are outside the domain of the function. Let ' be a state property. The '-recurrence semantics ⌧ ' r 2 ⌃ * O: complete for proving a recurrence property 23': Theorem 9.3.5 A program satisfies a recurrence property 23' for execu- tion traces starting from a given set of states I if and only if I ✓ dom(⌧ ' r ).

  In this way, to each program control point l 2 L corresponds a partial function f : E * O, and to each program instruction stmt corresponds a recurrence semantics ⌧ ' r J stmt K : (E * O) ! (E * O). The recurrence semantics ⌧ ' r J stmt K : (E * O) ! (E * O) of each program instruction stmt takes as input a ranking function whose domain represents the environments always leading infinitely often to ' from the final label of stmt, and determines the ranking function whose domain represents the environments always leading infinitely often to ' from the initial label of stmt, and whose value represents an upper bound on the number of program execution steps remaining to the next occurrence of '. In particular, each function

=

  {x}. We consider the following ranking function f : E * O: x := x + [1, 2] and the recurrence property 23(x = 3). The recurrence semantics of the assignment is:

  def = ⇢ 2 dom(S) \ dom(f ).

  ) + 1, f(⇢) + 1} JbexpK⇢ = {true, false} undefined otherwise and the ranking function F 1 [x] : E * O whose domain is the set of environments ⇢ 2 E that belong to the domain of S and that must satisfy bexp:F 1 [x] def = ⇢ 2 dom(S).( S(⇢) + 1 JbexpK⇢ = {true} undefined otherwise and the ranking function F 2 [f ] : E * O whose domain is the set of environments that belong to the domain of the input function f and that cannot satisfy bexp:F 2 [f ] def = ⇢ 2 dom(f ).

(=F

  f (⇢) + 1 JbexpK⇢ = {false} undefined otherwiseThe resulting ranking function is defined by joining F [x], F 1 [x], and F 2 [f ], and resetting its value for the environments that belong to its domain and satisfy ':|= ' ^⇢ 2 dom(R) R(⇢) hl, ⇢i 6 |= ' ^⇢ 2 dom([x] [ F 1 [x] [ F 2 [f ].Finally, the recurrence semantics of the sequential combination of instructions stmt 1 stmt 2 , takes as input a ranking function f : E * O, determines from f the recurrence semantics ⌧ ' r J stmt 2 Kf of stmt 2 , and outputs the ranking function determined by the recurrence semantics of stmt 1 from ⌧ ' r J stmt 2 Kf :⌧ ' r J stmt 1 stmt 2 Kf def = ⌧ ' r J stmt 1 K(⌧ ' r J stmt 2 Kf ) (9.3.11)The recurrence semantics ⌧ ' r J prog K 2 E * O of a program prog is a ranking function whose domain represents the environments always leading infinitely often to ', which is determined by taking as input the totally undefined function, since the program final states cannot satisfy a recurrence property: Definition 9.3.8 (Recurrence Semantics) The recurrence semantics⌧ ' r J prog K 2 E * O of a program prog is: ⌧ ' r J prog K = ⌧ ' r J stmt l K def = ⌧ ' r J stmt K ; (9.3.12)where the function ⌧ ' r J stmt K : (E * O) ! (E * O) is the recurrence semantics of each program instruction stmt.

Figure 9

 9 Figure 9.2: Example of dual widening of piecewise-defined function of one variable, shown in (a) and (b), respectively. The result is shown in (c).

def=(

  Figure 9.3: Abstract recurrence semantics of instructions stmt.

  R, LEAF : ? F ) (9.3.15) where the abstract recurrence semantics ⌧ '\ r J stmt K : T ! T of each program instruction stmt is defined in Figure9.3.In absence of run-time errors, the abstract recurrence semantics ⌧ '\ r J prog K 2 T , given a sound numerical over-approximation R 2 D of the reachable environments ⌧ I (iJ prog K), is sound with respect to ⌧ ' r J prog K 2 E * O:Theorem 9.3.11 ⌧ ' r J prog K 4 T [R]⌧ '\ r J prog K Proof (Sketch).The proof follows from the soundness of the operators of the decision trees abstract domain (cf. Lemma 9.3.9) used for the definition of ⌧ '\ r J prog K 2 T .⌅In particular, the abstract recurrence semantics provides su cient preconditions for ensuring a recurrence property 23' for a given over-approximation R 2 D of the set of initial states I ✓ ⌃:Corollary 9.3.12 A program satisfies a recurrence property 23' for execu- tion traces starting from a set of states D (R) if D (R) ✓ dom( T [R]⌧ '\ r J prog K).

  These and additional examples are available from FuncTion web interface: http://www.di.ens.fr/ ~urban/FuncTion.html. Example 9.4.1 Let us consider again the program of Example 9.1.1: while 1 (x 0) do 2 x := x + 1 od while 3 ( true ) do if 4 (x  10) then 5 x := x + 1 then 6 x := x fi od 7

Example 9.4. 2

 2 Let us consider the following program: 1 c := 1 while 2 ( true ) do 3 x := c while 4 (0 < x) do 5 x := x 1 6 c := c + 1 od od 7

x := x 1 else 6 x := x + 1 fi od od 7

 67 Example 9.4.3 Let us consider the following program:while 1 ( true ) do 2 x := ? while 3 (x 6 = 0) do if 4 (0 < x) then5 Each iteration of the outer loop, resets the value of the program variable x with the non-deterministic assignment x := ?; then, the inner loop decreases or increases the value of x until it becomes equal to zero.The recurrence property 23(x = 0) is clearly satisfied by the program.

  Example 9.4.4 Let us consider Peterson's algorithm[START_REF] Gary | Myths About the Mutual Exclusion Problem[END_REF] for mutual exclusion:

Let C def =

 def ⌧ Mt J if l bexp then stmt 1 else stmt 2 fi K T [D]t and let A def = T [R](F \ 1 [t] g T [R] F \ 2 [t]). By structural induction, we have ⌧ Mt J stmt 1 K T [D]t 4 T [R](⌧ \ Mt J stmt 1 Kt) and ⌧ Mt J stmt 2 K T [D]t 4 T [R](⌧ \ Mt J stmt 2 Kt).We prove that dom(C) ◆ dom(A) and 8⇢ 2 dom(A) : C(⇢)  A(⇢) (cf. Equation 4.2.12).

S 1

 1 denote ⌧ Mt J stmt 1 K T [D]t and let S 2 denote ⌧ Mt J stmt 2 K T [D]t. We have, by definition of ⌧ Mt J if l bexp then stmt 1 else stmt 2 fi, C(⇢) = S 1 (⇢) + 1 or C(⇢) = S 2 (⇢) + 1 or C(⇢) = sup{S 1 (⇢) + 1, S 2 (⇢) + 1}. Let S \ 1 denote T [R](⌧ \ Mt J stmt 1 Kt) and let S \ 2 denote T [R](⌧ \ Mt J stmt 2 Kt).

⌅

  Lemma 5.2.16 Let F \ 1 [x] def = (FILTER T J bexp KR)(⌧ \ Mt J stmt Kx) and F \ 2 [t]

  2.16. Let C def = Mt ( D [R]x) and let A def = T [R]( \ Mt (x)). By structural induction, we have⌧ Mt J stmt K T [R]x 4 T [R](⌧ \ Mt J stmt Kx).We prove that dom(C) ◆ dom(A) and 8⇢ 2 dom(A) : C(⇢)  A(⇢) (cf. Equation 4.2.12).Let us assume, by absurd, that dom(C) ⇢ dom(A). Then, there exists an environment ⇢ 2 E such that ⇢ 2 dom(A) and ⇢ 6 2 dom(C). Since ⇢ 2 dom(A), by definition of 4 T [D] (cf. Algorithm 6) and FILTER T (cf. Algorithm 12), we have⇢ 2 dom( T [R](⌧ \ Mt J stmt Kx)) or ⇢ 2 dom( T [D]t),or both. In fact, Algorithm 12 prunes a decision tree (cf. Line 12) and Algorithm 6 favors undefined leaf nodes over defined leaf nodes (cf. Equation 5.2.13). Thus, by structural induction, we have ⇢ 2 dom(⌧ Mt J stmt K T [R]x) or ⇢ 2 dom( T [D]t), or both. In absence of run-time errors, by definition of Mt (cf. Equation 4.3.5), we have ⇢ 2 dom(C) which is absurd. Therefore, we conclude that dom(C) ◆ dom(A). Let us assume now, by absurd, that 9⇢ 2 dom(A) : C(⇢) > A(⇢). Let S denote ⌧ Mt J stmt K T [R]x. We have, by definition of Mt , C(⇢) = S 1 (⇢) + 1 or C(⇢) = ( T [D]t)(⇢) + 1 or C(⇢) = sup{S 1 (⇢) + 1, ( T [D]t)(⇢) + 1}. Let S \ denote T [R](⌧ \

  n O \ Mt (y n ) (cf. Equation 5.2.24).

  and only if the property P is implied by the collecting semantics {S} 2 P(P(⌃ +1 )) of the program, that is, if and only if {S} ✓ P .In practice, a weaker form of program correctness is often used. In fact, the traditional safety and liveness properties are trace properties and thus can be modeled as sets of traces. In this case, a program satisfies a property P 2 P(⌃ +1 ) if and only if its semantics S 2 P(⌃ +1 ) implies the property P , that is, if and only if S ✓ P . Let us consider a program with semantics S 2 P(⌃ +1 ). We can model the property of program termination as the set of all non-empty finite sequences ⌃ + . The program terminates if and only if S ✓ ⌃ + .

	Example 2.2.13

  is an over-approximation of the set of environments ⌧ I (l).

	In some cases, there also exists a Galois connection (cf. Remark 2.2.19):
	hP(E), ✓i	! ↵ D D	hD, v D i
	By pointwise lifting (cf. Equation 2.1.1) we obtain the following:
	hL ! P(E), ✓i	˙ D hL ! D, vD i
	or, when an abstraction function ↵ D : P(E) ! D also exists:
	hL ! P(E), ✓i	! ↵D ˙ D	hL ! D, vD i
	which provides a (concretization-based) abstraction of the invariance seman-
	tics ⌧ I 2 L ! P(E) by partitioning with respect to the program control points. No approximation is made on L. On the other hand, each program control point l 2 L is associated with an element d 2 D.
	Numerical Abstract Domains. The abstract domain hD, v D i is a numer-ical abstract domain and it obeys the following signature:
	Definition 3.4.1 (Numerical Abstract Domain) A numerical abstract do-
	main is characterized by a choice of:

  .2.8: Theorem 4.2.15 (Potential Termination Semantics) The potential termination semantics ⌧ mt 2 ⌃ * O of a program can be expressed as a least fixpoint in the partially ordered set h⌃ * O, vi:

  Thus, in the following, we consider all linear constraints in C to have the form c 1 X 1 +. . .+c

	we require gcd(|c 1 |, . . . , |c	k |, |c	k+1 |) = 1:
			k X	k +c	k+1	0. More-
	over, in order to ensure a canonical representation of the linear constraints,

  t 2 2 T NIL , C 2 P(C)

	5:	if ¬isNode(t 1 ) ^¬isNode(t 2 ) then return (t 1 , t 2 )
	34:
	35: function unification(D, t 1 , t 2 ) 36:	. D 2 D, t 1 , t 2 2 T NIL

6:

else if ¬isNode(t 1 ) _ (isNode(t 1 ) ^isNode(t 2 ) ^t1 .c < C t 2 .c) then 7: if isRedundant(t 2 .c, C) then 8: return unification-aux(t 1 , t 2 .l, C) 9: else if isRedundant(¬t 2 .c, C) then 10: return unification-aux(t 1 , t 2 .r, C) 11: else . t 2 .c can be added to t 1 and kept in t 2 12:

(l 1 , l 2 ) unification-aux(t 1 , t 2 .l, C [ {t 2 .c}) 13: (r 1 , r 2 ) unification-aux(t 1 , t 2 .r, C [ {¬t 2 .c}) 14: return (NODE{t 2 .c} : l 1 ; r 1 , NODE{t 2 .c} : l 2 ; r 2 ) 15: else if ¬isNode(t 2 ) _ (isNode(t 1 ) ^isNode(t 2 ) ^t2 .c < C t 1 .c) then 16: if isRedundant(t 1 .c, C) then 17:

return unification-aux(t 1 .l, t 2 , C) 18: else if isRedundant(¬t 1 .c, C) then 19: return unification-aux(t 1 .r, t 2 , C) 20: else . t 1 .c can be kept in t 1 and added to t 2 21: (l 1 , l 2 ) unification-aux(t 1 .l, t 2 , C [ {t 1 .c}) 22: (r 1 , r 2 ) unification-aux(t 1 .r, t 2 , C [ {¬t 1 .c}) 23: return (NODE{t 1 .c} : l 1 ; r 1 , NODE{t 1 .c} : l 2 ; r 2 ) 24: else if isNode(t 1 ) ^isNode(t 2 ) then 25: c t 1 .c . t 1 .c and t 2 .c are equal 26: if isRedundant(c, C) then 27: return unification-aux(t 1 .l, t 2 .l, C) 28: else if isRedundant(¬c, C) then 29: return unification-aux(t 1 .r, t 2 .r, C) 30: else . c can be kept in t 1 and t 2 31: (l 1 , l 2 ) unification-aux(t 1 .l, t 2 .l, C [ {c}) 32: (r 1 , r 2 ) unification-aux(t 1 .r, t 2 .r, C [ {¬c}) 33:

return (NODE{c} : l 1 ; r 1 , NODE{c} : l 2 ; r 2 )

  f

	4: 5:	else if isNode(t 1 ) ^isNode(t 2 ) then c t 1 .c
	6: 7: 8:	l r return l order-aux(t 1 .l, t 2 .l, C [ {c}) order-aux(t 1 .r, t 2 .r, C [ {¬c}) ^r

9:

10: function order(E,

D, t 1 , t 2 ) . D 2 D, t 1 , t 2 2 T , E 2 {4 F , v F } 11:

(t 1 , t 2 ) unification(D, t 1 , t 2 )

12:

  The join of decision trees represents a ranking function defined over the union of their partitions. It is implemented by Algorithm 5: the function Algorithm 5 : Tree Join 1: function join-aux( , t 1 , t 2 , C) . t 1 , t 2 2 T NIL , C 2 P(C), 2 {g F , t F }

	Algorithm 4 : Tree Computational Order
	1: function c-order(D, t 1 , t 2 ) 2: return order(v F , D, t 1 , t 2 )	. D 2 D, t 1 , t 2 2 T
	2:	if isNil(t 1 ) then return t 2
	3:	else if isNil(t 2 ) then return t 1
	4:

else if isLeaf(t 1 ) ^isLeaf(t 2 ) then 5:

  return LEAF : t 1 .f g F [↵ C (C)] t 2 .f

	88		5. Piecewise-Defined Ranking Functions
	Algorithm 8 : Tree Meet
	1: function meet-aux(t 1 , t 2 , C) 2: if isNil(t 1 ) _ isNil(t 2 ) then return NIL 3: else if isLeaf(t 1 ) ^isLeaf(t 2 ) then 4:	. t 1 , t 2 2 T NIL , C 2 P(C)
	5: 6:	else if isNode(t 1 ) ^isNode(t 2 ) then c t 1 .c
	7:	(l 1 , l 2 )	meet-aux(t 1 .l, t 2 .l, C [ {c})
				2.19)

8:

(r 1 , r 2 ) meet-aux(t 1 .r, t 2 .r, C [ {¬c})

9:

return (NODE{c} : l 1 ; r 1 , NODE{c} : l 2 ; r 2 ) 10:

11: function meet(D, t 1 , t 2 ) . D 2 D,

t 1 , t 2 2 T NIL 12: (t 1 , t 2 ) unification(D, t 1 , t 2 ) 13: return meet-aux(t 1 , t 2 , C (D)) Algorithm 9 : Tree Step 1: function step(t) . t 2 T 2: if isLeaf(t) then 3: return LEAF : step F (t.f ) 4: else if isNode(t) then 5:

  ).

	96	5. Piecewise-Defined Ranking Functions
	Algorithm 12 : Tree Filter
	1: function filterJ bexp K(D, t) 2: switch bexp do	. D 2 D, t 2 T
	3:	case ? : return t
	4:	case not bexp :
	5: 6:	return filterJ ¬bexp K(D, t) case bexp 1 and bexp 2 :
	7:	return meet(D, filterJ bexp 1 K(D, t), filterJ bexp 2 K(D, t))
	Proof.
	See Appendix A.3.	⌅

8:

case bexp 1 or bexp 2 : 9: return a-join(D, filterJ bexp 1 K(D, t), filterJ bexp 2 K(D, t)) 10: case aexp 1 ./ aexp 2 : 11: J filter C J aexp 1 ./ aexp 2 KD 12:

  then return t 2 .f

4: else return LEAF : > F 5: else if isNode(t 1 ) ^isNode(t 2 ) then 6: l caseA-aux(t 1 .l, t 2 .l, C [ {t 2 .c}) 7: r caseA-aux(t 1 .r, t 2 .r, C [ {¬t 2 .c}) 8: return NODE{t 2 .c} : l; r 9: 10: function caseA(D, t 1 , t 2 ) . D 2 D, t 1 , t 2 2 T 11: (t 1 , t 2 ) unification(D, t 1 , t 2 ) 12:

  , t 2 2 T , C 2 P(C), 2 {g F , t F } 3: if isLeaf(t 1 ) ^isLeaf(t 2 ) then return (t 1 , t 2 ) 4: else if isLeaf(t 1 ) _ (isNode(t 1 ) ^isNode(t 2 ) ^t1 .c < C t 2 .c) then D, t 1 , t 2 2 T , 2 {g F , t F }

	5.2. Decision Trees Abstract Domain 102	101 5. Piecewise-Defined Ranking Functions
	Algorithm 15 : Tree Left Unification
	1: function left-unification-aux( , t 1 , t 2 , C)
	2: . t 1 5: if isRedundant(t 2 .c, C) then
	30:
	31: function left-unification( , D, t 1 , t 2 )
	32: . D 2 33: return left-unification-aux(t 1 , t 2 , C (D))

6:

return left-unification-aux(t 1 , t 2 .l, C) 7: else if isRedundant(¬t 2 .c, C) then 8: return left-unification-aux(t 1 , t 2 .r, C) 9: else . t 2 .c should be removed from t 2 10: return left-unification-aux(t 1 , t 2 , join( , ↵ C (C), t 2 .l, t 2 .r)) 11: else if isLeaf(t 2 ) _ (isNode(t 1 ) ^isNode(t 2 ) ^t2 .c < C t 1 .c) then 12: if isRedundant(t 1 .c, C) then 13: return left-unification-aux(t 1 .l, t 2 , C) 14: else if isRedundant(¬t 1 .c, C) then 15: return left-unification-aux(t 1 .r, t 2 , C) 16: else . t 1 .c can be kept in t 1 and added to t 2 17: (l 1 , l 2 ) left-unification-aux(t 1 .l, t 2 , C [ {t 1 .c}) 18: (r 1 , r 2 ) left-unification-aux(t 1 .r, t 2 , C [ {¬t 1 .c}) 19: return (NODE{t 1 .c} : l 1 ; r 1 , NODE{t 1 .c} : l 2 ; r 2 ) 20: else if isNode(t 1 ) ^isNode(t 2 ) then 21: c t 1 .c . t 1 .c and t 2 .c are equal 22: if isRedundant(c, C) then 23: return left-unification-aux(t 1 .l, t 2 .l, C) 24: else if isRedundant(¬c, C) then 25: return left-unification-aux(t 1 .r, t 2 .r, C) 26: else . c can be kept in t 1 and t 2 27: (l 1 , l 2 ) left-unification-aux(t 1 .l, t 2 .l, C [ {c}) 28: (r 1 , r 2 ) left-unification-aux(t 1 .r, t 2 .r, C [ {¬c}) 29:

return (NODE{c} : l 1 ; r 1 , NODE{c} : l 2 ; r 2 )

  f

	5.2. Decision Trees Abstract Domain	107
			x
		6	10
		(a)
	33:	return f
	34:	else return t 2 .f
	35: 36: 37:	else if isNode(t 1 ) ^isNode(t 2 ) then l widen-aux(t, t 1 .l, t 2 .l, C [ {t 2 .c}) r widen-aux(t, t 1 .r, t 2 .r, C [ {¬t 2 .c})

38:

return NODE{t 2 .c} : l; r

  then

	9:	carry	true
	10:	else
	11:	if carry then
	12:		r[i]	STEP F (f )
	13:		carry	false
	14:	else
	15:		r[i]	f
	16:	i	i + 1
	17: 18:	if ¬carry then return r
	19:	else		. maximum degree of the polynomial exceeded
	20:

  . From

		Tot Time Timeouts
	FuncTion	20	0.1s	1
	AProVE [SAF + 15]	20	4.5s	3
	FuncTion [Urb15]	18	0.2s	0
	HIPTnT+ [LQC15] 19	0.3s	1
	Ultimate [HDL + 15] 22	7.4s	1
		(a)

  .1). The predicate l : bexp allows specifying a program state property at a particular program control point l 2 L. When a program state s 2 ⌃ satisfies the property ', we write s |= ' and we say that s is a '-state. We also slightly abuse notation and write ' to also denote the set {s 2 ⌃ | s |= '} of states that satisfy the property '.

	Example 9.1.1
	Let us consider the following program:
	while 1 (x 0) do
	2	x := x + 1
	od
	while 3 ( true ) do
	if 4 (x  10) then 5

  T ✓ ⌃ +1 is the set of sequences 0 2 T with a common prefix with (cf. Equation 4.2.3). A finite subsequence of a program trace satisfies a guarantee property if and only if it terminates in the desirable set of states (and never encounters a desirable state before), and its neighborhood in the subsequences of the program semantics consists only of sequences that are terminating in the desirable set of states (and never encounter a desirable state before). The corresponding guarantee abstraction ↵ g [S] : P(⌃ +1 ) ! P(⌃ + ) is parameterized by a set of desirable states S ✓ ⌃ and it is defined as follows: S and the function sf : P(⌃ +1 ) ! P(⌃ +1 ) yields the set of su xes of a set of sequences T ✓ ⌃ +1 :

	↵ g [S]T	def =	s 2 sq(T )	2 S⇤	, s 2 S, nhbd( , sf(T ) \ S+1 ) = ; (9.2.2)
	where	S def = ⌃ \ sf(T )	def =	[	{ 2 ⌃ +1 | 9 0 2 ⌃ ⇤ : 0 2 T }.	(9.2.3)
	Example 9.2.1
	Let T	def = {(abcd) !	, (cd) !	, a !	, cd ! } and let S

def

= {c}. We have sf(T ) \ S+1 = {a !

  In this way, to each program control point l 2 L corresponds a partial function f : E * O, and to each program instruction stmt corresponds a guarantee semantics ⌧ ' g J stmt K : (E * O) ! (E * O). The guarantee semantics ⌧ ' g J stmt K : (E * O) ! (E * O) of each program instruction stmt takes as input a ranking function whose domain represents the environments always leading to ' from the final label of stmt, and determines the ranking function whose domain represents the environments always leading to ' from the initial label of stmt, and whose value represents an upper bound on the number of program execution steps remaining to '.

	9.2.2 Denotational Guarantee Semantics
	In the following, we provide a structural definition of the '-guarantee seman-
	tics ⌧ ' g 2 ⌃ * O by induction on the syntax of programs written in the small language presented in Chapter 3.
	We partition ⌧ ' g with respect to the program control points: ⌧ ' g 2 L ! (E * O).
	Theorem 9.2.5 A program satisfies a guarantee property 3' for execution traces starting from a given set of initial states I if and only if I ✓ dom(⌧ ' g ).
	Proof.
	See Appendix A.6.	⌅

  . . , X k . 0 RESET F (> F ) Algorithm 25 : Tree Dual Widening 1: function dual-widen-aux(t 1 , t 2 , C) . t 1 , t 2 2 T , C 2 P(C) if t 2 .f v F [↵ C (C)] t 1 .fthen return t 2 .f -aux(t 1 .l, t 2 .l, C [ {t 2 .c}) -aux(t 1 .r, t 2 .r, C [ {¬t 2 .c}) function dual-widen(d,t 1 ,t 2 ) . d 2 D, t 1 , t 2 2 T 11: (t 1 , t 2 ) left-unification(g F , d, t 1 , t 2 ) . domain widening

	9.3. Recurrence Semantics	191
	2: 3:	if isLeaf(t 1 ) ^isLeaf(t 2 ) then
	4: 5: 6: dual-widen7: else return LEAF : ? F else if isNode(t 1 ) ^isNode(t 2 ) then l r dual-widen8: return NODE{t 2 .c} : l; r
	9:
	10: 12:
			(9.3.13)
		def = > F

  FILTER T J bexp KR)(⌧ \ Mt J stmt 1 Kt) and F \ 2 [t] def = (FILTER T J not bexp KR)(⌧ \ Mt J stmt 2 Kt).Then, for all t 2 T , we have:

	⌅
	Lemma 5.2.15 Let F \ 1 [t]

def = (

Abstract Interpretation

A Small Imperative Language

3.2. Maximal Trace Semantics

An Abstract Interpretation Framework for Termination

x := x 1 od

Future Directions

In the following example, the widening is required for convergence. We present the analysis of the program using polyhedral constraints based on the polyhedra abstract domain (cf. Section 3.4.2) for the decision nodes, and a ne functions for the leaf nodes (cf. Equation 5.2.6).

The starting point is the zero function at the program final control point:

3 : LEAF : x. y. r. 0

The ranking function is then propagated backwards towards the program initial control point taking the loop into account:

1 :

NODE{r 1 0} : (LEAF : ? F ); (LEAF : x. y. r. 1)

The first iterate of the loop is able to conclude that the program terminates in at most one program step if the loop condition r > 0 is not satisfied. Then, at program control point 3, the operator ASSIGN T replaces the program variable r with the expression r y within the decision tree: 3 : NODE{y r 0} : (LEAF : x. y. r. 2); (LEAF : ? F ) and at program control point 2, it replaces r with r + x:

:

NODE{x y + r 1 0} : (LEAF : ? F ); (LEAF : x. y. r.

3)

The second iterate of the loop concludes that the program terminates in at most four execution steps, when the loop is executed only once, and in at most one program step, when the loop is not entered:

1 :

NODE{r 1 0} : NODE{x y + r 1 0} : (LEAF : ? F ); (LEAF : x. y. r. 4); LEAF : x. y. r. 1

The third iterate concludes that the program terminates in at most seven execution steps when the loop is executed twice, in at most four steps when the loop is executed once, and in at most one step when the loop is not entered:

We present the analysis of the program using interval constraints based on the intervals abstract domain (cf. Section 3.4.1) for the decision nodes, and ordinal-valued functions for the leaf nodes (cf. Chapter 6).

The starting point is the zero function at the program final control point:

The ranking function is then propagated backwards towards the program initial control point taking into account the call to the recursive procedure f.

At program control point 5 the semantics of the return instruction simply increases the value of the ranking function:

The semantics of the skip instruction does the same at program point 4:

Instead, the recursive call at program control point 3 returns:

which is propagated by the variable assignment at program control point 2:

2 : LEAF : ? F .

Thus, the first iterate of the call to f is able to conclude that the procedure terminates in at most three execution steps when 1 < x is not satisfied:

Then, during the second iterate, the recursive call at program control point 3 increases the value of the ranking function obtained after the first iterate (plus the ranking function obtained at program control point 5):

:

NODE{x 2 0} : (LEAF : ? F ); (LEAF : x. 5) and, at program control point 2, the operator ASSIGN T replaces the program variable x with the expression x 1 within the decision tree:

:

NODE{x 3 0} : (LEAF : ? F ); (LEAF : x. 6).

Thus, the second iterate of the call to f is able to conclude that the procedure terminates in at most seven execution steps, when it calls itself recursively only once, and in at most three program steps when 1 < x is not satisfied:

if isEmpty(J) then or its negation ¬j (cf. Lines 14-20), or continues the descent along the paths of the decision tree (cf. Lines 21-36). In the first case, reset-aux tests j and ¬j for redundancy with respect to C (cf. Lines 15-16): when ¬j is redundant with respect to C the whole decision tree is returned unmodified; otherwise, resetaux adds a decision node for j while leaving unmodified its right subtree (cf. Line 18), if j is already in canonical form (cf. Line 17), or it adds a decision node for for ¬j while leaving unmodified its left subtree (cf. Line 20), if ¬j is the canonical form of j (cf. Line 19). In the second case, reset-aux accumulates in C the encountered linear constraints (cf. Lines 26-27), possibly removing redundant decision nodes (cf. Lines 22-24) and leaving the right

The halting problem is undecidable.

Proof (by Geo↵rey K. Pullum).

Scooping the Loop Snooper

No general procedure for bug checks will do. Now, I won't just assert that, I'll prove it to you. I will prove that although you might work till you drop, you cannot tell if computation will stop.

For imagine we have a procedure called P that for specified input permits you to see whether specified source code, with all of its faults, defines a routine that eventually halts.

You feed in your program, with suitable data, and P gets to work, and a little while later (in finite compute time) correctly infers whether infinite looping behavior occurs.

If there will be no looping, then P prints out 'Good.' That means work on this input will halt, as it should.

But if it detects an unstoppable loop, then P reports 'Bad!' -which means you're in the soup.

A. Proofs

Well, the truth is that P cannot possibly be, because if you wrote it and gave it to me, I could use it to set up a logical bind that would shatter your reason and scramble your mind.

Here's the trick that I'll use -and it's simple to do. I'll define a procedure, which I will call Q, that will use P's predictions of halting success to stir up a terrible logical mess.

For

Proof of Lemma 5.2.2. Let D 2 D. We reason by cases. First, we consider the case of defined and undefined leaf nodes. Then, we consider the case of defined leaf nodes.

Let 5.3a. Moreover, from Equation 5.2.9, we have 5.2.9, we have dom(

. Moreover, from Equation 5.2.7, for all ⇢ 2 D (D) we have

). Thus, from Equation 4.2.12, we have

This concludes the proof that F [D] is monotonic.

The approximation ordering 4 T between decision trees is implemented by Algorithm 3: the functions a-order calls (the function order of Algorithm 2, which in turn calls) Algorithm 1 for tree unification, and then compares the decision trees "leaf-wise". Algorithm 1 forces the decision trees to have the same structure. Indeed, the missing linear constraints (cf. Line 6 and Line 15) are added to the decision trees (cf. Line 14 and Line 23). Thus, after the tree unification, all paths to the leaf nodes coincide between the decision trees. Let C 2 C denote the set of linear constraints satisfied along a path of the unified decision trees, and let f 1 , f 2 2 F denote the leaf nodes reached following the path C within the first and the second decision tree, respectively. We have

The proof follows from Lemma 5.2.2.

Proof of Lemma 5.2.8. We have

. We prove that dom(C) ◆ dom(A) and 8⇢ 2 dom(A) : C(⇢)  A(⇢) (cf. Equation 4.2.12).

Let us assume, by absurd, that dom(C) ⇢ dom(A). Then, there exists an environment ⇢ 2 E such that ⇢ 2 dom(A) and ⇢ 6 2 dom(C). In particular, ⇢ 2 D (R). Thus, since ⌧ I J l skip K D (R) ✓ D (D) and by definition of ⌧ I J l skip K (cf. Figure 3.9), we have D (R) ✓ D (D) which implies ⇢ 2 D (D). Moreover, since ⇢ 2 dom(A) and by definition of STEP T (cf. Algorithm 9), we must have ⇢ 2 dom( T [D]t). In fact, Algorithm 9 simply invokes STEP F for every leaf node of a decision tree, which leaves undefined leaf nodes unaltered (cf. Equation 5.2.19). Thus, by definition of ⌧ Mt J l skip K (cf. Equation 4.3.1), we have ⇢ 2 dom(C), which is absurd. Therefore, we have dom(C) ◆ dom(A).

Let us assume now, by absurd, that 9⇢ 2 dom(A) : C(⇢) > A(⇢). We have, by definition of

Moreover, by definition of STEP T (cf. Algorithm 9), we have ( T [D]t)(⇢) < A(⇢). In fact, Algorithm 9 invokes STEP F , which increases the value of the defined leaf nodes of a decision tree (cf. Equation 5.2.19). Thus, C(⇢)  A(⇢), which is absurd. Therefore, we conclude that 8⇢ 2 dom(A) : C(⇢)  A(⇢).

This concludes the proof. Let us assume, by absurd, that dom(C) ⇢ dom(A). Then, there exists an environment ⇢ 2 E such that ⇢ 2 dom(A) and ⇢ 6 2 dom(C). In particular, ⇢ 2 D (R). Thus, since ⌧ I J l X := aexp K D (R) ✓ D (D) and by definition of ⌧ I J l X := aexp K (cf. Figure 3.9), we have 8v 2 J aexp K⇢ : ⇢[X v] 2 D (D). Moreover, since ⇢ 2 dom(A) and by definition of B-ASSIGN T (cf. Algorithm 11), we must have 8v 2

for some z 2 J aexp K⇢, must be represented by an undefined leaf node f 2 F\{? F , > F } in t 2 T (cf. Equation 5.2.11 and Equation 5.2.9). Moreover, Algorithm 11 invokes B-ASSIGN F for every leaf node of a decision tree, which leaves undefined leaf nodes unaltered (cf. Equation 5.2.21), and a-join to handle possibly overlapping partitions (cf. Line 10 and Line 20), which favors undefined leaf nodes over defined leaf nodes (cf. Algorithm 6 and Equation 5.2.13). Thus, by definition of ⌧ Mt J l X := aexp K (cf. Equation 4.3.2) and in absence of run-time errors, we have ⇢ 2 dom(C), which is absurd. Therefore, we conclude that dom(C) ◆ dom(A).

Let us assume now, by absurd, that 9⇢ 2 dom(A) : C(⇢) > A(⇢). We have, by definition of

Proof of Lemma 5.2.24.

. We prove that dom(C) ◆ dom(A) and 8⇢ 2 dom(A) : C(⇢)  A(⇢) (cf. Equation 4.2.12).

The proof follows from Lemma 5.2.16, Lemma 5.2.17, and Lemma 5.2.19, and Lemma 5.2.20 and from the definition of O T (cf. Algorithm 13). In fact from Lemma 5.2.16, whenever some iterate y n under-approximates the value of the termination semantics or over-approximates its domain of definition (cf. Figure 5.10), it cannot be the limit of the iteration sequence with widening because it violates either \ Mt (y 5.2.24). Moreover, from Lemma 5.2.17, and Lemma 5.2.19, and Lemma 5.2.20 and from the definition of O T (cf. Algorithm 13), we know that further iterates resolve the issue. In fact, Algorithm 13 specifically invokes caseA and caseBorC to this end. Thus, this concludes the proof since the limit of the iteration sequence with widening must over-approximate the value of the termination semantics and under-approximate its domain of definition.

Proof of Lemma 6.3.1. Let D 2 D. We reason by cases. First, we consider the case of defined and undefined leaf nodes. Then, we consider the case of defined leaf nodes.

Let p 1 2 W \ {? W , > W } and let p 2 2 {? W , > W }. We have p 1 4 W [D]p 2 from Figure 6.2a. Moreover, from Equation 6.3.4, we have W [D]p 2 = ;. Thus, since dom( W [D]p 2 ) = ;, we have dom( W [D]p 1 ) ◆ dom( W [D]p 2 ) and, from Equation 4.2.12, we have

Proof of Lemma 6.4.1 (Sketch).

The proof for a skip instruction follows from Lemma 5.2.8 and the definition of the STEP W operator (cf. Equation 6.3.8). The proof for a variable assignment follows from Lemma 5.2.14 and the definition of the

Proof of Lemma 7.3.3.

. We prove that dom(C) ◆ dom(A) and 8⇢ 2 dom(A) : C(⇢)  A(⇢) (cf. Equation 4.2.12). Let us assume, by absurd, that dom(C) ⇢ dom(A). Then, there exists an environment ⇢ 2 E such that ⇢ 2 dom(A) and ⇢ 6 2 dom(C). Thus, since ⇢ 2 dom(A) and by definition of the step operator STEP T (cf. Algorithm 9) and the sum operator + T (cf. Algorithm 23), we must have ⇢ 2 dom( T [D]t) and ⇢ 2 dom( T [D]T ). In fact, Algorithm 23 invokes the leaves sum operator + F , which favors undefined leaf nodes over defined leaf nodes (cf. Equation 7.3.6 and Equation 7.3.7) and Algorithm 9 simply invokes STEP F for every leaf node of a decision tree, which leaves undefined leaf nodes unaltered (cf. Equation 5.2.19). Thus, by definition of ⌧ Mt J l call M K M (cf. Equation 7.3.1), we have ⇢ 2 dom(C), which is absurd. Therefore, we have dom(C) ◆ dom(A).

Let us assume now, by absurd, that 9⇢ 2 dom(A) : C(⇢) > A(⇢). We have, by definition of

Moreover, by definition of STEP T (cf. Algorithm 9) and + T (cf. Algorithm 23), we have ( T [D]t)(⇢) + ( T [D]T )(⇢) < A(⇢). In fact, Algorithm 23 invokes + F , which additions the value of the leaf nodes that are defined in both decision trees (cf. Equation 7.3.7), and Algorithm 9 invokes STEP F , which increases the value of the resulting defined leaf nodes (cf. Equation 5.2.19). Thus, C(⇢)  A(⇢), which is absurd. Therefore, 8⇢ 2 dom(A) : C(⇢)  A(⇢).

This concludes the proof. Proof of Lemma 7.3.4.

The soundness of I follows from the definition of (⌧ Mt J l call M K P (cf. Equation 7.3.2) and from Lemma 5.2.24.

Let

Let us assume, by absurd, that dom(C) ⇢ dom(A). Then, there exists an environment ⇢ 2 E such that ⇢ 2 dom(A) and ⇢ 6 2 dom(C). Thus, since ⇢ 2 dom(A) and by definition of STEP T (cf. Algorithm 9), we must have ⇢ 2 dom( T [D]t). In fact, Algorithm 9 simply invokes STEP F for every leaf node of a decision tree, which leaves undefined leaf nodes unaltered (cf. Equation 5.2.19). Thus, by definition of (⌧ Mt J l call M K P , we have ⇢ 2 dom(C), which is absurd. Therefore, we have dom(C) ◆ dom(A).

Let us assume now, by absurd, that 9⇢ 2 dom(A) : C(⇢) > A(⇢). We have, by definition of (⌧ Mt J l call M K P , C(⇢) = ( T [D]t)(⇢) + 1. Moreover, by definition of STEP T (cf. Algorithm 9), we have ( T [D]t)(⇢) < A(⇢). In fact, Algorithm 9 invokes STEP F , which increases the value of the defined leaf nodes of a decision tree (cf. Equation 5.2.19). Thus, C(⇢)  A(⇢), which is absurd. Therefore, we conclude that 8⇢ 2 dom(A) : C(⇢)  A(⇢).

This concludes the proof.

. We prove that dom(C) ◆ dom(A) and 8⇢ 2 dom(A) : C(⇢)  A(⇢) (cf. Equation 4.2.12).

Let us assume, by absurd, that dom(C) ⇢ dom(A). Then, there exists an environment ⇢ 2 E such that ⇢ 2 dom(A) and ⇢ 6 2 dom(C). Thus, since ⇢ 2 dom(A) and by definition of STEP T (cf. Algorithm 9), we must have ⇢ 2 dom( T [D]t). In fact, Algorithm 9 simply invokes STEP F for every leaf node of a decision tree, which leaves undefined leaf nodes unaltered (cf. Equation 5.2.19). Thus, by definition of ⌧ Mt J l return K (cf. Equation 7.3.3), we have ⇢ 2 dom(C), which is absurd. Therefore, we have dom(C) ◆ dom(A).

Let us assume now, by absurd, that 9⇢ 2 dom(A) : C(⇢) > A(⇢). We have, by definition of ⌧ Mt J l return K, C(⇢) = ( T [D]t)(⇢) + 1. Moreover, by definition of STEP T (cf. Algorithm 9), we have ( T [D]t)(⇢) < A(⇢). In fact, Algorithm 9 invokes STEP F , which increases the value of the defined leaf nodes of a decision tree (cf. Equation 5.2.19). Thus, C(⇢)  A(⇢), which is absurd. Therefore, we conclude that 8⇢ 2 dom(A) : C(⇢)  A(⇢).

This concludes the proof.