CSC195, Class 50: Loop Invariants and the Ilk Overview: * Form of an annotated loop * What do we want to do with loops * Gries's checklist for understanding loops * An example: Finding the minimum in an array * Some principles Notes: * I'm unhappy that you did not do the reading for Monday. * Exam 2 is ready. Surprisingly, it does not reflect that unhappiness. * Mom says that I use too many in jokes and that I pick on Sanchit too much. Sorry. + Yes, some of the Gries implementation stuff is trial and error. However, the trial is done with careful analysis and not just test cases. * I HATE THOSE WHO USE THE WORK OF OTHERS INAPPROPRIATELY I SEVERELY DISLIKE (BUT DON'T HATE) STUDENTS WHO DON'T DO THE READING EVEN AFTER I RANT ABOUT IT * Reminder: The final is optional. I will reschedule it as requested, if necessary (except for Reese). + In class. ---------------------------------------- What does an annotated loop look like? { precondition: C } { invariant: I } { bound: t } do G1 -> S1 | G2 -> S2 | ... | Gn -> Sn od { postcondition: P } How do you know that when you start with C you end with P? What needs to hold in order for (the above)? 1. The invariant is kept true after every statement 2. The invariant is also true when the loop terminates. ((not G1) and (not G2) and ... (not Gn)) => P 3. The loop must terminate. In order for the loop to terminate, the bound function must decrease at every step. (Assume stops when bound function is 0.) It's "the checklist thingy" (p. 145) 1. Verify that I holds before the loop begins C => I 2. Show that { I ^ Gi } Si { I } for all 1 <= i <= n The invariant is kept true after every repetition of the loop 3. Show that (I ^ (not G1) and (not G2) and ... (not Gn)) => P When the loop stops, it stops with a correct result. 4. I ^ (G1 or G2 or ... Gn) => t > 0 t is our termination function 5. { I ^ Gi } u := t; Si { t < u } for 1 <= i <= n t decreases at every step Reflective detour: Can t return a real number? "Preferably not". Why not? * Infinite number of reals => possible nontermination * t must return a nonnegative integer How do we use all of this to develop loops? 1. Write preconditions and postconditions. 2. Write "reasonable" invariant. Intuition; Trial and error 3. Does there exist an X such that (I and X) => P? Yes -> The invariant might be helpful. No -> The invariant is wrong. Go back to step 2. 4. You now know one possible guard for the loop: (not X) 5. See if that guard helps you come up with a statement. ... Goal: Set s to the smallest value in an array a, indexed from 1 to n. Precondition: C = { a = A } Postcondition: P = { smallest(s,a); a = A } Rewrite postcondition: Hint: What does it mean for x to be the smaller of y and z? Postcondition: P = { elementOf(s,a) and for all 1 <= i <= n , s <= a[i] and a = A } Rewrite postcondition: Postcondition: P = { (exists 1 <= i <= n, s = a[i]) and (for all 1 <= i <= n, s <= a[i]) and (a = A) } Analysis suggests we now need to extend the precondition so that the first part of the postcondition holds Precondition: C = { a = A and n >= 1} What's a useful invariant? "s is the smallest element in the part of the array you've looked at so far" Invariant I = { (exists 1 <= i <= j, s = a[i]) and (for all 1 <= i <= j, s <= a[i]) and (a = A) } Introducing a new variable, j Precondition: C = { a = A and n >= 1} GriesSort do a[i] > a[i+j]: swap a[i],a[j] od