Automated verification of termination certificates - Inria - Institut national de recherche en sciences et technologies du numérique
Thèse Année : 2014

Automated verification of termination certificates

Vérification automatique de certificats de terminaison

Résumé

Making sure that a computer program behaves as expected, especially in critical applications (health, transport, energy, communications, etc.), is more and more important, all the more so since computer programs become more and more ubiquitous and essential to the functioning of modern societies. But how to check that a program behaves as expected, in particular when the range of its inputs is very large or potentially infinite? To express with exactness what is the expected behavior of a program, one first needs to use some formal logical language. However, as shown by Gödel, in any formal system rich enough for doing arithmetic, there are valid formulas that cannot be proved. Therefore, there is no program that can decide whether any property is true or not. However, we can have a program that decides whether any proof is correct or not, and the present work will use in an essential way such a program, namely Coq, to formally prove the correctness of some particular program. An important program property, especially in systems with strong time constraints, is termination: will the program always provide an answer? (Un)fortunately, as shown by Turing, termination is not decidable: there is no Turing-machine that, for any pair (p; i) made of a finite program description p and a finite input i for p, can tell in a finite amount of time whether p terminates on i or not. This led to the development of many different heuristics and tools (e.g. AProVE, TTT2, . . . ) for trying to prove the termination of programs. In particular, term rewriting theory, introduced by Knuth as a tool for deciding algebraic equational theories, provides a general framework for studying program termination with applications to concrete programming languages like Prolog, Haskell, Java, . . . This is the framework that we will consider in this work. But, in turn, how to guarantee that a program implementing such a heuristic is correct? One way to break this vicious circle relies on the fact that, for a given problem, checking that a solution is correct is usually easier than finding such a solution, because the latter involves some back-tracking mechanism while the former only requires blind computations. Hence, we can imagine the following scenario: modify the tool so that it does not only answer YES or NO, but also outputs some data, called certificate, that can be used to verify the correctness of the answer; and design these certificates in such a way that their verification is amenable to a complete formalization and correctness proof. Althought it seems to only move the problem from one program to another, the certificate verifier, there is in fact a gain in complexity. For instance, finding a boolean assignment satisfying some boolean formula (SAT problem) is (in the worst case) exponential in the number of boolean variables, while verifying the correctness of a given assignment (the certificate) is linear in the size of the formula. This is the approach that various automated provers for the termination of firstorder term rewrite systems started to adopt in 2007. A common formal language, CPF (Certification Problem Format), has then been designed for representing termination certificates, and certificate verifiers started to be developed: Rainbow, CiME3 and CeTA. In this work, we explain the development of a new, faster and formally proved version of Rainbow based on the extraction mechanism of Coq. The previous version of Rainbow verified a CPF file in two steps (see Figure 1.1). First, it used a non-certified OCaml program to translate a CPF file into a Coq script, using the Coq libraries on rewriting theory and termination CoLoR and Coccinelle. Second, it called Coq to check the correctness of the script. This approach is interesting for it provides a way to reuse in Coq termination proofs generated by external tools. This is also the approach followed by CiME3. However, it suffers from a number of deficiencies. First, because in Coq functions are interpreted, computation is much slower than with programs written in a standard programming language and compiled into binary code. Second, because the translation from CPF to Coq is not certified, it may contain errors and either lead to the rejection of valid certificates, or to the acceptance of wrong certificates. Moreover, the data type used for representing certificates internally and the parsing function used to create a value of this data type from a text file are written by hand. This is a possible source of errors and is time-consuming. To solve the latter problem, one needs to define and formally prove the correctness of a function checking whether a certificate is valid or not. To avoid the problem of parser, one can develop a simple compiler for generating a Coq data type definition for representing XML Schema data types, and an XML parser for CPF. To solve the former problem, one needs to compile this function to binary code. The present work shows how to solve these two problems by using the proof assistant Coq and its extraction mechanism to the programming language OCaml. Indeed, data structures and functions defined in Coq can be translated to OCaml and then compiled to binary code by using the OCaml compiler. A similar approach was first initiated in CeTA using the Isabelle proof assistant.
S’assurer qu’un programme informatique se comporte bien, surtout dans des applications critiques (santé, transport, énergie, communications, etc.) est de plus en plus important car les ordinateurs et programmes informatiques sont de plus en plus omniprésents, voire essentiel au bon fonctionnement de la société. Mais comment vérifier qu’un programme se comporte comme prévu, quand les informations qu’il prend en entrée sont de très grande taille, voire de taille non bornée a priori ? Pour exprimer avec exactitude ce qu’est le comportement d’un programme, il est d’abord nécessaire d’utiliser un langage logique formel. Cependant, comme l’a montré Gödel, dans tout système formel suffisamment riche pour faire de l’arithmétique, il y a des formules valides qui ne peuvent pas être prouvées. Donc il n’y a pas de programme qui puisse décider si toute propriété est vrai ou fausse. Cependant, il est possible d’écrire un programme qui peut vérifier la correction d’une preuve. Ce travail utilisera justement un tel programme, Coq, pour formellement vérifier la correction d’un certain programme. Une propriété importante, en particulier dans les systèmes informatiques avec des contraintes temporelles fortes, est la terminaison : le programme va-t-il me fournir une réponse ? Malheureusement, comme l’a montré Turing, la terminaison n’est pas décidable en général : il n’y a pas de machine de Turing qui, pour toute paire (p; i) où p est un programme et i une donnée pour p, puisse dire en un temps fini si p termine sur i ou non. Cela a conduit au développement de nombreuses heuristiques et d’outils les implémentant (e.g. AProVE, TTT2, . . . ) pour essayer de montrer la terminaison de programmes informatiques. En particulier, la théorie de la réécriture, introduite par Knuth comme un outil pour décider des théories algébriques, fournit un cadre général pour étudier la terminaison des programmes avec des applications à des langages de programmation concrets tels que Prolog, Haskell ou Java. C’est dans ce cadre théorique que nous avons conduit notre travail. Nous avons vu qu’il n’est pas possible d’avoir un programme qui puisse nous dire si tout programme est correct ou non. Alors, comment s’assurer que les outils de terminaison implémentant une certaine heuristique sont corrects ? Une manière de briser ce cercle vicieux repose sur le fait que, pour un problème donné, il est généralement plus facile de vérifier qu’une solution est correcte que de trouver une telle solution, car trouver une solution nécessite souvent d’en essayer plusieurs avant d’en trouver une qui marche (back-tracking), tandis que vérifier si une solution est correcte ne nécessite souvent que de faire un calcul. Ainsi, on peut imaginer le scénario suivant. Premièrement, modifier l’outil de façon à ce qu’il ne réponde pas seulement OUI ou NON, mais fournisse également un ensemble de données, que nous appellerons certificat, qui peut être utilisé pour vérifier la correction de la réponse. Deuxièmement, définir ces certificats de façon à ce que leur vérification peut être complètement formalisée et prouvée. C’est l’approche qu’ont prise plusieurs prouveurs automatiques de terminaison pour les systèmes de réécriture du premier ordre à partir de 2007. Un langage pour les certificats de terminaison, CPF, a ainsi été développé et des vérificateurs de certificats ont commencé à être développés : Rainbow, CiME3 et CeTA. Dans cette thèse, nous expliquons le développement d’une nouvelle version de Rainbow, plus rapide et plus sûre, basée sur le mécanisme d’extraction de Coq. La version précédente de Rainbow vérifiait un certificat en deux étapes. Premièrement, elle utilisait un programme OCaml non certifié pour traduire un fichier CPF en un script Coq, en utilisant les bibliothèques Coq sur la théorie de la réécriture et la terminaison CoLoR et Coccinelle. Deuxièmement, elle appelait Coq pour vérifier la correction du script ainsi généré. Cette approche est intéressante car elle fournit un moyen de réutiliser dans Coq des preuves de terminaison générées par des outils extérieurs à Coq. C’est également l’approche suivie par CiME3. Mais cette approche a aussi plusieurs désavantages. Premièrement, comme dans Coq les fonctions sont interprétées, les calculs sont beaucoup plus lents qu’avec un langage où les programmes sont compilés vers du code binaire exécutable. Deuxièmement, la traduction de CPF dans Coq peut être erronée et conduire au rejet de certificats valides ou à l’acceptation de certificats invalides. Pour résoudre ce deuxième problème, il est nécessaire de définir et prouver formellement la correction de la fonction vérifiant si un certificat est valide ou non. Et pour résoudre le premier problème, il est nécessaire de compiler cette fonction vers du code binaire exécutable. Cette thèse montre comment résoudre ces deux problèmes en utilisant l’assistant à la preuve Coq et son mécanisme d’extraction vers le langage de programmation OCaml. En effet, les structures de données et fonctions définies dans Coq peuvent être traduites dans OCaml et compilées en code binaire exécutable par le compilateur OCaml. Une approche similaire est suivie par CeTA en utilisant l’assistant à la preuve Isabelle et le langage Haskell.
Fichier principal
Vignette du fichier
main.pdf (875.08 Ko) Télécharger le fichier
Loading...

Dates et versions

tel-01097793 , version 1 (22-12-2014)
tel-01097793 , version 2 (03-07-2017)

Identifiants

  • HAL Id : tel-01097793 , version 1

Citer

Kim Quyen Ly. Automated verification of termination certificates. Logic in Computer Science [cs.LO]. Université Joseph Fourier, 2014. English. ⟨NNT : ⟩. ⟨tel-01097793v1⟩

Collections

INRIA2
529 Consultations
275 Téléchargements

Partager

More