Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This was a surprisingly challenging proof. It really highlights some of the pain involved in verifying programs which perform many array modifications without something isomorphic to separation logic, because one has to hold on to information about the rest of the array across many function calls that could potentially modify any part of the array.
I tried using invariants based on indexes, describing sorting in the form
i < j -> as[i] <= as[j]
with various restrictions on i,j in the algorithm, but this turned out to be quite painful (some remnant of this still remains in the definition ofPermStabilizing
). What worked better is lemmas likeswap_of_append
which just relate the array to a list expression likeA ++ a :: B ++ b :: C
whereA.length = i
and(A ++ a :: B).length = j
, because this way the lists don't interfere with each other (there is only oneA
preserved before and after the operation), by comparison to array ops likeset
andswap
which turn into if statements and arithmetic goals after every operation.