Embeddings peu profonds ou profonds


47

Lorsque vous encodez une logique dans un assistant de preuve tel que Coq ou Isabelle, vous devez choisir entre utiliser une intégration peu profonde et une intégration profonde . Dans une imbrication peu profonde, les formules logiques sont écrites directement dans la logique du prouveur de théorèmes, alors que dans une imbrication profonde, les formules logiques sont représentées sous la forme d'un type de données.

  • Quels sont les avantages et les limites des différentes approches?
  • Existe-t-il des directives pour déterminer laquelle utiliser?
  • Est-il possible de basculer entre les deux représentations de manière systématique?

En guise de motivation, j'aimerais coder diverses logiques liées à la sécurité dans Coq et je me demande quels sont les avantages et les inconvénients des différentes approches.

Réponses:


28

Quels sont les avantages et les limites des différentes approches?

  • Avantages des imbrications profondes: Vous pouvez prouver et définir des choses par induction sur la structure des formules. Des exemples d'intérêts sont la taille d'une formule.

  • Inconvénients des imbrications profondes: Vous avez explicitement affaire à la liaison des variables. C'est généralement très laborieux.

Existe-t-il des directives pour déterminer laquelle utiliser?

Les imbrications superficielles sont très utiles pour importer des résultats prouvés dans la logique des objets. Par exemple, si vous avez prouvé quelque chose dans une petite logique (par exemple, une logique de séparation), des plongements peu profonds peuvent être un outil de choix pour importer votre résultat dans Coq.

D'un autre côté, l'intégration profonde est presque obligatoire lorsque vous voulez prouver des méta-théorèmes sur la logique de l'objet (comme l'élimination des coupures, par exemple).

Est-il possible de basculer entre les deux représentations de manière systématique?

L’idée derrière l’incorporation peu profonde est de travailler directement dans un modèle des formules d’objet. Habituellement, les gens mappent une formule d'objet P directement (en utilisant des notations ou en effectuant la traduction à la main) avec un habitant de Prop. Bien sûr, il existe des habitants de Prop qui ne peuvent pas être obtenus en incorporant une formule de la logique de l'objet. Par conséquent, vous perdez une sorte de complétude.

Il est donc possible d’envoyer chaque résultat obtenu dans un contexte d’enfoncement profond via une fonction d’interprétation.

Voici un petit exemple de coq:

Formule inductive: Set: =
    Ftrue: formule
  | Ffalse: formule
  | Fand: formule -> formule -> formule
  | Pour: formule -> formule -> formule.

Point fixe interpréter (F: formule): Prop: = match F avec 
    Vrai => Vrai
  | Ffalse => False
  | Fand ab => (interpréter a) / \ (interpréter b)
  | Pour ab => (interpréter a) \ / (interpréter b)
 fin.

Dérivation inductive: formule -> Prop: = 
    deep_axiom: dérivable vrai
  | deep_and: forall ab, dérivable a -> dérivable b -> dérivable (Fand ab)
  | deep_or1: forall ab, dérivable a -> dérivable (pour ab)
  | deep_or2: forall ab, dérivable b -> dérivable (pour ab).

Adaptable par induction: Prop -> Prop: = 
    shallow_axiom: sderivable True 
  | shallow_and: forall ab, sderivable a -> sdivable b -> sdivable (a / \ b)
  | shallow_or1: forall ab, sderivable a -> sderivable (a \ / b)
  | shallow_or2: forall ab, sderivable b -> sdivable (a \ / b).

(* Vous pouvez prouver le lemme suivant: *)
Lemma shallow_deep: 
   forall F, dérivable F -> désactivable (interpréter F).

(* Vous ne pouvez PAS prouver le lemme suivant: *)
Lemma t: 
   pour tout P, ​​on peut diviser P -> existe F, interpréter F = P.

22

En gros, avec une logique profondément intégrée, vous (1) définissez un type de données représentant la syntaxe de votre logique, (2) donnez un modèle de la syntaxe et (3) prouvez que les axiomes de votre syntaxe sont sains avec respect au modèle. Avec une incorporation peu profonde, vous sautez les étapes (1) et (2), commencez simplement par un modèle et prouvez les incohérences entre les formules. Cela signifie que les enfoncements peu profonds demandent généralement moins de travail, car ils représentent un travail que vous finirez généralement par faire avec une incrustation profonde.

Cependant, si vous avez une intégration profonde, il est généralement plus facile d’écrire des procédures de décision réfléchies, car vous travaillez avec des formules qui ont une syntaxe sur laquelle vous pouvez revenir. De plus, si votre modèle est étrange ou compliqué, vous ne souhaitez généralement pas travailler directement avec la sémantique. (Par exemple, si vous utilisez la biorthogonalité pour forcer la fermeture admissible ou les modèles de style Kripke pour forcer les propriétés du cadre dans les logiques de séparation, ou des jeux similaires.) , qui remplira votre cœur de rage, puisque c’est (a) trivial, et (b) une source ininterrompue de contrariété.

La bonne séquence à suivre est la suivante: (1) essayez de vous en servir avec une imbrication peu profonde. (2) Lorsque cela s'essouffle, essayez d'utiliser des tactiques et des devis pour exécuter les procédures de décision que vous souhaitez exécuter. (3) Si cela s'essouffle également, abandonnez et utilisez une syntaxe typée de manière dépendante pour votre intégration profonde.

  • Prévoyez de prendre quelques mois (3) s'il s'agit de votre première sortie. Vous aurez besoin de se familiariser avec la fantaisie fonctionnalités de votre assistant preuve rester sain d' esprit. (Mais c'est un investissement qui rapportera en général.)
  • Si votre assistant de preuve n'a pas de types dépendants, restez au niveau 2.
  • Si votre langage objet est lui-même dactylographié, restez au niveau 2.

Aussi, n'essayez pas de monter graduellement dans l'échelle. Lorsque vous décidez de gravir les échelons de la complexité, faites un pas complet à la fois. Si vous faites les choses petit à petit, vous obtiendrez un grand nombre de théorèmes étranges et inutilisables (par exemple, vous obtiendrez plusieurs syntaxes à moitié assondues et des théorèmes qui mélangent la syntaxe et la sémantique de façon étrange), ce que vous obtiendrez. finalement avoir à jeter.

EDIT: Voici un commentaire expliquant pourquoi il est si tentant de gravir progressivement les échelons et pourquoi cela conduit (en général) à la souffrance.

Concrètement, supposons que vous avez un peu profonde intégration de la logique de séparation, avec les conjonctions et unité . Ensuite, vous allez prouver des théorèmes du type et , etc. Maintenant, lorsque vous essayez réellement d’utiliser la logique pour prouver que le programme est correct, vous finirez par avoir quelque chose comme et vous voudrez en fait quelque chose comme .ABIABBA(AB)CA(BC)(IA)(BC)A(B(CI))

À ce stade, vous serez ennuyé de devoir réassocier manuellement des formules et vous penserez: "Je sais! Je vais interpréter un type de données de listes comme une liste de formules séparées. Ainsi, je peux interpréter comme concaténation de ces listes, puis les formules ci-dessus seront égales par définition! "

C'est vrai et ça marche! Cependant, notez que la conjonction est également ACUI, de même que la disjonction. Donc, vous allez suivre le même processus dans d'autres preuves, avec différents types de données de liste, puis vous aurez trois syntaxes pour différents fragments de la logique de séparation, et vous aurez des métathéorèmes pour chacun d'eux, qui seront inévitablement différents, et vous vous retrouverez à vouloir un métathéorème que vous avez prouvé pour séparer la conjonction de la disjonction, puis vous aurez envie de mélanger les syntaxes, puis vous deviendrez fou.

Il est préférable de cibler le plus gros fragment que vous pouvez manipuler avec un effort raisonnable, et de le faire.


Merci pour cette excellente réponse, Neel. J'aimerais pouvoir accepter deux réponses (j'ai décidé en fonction des votes des autres).
Dave Clarke

Aucun problème. Je viens de me rappeler quelque chose que je dois ajouter à cette réponse, à savoir pourquoi il est si tentant d’agir progressivement.
Neel Krishnaswami le

Traiter avec les propriétés ACUI est toujours une nuisance. Pourquoi Coq ne peut-il pas prendre une feuille du livre de Maude?
Dave Clarke le

14

Il est important de comprendre qu'il existe un spectre allant du plus profond au moins profond. Vous modélisez profondément les parties de votre langage qui devraient en quelque sorte participer à un argument inductif au sujet de sa construction, il est préférable de laisser le reste dans la vue superficielle de la sémantique directe du substrat de la logique.

Par exemple, lorsque vous voulez raisonner sur Hoare Logic, vous pouvez modéliser le langage d'expression de manière superficielle, mais le contour du langage assign-if-while doit être un type de données concret. Vous n'avez pas besoin d'entrer la structure de x + y ou a <b, mais vous devez travailler avec whileetc.

Dans les autres réponses, il y avait des allusions à des types dépendants. Cela rappelle le problème ancien de représenter les langues avec des classeurs de manière saine, de manière à ce qu'elles soient aussi superficielles que possible, tout en admettant certains arguments inductifs. Mon impression est que le jury est toujours en train de juger de toutes les approches et communications différentes qui ont émergé au cours des 10-20 dernières années sur ce sujet. Le "défi POPLmark" pour les différentes communautés d'assistants de preuve était également à ce sujet dans une certaine mesure.

Bizarrement, dans HOL classique sans types dépendants, l’approche HOL-Nominal de C. Urban fonctionnait assez bien pour la reliure superficielle, bien qu’elle ne tienne pas compte des changements culturels dans ces communautés de la formalisation du langage de programmation.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.