Application Correctness of Algorithms Lecture 22 Section 4

  • Slides: 42
Download presentation
Application: Correctness of Algorithms Lecture 22 Section 4. 5 Fri, Feb 18, 2005

Application: Correctness of Algorithms Lecture 22 Section 4. 5 Fri, Feb 18, 2005

Assertions An assertion in a computer program is a statement that is supposed to

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. ¢

The assert() Macro ¢ In C++ the assert() macro is convenient for this purpose.

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. ¢

The assert() Macro ¢ The assert macro generates an automatic error message that gives

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

Pre-Conditions and Post. Conditions A pre-condition is an assertion that should be true at

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); : }

Example: Post-Condition int List: : Search(const T& value) { : // Test the post-condition

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; }

Guard Conditions ¢ ¢ A guard condition is a boolean expression that appears in

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.

Example: Guard Condition int List: : Search(const T& value) { : // Test the

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

Loop Invariants A loop invariant is a predicate I(k), where k is the number

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. ¢

Example: Loop Invariants ¢ Consider the Bubble. Sort() function: void Bubble. Sort(int a[], int

Example: Loop Invariants ¢ Consider the Bubble. Sort() function: void Bubble. Sort(int a[], int size) { for (int i = 1; i <= size – 1; i++) for (int j = 0; j < size – i; j++) if (a[j] > a[j + 1]) { int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } return; }

Example: Loop Invariants ¢ The Bubble. Sort() function could have the following loop invariant

Example: Loop Invariants ¢ The Bubble. Sort() function could have the following loop invariant I(k). assert(a[size – i - 1] < a[size – i]); ¢ Why is that not very helpful?

Example: Loop Invariants ¢ The following for loop adds up the elements of an

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

A Problem with Loop Invariants ¢ As the previous example shows, sometimes it can

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

The Loop Invariant Theorem ¢ Theorem: Let G be the guard condition and let

The Loop Invariant Theorem ¢ Theorem: Let G be the guard condition and let I(k) be the loop invariant. Suppose the following statements are true. If the pre-condition is true, then I(0) is true before the first iteration. l 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. l

Theorem, continued For some non-negative integer N, G will be false at the end

Theorem, continued For some non-negative integer N, G will be false at the end of the N-th iteration. (Assume N is the smallest such integer. ) l If G is false and I(N) is true, then the postcondition is true. l ¢ Then if the pre-condition is true before the while loop begins, then the post-condition will be true after the while loop ends.

The Form of the Theorem The theorem can be outlined as follows. ¢ If

The Form of the Theorem The theorem can be outlined as follows. ¢ If ¢ pre I(0) l N 0, G l k 0 with k < N, G I(k) I(k + 1) l G I(N) post l ¢ Then l pre post.

Correctness of the Division Algorithm ¢ Given a nonnegative integer a and a positive

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++; }

The Assertions ¢ The pre-condition is (a >= 0) && (d > 0) &&

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

Determine the Loop Invariant ¢ To determine the loop invariant, consider an example. l

Determine the Loop Invariant ¢ To determine the loop invariant, consider an example. l Let a = 40 and d = 13. n a d r q 0 40 13 40 0

Determine the Loop Invariant ¢ To determine the loop invariant, consider an example. l

Determine the Loop Invariant ¢ To determine the loop invariant, consider an example. l Let a = 40 and d = 13. n a d r q 0 40 13 40 0 1 40 13 27 1

Determine the Loop Invariant ¢ To determine the loop invariant, consider an example. l

Determine the Loop Invariant ¢ To determine the loop invariant, consider an example. l Let a = 40 and d = 13. n a d r q 0 40 13 40 0 1 40 13 27 1 2 40 13 14 2

Determine the Loop Invariant ¢ To determine the loop invariant, consider an example. l

Determine the Loop Invariant ¢ To determine the loop invariant, consider an example. l Let a = 40 and d = 13. n a d r q 0 40 13 40 0 1 40 13 27 1 2 40 13 14 2 3 40 13 1 3

Determine the Loop Invariant What is invariant in the four cases? ¢ The invariant

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

The Code in C++ // // // r = a; q = 0; Test

The Code in C++ // // // r = a; 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);

Verification of I(0) ¢ pre I(0) l If a 0, d > 0, r

Verification of I(0) ¢ pre I(0) l If a 0, d > 0, r = a, and q = 0, then qd + r = 0 d + a = a.

Verification of the Inductive Step ¢ G I(k) I(k + 1) Suppose that r

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

Verification that the Guard Condition Fails ¢ G must eventually fail. Initially, r 0.

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

Verification of the Post Condition ¢ G I(N) post Suppose that r d is

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

Verification of the Post Condition ¢ Thus, when the while loop ends, it must

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

Correctness of the Euclidean Algorithm ¢ Given integers A and B, with A >

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; }

The Assertions ¢ The pre-condition is (A > B) && (B >= 0) &&

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

Determine the Invariant ¢ To determine the loop invariant, consider an example where A

Determine the Invariant ¢ To determine the loop invariant, consider an example where A = 40 and B = 14. n a b r 0 40 14 14

Determine the Invariant ¢ To determine the loop invariant, consider an example where A

Determine the Invariant ¢ To determine the loop invariant, consider an example where A = 40 and B = 14. n a b r 0 40 14 14 12 12

Determine the Invariant ¢ To determine the loop invariant, consider an example where A

Determine the Invariant ¢ To determine the loop invariant, consider an example where A = 40 and B = 14. n a b r 0 40 14 14 12 12 2 2

Determine the Invariant ¢ To determine the loop invariant, consider an example where A

Determine the Invariant ¢ To determine the loop invariant, consider an example where A = 40 and B = 14. n a b r 0 40 14 14 12 12 2 2 3 2 0 0

Determine the Invariant ¢ ¢ There are two invariants l a > b >=

Determine the Invariant ¢ ¢ There are two invariants l a > b >= 0 l 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.

The Code in C++ // // a = A; b = B; Test the

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); }

Verification of I(0) ¢ pre I(0) l If A > B 0, a =

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

Verification of the Inductive Step ¢ G I(k) I(k + 1) Suppose that b

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). l Define r' = a mod b, a' = b, and b' = r'. l Then by the Quotient-Remainder Theorem, 0 r' < b. l Also, a' = b, and b' = r', so a' > b' 0. l Furthermore, gcd(a', b') = gcd(b, a mod b). l

Verification of the Inductive Step Therefore, gcd(a', b') = gcd(b, a mod b) =

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

Verification that the Guard Condition Fails ¢ G must eventually fail. Initially, b 0.

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

Verification of the Post Condition ¢ G I(N) post Suppose that b 0 is

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). l Then b = 0 and a > 0. l Therefore, gcd(a, b) = gcd(a, 0) = a. l So, a = gcd(A, B). l