Comment gérer les tableaux pendant les épreuves de correction de style Hoare

11

Dans la discussion autour de cette question , Gilles mentionne correctement que toute preuve d'exactitude d'un algorithme qui utilise des tableaux doit prouver qu'il n'y a pas d'accès de tableau hors limites; selon le modèle d'exécution, cela entraînerait une erreur d'exécution ou l'accès à des éléments non-tableau.

Une technique courante pour effectuer de telles preuves d'exactitude (au moins dans les études de premier cycle et probablement dans la vérification automatisée) consiste à utiliser la logique Hoare . Je ne suis pas au courant que l'ensemble de règles standard contient quoi que ce soit concernant les tableaux; ils semblent être limités aux variables monadiques.

Je peux imaginer ajouter des axiomes de la forme

{0i<A.lengthP[A[i]/E]} A[i]:=E; {P}

Cependant, il est clair pour moi comment vous traitez avec un accès au tableau sur le côté droit, à savoir si elle fait partie d'une expression complexe dans une déclaration .x : = EEx:=E

Comment les accès aux tableaux peuvent-ils être modélisés dans la logique Hoare afin que l'absence d'accès non valide puisse et doit être prouvée pour l'exactitude du programme?

Les réponses peuvent supposer que nous interdisons l'utilisation d'éléments de tableau dans des instructions autres que ou dans le cadre de certains E dans x : = E car cela ne restreint pas l'expressivité; on peut toujours affecter à une variable temporaire la valeur souhaitée, c'est-à-dire écrire t : = A [ i ] ; i f ( t > 0 ) au lieu de i f ( A [ i ] > 0 ) A[i]:=EEx:=Et:=A[i]; if(t>0)if(A[i]>0).

Raphael
la source

Réponses:

8

Votre axiome n'est pas vraiment un axiome, il manque des hypothèses. Des présentations simples de la logique Hoare manipulent des formules de la forme P et P ' sont des formules logiques et C est une commande. Vous devez vous assurer que C est bien formé . Dans des langages simples comme ceux souvent utilisés pour une première introduction à la logique Hoare, la bonne forme est syntaxique: il s'agit généralement de vérifier que C{P}C{P}PPCCCse conforme à une grammaire sans contexte, et peut-être que les variables libres sont dans un ensemble autorisé. Si le langage comprend des constructions qui ont une exactitude sémantique, telles que les accès aux éléments du tableau, vous devez ajouter des hypothèses pour exprimer cette exactitude sémantique.

Formellement, vous pouvez ajouter des jugements pour exprimer la correction d'expressions et de commandes. Si les expressions n'ont pas d'effets secondaires, elles n'ont pas besoin de post-conditions, seulement de conditions préalables. Par exemple, vous pouvez écrire des règles de bonne forme telles que et n'autorisent que des expressions bien formées dans les commandes: {P[xE]}

{P}E wf{P0E<length(A)}A[E] wf{P}E1 wf{P}E2 wf{P}E1+E2 wf
{P[xE]}E wf{P[xE]}x:=E{P}

Une approche différente consiste à traiter toutes les expressions comme bien formées, mais à faire en sorte que toute expression impliquant un calcul mal formé ait une valeur spéciale . Dans les langues avec vérification des limites d'exécution, e r r o r signifie «ce programme a déclenché une exception fatale». Vous suivriez alors si un programme s'est trompé via un prédicat logique E r r o r ; un programme n'est valable que si vous pouvez prouver que sa postcondition implique ¬ E r r o r . errorerrorError¬Error

{P[xE]}x:=E{PError}P[xE]Eerror{P[xE]}x:=E{P}

Une autre approche consiste à considérer un triple de Hoare comme valable uniquement si le programme se termine correctement. Il s'agit de l'approche habituelle pour les programmes non terminés: la postcondition se maintient lorsque la commande se termine, ce qui peut ne pas toujours se produire. Si vous traitez les erreurs d'exécution comme non terminées, vous balayez tous les problèmes de correction sous le capot. Vous devrez toujours prouver l'exactitude du programme d'une manière ou d'une autre, mais ce n'est pas nécessairement dans la logique Hoare si vous préférez un autre formalisme pour cette tâche.

Soit dit en passant, noter que l'expression de ce qui se produit lorsqu'une variable composée telle qu'un tableau est modifié est plus complexe que ce que vous avez écrit. Supposons que était, disons, je s S o r t e d ( A ) : la substitution A [ i ] E ne changerait pas P , mais l'affectation A [ i ] P pourrait invalider P . Même si vous limitez la syntaxe des prédicats pour ne parler que des atomes, considérez l'affectation A [ A [ 0PIsSorted(A)A[i]EPA[i]PP sous la condition préalable A [ 0 ] = 2 A [ 1 ] = 3 : vous ne pouvez pas faire une simple substitution pour obtenir la postcondition correcte A [ 0 ] = 1 A [ 1 ] = 1 , vous devez évaluer A [ 0 ] (ce qui peut être difficile en général, car la précondition peut ne pas spécifier une seule valeur possible pour AA[A[0]1]:=A[0]A[0]=2A[1]=3A[0]=1A[1]=1A[0] ). Vous devez effectuer la substitution sur le tableau lui-même: A A [ i E ] . Les notes de cours de Mike Gordonont une bonne logique Hoare de présentation avec des tableaux (mais sans vérification d'erreur).A[0]AA[iE]

Gilles 'SO- arrête d'être méchant'
la source
0

Comme mentionné par Gilles, il existe un axiome d'affectation de tableau (voir les notes de Gordon, Sec. 2.1.10 ):

{Q[AA.store(i,expr)]}A[i]=expr{Q}
A.store(i,expr)iexprA.store(i,vi)A[j]=vjA.store(j,vj).store(i,vi)

De plus, nous avons besoin de l'axiome d'accès au tableau: A.store(i,v)[i]peut être remplacé par v("si vous accédezjee élément que vous venez de mettre à jour, puis renvoyez la valeur attribuée ").

Je pense que pour prouver qu'un programme avec des tableaux est correct ("pas d'accès hors limites"), les axiomes ci-dessus suffisent. Prenons le programme:

...
A[i] = 12
...

Nous annoterions ce programme:

...
@ {0<i<A_length}
A[i] = 12
...

A_lengthest une variable qui spécifie la longueur du tableau. Essayez maintenant de prouver l'annotation - à savoir, travaillez-la à l'envers (de bas en haut, "comme d'habitude" dans les épreuves Hoare). Si vous obtenez en haut {false}, l'accès hors limite peut se produire, sinon l'expression que vous avez est la condition préalable sous laquelle aucun accès hors limite n'est possible. (aussi, nous devons nous assurer que lorsque le tableau est créé comme int A=int[10];alors dans la post-condition que nous avons {A_length==10}).

Ayrat
la source
Vos axiomes ne modélisent pas l'accès hors limites: ils ne mentionnent même pas la longueur! Dans votre programme d' exemple, comment voulez - vous rapportez lengthà A?
Gilles 'SO- arrête d'être méchant'
À droite, les axiomes ne modélisent pas les accès hors limites. Tout d'abord, pour prouver qu'un programme est correct, j'ajoute des annotations qui nécessitent qu'un accès soit dans les limites. (a lengthété renommé A_length.) Deuxièmement, nous avons besoin d'axiomes de "création" de tableaux comme int[] a = int[length] {a_length==length}. Je pense que cela devrait suffire.
Ayrat