Lecture 15
In this lecture we will see more examples on establishing and proving loop invariants.
Dot_Product.
double dot_product ( int nelt, double *v1, double *v2 ) {
int i;
double t =
0.0;
for ( i=
0; i < nelt; i++ ) {
t
+= v1[i] * v2[i];
}
return t;
}
To establish the invariant first look into the specifications of the dot_product routine, i.e. the pre-conditions and the post-conditions.
Pre-conditions: nelt > 0;
v1, v2 are vectors of length nelt.
Post-conditions: The routine must return ånelt - 1 v1[i] * v2[i]
i=0
Hence, the loop invariant is:
t = sum so far
= å i - 1 v1[j] * v2[j]
j=0
Initially, i = 0 and t = 0.0.
Simulating the execution,
Assume t = å i - 1 v1[j] * v2[j]
j=0
t' = t + v1[i] * v2[i]
i' = i + 1
Now, t' = å j = i - 1 v1[j] * v2[j] + v1[i] * v2[i]
j=0
= å j = i v1[j] * v2[j]
j=0
But i = i' - 1
Therefore, t' = åi’ - 1 v1[j] * v2[j]
j=0
The loop terminates when i = nelt and hence:
t = å j = nelt - 1 v1[j] * v2[j]
j=0
which satisfies the post-condition.
Loop Invariant for an if statement:
double exp ( double b, int e ) {
double x =
1.0, y = b;
//
Imagine i=0
while ( 0
!= e ) {
if
( e odd ) {
x = x * y;
}
y = y * y;
e = e div
2; // imagine i = i+ 1
}
return x;
}
Explanation
of strategy:
The binary expansion of e is e = e31 e30…e1 e0 = å31 2i * ei
i = 0
ð be = b raised to ( å31 2i * ei )
i = 0
= Õ31 ( ( b raised to 2i ) raised to ei )
i=0
= ( b raised to e0 ) * ( ( b2 ) raised to e1) * ( ( b4 ) raised to e2 )…
Loop Invariant:
For all i from 0 to 31, x = Õi ( ( b raised to 2j ) raised to ej ) y = b raised to 2j
j = 0
At every iteration, y’ = y * y = y2 = ( (b raised to 2i) raised to 2 ) = b raised to 2i + 1
The only values of ei are 0 or 1.
if ei = 0,
x’ = x
When, i’ = i +1
j=0
= ( Õi-1 ( ( b raised to 2j ) raised to ej ) ) * ( ( b raised to 2i ) raised to ei )
j=0
= Õi ( ( b raised to 2j ) raised to ej )
j=0
= Õi’-1 ( ( b raised to 2j ) raised to ej )
j=0
if ei = 1
x’ = x * y
= Õi-1( ( b raised to 2j ) raised to ej ) * ( ( b raised to 2i ) raised to ei )
j=0
= Õi ( ( b raised 2j ) raised to ej )
j=0