Umgang mit Arrays bei Korrektheitsprüfungen im Hoare-Stil

11

In der Diskussion um diese Frage erwähnt Gilles richtig, dass jeder Korrektheitsnachweis eines Algorithmus, der Arrays verwendet, beweisen muss, dass es keine Array-Zugriffe außerhalb der Grenzen gibt. Abhängig vom Laufzeitmodell würde dies einen Laufzeitfehler oder den Zugriff auf Nicht-Array-Elemente verursachen.

Eine übliche Technik, um solche Korrektheitsnachweise durchzuführen (zumindest in Grundstudien und wahrscheinlich in der automatisierten Verifizierung), ist die Verwendung der Hoare-Logik . Mir ist nicht bekannt, dass das Standardregelwerk alles enthält, was sich auf Arrays bezieht. Sie scheinen auf monadische Variablen beschränkt zu sein.

Ich kann mir vorstellen, Axiome der Form hinzuzufügen

{0ich<EIN.lenGthP.[EIN[ich]]/.E.]]}} EIN[ich]]: =E.;; {P.}}

Mir ist jedoch nicht klar, wie Sie mit einem Array-Zugriff auf der rechten Seite umgehen würden, dh wenn er Teil eines komplexen Ausdrucks in einer Anweisung .x : = E.E.x: =E.

Wie können Arrays-Zugriffe in der Hoare-Logik modelliert werden, damit das Fehlen ungültiger Zugriffe für die Programmkorrektheit nachgewiesen werden kann und muss?

Antworten können davon ausgehen, dass wir die Verwendung von Array-Elementen in anderen Anweisungen als oder als Teil eines in nicht zulassen, da dies die Ausdruckskraft nicht einschränkt. Wir können einer temporären Variablen immer den gewünschten Wert zuweisen, dh anstelle von .E x : = E t : = A [ i ] ; i f ( t > 0 ) i f ( A [ i ] > 0 ) EIN[ich]]: =E.E.x: =E.t: =EIN[ich]];; ichf(t>0)ichf(EIN[ich]]>0)

Raphael
quelle

Antworten:

8

Ihr Axiom ist nicht wirklich ein Axiom, es fehlen Hypothesen. Einfache Darstellungen der Hoare-Logik manipulieren Formeln der Form wobei P und P logische Formeln sind und C ein Befehl ist. Sie müssen sicherstellen, dass C gut geformt ist . In einfachen Sprachen, wie sie häufig für eine erste Einführung in die Hoare-Logik verwendet werden, ist Wohlgeformtheit syntaktisch: In der Regel muss überprüft werden, ob C.{P.}}C.{P.'}}P.P.'C.C.C.entspricht einer kontextfreien Grammatik und möglicherweise, dass sich die freien Variablen innerhalb einer zulässigen Menge befinden. Wenn die Sprache Konstrukte enthält, die eine semantische Korrektheit aufweisen, z. B. Zugriffe auf Array-Elemente, müssen Sie Hypothesen hinzufügen, um diese semantische Korrektheit auszudrücken.

Formal können Sie Beurteilungen hinzufügen, um die Korrektur von Ausdrücken und Befehlen auszudrücken. Wenn Ausdrücke keine Nebenwirkungen haben, benötigen sie keine Nachbedingungen, sondern nur Vorbedingungen. Sie können beispielsweise wohlgeformte Regeln wie { P } schreiben. und erlauben nur wohlgeformte Ausdrücke in Befehlen: {P[xE]}

{P.}}E. wf{P.0E.<lenGth(EIN)}}EIN[E.]] wf{P.}}E.1 wf{P.}}E.2 wf{P.}}E.1+E.2 wf
{P.[xE.]]}}E. wf{P.[xE.]]}}x: =E.{P.}}

errÖrerrÖrE.rrÖr¬E.rrÖr

{P.[xE.]]}}x: =E.{P.E.rrÖr}}P.[xE.]]E.errÖr{P.[xE.]]}}x: =E.{P.}}

Ein weiterer Ansatz besteht darin, ein Hoare-Triple nur dann zu halten, wenn das Programm korrekt beendet wird. Dies ist der übliche Ansatz für nicht endende Programme: Die Nachbedingung gilt, wenn der Befehl beendet wird, was möglicherweise nicht immer der Fall ist. Wenn Sie Laufzeitfehler als Nichtbeendigung behandeln, kehren Sie alle Korrektheitsprobleme unter die Haube. Sie müssen immer noch die Richtigkeit des Programms irgendwie beweisen, aber es muss nicht in der Hoare-Logik sein, wenn Sie einen anderen Formalismus für diese Aufgabe bevorzugen.

Beachten Sie übrigens, dass das Ausdrücken, was passiert, wenn eine zusammengesetzte Variable wie ein Array geändert wird, mehr involviert ist als das, was Sie geschrieben haben. Angenommen, war beispielsweise I s S o r t e d ( A ) : Die Substitution A [ i ] E würde P nicht ändern , aber die Zuweisung A [ i ] P könnte P ungültig machen . Auch wenn Sie die Syntax von Prädikaten so einschränken, dass nur über Atome gesprochen wird, berücksichtigen Sie die Zuordnung A [ A [ 0P.ichsS.Örted(EIN)EIN[ich]]E.P.EIN[ich]]P.P. unter der Voraussetzung A [ 0 ] = 2 A [ 1 ] = 3 : Sie können keine einfache Substitution vornehmen, um die korrekte Nachbedingung A [ 0 ] = 1 A [ 1 ] = zu erhalten In 1 müssen Sie A [ 0 ] bewerten(was im Allgemeinen schwierig sein kann, da die Vorbedingung möglicherweise keinen einzigen möglichen Wert für A angibtA[A[0]1]:=A[0]A[0]=2A[1]=3A[0]=1A[1]=1A[0] ). Sie müssen die Ersetzung für das Array selbst durchführen: A A [ i E ] . Mike Gordons Vorlesungsunterlagen enthalteneine gute Präsentation der Hoare-Logik mit Arrays (jedoch ohne Fehlerprüfung).A[0]AA[iE]

Gilles 'SO - hör auf böse zu sein'
quelle
0

Wie von Gilles erwähnt, gibt es ein Axiom für die Arrayzuweisung (siehe Gordons Anmerkungen, Abschnitt 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)

A.store(i,v)[i]vi

Ich denke, um zu beweisen, dass ein Programm mit Arrays korrekt ist ("keine unbegrenzten Zugriffe"), reichen die obigen Axiome aus. Betrachten wir das Programm:

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

Wir würden dieses Programm kommentieren:

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

Dabei A_lengthhandelt es sich um eine Variable, die die Arraylänge angibt. Versuchen Sie nun, die Annotation zu beweisen - und arbeiten Sie sie rückwärts aus (von unten nach oben, "wie gewöhnlich" in Hoare-Proofs). Wenn Sie oben erhalten {false}, kann der Zugriff außerhalb der Grenzen erfolgen. Andernfalls ist der Ausdruck, den Sie erhalten haben, die Voraussetzung, unter der keine Zugriffe außerhalb der Grenzen möglich sind. (Außerdem müssen wir sicherstellen, dass beim Erstellen eines Arrays wie int A=int[10];damals in der Nachbedingung, die wir haben {A_length==10}).

Ayrat
quelle
Ihre Axiome modellieren keinen Zugriff außerhalb der Grenzen: Sie erwähnen nicht einmal die Länge! Wie verhalten Sie sich lengthin Ihrem Beispielprogramm A?
Gilles 'SO - hör auf böse zu sein'
Richtig, die Axiome modellieren nicht aus gebundenen Zugriffen heraus. Um zu beweisen, dass ein Programm korrekt ist, füge ich zunächst Anmerkungen hinzu, für die ein Zugriff innerhalb der Grenzen erforderlich ist. ( lengthwurde umbenannt A_length.) Zweitens brauchen wir Array "Schöpfung" Axiome wie int[] a = int[length] {a_length==length}. Ich denke das sollte reichen.
Ayrat