290 likes | 632 Views
Loop variant & invariant. Some kinds of errors are typical for loops The loop does not terminate The loop body is execute once too often or too less Special cases like zero iterations are not handled. Loop invariant. The loop invariant specifies a condition that must be satisfied at
E N D
Loop variant & invariant • Some kinds of errors are typical for loops • The loop does not terminate • The loop body is execute once too often or too less • Special cases like zero iterations are not handled
Loop invariant • The loop invariant specifies a condition that must be satisfied at • the begin of the loop, • after every iteration and • when the loop has terminated. • This is used to express global properties of the loop like the range of the loop variable.
Loop variant • The loop variant declares an integer expression that is decreased with every loop iteration but never below zero. • Thus the loop variant guaranties the termination of the loop.
What should we ask ? • Loop invaiant • Begin with: What has happened so far? • What is supposed to be true as a result of the completion of the loop? (I.e. what is the intermediate result so far) • Loop variant • What is the termination condition? • If the termination condition is not met the loop is entered. Will the loop body insure progress toward termination? (I.e. how far are we from termination)
A program technique for loops • What is the long term goal, i.e. the overall post-condition? • What are its short term goals, i.e. what is it doing while looping?What must it satisfy to be doing “okay so far”? (“okay so far” is the loop invariant). • How does it make progress, i.e. what is its variant?
Example #1 public boolean contains(Object o) { /** require o != null; **/for (int i = 0; i < buffer.length; i++) /** invariant 0 <= i && i <= buffer.length; **/ /** variant buffer.length - i **/ if (buffer[i].equals(o)) return true; return false; /** ensure changeonly{}; I.e. change nothing **/ }
Example #2 int Negs (int [] A) { //pre: none init: i=0; result=0; //invariant: -- ? -- //variant: -- ? -- while (i<=A.length-1) { if (A[i]<0) result = result + 1; i++; } return result; //post: result = sum(i=0 to i=(A.length)-1) (if A[i] < 0 then 1 else 0) }
Example #3 Precondition: a is nonempty Postcondition: s is the smallest element in a from i := a.lower s := a.item (i) invariant -- ? -- variant -- ? -- until i = a.upper loop i := i + 1 s := s.min (a.item (i)) end
Example #3 Precondition: a is nonempty Postcondition: s is the smallest element in a from i := a.lower s := a.item (i) invariant -- ? -- variant a.upper - i until i = a.upper loop i := i + 1 s := s.min (a.item (i)) end
Example #3 Precondition: a is nonempty Postcondition: s is the smallest element in a from i := a.lower s := a.item (i) invariant -- s is the smallest element in the set {a.item (a.lower), ..., a.item (i)} variant a.upper - i until i = a.upper loop i := i + 1 s := s.min (a.item (i)) end
Mystery Program input(x,y) z := 1;while y != 0 doif odd(y)then y := y -1; z := x*z;else x := x * x; y := y / 2; output(z);
Mystery Program The missing loop invariant and variant are: invariant -- z*xy= ab y >= 0 variant y
MinSum - example 0 1 2 3 4 a: 5 -3 2 -4 1 minimum-sum section is a[1:3] = (-3,2,-4). The sum is -5. 0 1 2 3 4 a: 5 2 5 4 2 The two minimum-sum sections are a[1:1] and a[4:4]. The sum is 2.
… 0 1 2 3 4 N MinSum a: MINSUM : k : = 1; sum := a[0]; x := 0;while k != N do x := min(x + a[k], a[k]); sum := min(sum,x); k := k + 1;od We’re looking for a section a[i:j] s.t. the sum of the elements in this subsection is minimal over all possible subsections.
initialization k := 1; sum := a[0];
post condition The sum of the minimum-sum section of a[0:k-1]
variant Because p --> N - k >= 0 we chooset : N - k as the bound function. (variant)
Product of Two natural Numbers prod := 0; count := y; while count > 0 do prod := prod + x; count := count - 1; od return prod x,y,prod,count are integer variables.
Fibonacci x:=0; y:=1; count:=n; while count > 0 do h:=y; y:=x+y; x:=h; count := count-1; od return y x,y,n,h,count are all integers.
Fibonacci (2) <pre: n>0> i := 1 a := 1 b := 0 <preloop: i=1 and a=1 and b=0> loop<INV: 1<=i<=n and a=f_i and b=f_{i-1}> exit when i>= n i := i + 1 temp := a a := a+b b := temp end loop <post: a=f_n>
find (x:G; a:ARRAY[G]; from, to:INTEGER):INTEGER is requirea != Voidto+1 >= fromto < a.upperfrom >= a.lower local save: G; i:INTEGER dofrom save := a@(to + 1) a.put(x, to + 1) i := from invariant variant until a@i = x loop i := i + 1 end Result := i a.put(save, to + 1) ensure-- for each k, from <= k < Result implies a@k != xResult <= to implies a@Result = x end
Searches for the first occurrence of a value x between indexes from and to in an array a. • Instead of checking for the end of the search segment, it puts the value x immediately after the segment, so that the value will always be found.
variant: to + 1 - i
invariant: from <= I <= to-- bound -- for each k, from <= k <= i, implies a@k != x -- not found a@(to + 1) = x -- top
The loop invariant holds on entry to the loop • On entry, i = from, By the precondition, to + 1 >= from • Not found: is vacuously true, since the range is empty • Top: follows from the second line of the initialization
The loop invariant is maintained be one pass through the loop • i` is the previous value of i • Bound: • i = i` + 1 > i` >= from • By top: a@(to +1) = xBy exit condition, a@i` != x, so i`!=to +1therefore i` <= to and i=i`+1 <= to + 1 • Top: • Follows from the invariant, since the array, x and to aren’t modified in the loop
Not found: • For from <= k <= i-1, follows from the invariant at the beginning of the pass. • For k=i-1, we know by the exit condition that a@(i-1) = a@i` != x
The postcondition follows from the loop inv and exit code • The first line of the postcondition follows from “not found”, since on exit Result = I • Immediately after the loop, we havea@i =x, by the exit condition. • If i!=to+1, the subsequence assignment to element to+1 of the array does not change the value of a@i, and since Result=i on exist, it follows that Result != to+1 implies a@Result = x, which is stronger than the postcondition.