The invariant used for this example comes from https://www.win.tue.nl/~kbuchin/teaching/JBP030/notebooks/loop-invariants.html
I'm confused though. The code in the example uses a for
loop.
I translated it to a while
loop, because I understand this better, and I added assertions to test the invariant.
The while
example makes total sense to me, and I can see how the invariant holds at each of the assertion points.
However, in the for
example, the assertion assert total == sum(A[0:i]) and i >= len(A)
fails.
I can see why it might for the i
value, as i
stops incrementing at 4
. But I'm not sure why the final assertion for the sum needs to be assert total == sum(A[0:i + 1])
.
It seems like quite a subtle thing going on here, around "off by one errors." I'm also a bit uncomfortable about the "hard-coding" of the invariant in assert total == sum(A[0:0])
Can anyone please provide an exact conversion of the while
version of my code to a for
version, with all the neccessary assersions for the invariant, and an explanation of how/why they are different?
Any help much appreciated.
def my_sum_while(A):
"""
Loop Invariant: At the start of iteration i of the loop, the variable
`total` should contain the sum of the numbers from the subarray A[0:i].
"""
i = 0
total = 0
assert total == sum(A[0:i])
while i < len(A):
assert total == sum(A[0:i])
total += A[i]
i += 1
assert total == sum(A[0:i]) and i >= len(A)
return total
xs = [1, 2, 3, 4, 5]
print(my_sum_while(xs))
def my_sum_for(A):
"""
Loop Invariant: At the start of iteration i of the loop, the variable
`total` should contain the sum of the numbers from the subarray A[0:i].
"""
total = 0
assert total == sum(A[0:0])
for i in range(len(A)):
assert total == sum(A[0:i])
total += A[i]
assert total == sum(A[0:i]) and i >= len(A)
return total
xs = [1, 2, 3, 4, 5]
print(my_sum_for(xs))