2

I am trying to learn about loop invariants in C. I have a code and I have the loop invariant but I do not fully understand why. Here is the code:

/* 0 ≤ m < n < ASIZE AND A[m] ≥ A[m+1] ≥ ... ≥ A[n] */
void ReverseArray(int A[], int m, int n)
{
  int temp;
  while (m < n)
  {
        temp = A[m]; A[m] = A[n]; A[n] = temp;
        m++;
        n--;
        /* loop invariant: 0 < m < n < ASIZE OR m == n OR m == n+1 */
} 
}
/* for the initial values of m and n, A[m] ≤ A[m+1] ≤ ... ≤ A[n] */

The loop invariant is: 0 < m < n < ASIZE OR m == n OR m == n+1

I think I understand the 0 < m < n < ASIZE. It would be because of the while loop and it says that m cant be 0 but it has to be less than n. And n has to be smaller than the array size.

But I do not understand why m == n and m == n+1.

Any thoughts?

Daniel Daranas
  • 22,454
  • 9
  • 63
  • 116
user081608
  • 1,093
  • 3
  • 22
  • 48
  • 1
    Is this some extension of C? Is there a particular reason you used those characters? – Joe Oct 03 '13 at 16:53
  • @Joe Some forms of pseudocode use braces + asterisks, or in this case diamonds, for comments. It is not valid C. – Kninnug Oct 03 '13 at 16:55
  • Those characters actually given there to understand what is Loop invariant. See [informal example about Loop_invariant](http://en.wikipedia.org/wiki/Loop_invariant) – Gangadhar Oct 03 '13 at 16:56
  • @Kninnug I thought it might be some Literate Programming type extension. I've seen pseudocode with all kinds of things in it, but this is real code, hence my curiosity. – Joe Oct 03 '13 at 18:56

3 Answers3

1

But I do not understand why m == n and m == n+1.

At the point were the loop invariant is located, this expression (the loop invariant) is guaranteed to be true:

0 < m < n < ASIZE OR m == n OR m == n+1

However, this (the "part that you understand") is not always true:

0 < m < n < ASIZE

Why? Because m is incremented, n is decremented, hence m < n may not be true anymore.

That's why you need to "amplify" the loop invariant so that it is always true, including these cases, m == n and m == n+1, which may arise during the normal execution of the loop.

So if you said that the invariant is just the "part that you understand", you would be wrong - your loop invariant would fail, which is (by definition) a no-no.

Daniel Daranas
  • 22,454
  • 9
  • 63
  • 116
1

Write down 2 cases of procedure - for even and odd length of array. For example create a table with number of iteration, array and values of m and n before itera. I believe it would be simplest to do it on your own and proceed by code line by line (table itself might not be so helpful in understanding the whole problem as doing it).

PS. The invariant seems to be too weak to establish the postcondition.

Maciej Piechotka
  • 7,028
  • 6
  • 39
  • 61
  • What do you mean by it seems to weak? – user081608 Oct 03 '13 at 17:01
  • 1
    @user081608: As written, the loop invariant only says things about *m* and *n*. In order to establish that the array has been rearranged as desired, the loop invariant must also say things about the contents of the array. – Eric Postpischil Oct 03 '13 at 17:04
1

If before the loop body, it was the case that m + 1 == n, then at the end of the loop, m will have been incremented and n will have been decremented. At that point, m == n + 1.

For example, when m has the value 2, and n has the value 3. Then after m++; n--;, m has the value 3 and n has the value 2.

If before the loop body, it was the case that m + 2 == n, then after the loop body, m == n. For example if m has the value 2 and n has the value 4, then afterwards, m is 3 and n is 3.

For either of the cases where after the loop body the result is m == n or m == n + 1, the loop control will be false, and so that case will cause the loop to stop.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • Okay that logic makes sense. When approaching functions and trying to find the loop invariant is there a method used to test these type of things? Or is it just something you know by looking at the function? – user081608 Oct 03 '13 at 17:04
  • Before you start the loop, there is an initial state of your data, and there is a goal state to be reached when the loop is done. The loop invariant should be something that will validate that you are getting closer to your goal. – jxh Oct 03 '13 at 17:09
  • Okay so basically, the loop invariant finds proofs of what can happen when you plug different types of data into the function? – user081608 Oct 03 '13 at 17:14
  • The loop invariant should look like a post condition that somehow spells out that you are getting closer to your real post condition. Like, if you are computing a sum of an array of integers, the loop invariant would be something like (`0 <= i` and `i < n` and `sum ==` sum of all numbers `a[0]`..`a[i]`, OR `i == n`). – jxh Oct 03 '13 at 17:18