Wie wird die Schleifeninvariante in diesem Algorithmus zum Finden der Quadratwurzelgrenze erhalten?

10

Ursprünglich auf math.SE, aber dort unbeantwortet.

Betrachten Sie den folgenden Algorithmus.

u := 0
v := n+1;
while ( (u + 1) is not equal to v) do
   x :=  (u + v) / 2;
   if ( x * x <= n) 
     u := x;
   else
     v := x;
   end_if
end_while 

Dabei sind u, v und n ganze Zahlen und die Divisionsoperation ist eine ganzzahlige Division.

  • Erklären Sie, was vom Algorithmus berechnet wird.
  • Stellen Sie anhand Ihrer Antwort auf Teil I als Nachbedingung für den Algorithmus eine Schleifeninvariante her und zeigen Sie, dass der Algorithmus beendet wird und korrekt ist.

In der Klasse wurde gefunden, dass die Nachbedingung und die Invariante 0 u 2n < v 2 , u + 1 v ist . Ich verstehe nicht wirklich, wie die Nachbedingung und die Invarianten erhalten wurden. Ich denke, die Post-Bedingung war u + 1 = v0u2n<(u+1)20u2n<v2,u+1vu+1=v... was eindeutig nicht der Fall ist. Ich frage mich also, wie die Nachbedingung und Invariante erhalten wurde. Ich frage mich auch, wie die Vorbedingung unter Verwendung der Nachbedingung erhalten werden kann.

Ken Li
quelle
Kennen Sie die Hoare-Logik und erwarten Sie eine Antwort, die sie berührt?
Raphael

Antworten:

8

Gilles hat Recht, dass die allgemeine Technik darin besteht, nach interessanten Beobachtungen zu fischen.

In diesem Fall können Sie feststellen, dass das Programm eine Instanz der binären Suche ist, da es die folgende Form hat:

while i + 1 != k
  j := strictly_between(i, k)
  if f(j) <= X then i := j
  if f(j) > X then k := j

Dann sind Sie in Ihrem speziellen Stecker nur f, X... in die allgemeinen invariant für binäre Suche. Dijkstra hat eine nette Diskussion über die binäre Suche .

rgrig
quelle
7

ist in der Tat eine Nachbedingung der while-Schleife (warum ist dies Ihrer Meinung nach „eindeutig“ nicht der Fall?). Dies ist immer der Fall bei einer while-Schleife, die kein: enthält. Wenn die Schleife beendet wird, kann dies nur daran liegen, dass die Schleifenbedingung (hier u + 1 v ) falsch ist. Es ist nicht das einzige, was wahr sein wird, wenn die Schleife hier beendet wird (dieser Algorithmus berechnet tatsächlich etwas Interessantes, wie Sie in Ihrer Klasse gesehen haben, also sind u = [dieses interessante Ding] und v = [dieses interessante Ding] auch Nachbedingungen ), aber es ist das offensichtlichste.u+1=vbreaku+1vu=[this interesting thing]v=[this interesting thing]

Um andere interessante Eigenschaften zu finden, gibt es kein allgemeines Rezept. Tatsächlich gibt es einen formalen Sinn, in dem es kein allgemeines Rezept gibt, um Schleifeninvarianten zu finden. Das Beste, was Sie tun können, ist, einige Techniken anzuwenden, die nur in einigen Fällen funktionieren, oder im Allgemeinen nach interessanten Beobachtungen zu fischen (was mit zunehmender Erfahrung immer besser funktioniert).

Wenn Sie die Schleife für einige Iterationen mit dem Wert ausführen , wird dies bei jeder Iteration angezeigt:n

  • entweder springt auf ( u + v ) / 2 ;u(u+v)/2
  • oder springt nach unten zu ( u + v ) / 2 .v(u+v)/2

uvuvn+10uvn+1

uvuvx=u=vuvu<vuvu+1v

v=u+1u2n<v20u2nnn

  • uxv
  • x2nuxu2nv
  • x2>nvxn<v2u

u2n<v2

u2n(u+1)2>nun

Gilles 'SO - hör auf böse zu sein'
quelle
"Sie müssen also beweisen, dass u und v gleich werden, um zu beweisen, dass der Algorithmus korrekt ist." Ich denke, in diesem Satz fehlt ein "nicht".
sepp2k
@ KenLi Da dies Ihre Frage im Sinne von Stack Exchange ist, möchten Sie eine bestimmte Verbesserung erzielen?
Gilles 'SO - hör auf böse zu sein'