Solution:

English: The items in the array at indices low .. i are less than or equal to pivot and the items in the array at indices j .. high are greater than or equal to pivot.

Logic: ((for all r) (low <= r r <= i ) (a[r] <= pivot))

((for all s) (j <= s s <= high) (a[s] >= pivot))

Optional proof sketch:

This invariant is certainly true the first time, since i is initialized to low-1 and j to high+1, and the range of quantified values is therefore empty.

In between two iterations of the loop, items < pivot which have indices less than i are left in place, until an item >= pivot is found. Similarly, items > pivot which have indices greater than j are left in place, until an item <= pivot is found. These two items are then swapped, so the invariant is maintained.

When the loop exits, i >= j. Then every element with an index <= i is <= pivot and every element with an index >= j is >= pivot. By sorting those two array segments, we then have a sorted array.