algorithmloopsproofloop-invariant

Using loop invariants to prove correctness of a simple algorithm


I'm attempting to learn the loop invariant technique to produce more efficient algorithms. My understanding of proving correctness through evaluating loop invariants is that the loop invariants must be true before iteration, and after iteration, to confirm the wanted output.

In the case of the algorithm I put together below (sorting a sequence in decreasing order)- this is the property I believe satifies confirmation of correctness:

"Target would be sequence is decreasing such that A[j] > A[i] for all i from 0 to j-1"

I also think i >=0 and i < A.length would be loop invariants in this case.

In examing the three steps for loop invariants (initialization, maintenance, termination)...does what I came up with make sense in this context? I feel like I'm still not quite understanding how to apply the concept in this instance.

static void Sort(int array[]) {
  int size = array.length; 
  
  for (int i = 0; i < size - 1; i++)
   
     for (int j = i + 1; j < size; j++)
     
        if (array[j] > array[i]) {
        
           // swapping elements. 
           int buffer = array[j];
           array[j] = array[i];
           array[i] = buffer;
           
        } 

Solution

  • There is a "background invariant" saying that the content of the array is only permuted (no value modified, suppressed or added). The invariance is guaranteed by the fact that the only operations that modify the array are swaps.

    Now, observe that the inner loop addresses only the elements as of i, where i goes increasing. This means that the initial section of the array (until i-1) must be the beginning of the sorted sequence. This is an invariant for the outer loop. So the purpose of the inner loop is to find the next element of the sorted sequence and bring it to the position i.

    This leads us to the invariant of the inner loop, which expresses that the slot i contains the smallest value among the values seen so far, i.e. in the range i..j.

    Illustration:

    If we apply the algorithm to the array

    6 8 1 3 4 7 0 9
    

    we can affirm that after two executions of the outer loop, the array will start with

    1 3
    

    As the rest of the array may have been scrambled, it is difficult to predict what happens next in the inner loop.

    Anyway, during the first iteration of the outer loop, after three iterations of the inner loop, we know that the first value will be

    1
    

    as it is the smallest among

    6 8 1
    

      for (int i = 0; i < size - 1; )
         // array[0..i-1] is the prefix of the sorted sequence
         for (int j = i + 1; j < size; )
            // array[i] is the smallest among array[i..j-1]
            if (array[j] > array[i]) {
               // swapping elements. 
               int buffer = array[j];
               array[j] = array[i];
               array[i] = buffer;              
            } 
            // array[i] is the smallest among array[i..j]
            j++;
            // array[i] is the smallest among array[i..j-1]
         }
         // array[0..i] is the prefix of the sorted sequence
         i++;
         // array[0..i-1] is the prefix of the sorted sequence