Presentation is loading. Please wait.

Presentation is loading. Please wait.

Application: Correctness of Algorithms Lecture 22 Section 4.5 Fri, Mar 3, 2006.

Similar presentations


Presentation on theme: "Application: Correctness of Algorithms Lecture 22 Section 4.5 Fri, Mar 3, 2006."— Presentation transcript:

1 Application: Correctness of Algorithms Lecture 22 Section 4.5 Fri, Mar 3, 2006

2 Assertions An assertion in a computer program is a statement that is supposed to be true. It is a standard programming practice to test assertions.

3 The assert() Macro In C++ the assert() macro is convenient for this purpose. assert(pos >= 1 && pos <= size + 1); If the expression is true, nothing happens. If the expression is false, an error message is displayed and the program quits.

4 The assert() Macro The assert macro generates an automatic error message that gives the boolean expression that failed, the file name, and the line number. Assertion(pos >= 1 && pos <= size + 1) failed in “arraylist.h” on line 50

5 Pre-Conditions and Post- Conditions A pre-condition is an assertion that should be true at the beginning of a function. A post-condition is an assertion that should be true at the end of a function. void List::Insert(const T& value, int pos) { // Test the pre-condition assert(pos >= 1 && pos <= size + 1); : }

6 Example: Post-Condition int List::Search(const T& value) { : // Test the post-condition assert(pos == -1 || (pos >= 0 && pos < size && element[pos] == value)); return pos + 1; }

7 Guard Conditions A guard condition is a boolean expression that appears in the while statement of a loop. The guard condition is tested at the beginning of each iteration. The loop continues as long as the guard condition is true. The loop terminates as soon as the guard condition is found to be false.

8 Example: Guard Condition int List::Search(const T& value) { : // Test the guard condition while (i < size && list[i] != value) { : }

9 Loop Invariants A loop invariant is a predicate I(k), where k is the number of times the body of the while loop has been executed. The loop invariant I(k) is supposed to be true at the end of the k-th iteration.

10 Computing Square Roots The problem is to approximate the square root of a number x > 1. Let a 0 = x and b 0 = 1. Then repeatedly apply the following, for i = 1, 2, 3, …

11 Computing Square Roots There are several loop invariants. a i b i = x. a i – 1 > a i >  x. b i – 1 < b i <  x. a i – b i < (1/2)(a i – 1 – b i – 1 ) 2. These invariants together guarantee that the procedure will converge rapidly to  x.

12 Example: SquareRoots.cpp

13 Example: Loop Invariants The following for loop adds up the elements of an array. The loop invariant I(k) is that “sum” equals array[0] + … + array[k – 1]. Why is that not very helpful? double sum = 0; for (int i = 0; i < size; i++) sum += array[i];

14 A Problem with Loop Invariants As the previous example shows, sometimes it can be difficult or pointless to verify an invariant. The verification would involve repeating the calculation. This raises a further issue: How do we know that the invariant itself is correct?

15 The Loop Invariant Theorem Theorem: Let G be the guard condition and let I(k) be the loop invariant. Suppose the following four statements are true. If the pre-condition is true, then I(0) is true before the first iteration. If G and I(k) are true at the end of the k-th iteration,then I(k + 1) is true at the end of the (k + 1)-th iteration.

16 Theorem, continued After some finite number of iterations, G will be false. If N is the least number of iterations after which G is false and I(N) is true, then the post-condition is true. Then if the pre-condition is true before the while loop begins, then the post-condition will be true after the while loop ends.

17 The Form of the Theorem The theorem can be outlined as follows. If pre  I(0)  N  0,  G  k with 0  k < N, G  I(k)  I(k + 1)  k with 0  k < N, G  G  I(N)  post Then pre  post.

18 Correctness of the Division Algorithm Given a nonnegative integer a and a positive integer d, the following algorithm will produce the quotient q and remainder r when a is divided by d. r = a; q = 0; while (r >= d) { r = r – d; q++; }

19 The Assertions The pre-condition is (a >= 0) && (d > 0) && (r == a) && (q == 0) The post-condition is (a == q * d + r) && (r >= 0) && (r < d) The guard condition is r >= d

20 Determine the Loop Invariant To determine the loop invariant, consider an example. Let a = 40 and d = 13. nadrq 04013400

21 Determine the Loop Invariant To determine the loop invariant, consider an example. Let a = 40 and d = 13. nadrq 04013400 1 13271

22 Determine the Loop Invariant To determine the loop invariant, consider an example. Let a = 40 and d = 13. nadrq 04013400 1 13271 24013142

23 Determine the Loop Invariant To determine the loop invariant, consider an example. Let a = 40 and d = 13. nadrq 04013400 1 13271 24013142 3401313

24 Determine the Loop Invariant What is invariant in the four cases? The invariant is that a = qd + r. Therefore, the predicate I(k) is a == q * d + r

25 The Code in C++ int r = a; int q = 0; // Test the pre-condition assert(a >= 0 && d > 0 && r == a && q == 0); while (r >= d) { r = r – d; q++; // Test the loop invariant assert(a == q * d + r); } // Test the post-condition assert(a == q * d + r && r >= 0 && r < d);

26 Example: DivisionAlgorithm.cpp

27 Verification of I(0) pre  I(0) If a  0, d > 0, r = a, and q = 0, then qd + r = 0  d + a = a.

28 Verification of the Inductive Step G  I(k)  I(k + 1) Suppose that r  d and a = qd + r. Define r' = r – d and q' = q + 1. Then q'd + r' = (q + 1)d + (r – d) = qd + r = a.

29 Verification that the Guard Condition Fails G must eventually fail. Initially, r  0. On each iteration, r' < r. Eventually, r will be less than d. Let N be the first integer for which G fails. On the Nth iteration, r  d, but r' < d.

30 Verification of the Post Condition  G  I(N)  post Suppose that r  d is false and that a = qd + r. Then r < d. Suppose r < 0. Then on the previous iteration, the previous value must have been r + d, which is < d. This is a contradiction. Therefore, r  0.

31 Verification of the Post Condition Thus, when the while loop ends, it must be the case that a = qd + r with 0  r < d.

32 Correctness of the Euclidean Algorithm Given integers A and B, with A > B >= 0, the following algorithm will produce the greatest common divisor a of A and B. a = A; b = B; r = B; while (b != 0) { r = a % b; a = b; b = r; }

33 The Assertions The pre-condition is (A > B) && (B >= 0) && (a == A) && (b == B) && (r == B) The post-condition is a == gcd( A, B ) The guard condition is b != 0

34 Determine the Invariant To determine the loop invariant, consider an example where A = 40 and B = 14. nabr 04014

35 Determine the Invariant To determine the loop invariant, consider an example where A = 40 and B = 14. nabr 04014 1 12

36 Determine the Invariant To determine the loop invariant, consider an example where A = 40 and B = 14. nabr 04014 1 12 2 22

37 Determine the Invariant To determine the loop invariant, consider an example where A = 40 and B = 14. nabr 04014 1 12 2 22 3200

38 Determine the Invariant There are two invariants a > b >= 0 gcd( a, b ) = gcd( A, B ) Therefore, I(k) is (a > b) && (b >= 0) && ( gcd( a, b ) == gcd( A, B ) ) It is not practical to test the condition gcd( a, b ) == gcd( A, B ) in the program.

39 The Code in C++ a = A; b = B; // Test the pre-condition assert(A > B && B >= 0 && a == A && b == B); while (b != 0) { r = a % b; a = b; b = r; // Test the loop invariant assert(a > b && b >= 0); }

40 Verification of I(0) pre  I(0) If A > B  0, a = A, b = B, and r = B, then a > b >= 0 and gcd(a, b) = gcd(A, B).

41 Verification of the Inductive Step G  I(k)  I(k + 1) Suppose that b  0 and that a > b  0 and gcd(a, b) = gcd(A, B). Define r' = a mod b, a' = b, and b' = r'. Then by the Quotient-Remainder Theorem, 0  r' < b. Also, a' = b, and b' = r', so a' > b'  0. Furthermore, gcd(a', b') = gcd(b, a mod b).

42 Verification of the Inductive Step Therefore, gcd(a', b') = gcd(b, a mod b) = gcd(a, b) = gcd(A, B). Thus, G  I(k)  I(k + 1).

43 Verification that the Guard Condition Fails G must eventually fail. Initially, b  0. On each iteration, 0  b' < b. Therefore, eventually, b' will be 0. Let N be the first integer for which G fails.

44 Verification of the Post Condition  G  I(N)  post Suppose that b  0 is false and that a > b  0 and gcd(a, b) = gcd(A, B). Then b = 0 and a > 0. Therefore, gcd(a, b) = gcd(a, 0) = a. So, a = gcd(A, B).


Download ppt "Application: Correctness of Algorithms Lecture 22 Section 4.5 Fri, Mar 3, 2006."

Similar presentations


Ads by Google