Java Reference
In-Depth Information
IV.6
A neat example: fusc
Consider a function f defined as follows —e.g.
f(13)
is
5
.
f(0) = 0
f(1) = 1
f(2*n) = f(n) (for n > 0)
f(2*n+1) = f(n) + f(n+1) (for n > 0)
We want a program segment
S
that, given
N≥0
, calculates
f(N)
. One idea
would be to assign
N
to a fresh variable
n
and then repeatedly decrease
n
, main-
taining some invariant, until
n
is
0
or
1
. The first, naive, invariant would then be:
f(N) = f(n)
Indeed, if
n
is even, we can divide
n
by
2
and the invariant is maintained (since
f(2n) = f(n)
. But if
n
is odd, there is no way to decrease
n
and keep this invari-
ant true. The invariant is too simple.
Where do we look for inspiration in developing the invariant? The
only
pos-
sible place is the definition of
f
. Even a postcondition like
f(N) = b
(meaning
b
contains the answer) would not help. In Sec. IV.4, in developing a program seg-
ment to calculate
max(x, y)
, we also had to turn to the definition of
max
. Here,
it is the same thing: a definition provides the inspiration.
Notice that the right sides of two recursive formulas for
f
:
f(2*n) = f(n)
f(2*n+1) = f(n) + f(n+1)
are linear combinations of
f(n)
and
f(n+1)
:
f(2*n) = 1*f(n) + 0*f(n+1)
f(2*n+1) = 1*f(n) + 1*f(n+1)
and this inspires us to try an invariant in which the righthand side is a (more gen-
eral) linear combination of
f(n)
and
f(n+1)
:
P: f(N) = a*f(n) + b*f(n+1)
Now, we write the loop, hoping that we can make progress by halving
n
at
each iteration —but we assume we would need two cases, depending on whether
n
is even or odd. We have skipped all the obvious steps of this development.
{
N>=0
}
n= N; a= 1; b= 0;
{
invariant
P: f(N) = a*f(n) + b*f(n+1)
}
while
(n != 0) {
if
(n
is even
) n, a, b= n/2, E, F;
else
n, a, b= n/2, G, H;
}
{
f(N) = b
}
Search WWH ::
Custom Search