With a for loop, it's not clear whether the loop invariant should be defined as being true before the variable gets incremented, or after. So let's use more traditional Hoare-logic syntax and turn it into a while loop:
- Code: Select all
k := 0;
while k ≠ n do
k := k + 1;
C(i,j) := A(i,k) * B(k,j) + C(i,j)
done
What we want to prove is that, given the precondition C(i,j) = 0, this code will establish the postcondition that C(i,j) equals the entry of the matrix product, i.e. C(i,j) = sum(k = 1 to n: A(i,k) * B(k,j)).
The Hoare rule for a while loop is:
- Code: Select all
{P ∧ B} S {P}
------------------------------
{P} while B do S done {¬B ∧ P}
The main thing the loop invariant P needs to do is describe the loop's progress in making our desired postcondition happen. At each iteration of the loop, C(i,j) is the sum of the first k products: C(i,j) = sum(x = 1 to k: A(i,x) * B(x,j)). Using that as the invariant would give us our postcondition; if C(i,j) is the sum of the first k products, and the loop condition B is now false (meaning k = n), then C(i,j) is the sum of all n products like we want.
Just one issue: the rule requires that we prove the loop body S actually preserves the invariant provided the condition is true initially ({P ∧ B} S {P}), and we can't quite do that yet because P is a nonsensical statement when k is out of bounds. So, we need to make the loop invariant express the fact that k will always be within bounds: the full loop invariant is 0 ≤ k ≤ n ∧ C(i,j) = sum(x = 1 to k: A(i,x) * B(x,j))
With this invariant, it should be possible to prove the inner loop does what it's supposed to. The other two loops will likewise have their own invariants describing their progress as they iterate (for the j loop: that the first j elements of row i of C are correct; for the i loop: that the first i rows of C are correct).