Es gibt immer unendlich viele gültige Schleifeninvarianten. Der Trick besteht darin, einen zu finden, der ausreicht, um zu beweisen, was Sie über den Algorithmus beweisen möchten, und den Sie beweisen können (normalerweise durch Induktion über die Anzahl der Schleifeniterationen).
Der Nachweis der Richtigkeit dieses Algorithmus besteht aus drei Teilen:
- Der Algorithmus führt niemals einen falschen Schritt aus. Hier besteht der mögliche Fehler darin, auf ein Array-Element außerhalb der Grenzen des Arrays zuzugreifen.
- Wenn der Algorithmus
YES
oder zurückgibt NO
, ist diese Ausgabe korrekt.
- Der Algorithmus wird für jede Eingabe beendet.
Für die Richtigkeit müssen Sie das beweisen 1≤i≤n und 1≤j≤n. Dies sollte besser Teil Ihrer Invariante sein. Angesichts der Schleifenbedingungi<jkönnen Sie dies verdichten 1≤i<j≤nam Eingang in den Schleifenkörper. Diese Bedingung ist nicht erfüllt, wenn der Schleifentest am Ende erreicht ist, aber es kann nützlich sein, dies zu bemerkeni≤j (weil innerhalb des Schleifenkörpers mit i<j, i und j nur ändern durch 1, die im schlimmsten Fall diese strikte Ungleichung in Gleichheit verwandeln kann).
Wann return YES
wird ausgeführt,A[i]+A[j]=bist offensichtlich. Für diesen Teil muss also nichts Besonderes bewiesen werden.
Wenn die letzte return NO
Anweisung ausgeführt wird, bedeutet dies, dass die Schleife normal beendet wurde (und so weiter)i<j ist falsch), müssen Sie das beweisen ∀i,∀j,A[i]+A[j]≠b. Diese Eigenschaft ist im Allgemeinen offensichtlich nicht wahr: Sie gilt nicht, wenn die Antwort lautet YES
. Sie müssen diese Eigenschaft stärken : Sie haben einen Sonderfall, der verallgemeinert werden muss. Dies ist ein typischer Fall einer Eigenschaft, die nur für den Teil des Arrays gilt, der bereits durchlaufen wurde: Die Schleife ist so aufgebaut, dass if(x,y) ist ein vorheriger Wert von (i,j) (dh 1≤x≤i und j≤y≤n und (x,y)≠(i,j)) dann A[x]+A[y]≠b. Dies sollte besser in der Schleifeninvariante ausgedrückt werden.
Sind wir dort fertig? Nicht ganz; Alles, was wir über die normale Schleifenbeendigung wissen, ist das∀x≤i,∀y≤j,A[x]+A[y]≠b. Was wäre, wenn wir hättenx>i und y≤j, oder x≤i und y>j: Können wir haben A[x]+A[y]≠b? Ohne weitere Informationen ist das schwer zu sagen. In der Tat sollten wir einige Fälle besser unterscheiden, wennA[x]+A[y]>b und die Fälle, wenn A[x]+A[y]<b. Mit diesen Eigenschaften können wir die Tatsache verwenden, dass das Array sortiert ist, um Fakten über andere Positionen im Array abzuleiten. nur mit≠bWir haben nichts zu arbeiten. Wir wissen nicht in welche RichtungA[x]+A[y] Lügen für einige zufällige x<i und y>j;; aber wir wissen, was an der Grenze passiert: wenni wird erhöht, es liegt daran A[i]+A[j] ist zu klein und wenn j wird dekrementiert, weil A[i]+A[j]es ist zu groß. Überlegen Sie, welche Schleifeninvariante dies ausdrücken könnte. Ich werde unten eine Möglichkeit geben.
Beachten Sie, dass diese Eigenschaft Ihnen nicht direkt die gewünschte Bedingung für die return NO
Anweisung gibt. Sie müssen sich noch ansehen, was im letzten Durchlauf der Schleife passiert ist, oder alternativ eine stärkere Schleifeninvariante nachweisen, die genauer betrachtet, wannA[x]+A[y]<b und wann A[x]+A[y]>b.
Schließlich müssen Sie zur Kündigung eine Beziehung herstellen i und jmit der Anzahl der Iterationen durch die Schleife. Hier ist das einfach: entwederi oder j bewegt sich bei jeder Runde, also j−i nimmt um ab 1bei jeder Schleifeniteration; Sie müssen keine Schleifeninvariante verwenden, um dies zu beweisen.
Wir haben die folgende Invariante erhalten:
1≤i≤j≤n∧(∀x<i,∀y<j,A[x]+A[y]≠b)∧(∀x<i,A[x]+A[j]<b)∧(∀y>j,A[i]+A[y]>b)