Conception Formelle en PVS Roland Atoui Xavier Dumas Sébastien Jardel Laurent Vendredi Chef de projet : Mr Pierre Castéran 1 Remerciements : Nous tenons à remercier particulièrement Monsieur César Munoz, le professeur P.Y. Gloess ainsi que le professeur Pierre Castéran pour leur aide précieuse et constructive tout au long de ce projet. Résumé La conception formelle de systèmes informatiques est une démarche relativement jeune dans le monde de la science. Plusieurs technologies ont été développées pour la modélisation de systèmes sûrs. Nous nous intéressons dans ce document à l'étude de l'une d'entre elles : La technologie PVS (Prototype Verication System). L'initiation à cet outil a pour objectif de regarder si les notions de développement de programmes prouvés et de ranement sont en adéquation avec PVS. Nous poursuivons cette étude par une évaluation de PBS permettant la transcritpion d'une machine abstraite B en théorie PVS. Enn, nous testons le prouveur de théorème de PVS en résolvant les obligations de preuves générées pour en apprécier son ecacité. Table des matières 1 Présentation de PVS 3 2 PBS : de B à PVS 5 1.1 2.1 2.2 Le langage PVS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.1 Un langage fortement typé . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.2 Trois types de langage . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction à la méthode B . . . 2.1.1 Survol du langage . . . . . 2.1.2 Les obligations de preuves L'outil PBS . . . . . . . . . . . . 2.2.1 Les machines PBS . . . . 2.2.2 Sémantique et validité des 2.2.3 Le ranement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . machines PBS . . . . . . . . . 3 Le Prouveur PVS 3.1 3.2 3.3 Introduction au prouveur PVS . . . . . 3.1.1 Rappel sur la déduction naturelle 3.1.2 Le prouveur . . . . . . . . . . . . Le déroulement d'une preuve . . . . . . 3.2.1 Exemples de preuves . . . . . . . Le prouveur : PVS versus Atelier B . . . 3.3.1 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 4 5 5 7 7 8 11 14 20 20 20 21 21 21 27 29 4 Conclusion 39 Bibliographie 41 A Installation 42 B Le langage PVS 43 A.1 PVS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 PBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.0.1 Les Mots Clés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.1 Le Prouveur PVS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 42 42 43 43 TABLE DES MATIÈRES 2 B.1.1 Commandes de haut et bas niveau . . . . . . . . . . . . . . . . . . . . . B.1.2 Les stratégies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C Exemples PBS C.1 Dispenser . . . . . . . . . . . . . . . . . . . . . . . . C.1.1 La Machine PVS : Dispenser . . . . . . . . . C.1.2 La Théorie PVS : Dispenser . . . . . . . . . . C.1.3 Preuves des TCCs de la théorie Dispenser . . C.2 Ens : spécication d'un tableau . . . . . . . . . . . . C.2.1 La Machine PVS de Ens1 . . . . . . . . . . . C.2.2 La Théorie PVS de Ens1 . . . . . . . . . . . . C.2.3 Preuves des TCCs de la théorie Ens1 . . . . . C.3 CtxMenu . . . . . . . . . . . . . . . . . . . . . . . . C.3.1 La Machine PBS de CtxMenu . . . . . . . . . C.3.2 La théorie PVS de CtxMenu . . . . . . . . . C.3.3 Preuves des TCCs de la théorie CtxMenu . . C.4 CtxDistributeur . . . . . . . . . . . . . . . . . . . . . C.4.1 La Machine PBS de CtxDistributeur . . . . . C.4.2 La théorie PVS de CtxDistributeur . . . . . . C.4.3 Preuves de la théorie PVS de CtxDistributeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 45 48 48 48 50 52 52 52 53 54 55 55 56 58 59 59 60 61 Chapitre 1 Présentation de PVS PVS est un système de vérication, développé par l'équipe méthode formelle du SRI Inter- national. Il a été présenté en 1992 par [OSRSC99a]. PVS est un langage de spécication intégré avec un prouveur de théorème. Dans ce chapitre, nous nous attachons à l'apprentissage de PVS. Nous regardons, dans un premier temps, la syntaxe du langage que fournit PVS. Nous essayons ensuite de comprendre comment fonctionne le système. Nous clôturons ce chapitre en nous intéressant au prouveur de PVS. 1.1 Le langage PVS PVS est un langage de spécication, il va donc générer des obligations de preuve, qui devront être prouvées par la suite. Trés utilisés dans la vérication, les langages de spécication permettent de valider un logiciel au niveau de la sécurité de code. PVS comme tout langage s'appuie sur des principes et sur des mots clés, dans les parties qui suivent, nous décrirons les grandes lignes du manuel de référence du langage [OSRSC99a]. (Cette description proposera également un parallèle avec la méthode B, ce qui permettra de mieux introduire le coeur du projet qui est la capacité de PVS à traduire les notions abordées dans le cours de B. ) 1.1.1 Un langage fortement typé PVS s'appuie sur la logique d'ordre supérieur (HOL : Higher Order Logic). La logique d'ordre supérieur est plus étendue que celle du premier ordre. Elle permet d'utiliser les variables dans les expressions en tant que fonctions et prédicats. PVS repose sur l'utilisation des types. Le type d'une variable peut être nat, int, etc... Il peut également être un type construit par l'utilisateur, ou déjà déni dans la librairie PVS, on peut par exemple construire une fonction puis la dénir comme type. Nous le verrons par la suite il existe un moyen de préciser si un type est vide ou non. La cohérence de chaque type doit être vérier, c'est le rôle que joue le typechecking de PVS. 3 CHAPITRE 1. PRÉSENTATION DE PVS 4 1.1.2 Trois types de langage Dans ce projet nous avons rencontré 3 types de langage : Le langage B de la méthode B Le langage PVS basé sur la logique d'ordre supérieur Le langage PBS qui décrit une machine B en PVS Le langage B est un un langage de spécication mettant en jeu une machine abstraite, plusieurs ranements (déterminisation, fonctions totales) pour ainsi arriver à une implantation et une implémentation en C ou ADA générée par l'atelier B. Le langage PVS est un autre langage de spécication logique utilisant de nombreuses notions mathématiques Le langage PBS est l'intermédiaire entre une machine B et la théorie PVS. Le chier PBS (machine PBS) est le chier d'entrée de l'outil PBS. Avec ce chier PBS que l'on implémente, l'outil PBS génère automatiquement une théorie PVS correspondante. Chapitre 2 PBS : de B à PVS Plusieurs méthodes, notations et outils destinés au développement de logiciels sûrs existent. Nous nous intéressons ici à l'élaboration d'un logiciel à l'aide d'une méthode formelle (B) imbriquée dans une logique d'un système de vérication (PVS). Le système nous permettant de réaliser ceci est PBS mis au point par César A. Muñoz. Ce chapitre est destiné à initier le lecteur à ce système. Nous introduisons en premier lieu la méthode B, avant de décrire les possibilités de PBS. Nous nissons en donnant les limitations et les perspectives d'évolution de ce logiciel. 2.1 Introduction à la méthode B B est une méthode formelle pour le développement logiciel qui a été mise au point par Jean Raymond Abrial dans les années 80. Elle fournit un langage uniforme (le langage B) qui est utilisé pour l'écriture d'une machine abstraite, pour spécier, concevoir et implémenter des systèmes. La méthode B se base sur la logique du premier ordre. Le but de ce document n'étant pas de faire un cours sur cette méthode, nous survolons rapidement son langage et sa méthodologie. Pour plus de détails à son sujet, nous vous renvoyons au cours de B de Christine Paulin [Pau01]. 2.1.1 Survol du langage La méthode B comporte trois étapes importantes : L'écriture d'une machine abstraite. L'écriture d'un ou plusieurs ranements. L'implantation. Chaque machine abstraite et chaque ranement doivent être contrôlés par la vérication de quelques propriétés appelées obligation de preuves. Elles doivent vérier que : Une instanciation pour les paramètres, les ensembles et les constantes satisfaisant les contraintes existe. 5 CHAPITRE 2. PBS : DE B À PVS 6 L'état initial satisfait l'invariant. [S0 ]I avec S0 l'état initial et I l'invariant. L'invariant est préservé par les opérations. I ⇒ [S]I avec S une substitution quelconque. La structure d'une machine abstraite Elle ressemble typiquement à celle de la gure 2.1. MACHINE nom SETS EN S1 ,...,EN S2 VARIABLES x1 ,...,x2 INVARIANT I INITIALIZATION S0 OPERATIONS ... END /* /* /* /* /* /* nom de la machine */ nom des ensembles */ nom des variables */ propriété */ substitution */ substitutions */ Fig. 2.1 Structure d'une Machine Abstraite Le ranement Le ranement est une technique utilisée au cours du processus de développement logiciel pour transformer un modèle abstrait en modèle plus concret. Comme pour les machines abstraites, le ranement doit vérier : l'invariant dans l'initialisation des variables dans les opérations dans les inclusions vérier la cohérence des invariants entre la machine abstraite et son ranement. L'implantation L'implantation est un cas particulier du ranement, c'est la dernière étape. Sa structure générale est représentée à la gure 2.2 IMPLEMENTATION nomI REFINES nom ... END /* nom de la machine d'implantation */ /* nom de la machine ranée */ Fig. 2.2 Structure d'une Machine d'implantation CHAPITRE 2. PBS : DE B À PVS 7 2.1.2 Les obligations de preuves C'est certainement la notion la plus délicate à aborder. Après l'écriture de chaque machine il est nécessaire de vérier les proriétés énoncées (cf section 2.1.1) : Selon les substitutions que l'on rencontre dans une machine, les formules peuvent changer. Le but n'étant pas d'être exhaustif sur ce point, nous montrons seulement l'allure d'une preuve devant vérier que l'invariant reste vrai après une substitution du type var1 ← nom_operation(var2 ) = P RE P T HEN S EN D I ⇒ ∀(var1 , var2 )P ⇒ [S]I Un cas plus délicat est celui des propriétés provenant d'un ranement. Il faut dans ce cas tenir compte des propriétés de la machine qu'elle rane. En reprenant l'exemple de la substitution de la forme P RE P1 T HEN S1 EN D On imagine un ranement où cette substitution devient P RE P2 T HEN S2 EN D alors la formule à verier devient Inv1 ∧ Inv2 ∧ P1 ⇒ (P2 ∧ [S2 ](¬[S1 ]¬Inv2 )) Avec Inv1 Inv2 les invariants respectifs de la machine abstraite et du ranement. 2.2 L'outil PBS PBS est un support pour la méthode B en PVS. PVS n'a pas de méthodologie particulière de construction de logiciel. L'article de César Muñoz [Muñ99] montre comment une machine abstraite B peut être supportée par PVS. PBS est implémenté en Ocaml, il utilise les lexers et les parser des librairies ocamllex et ocmlyacc fournies par le langage. PBS fonctionne comme un compilateur, il prend en entrée un chier m.pbs contenant une machine PBS et génère la théorie PVS associée comme le montre la gure 2.3 deep and shallow embedding (plongement en surface/profondeur) Il y a deux ap- proches pour l'enchassement d'un langage spécialisé d'une méthodologie vers un langage de spécication général supporté par un prouveur de théorème : Le plongement en profondeur (deep embedding). Le plongement en surface (shallow embedding). Muñoz préconise cette dernière. Ainsi, il ne traduit pas la machine abstraite en PVS, mais ajoute la notation de PBS comme une couche sur le langage de PVS. La contribution de ses travaux pointe vers deux directions. D'un coté, PVS est mis en valeur grâce à la méthodologie de B et de l'autre le langage B est enrichi d'un langage de spécication fortement typé et d'un prouveur de théorème puissant (PVS). CHAPITRE 2. PBS : DE B À PVS 8 Fig. 2.3 Fonctionnement de PBS 2.2.1 Les machines PBS Avant d'aller plus loin, il est important de dénir deux choses : Une machine PBS Une théorie PVS Une machine PBS est un chier dont l'extension est .pbs, c'est le chier d'entrée du système PBS comme le montre le gure 2.3. Une théorie PVS est le chier de sortie du système PBS et le chier d'entrée du système PVS. Notons que le passage d'une machine abstraite B à une machine PBS se fait manuellement. Par abus de langage, nous appelerons un chier PBS machine PBS. Les machines abstraites de B en PVS Le langage de spécication de PVS est basé sur la logique d'ordre supérieur (Higher-Order Logic : HOL) mise en valeur grâce à un système fortement typé. Le typage est tellement expressif que le typechecking est indécidable. Le typechecking génère des obligations de preuves que l'utilisateur doit résoudre. Cette tâche peut être eectuée en utilisant les diérentes procédures de décision et les outils de preuves automatiques fournis par le système. Nous rappelons que PVS est structuré en théories. Une théorie peut être paramétrée. Elle comporte des déclarations de constantes (tels que les types non-interprétés, variables, contantes abstraites), dénitions (tels que les types, les sous-types, fonctions, prédicats) et objets logiques (tels que les axiomes, théorèmes, conjectures). Une théorie PVS peut utiliser d'autres théories grâce à un mécanisme d'importation. PVS n'impose pas de style de spécications particulières, elles peuvent être axiomatiques, déclaratives et algorithmiques. On peut faire des machines PBS qui sont syntaxiquement similaires aux machines abstraites B modulo quelques spécications dues aux particularités de PVS. La diérence entre une machine CHAPITRE 2. PBS : DE B À PVS 9 abstraite B et une machine PBS et que cette dernière est basée sur la logique d'ordre supérieur et la théorie des types de PVS. Nous allons illustrer les diérences à travers un exemple concret. Prenons l'exemple du compteur de la machine abstraite B de la gure 2.4, son équivalent en PBS est représenté à la gure 2.5. MACHINE Counter(maxi) CONSTRAINTS maxi : NAT1 VARIABLES value INVARIANT value : NAT & value <= maxi INITIALISATION value := 0 OPERATIONS reset = BEGIN value := 0 END; next = PRE value < maxi THEN ANY val WHERE val : NAT & val <= maxi & val > value THEN value := val END END END Fig. 2.4 Machine Abstraite B Counter Les diérences Ces machines sont très proches syntaxiquement, on note toutefois les diérences suivantes : Les variables et les paramètres doivent être explicitement typés. CHAPITRE 2. PBS : DE B À PVS counter [maxi:posnat]: MACHINE BEGIN PVS `IMPORTING finite_sets@top' VARIABLES value : `nat' INVARIANT `value <= maxi' INITIALIZATION value := 0 OPERATIONS reset = value := 0 next = PRE `value < maxi' THEN ANY val : nat WHERE `val <= maxi AND val > value' THEN value := val ENDANY END END counter Fig. 2.5 Machine PBS Counter 10 CHAPITRE 2. PBS : DE B À PVS 11 Les expressions sont déclarées entre quotes. L'exemple de compteur etant minimaliste, il ne permet pas de mettre en valeur toutes les diérences qui existent, nous allons tout de même essayer de les enumérer. Les mots clés Certains mots clés sont remplacés par d'autres. Le mot clé SETS désignant la partie d'une machine abstraite où l'on déclare les ensembles est remplacé par TYPES dans une machine PVS. Certains mots clés du langage B ne sont tous simplement pas représentables, comme CONSTRAINTS, CONCRETE_VARIABLES, CONCRETE_CONSTANTS. Cela peut sembler gênant au premier abord, mais ne constitue pas de diculté particulière. En général, on peut simuler ces mots dans les machines PVS. Les limitations Il n'est pas possible d'exprimer les notions de SEES, USES, PROMOTES, EXTENDS. Une des dicultés principales vient du fait qu'en PVS, les fonctions sont totales. Néanmoins, il est possible de représenter des fonctions partielles en utilisant des sous-types et des types dépendants. Dans la théorie de type, les fonctions ne sont pas interprétées comme des relations binaires mais comme des objets calculables. 2.2.2 Sémantique et validité des machines PBS Une machine PBS est transcrite en théorie PVS, où les paramètres et les types de la machine deviennent paramètres et types de la théorie. L'état de la machine PBS est encodé de façon fonctionnel dans PVS. Les variables de la machine dénissent un enregistrement de type appelé type général, chaque champ correspond à une variable de la machine. Dans le langage PVS, le type général est écrit à l'aide de crochet et du symbole dièse [# ... #]. Si l'on reprend l'exemple du compteur, le système PBS génère la théorie PVS de la gure 2.6 . Le type général de la machine contient value qui est la seule variable de la machine. counter_Type : TYPE = [# value:nat #] L'invariant de la machine est exprimé dans la théorie PVS comme un sous-type du type général. La dépendance mutuelle entre les variables données par les contraintes sont générées par un mécanisme de type dépendant de PVS. counter : TYPE = { self: counter_Type | value(self) <= maxi AND value(self)>=0 } L'initialisation des champs du type général se fait entre (# et #) CHAPITRE 2. PBS : DE B À PVS %%% counter.pvs -- File generated by PBS %% Theory: Counter Machine counter [ maxi:posnat ]: THEORY BEGIN %% PVS Commands IMPORTING finite_sets@top %% General Type counter_Type : TYPE = [# value:nat #] %% Invariant Type counter : TYPE = { self: counter_Type | value(self) <= maxi AND value(self)>=0 } %% Initialization init : counter = LET self = (# value := 0 #) IN self %% Operations reset(self:counter) : counter = LET self = self WITH [ value := 0 ] IN self 12 CHAPITRE 2. PBS : DE B À PVS 13 next(self:counter | value(self) < maxi) : counter = LET self = LET val = choose! (val:nat) : ( val <= maxi AND val > value(self) ) IN LET self = self WITH [ value := val ] IN self IN self END counter Fig. 2.6 Théorie PVS Counter init : counter = LET self = (# value := 0 #) IN self Tandis que l'aectation d'une variable dans une opération (autrement dit une substitution) se fait avec la construction W IT H [ ... ] comme le montre l'exemple de compteur : reset(self:counter) : counter = LET self = self WITH [ value := 0 ] IN self Une opération de machine est traduite par une fonction en PVS. Cette fonction reçoit un paramètre supplémentaire avec l'enregistrement d'état satisfaisant l'invariant et la précondition. Les substitutions généralisées sont interprétées comme une expression PVS, mais PVS ne supporte pas les substitutions suivantes : WHILE P DO S INVARIANT I VARIANT V. La sémantique de cette substitution est celle des boucles en langages de programmation impérative. Le mécanisme de fonction récursive fourni par le langage est mieux adapté pour la notation des machines PBS. SELECT P THEN S. Si P est un prédicat et S est une substitution généralisée, la sémantique informelle est que S s'applique si P est vraie. Cette substitution n'est pas CHAPITRE 2. PBS : DE B À PVS 14 gérée par PVS car elle a besoin d'un contrôle explicite de l'exécution qui n'est pas fourni par PVS. La plupart du temps, elle peut être simulée par un mécanisme conditionnel de PVS. Obligations de preuves Les obligations de preuves sont également générées du fait de l'existence de paramètres, ensembles et constantes satisfaisant les contraintes. Une obligation de preuve en PVS est communément appelée Type Correctness Condition abrégée en TCC. Seules les TCCs générées par PVS sont à démontrer avec l'aide du prouveur interactif de PVS. Nous développerons ce sujet dans le chapitre suivant. Attardons nous plutôt sur le principe de ranement exploité par PBS pour générer des théories PVS. 2.2.3 Le ranement Comme dans le cas du ranement en B, le ranement de PVS hérite des paramètres, des propriétés constantes de la machine abstraite. En PVS, le ranement se fait par l'utilisation du mot clé IMPORTING. PVS se comporte comme un langage de programmation orienté objet. En eet on peut redénir et surcharger des fonctions, dénir un espace de nom, redénir des opérateurs. Ainsi le mécanisme d'importation peut être associé à la notion de réutilisabilité et modularité des langages de programmation : diviser pour mieux régner. Chaque théorie peut être considérée comme une classe que l'on peut raner en y ajoutant de nouvelles fonctionnalités, ou en l'incorporant dans une autre classe. On peut ainsi partir d'une théorie totalement abstraite pour arriver à une théorie complexe mettant en jeu diérentes théories. Le ranement entre la méthode B et PVS semble donc très similaire. Nous allons regarder en détail comment PBS met cela en ÷uvre. La diérence syntaxique principale réside dans le fait que le ranement de la machine PBS possède deux invariants : INVARIANT : contraint les variables locales du ranement avec les variables locales de la machine ranée. REFINE_INVARIANT : contraint les variables de la machine ranée avec les variables locales déclarées dans le ranement. La gure 2.7 représente le ranement du compteur en B. Sa transcription en machine PBS est représentée à la gure 2.8. Analysons la théorie PVS que génère PBS qui se trouve à la gure 2.9. Nous avons trouvé une diculté lors de l'implémentation du ranement counter. Nous en avons longuement discuté avec Monsieur Munoz ainsi que Monsieur Castéran. En eet, l'atelier B utilise une sémantique relationnelle alors que PVS utilise une sémantique fonctionnelle. Ainsi l'atelier B garde dans sa sémantique toutes les valeurs possibles alors que PVS en détermine CHAPITRE 2. PBS : DE B À PVS MACHINE counterRef(maxi) REFINES counter VARIABLES value INITIALISATION value := 0 OPERATIONS next = value := value + 1 END Fig. 2.7 Ranement B de Counter counterRef [maxi:posnat]: REFINEMENT OF counter BEGIN VARIABLES value_ref : `nat' REFINE_INVARIANT `value_ref <= value' INITIALIZATION value_ref := 0 OPERATIONS next = value_ref := `value_ref + 1' END counterRef Fig. 2.8 Ranement de la Machine PBS de Counter 15 CHAPITRE 2. PBS : DE B À PVS 16 une directement. Ainsi valuer ef = value n'est pas prouvable en PVS. Une des solutions serait d'utiliser la même sémantique relationnelle qu'en B dans la prochaine version de PBS. CHAPITRE 2. PBS : DE B À PVS %%% counterRef.pvs -- File generated by PBS %% Theory: CounterRef Refinement counterRef [ maxi:posnat ]: THEORY BEGIN %% Refinement Importing IMPORTING counter[maxi] %% General Type counterRef_Type : TYPE = [# value_ref:nat #] %% Invariant Type counterRef : TYPE = counterRef_Type %% Refinement Type counterRef_Ref_Type : TYPE = [# counterRef:counterRef, counter:counter #] counterRef_Ref : TYPE = { self_ref: counterRef_Ref_Type | value_ref(counterRef(self_ref)) <= value(counter(self_ref)) } %% Initialization init : counterRef = LET self = (# value_ref := 0 #) IN self init_ref : counterRef_Ref = (# counterRef := counterRef.init, counter := counter.init #) 17 CHAPITRE 2. PBS : DE B À PVS 18 %% Operations next(self:counterRef) : counterRef = LET self = self WITH [ value_ref := value_ref(self) + 1 ] IN self next_ref(self_ref:counterRef_Ref | value(counter(self_ref)) < maxi) : counterRef_Ref = (# counterRef := counterRef.next(counterRef(self_ref)), counter := counter.next(counter(self_ref)) #) END counterRef Fig. 2.9 Théorie PVS du ranement de Counter La structure reste similaire à celle de la théorie du compteur. On retouve la partie General Type, Invariant Type, Initialization, et Operations. Regardons les diérences notables. La théorie PVS de Counter est importée : IMPORTING counter[maxi] La machine PVS n'ayant pas d'invariant (INVARIANT), on s'aperçoit tout de même que PBS génère un invariant : counterRef : TYPE = counterRef_Type La partie Renement Type est plus délicate à comprendre : counterRef_Ref_Type : TYPE = [# counterRef:counterRef, counter:counter #] counterRef_Ref : TYPE = { self_ref: counterRef_Ref_Type | value_ref(counterRef(self_ref)) <= value(counter(self_ref)) } Elle comprend deux parties. La première est la déclaration d'un type counterRef_Ref_Type qui est un enregistrement de type contenant deux champs : Une variable counterRef appartenant à counterRef Une variable counter appartenant à counter CHAPITRE 2. PBS : DE B À PVS 19 C'est cet enregistrement de type qui permet de faire le collage entre les variables des deux théories. La seconde partie est plus classique, elle déclare un ensemble de variables de type counterRef_Ref_Type respectant la propriété de l'invariant du ranement. counterRef_Ref est donc un sous-type de counterRef_Ref_Type. Il est ensuite initialisé : init_ref : counterRef_Ref = (# counterRef := counterRef.init, counter := counter.init #) De la même manière, l'opération next_ref met à jour l'opération next et son ranement à jour. C'est ce qui apparaît dans les deux champs, mais au préalable il faut que la valeur de value de counter qui est une variable de self_ref soit inférieure à maxi. next_ref(self_ref:counterRef_Ref | value(counter(self_ref)) < maxi) : counterRef_Ref = (# counterRef := counterRef.next(counterRef(self_ref)), counter := counter.next(counter(self_ref)) #) Conclusion PBS à toute les capacités pour introduire de manière clair les machines abstraites B et leur ranement en PVS. Certaines traduction reste toutefois délicates, et une bonne connaissance de PVS est nécessaire. Une évolution possible pour ce logiciel serait de se rapprocher un peu plus de certaines notions de B, car la transcription d'une machine abstraite B à une machine PVS conduit parfois à une perte de certaines restrictions dénies en B. Chapitre 3 Le Prouveur PVS Nous avons vu précédemment que PBS générait une théorie PVS. Nous nous intéressons donc dans cette partie à la résolution des obligations de preuves engendrées par PVS de ces chiers. Le but est d'évaluer la puissance du prouveur PVS et le comparer ainsi à celui de l'Atelier B. Enn nous discutons sur l'utilité d'un outil tel que PBS à l'aide de nos résultats. 3.1 Introduction au prouveur PVS Le premier chapitre montre comment utiliser le prouveur de PVS. Nous entrons dans les détails grâce à des exemples dans cette partie, mais avant cela il est impératif de faire un rappel sur la déduction naturelle. 3.1.1 Rappel sur la déduction naturelle La déduction naturelle est un formalisme pour décrire des preuves de calcul de prédicats proposée par Gentzen en 1935 pour eectuer des preuves intuitionnistes : c'est à dire dont le raisonnement se rapproche au maximum du raisonnement mathématique. Mais cette approche était assez dicile pour produire une preuve syntaxique en arithmétique. Ceci a conduit Gentzer à développer un formalisme plus adapté et symétrique : le calcul des séquents. Une suite de formules à gauche séparés par le symbole ` et une suite de formules à droite : A1 , A2 , ..., An ` B1 , B2 , ..., Bn Les Ai sont des formules appelées hypothèses ou antécédents et les Bi sont les formules appelées conclusions ou conséquents. Chaque formule peut apparaître plusieurs fois dans chaque ensemble. Les virgules à gauche du séquent peuvent être remplacées par des conjonctions et les virgules à droite par des disjonctions. Le symbole ` peut s'interprêter comme une implication dont le symbole est ⇒. A1 ∧ A2 ∧ ... ∧ An ⇒ B1 ∨ B2 ∨ ... ∨ Bn 20 CHAPITRE 3. LE PROUVEUR PVS 21 On peut traduire ce séquent par : En supposant que toutes les hypothèses soient vraies alors au moins une des conclusions est vraie. Il existe plusieurs règles principales pour la manipulation des séquents et leur simplication. Ces règles sont présentées dans le guide de référence du prouveur de PVS [SORSC99]. Les séquents procurent une grande lisibilité et des opérations de simplication assez ecaces. 3.1.2 Le prouveur Voici comment sont décrits les séquents dans le prouveur de PVS. Les antécédents sont numérotés par des entiers négatifs et les conséquents par des entiers positifs. On remarque que ces numéros sont entourés par des crochets [ ] ou des accolades { }. Ces deux notations ont une signication. En eet, [ ] signient que la règle appliquée au but courant n'a modié en rien le séquent et les accolades indiquent qu'il y a eu au contraire un changement dans la formule ou alors qu'un nouveau but plus simple a été créé. Pour démontrer un théorème, il y a trois possibilités : Soit de se ramener à la trivialité TRUE à droite du séquent, soit à FALSE à gauche du séquent Soit arriver au même terme à droite et à gauche du séquent. Dans ces trois cas, le théorème est démontré. Sinon on peut arriver à un contre exemple ou alors on ne peut tous simplement pas prouver le théorème correspondant. Le prouveur PVS se constitue ainsi par un arbre de preuves contenant lui-même des feuilles et sous-feuilles chacunes représentant une formule à prouver. Le séquent est prouvé si toutes les feuilles de l'arbre ont été démontrées. Le prouveur PVS contrairement à d'autres langages de spécications ayant un prouveur intégré, met en avant la facilité d'utilisation en ligne de commande du buer Emacs et la lisibilité e la construction de preuves tout au long de la démonstration plutôt que l'ecacité de l'exécution. En eet la philosophie de PVS est basée sur le 80 - 20. 3.2 Le déroulement d'une preuve Nous exploitons dans cette section quelques exemples que nous avons vu en cours de B. 3.2.1 Exemples de preuves On peut eectuer tous les types de preuves en PVS très facilement avec les puissantes commandes associées. Il existe principalement deux types de preuves : les preuves par induction les preuves itératives CHAPITRE 3. LE PROUVEUR PVS 22 En eet, les preuves par inductions sont très simples à mettre en oeuvre car il existe une commande très puissante pour ces démonstrations. Les preuves par prédicat sont très faciles à démontrer et en général on essaye de se ramener au même terme de part et d'autre du séquent dans ce genre de démonstration. On peut biensûr eectuer les preuves de nombreuses manières. Soit en utilisant les commandes de bas niveau pour avoir un contrôle total sur le déroulement de la démonstration ou bien des stratégies et règles très évoluées résolvant automatiquement certaines preuves. Nous allons voir quelques exemples dont le premier est une démonstration très simple sur les prédicats et le deuxième une preuve sur une théorie dénissant un compteur. Eectuons les preuves de la théorie suivante : propositions: theory begin A, B , C : bool prop: theorem (A ⊃ (B ⊃ C )) ∧ (A ⊃ B ) ∧ A ⊃ C end propositions On a déclaré 3 booléens A, B, C et on veut prouver le THEOREM. On commence par vérier s'il y a des erreurs de syntaxes (M − xparse). Il n'y en a aucunes. On continue par vérier la sémantique (Mx typecheck) ; aucune obligation de preuve n'est générée. On se positionne sur la ligne contenant le THEOREM et on exécute (Mx prove). On obtient : prop : |------{1} (A IMPLIES (B IMPLIES C)) AND (A IMPLIES B) AND A IMPLIES C On exécute la commande (f latten) pour simplier les conjonctions et disjonctions selon les règles de séquent. Ce qui nous donne : Trois hypothèses sont apparues (valeurs négatives entre accolades). La commande a enlevé les conjonctions AND et a placé les diérentes parties de la proposition en antécédent, car dans un séquent, les conjonctions de tous les antécédents doivent satisfaire les disjonctions des conséquents. On a donc une forme équivalente au séquent initial. CHAPITRE 3. LE PROUVEUR PVS 23 prop : {-1} (A IMPLIES (B IMPLIES C)) {-2} (A IMPLIES B) {-3} A |------{1} C Maintenant on peut essayer de simplier en utilisant la commande (split) qui va découper l'antécédent -1 en 3 buts : prop.1 : {-1} C [-2] (A IMPLIES B) [-3] A |------[1] C On va commencer par C. C satisfait bien C donc la prop.1 est vériée. On va maitenant vérier B qui correspond au deuxième sous-goal d'où vérier : prop.2 : [-1] (A IMPLIES B) [-2] A |------{1} B [2] C On peut encore découper l'antécédent [-1] par (split) Cela nous donne : B satisfait bien B. Il reste le A à satisfaire pour le deuxième sous-goal de la proposition 2 : CHAPITRE 3. LE PROUVEUR PVS 24 {-1} B [-2] A |------[1] B [2] C prop.2.2 : [-1] A |------{1} A [2] B [3] C On voit bien que A satisfait A donc on n'a rien à faire. La proposition 2 est alors vériée. Il nous reste le sous-goal 3 concernant le A du de la proposition de départ à satisfaire : prop.3 : [-1] (A IMPLIES B) [-2] A |------{1} A [2] C which is trivially true. This completes the proof of prop.3. Q.E.D. Ce qui est aussi vérié auomatiquement puisque c'est trivial. Le THEOREM est donc vérié. Nous allons commencer par dénir en pvs la théorie counter équivalente de la machine counter que nous avions développée avec l'atelier B : un compteur qui incrémente la variable "value" de 1 à chaque opération "next". Cette machine prenait en paramètre un entier positif : "maxi" qui était la valeur maximale que le compteur pouvait atteindre. Si la valeur de "value" est supérieur à "maxi" nous réinitialisons le compteur à 0. On veut aussi que le paramètre fournit en argument de la théorie soit un entier CHAPITRE 3. LE PROUVEUR PVS 25 naturel supérieur à 0 ; donc on ajoute un invariant dans la clause ASSUMPTION qui assure que "maxi" est toujours supérieur à 0. Maintenant nous devons ajouter un invariant sur la variable "value". C'est à dire dans la clause "THEOREM" et vérier que les préconditions et postconditions "value< maxi" sont toujours respectées. D'où la dénition de "Theocounter". Ce simple programme ne contient qu'un seul "THEOREM". le fait est que PVS nous permet de dénir ce même programme de plusieurs façon : En ajoutant des THEOREM, LEMMA En utilisant le typage de PVS La première méthode réduit le nombre d'obligations générées et augmente la lisibilité de la théorie. Mais l'utilisateur devra quand même prouver ces théorèmes. De plus les preuves mettant en jeu l'induction ne seront pas simpliées. La deuxième méthode consiste à créer des types complexes dans lesquels on exprime directement les contraintes et théorèmes que l'on veut vérier. L'avantage de cette méthode est que toutes les obligations de preuves sont générées dans les TCCs dans lesquels certaines inductions ont déjà été simpliées. Une méthode alternative aux deux précédentes lorsque les théorèmes deviennnent illisibles est d'utiliserle mot clé JUDGEMENT dans lequel on va introduire les théorèmes à vérier comme dans la méthode un tout en gardant l'avantage de la méthode deux. En eet JUDGEMENT se comporte comme s'il faisait partie d'un typage. £ ¤ counter maxi: nat : theory begin assuming inv: assumption 0 < maxi endassuming value: var nat next(value): nat = (if value < maxi then value + 1 else 0 endif) Theocounter: theorem (value < maxi ⇒ next(value) ≤ maxi) end counter CHAPITRE 3. LE PROUVEUR PVS 26 Nous vérions maintenant que ce programme est syntaxiquement correct par la commande (Mx pa) ou (Mx parse). La vérication ne génère pas d'erreur ; nous pouvons passer au "typechecking" : c'est à dire vérier si la sémantique est correcte (bonne dénition des types, sous-types, sous-types prédicats, dépendances des types) Ici, la théorie est relativement simple et aucun TCC (typecheck condition ou obligation de preuve lié au typecheck) n'est généré. On peut nalement essayer de prouver le "THEOREM". On place le curseur devant "Theocounter" et on exécute la commande (Mx pr) ou (Mx prove). On obtient le prompt suivant : Theocounter : |------{1} FORALL (value: nat): (value < maxi => next(value) <= maxi) Nous allons essayer de prouver 1. Pour simplier 1 on remarque le quanticateur FORALL que l'on peut réduire par la commande (skolem!) . En eet le FORALL va être remplacé par une constante de la forme x !1 ce qui nous donne : Rule? (skolem!) Skolemizing, this simplifies to: Theocounter : |------{1} (value!1 < maxi => next(value!1) <= maxi) Le FORALL a disparu et laisse place à la constante value !1. Maintenant on remarque l'implication qui peut être réécrite ; en eet, cela veut dire que 1 ⇔ value!1 < maxi| − − − − − − − − − −next(value!1) <= maxi) On a la commande (atten) qui eectue cette simplication : CHAPITRE 3. LE PROUVEUR PVS 27 Rule? (flatten) Applying disjunctive simplification to flatten sequent, this simplifies to: Theocounter : {-1} value!1 < maxi |------{1} next(value!1) <= maxi On se retrouve avec un antécédent -1 et un conséquent 1 On peut remarquer que l'on retrouve dans 1 la fonction "next" Pour pouvoir lire sa dénition et retrouver une partie de l'antécédent -1, on va déplier la fonction avec la commande (expand "next") : Rule? (expand "next") Expanding the definition of next, this simplifies to: Theocounter : [-1] value!1 < maxi |------{1} (IF value!1 < maxi THEN 1 + value!1 ELSE 0 ENDIF) <= maxi On a donc l'antécédent que l'on retrouve dans le conséquent. Maintenant il ne reste que des propositions logiques. Il existe une commande qui permet de nir la preuve gràce à ces propositions logiques et des procédures de décisions sur l'arithmétique, les égalités et inégalités. On va donc utliser une stratégie qui correspond à la commande (ground) qui applique elle-même la commande (prop) pour les propositions logiques (IF THEN etc ...) Rule? (ground) Applying propositional simplification and decision procedures, Q.E.D. La preuve est réussie ; nous avons terminé la preuve du THEOREM donc cette théorie est vériée et conrme la spécication exacte. 3.3 Le prouveur : PVS versus Atelier B Tout d'abord la méthode B utilise une interface graphique pour construire les machines, ranement, implémentation et les preuves. PVS utilise l'éditeur emacs. Les preuves en PVS sont plus lisibles que celles générées par l'Atelier B car seule l'information intéressante pour l'utilisateur est achée ; tout le reste est caché. De plus les CHAPITRE 3. LE PROUVEUR PVS 28 simplications sont très souples et automatisées, les expansions ne sont pas automatiques comme avec l'Atelier B. Enn on peut cacher, eacer des hypothèses, les réacher pour améliorer la lisibilité. Avec l'atelier B, le prouveur sur les prédicats utilise la logique de premier ordre basée sur la logique de Hoare alors que PVS utilise la logique d'ordre supérieur qui utilise la règle des séquents et une logique basée sur la déduction naturelle. Le prouveur PVS permet de créer une stratégie pouvant résoudre des obligations de preuves basées sur la logique de hoare. Le nombre de commande du prouveur PVS est réduit En B il existe énormément de commandes pour eectuer les preuves. PVS lui n'en possède nalement qu'assez peu. Il existe en B un prouveur automatique de forces diérentes : 0, 1 ou 2. Plus la force augmente, et plus les preuves sont poussées et plus le temps utilisé est long. Ainsi une la terminaison n'est pas assurée. En PVS il n'y a pas de prouveur automatique mais il existe des commandes très puissantes comme GRIND ou INDUCT-AND-SIMPLIFY qui peuvent prendre des arguments et preuvent à elles seules démontrer une grande partie des obligations de preuves. Le typechecking en B eectue la vérication de syntaxe mais en PVS c'est le parser qui eectue cette tache. Même si le typechecking fait appel au parser, sa fonction principale est de vérier la sémantique et le bon typage des théories. Or, dû au typage fort du langage PVS et la dénition de types poussées grâce au logique d'ordre supérieure, le typechecking en PVS est parfois indécidable ce qui ajoute des preuves supplémentaires à démontrer dans les TCCs. Le B qui n'utilise que la logique du premier ordre est un langage très faiblement typé ; le typechecking est donc totalement automatique et ne génère aucune obligation de preuves. Lors du typechecking en PVS, on retrouve toutes les obligations de preuves de B générées par le prouveur. En PVS elles sont regroupées en TCC dans la forme non expansée alors qu'on les retrouve sous forme de PO expansée en B. Un point important est qu'en B les preuves peuvent boucler et donc ne jamais terminer. En PVS les preuves ne bouclent pas car l'utilisateur à beaucoup plus de contrôle sur le déroulement et la construction de la démonstration. Dans les stratégies en eet la dernière commande est la commande (FAIL) ou (SKIP) décidant si les commandes précédentes ont échoué de quitter la preuve ou de ne rien faire. Les commandes et règles sont eectuées de manières atomiques. Si une commande échoue en PVS le prouveur nous ramène dans un état précédent stable en indiquant l'échec de la commande ou alors il ne fait rien en indicant que rien n'a changé par la dernière commande. PVS permet une plus grande souplesse pour eectuer les preuves de plusieurs manières diérentes. Il y a une notion de ranement dans les preuves pour essayer de simplier au maximum les commandes utilisées et ainsi aboutir à une preuve généralisée que l'on pourra transformer en stratégie. PVS nous donne plus d'information sur le déroulement des preuves et une arbre de preuves peut être généré et enregistré dans un chier ps. Les preuves en B sont très diciles à prouver alors qu'en PVS une bonne maîtrise des obligations de preuves permet de les résoudre très facilement. (cf : théorème de fermat). CHAPITRE 3. LE PROUVEUR PVS 29 B permet d'écrire des axiomes considérées comme justes mais qui ne sont pas prouvées par l'atelier B alors que PVS oblige la démonstration de tous les théorèmes et accroît ainsi la abilité des théories. PVS fournit des commandes de très bas niveau pour contrôler totalement le déroulement de la preuve de la manière la plus mathématique possible. PVS, une assez bonne expérience dans les preuves permet de résoudre pratiquement tous les théorèmes. En PVS, le fait d'utiliser les commandes de bas niveau augmente la abilité et l'absence de bug dans les théories. Le nombre de preuves en PVS est doublé ou triplé par rapport aux PO en B. Le ranement en B utilises des règles plus strictes qu'en PVS qui nalement peut être réduite à la clause IMPORTS et les techniques de programmation objet. 3.3.1 Exemple Illustrons ces remarques par un exemple : Comparons les obligations de preuves en B et en PVS en prenant la théorie compteur comme référence mais cette fois-ci générée par l'outil PBS (cf gure 2.5) : Lors du typechecking de la machine abstraite de la gure 2.4 en B, nous pouvons lire sur le terminal la sortie suivante : L'atelier B eectue le typechecking de la machine B de manière totalement automatisée (typechecking décidable contrairement à PVS). En eet elle commence par charger la machine, vérier le nom de la machine et la validité des diérentes clauses ainsi que les opérations. Elle enregistre enn les données collectées de la machine. A la n du typechecking, si aucune erreur n'est détectée, l'atelier B génère automatiquement les obligations de preuves. On observe que l'atelier B a procédé en deux étapes : La génération de preuves liées à l'initialisation ; c'est à dire vérier que l'invariant est respectée à l'initialisation. Ensuite l'atelier B génère les obligations de preuves associées aux opérations de la machine Counter ; c'est à dire que l'invariant est respectée avant et après chaque opération. On peut remarquer que l'atelier B automatise certaines preuves comme en PVS. En eet, l'initialisation étant très simple pour cette machine, les 4 obligations de preuves générées sont automatiquement démontrées. De même pour l'opération reset qui ressemble à une initialisation, les 5 obligations de preuves sont prouvées automatiquement. Enn pour l'opération next, l'atelier B a généré 5 obligations de preuves tout comme pour l'opération reset. Cette fois-ci, les 5 obligations de preuves ont aussi été démontrées de manières triviales. CHAPITRE 3. LE PROUVEUR PVS Type Checking machine Counter Loading referenced machines Checking names clashes Checking CONSTRAINTS clause Checking SEES clause Checking SETS clause Checking PROPERTIES clause Checking ABSTRACT_CONSTANTS clause Checking VARIABLES clause Checking CONCRETE_VARIABLES clause Checking INCLUDES clause Checking USES clause Checking EXTENDS clause Checking promotions Checking INVARIANT clause Checking gluing invariant Checking ASSERTIONS clause Checking INITIALISATION clause Checking operation reset Checking operation next Normalizing Counter Saving data of component Counter End of Type checking 30 CHAPITRE 3. LE PROUVEUR PVS Generating proof obligations of Machine Counter Initialisation : .... proof obligations: 0 obvious proof obligations: 4 reset : ..... proof obligations: 0 obvious proof obligations: 5 next : ..... proof obligations: 0 obvious proof obligations: 5 0 proof obligations generated 14 obvious proof obligations generated Generation complete 31 CHAPITRE 3. LE PROUVEUR PVS 32 Nous avons nalement obtenu 14 obligations de preuves générées automatiquement par l'atelier B et toutes prouvées automatiquement par le prouveur en force 0. Dans la théorie PVS, on ne peut plus utiliser les théorèmes pour les obligations de preuves car on part d'une machine PVS qui ne permet pas d'introduire cette notion. Toutes les obligations de preuves se retrouvent donc dans les TCCs. Après le typechecking en pvs, le prouveur a généré 4 TCCs. Si on regarde en détails ces TCCs, on remarque que l'on obtient une obligation de preuve pour l'initialisation, une obligation de preuve pour l'opération reset et deux obligations de preuves pour l'opération next. Si on exécute la commande Mx pr les deux premières obligations de preuves sont démontrées automatiquement ; il nous reste deux preuves à éectuer pour l'opération next. Regardons les obligations de preuves générées par l'atelier B. Rappellons les règles de correction d'une machine abstraite : correction de l'instanciation lors de l'inclusion de machines correction des assertions les initialisations doivent respecter l'invariant les opérations doivent respecter l'invariant Dans la machine B, toutes les 14 obligations de preuves étant prouvées automatiquement, ces obligations de preuves sont cachées par l'atelier B. Regardons ce que nous donne PVS : Les 4 obligations de preuves de l'atelier B pour l'initialisation sont regroupées dans un seul TCC. Avec PVS 4.0 l'obligation de preuve liée à l'initialisation nous demande de vérier l'invariant correspondant au type de la variable. PVS 3.2 ne demande pas cette vérication et nous simplie donc la tâche. Nous utiliserons PVS 3.2 qui est plus stable que PVS 4.0. Les TCCs sont données dans le format lisp agrémenté de code PVS. Le premier TCC nous demande de prouver que "value<=maxi". l'atelier B lui nous demande de prouver que value est un entier et qu'il est inférieur ou égal à maxi. Le deuxième TCC concerne l'opération reset et nous demande de vérier que quelque soit la valeur du compteur, elle est inférieure ou égale à maxi et que lorsque l'on appelle reset sa valeur devient nulle. Pour cela PVS génère un quanticateur universel FORALL qui parcourt toutes les valeurs possibles du compteur et cherche à vérier si la variable respecte bien les invariants dans tous ses états. CHAPITRE 3. LE PROUVEUR PVS 33 % Subtype TCC generated (at line 25, column 4) for % LET self = (# value := 0 #) IN self % expected type counter % unchecked init_TCC1: OBLIGATION (LET self = (# value := 0 #) IN self)`value <= maxi; % Subtype TCC generated (at line 34, column 4) for % LET self = self WITH [value := 0] IN self % expected type counter % unchecked reset_TCC1: OBLIGATION FORALL (self: counter): (LET self = self WITH [value := 0] IN self)`value <= maxi; Alors que l'atelier B a généré 5 obligations de preuves pour vérier si l'opération reset vérie toujours l'invariant, PVS grâce au quanticateur a réduit les obligations de preuves à un seul TCC. Les troisième et quatrième TCCs concernent l'opération next. Elles vérient que le compteur est bien aecté à une variable dans tous ses états et qu'elles vérient l'invariant. L'atelier B a généré 5 obligations de preuves pour ces mêmes démonstrations. Encore une fois le fait PVS permette de décrire les obligations de preuves comme du code PVS permet d'avoir des obligations de preuves compactes et moins nombreuses à l'aide notamment des quanticateurs qui vérient le bon environnement de chaque état. Ainsi PVS a réduit énormément le nombre d'obligations de preuves générées ; de 14 on est passé à 4. En revanche PVS nous demande plus de preuves manuelles, même si pour ces TCCs un (GRIND) sut. Comme nous l'avons dit précédemment PVS est basé surtout sur la lisibilité et l'ecacité de la construction de preuves et non sur l'ecacité de leur exécution. Pour la machine abstraite PVS génère les mêmes obligations de preuves que l'atelier B de manière plus lisible et plus concis. Dans les deux cas les preuves sont démontrées trivialement. Comparons maintenant le ranement counter : Nous recommençons les mêmes opérations que précédemment. PVS nous indique que 4 TCCs ont été générées et un subsumed ce qui veut dire qu'un des TCCs a pu être regroupé avec un autre. Finalement nous obtenons 3 TCCs dont un est démontré automatiquement CHAPITRE 3. LE PROUVEUR PVS % Subtype TCC generated for % LAMBDA (val: nat): (val <= maxi AND val > value(self)) % expected type p: (nonempty?[nat]) % unchecked next_TCC1: OBLIGATION FORALL (self: counter | self`value < maxi): nonempty?[nat](LAMBDA (val: nat): (val <= maxi AND val > self`value)); % Subtype TCC generated (at line 42, column 4) for % LET self = % LET val = % choose! (val: nat): (val <= maxi AND val > value(self)) % IN LET self = self WITH [value := val] IN self % IN self % expected type counter % unchecked next_TCC2: OBLIGATION FORALL (self: counter | self`value < maxi): (LET self = LET val = choose! (val: nat): (val <= maxi AND val > self`value) IN LET self = self WITH [value := val] IN self IN self)`value <= maxi; REFINEMENT CounterRef(maxi) REFINES Counter VARIABLES value INITIALISATION value := 0 OPERATIONS next = value := value + 1 END 34 CHAPITRE 3. LE PROUVEUR PVS 35 Generating proof obligations of Refinement CounterRef Initialisation : .. proof obligations: 0 obvious proof obligations: 2 next : ....... proof obligations: 4 obvious proof obligations: 3 reset : ... proof obligations: 0 obvious proof obligations: 3 4 proof obligations generated 8 obvious proof obligations generated Generation complete Normalizing... No previous proof method interactive file No previous PO file Merging... Done Proving CounterRef Proof pass 0, still 4 unproved PO clause next ++++ End of Proof Initialisation next reset TOTAL for CounterRef Proved Proved Proved Proved 0 4 0 4 Unproved Unproved Unproved Unproved 0 0 0 0 CHAPITRE 3. LE PROUVEUR PVS 36 Avec l'atelier B nous obtenons 12 Obligations de preuves dont 8 démontrées automatiquement. Il reste 4 obligations de preuves liées à l'opération next à démontrer. Comme on peut le constater une preuve automatique avec la force 0 sut pour tout démontrer. Comme on peut le voir la lecture des preuves de l'atelier B est moins agréable à lire que celles de PVS. On est amené à eectuer un "dd" pour isoler le but et rendre plus lisible les obligations de preuves. Les preuves en B utilisent les Hypothèses pour pouvoir prouver les PO. Chaque nouvelle hypothèse est ajoutée dans la liste et ainsi de suite on déduit et on simplie les preuves jusqu'à sa correction. CHAPITRE 3. LE PROUVEUR PVS 37 Hypothèses "`Component constraints'" & maxi: INTEGER & 0<=maxi & maxi<=2147483647 & not(maxi = 0) & maxi<=999 & maxi+1<=1000 & btrue & 1<=maxi & "`Previous components invariants'" & value$1: INTEGER & 0<=value$1 & value$1<=2147483647 & value$1<=maxi & "`Component invariant'" & value = value$1 & "`next preconditions in previous components'" & 1+value$1<=maxi & CounterRef.next.4 Les 4 obligations de preuves de l'atelier B permettent de vérier que l'opération "next" vérie bien l'invariant : Vérier que lorsque value est incrémenté, value reste toujours un entier inférieur ou égal à maxi. PRI > go(next.1) "`next preconditions in this component'" & value$1+1<=maxi & "`Check operation refinement - ref 4.4, 5.5'" & => value$1+1: INTEGER CHAPITRE 3. LE PROUVEUR PVS 38 Vérier value+1 est >= 0 PRI > go(next.2) "`next preconditions in this component'" & value$1+1<=maxi & "`Check operation refinement - ref 4.4, 5.5'" & => 0<=value$1+1 Vérier value+1 est <= 2147483647 PRI > go(next.3) "`next preconditions in this component'" & value$1+1<=maxi & "`Check operation refinement - ref 4.4, 5.5'" & => value$1+1<=2147483647 Vérier que value < value+1 PRI > go(next.4) "`next preconditions in this component'" & value$1+1<=maxi & "`Check operation refinement - ref 4.4, 5.5'" & => value<=value$1 PVS étant fortement typé, il n'a pas besoin de vérier 1, 2 et 3 qui est déchargé automatiquement. Par contre il vérie que dans la machine counter l'opération next vérie l'invariant et que l'opération du ranement satisfasse aussi l'invariant. 2 TCCs susent pour cela. Nous remarquons donc que PVS génère toutes les obligations générées par B mais demande plus de contrôle sur la démonstration des obligations de preuves car les TCCs sont décrites par du code PVS et non basées comme en B sur les substitutions, les prédicats et la théorie des ensembles. Chapitre 4 Conclusion PVS est un langage de spécication très performant tant au niveau de la description des théories utilisant la logique d'ordre superieur qu'au niveau des preuves. Il possède les mêmes qualités qu'un langage de programmation orienté objet avec en plus la possibilité de dénir des règles et théorèmes faisant de la théorie un modèle prouvé mathématiquement. La puissance du typage est un des grands atouts de ce langage de spécication qui ore ainsi de nombreuses possibilités et expressions de besoins dicilement exprimables en B. Au niveau des preuves, la lisibilité et la simplicité des commandes donnent beaucoup d'aisance dans la fabrication de preuves et la démonstration mathématique ardus. On arrive ainsi à généraliser les théories grâce à la générécité (TYPE, TYPE+) ainsi que les preuves avec la dénition de nouvelles stratégies. L'utilisation que nous avons fait de PBS montre quelques facettes de cet outil, mais ne reète en rien toutes ses possibilités. L'élaboration d'une machine plus complexe devient vite dicile lorsque l'on n'a pas une idée assez précise du code de la théorie qui doit être générée. Il en ressort donc qu'il faut une bonne maîtrise du langage PVS. Cela dit, PBS permet d'exprimer facilement des machines abstraites B simple en théories PVS. Le ranement est également très bien géré par PBS. Son intérêt étant de prouver les obligations de preuves de B plus facilement en utilisant la puissance de PVS. Cette double modélisation cahier des charges vers B ; B vers PBS et PBS vers PVS augmente les risques de mauvaises interprétations et à terme des spécications non conformes. Toutefois cette double modélisation demande plus d'eort pour l'utilisateur et une erreur dans le chier PVS généré peut venir soit de la spécication PBS, soit de la machine B auquel cas il faut tout recommencer. PBS essaye ainsi de pallier aux défaillances de la méthode B (des outils développés pour la méthode B) c'est à dire au niveau des preuves mais aussi fusionne les qualités de ces deux langages de spécications. Finalement, PVS est très bien adapté pour la conception de systèmes sûrs. Sans posséder un lexique aussi large que celui de B, PVS donne la possibilité d'interpréter quasiment toutes les notions de la méthode B. Cela donne à PVS un caractère plus souple, avec plus de contrôle, de puissance et de abilité, mais moins que Coq. Une amélioration de PVS serait la possibilité de générer un code exécutable pour arriver à une implémentation nale mais aussi implémenter et 39 CHAPITRE 4. CONCLUSION mettre en place la composition de machines. 40 Bibliographie [Muñ99] C. Muñoz. PBS : Support for the B-method in PVS. Technical Report SRI-CSL99-01, SRI International, February 1999. [OS93] Sam Owre and Natarajan Shankar. Abstract datatypes in PVS. Technical Report SRI-CSL-93-9R, Computer Science Laboratory, SRI International, Menlo Park, CA, December 1993. Extensively revised June 1997 ; Also available as NASA Contractor Report CR-97-206264. [OS97] Sam Owre and Natarajan Shankar. The formal semantics of PVS. Technical Report SRI-CSL-97-2, Computer Science Laboratory, SRI International, Menlo Park, CA, August 1997. [OSRSC99a] S. Owre, N. Shankar, J. M. Rushby, and D. W. J. Stringer-Calvert. PVS Language Reference. Computer Science Laboratory, SRI International, Menlo Park, CA, September 1999. [OSRSC99b] S. Owre, N. Shankar, J. M. Rushby, and D. W. J. Stringer-Calvert. PVS System Guide. Computer Science Laboratory, SRI International, Menlo Park, CA, September 1999. [Pau01] Christine Paulin. Introduction à la méthode b. Technical Report 1, Laboratoire de Recherche en Informatique, Université Paris-Sud, 2001. http ://www.lri.fr/ paulin/B/. [SORSC99] N. Shankar, S. Owre, J. M. Rushby, and D. W. J. Stringer-Calvert. PVS Prover Guide. Computer Science Laboratory, SRI International, Menlo Park, CA, September 1999. 41 Annexe A Installation A.1 PVS 1. Dans le .bashrc rajouter : export CMULISP_HOME=/usr 2. Créer un répertoire et y mettre l'archive (car lorsqu'il extrait, il ne créé pas directement de répertoire) 3. Ouvrir le chier BDD/ix86-Linux/Makele puis enlever -lbsd 4. Télécharger le patch à http ://www.cs.ru.nl/ tews/pvs-4-0-patch-makele-quote 5. Renommer le patch pvs-4-0-patch-makele-quote.patch 6. Exécuter la commande : patch -p 1 < pvs-4-0-patch-makefile-quote.patch 7. Il vous demande quel chier entrer : Makele.in 8. Puis ./congure 9. et make N'oubliez pas qu'il faut un interpréteur lisp (si vous avez emacs c'est bon). A.2 PBS Assurez vous simplement que Ocaml est installé, puis refaire l'étape 2 de l'installation de PVS et lire le README après extraction de l'archive. 42 Annexe B Le langage PVS B.0.1 Les Mots Clés Dans cette section nous ne détaillons bien evidemment pas tous les mots clés. BEGIN et END sont les deux mots clés qui marquent le début de la théorie PVS. BEGIN se placera juste aprés la ligne de déclaration de la théorie, c'est à dire le nom de la théorie et la liste des paramètres. IMPORTING est un mot clé associé soit à une librairie soit à une autre théorie. L'utilisateur pourra alors utiliser des fonctions, des types déclarés dans la librairie ou la théorie TYPE, TYPE+ permettent la généricité en PVS, la variable devant laquelle ils sont placés pourra être de n'importe quel type (nat, list..). La diérence entre ces deux types est que TYPE+ est forcément non vide ce qui n'est pas le cas pour TYPE. ASSUMING permet de contraindre les variables devant lesquelles il est placé. LEMMA, THEOREM,CONJECTURE sont les mots clés qui vont introduire les obligations de preuve. Ce sont les principaux, mais il en existe d'autre. Les obligations introduites par LEMMA permettent en général de prouver les obligations introduites par THEOREM. Pour CONJECTURE, elle peuvent soit être prouvées et elles deviennent alors THEOREM, soit démontrées fausses elles sont donc rejetées, soit on ne peut les prouver elles restent CONJECTURE. MACRO. Il permet de simplier et de rendre plus lisible le code. RECURSIVE permet d'introduire la récursivité en PVS. B.1 Le Prouveur PVS Nous introduisons dans cette section les principaux axes du guide d'utilisation du Prouveur de PVS [SORSC99]. Nous commencerons par décrire quelques commandes et leur utilité, puis nous donnerons un aperçu du genre de stratégie que nous propose PVS pour la résolution de preuves. 43 ANNEXE B. LE LANGAGE PVS 44 B.1.1 Commandes de haut et bas niveau Il existe peu de commandes en PVS, mais elles sont paramétrables, ce qui donne une grande liberté d'action à l'utilisateur. On peut séparer ces commandes en trois types : Les commandes simples (bas niveau). Les règles. Les stratégies. Les commandes simples permettent à l'utilisateur d'eectuer des preuves avec un très grand contrôle ou à passer des paramètres complexes. Les règles sont des suites de commandes de bas niveau qui sont exécutées de manières atomiques. Ces commandes portent en général sur des numéros de formules (abbrégé par fnums dans la documentation PVS) qui sont soit un entier positif (un but) ou négatif (une hypothèse), (+) > (tous les buts), (-) > (toutes les hypothèses), ou (*) > (tous les buts ou toutes les hypothèses). Dans les commandes on pourra aussi trouver term et constant qui désignent respectivement un terme (une expression du séquent courant, entre guillemets) ou une constante libre (une constante n'apparaissant pas dans le séquent courant). Il existe un certain nombre de commandes très utiles et très puissantes. Les quatre principales commandes à connaître sont : grind : permet d'essayer de prouver le but automatiquement (C'est la procédure de décision/simplication de PVS). quit : permet de quitter la preuve courante. undo : permet de revenir en arrière. On peut préciser en argument le nombre de pas qu'on veut eectuer en arrière. use "hypo" : ajouter le lemme "hypo" aux hypothèses. Les commandes suivantes sont les plus utilisées car elle peuvent simplier les buts à chaque étape : atten : permet de simplier les disjonctions et conjonctions. Une hypothèse de type A∧B est remplacée par deux hypothèses : A, B . Une conclusion de type A ∨ B est remplacée par deux conclusions A, B . Une conclusion A ⇒ B place A dans l'hypothèse et B dans la conclusion. split permet de remplacer un but en plusieurs buts. Une hypothèse A ∨ B est remplacée par deux sous buts : A dans les antécédents et B dans les conséquents. Une conclusion A ∧ B est remplacée par deux sous buts : A d'un côté et B de l'autre. Une hypothèse A ⇒ B est remplacée par l'hypothèse B dans un but et la conclusion A dans l'autre but. skolem ! permet de remplacer des variables de quanticateurs par des constantes internes générées automatiquement par le prouveur. La conclusion F ORALL est remplacée par une constante interne. L'hypothèse EXIST S est aussi remplacée par une constante interne. ANNEXE B. LE LANGAGE PVS 45 inst ? permet de trouver une correspondance entre les variables des hypothèses et celles des conclusions pour ainsi aboutir au même terme en instanciant certaines variables. Ces deux dernières commandes font référence aux commandes skolem et inst qui elles, prennent des arguments obligatoires en paramètre. expand est une commande très utile lorsque l'on veut déplier une fonction. Elle admet des arguments en paramètre.Par exemple pour déplier la dénition du prédicat antisymétrique ? expand antisymetrique ? . case "X=0" permet d'eectuer des analyses cas par cas de manière exhaustive. Dans cet exemple un but sera remplacé par l'hypothèse X = O et dans l'autre but (générée automatiquement) X! = 0. Il existe enn des commandes de très haut niveau admettant elles aussi des paramètres : grind présenté plus haut et induct-and-simplify qui sont les commandes les plus puissantes du prouveur permettant de démontrer un très grand nombre de buts. induct-and-simplify résoud automatiquement les preuves par inductions, récurrences. En général on commence toujours par utiliser la commande grind ou induct-and-simplify et ensuite on essaye de simplier les hypothèses et conclusions avec les diérentes règles atten, split, skolem !, expand. On utilise ainsi les stratégies au début, les règles et enn les commandes de bas niveau. B.1.2 Les stratégies Bien sûr les commandes et règles présentées ci-dessus ne sont qu'une partie de la puissance du prouveur PVS. La grande puissance du prouveur réside dans la dénition de stratégies choisies par l'utilisateur lui-même. On va décrire d'une façon explicite ce qu'est une stratégie. Les expressions de stratégies Toute stratégie peut être écrite comme une preuve, mais la syntaxe des expressions de stratégie est la suivante : { } {(step) := (primitive-rule)} | {(defined-rule)} | {(defined-strategy)} | (quote{(step)}) | (try{(step) (step) (step)}) | (if{(lisp-expression) (step) (step)}) | (let ({({(symbol) (lisp-expression)})}+) {(step)}) ANNEXE B. LE LANGAGE PVS 46 La dénition d'une stratégie Les stratégies dénies par l'utilisateur doivent être sauvegardées dans un chier qu'on appelle pvs-stratégies.PVS va charger les stratégies contenues dans ces chiers à la fois dans le répertoire de l'utilisateur et dans le répertoire du contexte courant. La dénition de stratégie à la forme suivante : (defstep {name} (required-parameters \&optional optional-parameters \&rest {parameter) strategy-expression documentation-string format-string) Ceci va générer une règle (blackbox) et une stratégie (glassbox). Les diérences entre une règle dénie et une stratégie sont : 1. La dénition d'une règle comme une règle primitive par exemple, est atomique, alors qu'une stratégie peut être dépliée comme une application de plusieurs règles atomiques. 2. La forme dépliée d'une stratégie est sauvegardée pour être réexécutée, alors qu'une règle est réexécutée sous sa forme initiale (non dépliée). 3. Une règle dénie renvoie simplement les nouveaux buts non prouvés tandis que la stratégie renvoie l'arbre de preuve déplié. Autrement, les règles dénies et les stratégies se ressemblent beaucoup. Les deux méthodes peuvent être récursives et peuvent impliquer l'application d'un certain nombre d'étapes de preuves, de primitives. les stratégies de base quote textitLa stratégie d'identité syntax : (quote step) eet : L'expression de stratégie (quote step ) s'évalue à step elle-même. La raison pour laquelle elle est utilisée est qu'elle est tout à fait typique pour construire une expression en lisp correspondante à une stratégie, mais celle-ci à besoin d'être unquoted par la suite pour être employées comme une stratégie. try : La stratégie de sous-but (subgoaling) et de marche en arrière (backtracking) syntax : (try step1 step2 step3) eet : C'est la base du contrôle de stratégie. Elle va appliquer step1 au but courant. Si step1 génère des sous-buts, alors step2 sera appliquée sur ces sous-buts.Dans le cas où step1 ne génère aucun sous-buts step3 sera appliquée au but courant. exemples : 1. (try (atten) (propax) (split) ) :Cette stratégie va appliquer une disjonction sur le but courant. Si le but est simplié par la disjonction, alors (propax) sera appliquée au but résultant sinon ce sera la conjonction (split) qui sera appliquée au but courant. ANNEXE B. LE LANGAGE PVS 47 2. (try (try (atten) (fail) (skolem 1 (a b))) (postpone) (prop)) :Si le but courant est simplié par disjonction , alors backtrack est appliquée puis prop, sinon on applique skolem puis simplication propositionnelle (postpone) ou prop dans le cas où skolem n'a pas réussi. On remarque que (fail) est utilisée pour eectuer une marche en arrière à partir d'un sous-but. if syntax : (if condition step1 step2) eet : Comme en Lisp si conditon est évaluée à NIL c'est step2 qui est appliquée sinon c'est step1. exemples : (if (equal (get-goalnum *ps*) 1) (groud) (prop)) : Si le but courant (*ps* est l'état de la preuve courante) est le premier sous-but, alors (ground) est appliquée, sinon (prop) est appliquée. let : Utilisation de Lisp dans les stratégies syntax : (let ((var_1 lexpr_1) ... (var_n lexpr_n)) step) eet : var sont des symboles, et lexpr sont des expressions en Lisp. Let permet de calculer quelques valeurs et de les appliquer aux stratégies. Elle est similaire à let* dans le langage lisp. exemple : (let ((input (qread 'Rule ?'))) (try input (query*) (query*))) : C'est un stratégie simple appellée query (question). La dénition en Lisp de qread est utilisée pour générer les règles Rule ? qui lit l'entrée de l'utilisateur. Annexe C Exemples PBS Dans ce chapitre nous présentons quelques exemples de théories générées par l'outil PBS et les preuves des chiers PVS ainsi obtenues. Toutes les théories ont été prouvées entièrement. C.1 Dispenser C.1.1 La Machine PVS : Dispenser % Dispenser Machine dispenser [ lifetime:nat ] : MACHINE BEGIN TYPES DSTATE = `{stocked, unstocked}' CONSTANTS ok : nat = 0 notok : nat = 1 VARIABLES dstate : DSTATE given : nat INVARIANT `given <= lifetime' INITIALIZATION dstate := unstocked || given := 0 48 ANNEXE C. EXEMPLES PBS OPERATIONS restock = dstate := stocked give_drink = PRE `dstate = stocked AND given < lifetime' THEN dstate :: DSTATE || given := `given + 1' END is_stocked : nat = `IF dstate = stocked THEN ok ELSE notok ENDIF' count : nat = given END dispenser Fig. C.1 Machine PVS dispenser 49 ANNEXE C. EXEMPLES PBS C.1.2 La Théorie PVS : Dispenser %%% dispenser.pvs -- File generated by PBS %% Theory: Dispenser Machine dispenser [ lifetime:nat ]: THEORY BEGIN %% Type Definitions DSTATE : TYPE = {stocked, unstocked} %% Constant Definitions ok: nat = 0 notok: nat = 1 %% General Type dispenser_Type : TYPE = [# dstate:DSTATE, given:nat #] %% Invariant Type dispenser : TYPE = { self: dispenser_Type | given(self) <= lifetime } %% Initialization init : dispenser = LET self = (# dstate := unstocked, given := 0 #) IN self 50 ANNEXE C. EXEMPLES PBS %% Operations Restock(self:dispenser) : dispenser = LET self = self WITH [ dstate := stocked ] IN self give_drink(self:dispenser | dstate(self) = stocked AND given(self) < lifetime) : dispenser = LET self = self WITH [ dstate := choose! (dstate:DSTATE) : ( TRUE ), given := given(self) + 1 ] IN self is_stocked(self:dispenser) : nat = IF dstate(self) = stocked THEN ok ELSE notok ENDIF count(self:dispenser) : nat = given(self) END dispenser Fig. C.2 Théorie PVS dispenser 51 ANNEXE C. EXEMPLES PBS 52 C.1.3 Preuves des TCCs de la théorie Dispenser Les TCCs engendrées par PVS sont déchargées automatiquement par la commande Mx tcp C.2 Ens : spécication d'un tableau C.2.1 La Machine PVS de Ens1 Ens1[maxe : `posnat'] : MACHINE BEGIN PVS `IMPORTING finite_sets@top' VARIABLES ens : `setof[nat]' INVARIANT `card(ens)<=maxe' INITIALIZATION ens := `emptyset[nat]' OPERATIONS ajout(n : nat) = PRE `NOT ens(n) AND card(ens)<maxe' THEN ens := `add(n,ens)' END END Ens1 Fig. C.3 Machine PVS Ens1 ANNEXE C. EXEMPLES PBS C.2.2 La Théorie PVS de Ens1 %%% Examples/myExamples/Ens1.pvs -- File generated by PBS %% Theory: Ens1 Machine Ens1 [ maxe:posnat ]: THEORY BEGIN %% PVS Commands IMPORTING finite_sets@top %% General Type Ens1_Type : TYPE = [# ens:setof[nat] #] %% Invariant Type Ens1 : TYPE = { self: Ens1_Type | card(ens(self))<=maxe } %% Initialization init : Ens1 = LET self = (# ens := emptyset[nat] #) IN self 53 ANNEXE C. EXEMPLES PBS %% Operations ajout(self:Ens1)(n:nat | NOT ens(self)(n) AND card(ens(self))<maxe) : Ens1 = LET self = self WITH [ ens := add((n::nat),ens(self)) ] IN self END Ens1 Fig. C.4 Théorie PVS Ens1 C.2.3 Preuves des TCCs de la théorie Ens1 Proof init_TCC1-1 for formula Ens1.init_TCC1 developed with SHOSTAK decision procedures ("" (SUBTYPE-TCC) (GRIND :THEORIES "finite_sets[nat]")) Proof ajout_TCC1-1 for formula Ens1.ajout_TCC1 developed with SHOSTAK decision procedures ("" (SUBTYPE-TCC) (GRIND :THEORIES "finite_sets[nat]")) Fig. C.5 Preuves TCCs Ens1 54 ANNEXE C. EXEMPLES PBS CtxMenu : MACHINE BEGIN PVS `IMPORTING CtxDistributeur, finite_sets@top' CONSTANTS nb_boissons nb_pieces : nat2boisson nat2piece : : nat = `card(BOISSONSET)' nat = `card(PIECESET)' : `[subrange(1,nb_boissons) -> BOISSON]' `[subrange(1,nb_pieces) -> PIECE]' END CtxMenu Fig. C.6 Théorie de la machine PBS CtxMenu C.3 CtxMenu C.3.1 La Machine PBS de CtxMenu (voir Fig.B.8) 55 ANNEXE C. EXEMPLES PBS C.3.2 La théorie PVS de CtxMenu (voir Fig.B.9) 56 ANNEXE C. EXEMPLES PBS %%% CtxMenu.pvs -- File generated by PBS %% Theory: CtxMenu Machine CtxMenu : THEORY BEGIN %% PVS Commands IMPORTING CtxDistributeur, finite_sets@top %% Constant Definitions nb_boissons: nat = card(BOISSONSET) nb_pieces: nat = card(PIECESET) nat2boisson: [subrange(1,nb_boissons) -> BOISSON] nat2piece: [subrange(1,nb_pieces) -> PIECE] %% General Type CtxMenu_Type : TYPE = [# dummy: nat #] %% Invariant Type CtxMenu : TYPE = CtxMenu_Type END CtxMenu Fig. C.7 Théorie PVS de CtxMenu 57 ANNEXE C. EXEMPLES PBS Proof n for formula CtxMenu.nat2boisson_TCC1 developed with SHOSTAK decision procedures ("" (INST * "(lambda (x:subrange(1, nb_boissons)): coca)") (SKOLEM!) (EXPAND "BOISSON?") (PROPAX)) Proof nat2piece_TCC1-1 for formula CtxMenu.nat2piece_TCC1 developed with SHOSTAK decision procedures ("" (EXISTENCE-TCC) (INST * "(lambda (i:subrange(1, nb_pieces)):p1)")) Fig. C.8 Preuves des TCCs la Théorie CtxMenu C.3.3 Preuves des TCCs de la théorie CtxMenu (voir Fig.B.10) 58 ANNEXE C. EXEMPLES PBS CtxDistributeur : MACHINE BEGIN PVS `IMPORTING finite_sets@top' TYPES BOISSON = {coca, pepsi, orangina, perrier} PIECE = {p1, p2, p5} CONSTANTS BOISSONSET : `finite_set[BOISSON]=fullset[BOISSON]' PIECESET : `finite_set[PIECE]=fullset[PIECE]' tarif : `[BOISSON -> nat]' val_piece : `[PIECE -> nat]' OPERATIONS afficher_boisson(bb : BOISSON) = SKIP afficher_piece(pp : PIECE) = SKIP END CtxDistributeur Fig. C.9 Machine PVS de CtxDistributeur C.4 CtxDistributeur C.4.1 La Machine PBS de CtxDistributeur (voir Fig.B.11) 59 ANNEXE C. EXEMPLES PBS CtxDistributeur : MACHINE BEGIN PVS `IMPORTING finite_sets@top' TYPES BOISSON = {coca, pepsi, orangina, perrier} PIECE = {p1, p2, p5} CONSTANTS BOISSONSET : `finite_set[BOISSON]=fullset[BOISSON]' PIECESET : `finite_set[PIECE]=fullset[PIECE]' tarif : `[BOISSON -> nat]' val_piece : `[PIECE -> nat]' OPERATIONS afficher_boisson(bb : BOISSON) = SKIP afficher_piece(pp : PIECE) = SKIP END CtxDistributeur Fig. C.10 La théorie PVS de CtxDistributeur C.4.2 La théorie PVS de CtxDistributeur (voir Fig.B.12) 60 ANNEXE C. EXEMPLES PBS Proof BOISSONSET_TCC1-1 for formula CtxDistributeur.BOISSONSET_TCC1 developed with SHOSTAK decision procedures ("" (EXPAND "fullset") (EXPAND "is_finite") (INST 1 "5" "LAMBDA(x:BOISSON): if x = coca then 0 elsif x = pepsi then 1 elsif x = orangina then 3 else 4 endif") (GRIND)) Proof PIECESET_TCC1-1 for formula CtxDistributeur.PIECESET_TCC1 developed with SHOSTAK decision procedures ("" (EXPAND "fullset") (EXPAND "is_finite") (INST 1 "5" "LAMBDA(x:PIECE): if x = p1 then 0 elsif x = p2 then 1 elsif x = p5 then 3 else 4 endif") (GRIND)) Fig. C.11 Preuves des Tccs de la théorie PVS de CtxDistributeur C.4.3 Preuves de la théorie PVS de CtxDistributeur (voir Fig.B.13) 61 Table des gures 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 Structure d'une Machine Abstraite . . . . . Structure d'une Machine d'implantation . . Fonctionnement de PBS . . . . . . . . . . . Machine Abstraite B Counter . . . . . . . . Machine PBS Counter . . . . . . . . . . . . Théorie PVS Counter . . . . . . . . . . . . Ranement B de Counter . . . . . . . . . . Ranement de la Machine PBS de Counter Théorie PVS du ranement de Counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 8 9 10 13 15 15 18 C.1 Machine PVS dispenser . . . . . . . . . . . . . . . . . C.2 Théorie PVS dispenser . . . . . . . . . . . . . . . . . . C.3 Machine PVS Ens1 . . . . . . . . . . . . . . . . . . . . C.4 Théorie PVS Ens1 . . . . . . . . . . . . . . . . . . . . C.5 Preuves TCCs Ens1 . . . . . . . . . . . . . . . . . . . C.6 Théorie de la machine PBS CtxMenu . . . . . . . . . . C.7 Théorie PVS de CtxMenu . . . . . . . . . . . . . . . . C.8 Preuves des TCCs la Théorie CtxMenu . . . . . . . . . C.9 Machine PVS de CtxDistributeur . . . . . . . . . . . . C.10 La théorie PVS de CtxDistributeur . . . . . . . . . . . C.11 Preuves des Tccs de la théorie PVS de CtxDistributeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 51 52 54 54 55 57 58 59 60 61 62 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .