Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Array.qsort_sorted #759

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

feat: Array.qsort_sorted #759

wants to merge 2 commits into from

Conversation

digama0
Copy link
Member

@digama0 digama0 commented Apr 21, 2024

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 of PermStabilizing). What worked better is lemmas like swap_of_append which just relate the array to a list expression like A ++ a :: B ++ b :: C where A.length = i and (A ++ a :: B).length = j, because this way the lists don't interfere with each other (there is only one A preserved before and after the operation), by comparison to array ops like set and swap which turn into if statements and arithmetic goals after every operation.

@nomeata
Copy link
Collaborator

nomeata commented Apr 22, 2024

Have you considered writing List.qsort, prove this correct, and then show how they are related? I found that that is often easier, at least when I verified a Trie data structure.

@digama0
Copy link
Member Author

digama0 commented Apr 22, 2024

Yes, I did. My original goal was to verify the sorting functions in Std.Data.Array.Merge, and all of the functions have natural list counterparts except Array.qsort, which uses Array.swap, index-based manipulation, and fixed size arrays heavily.

@nomeata
Copy link
Collaborator

nomeata commented Apr 22, 2024

I see, in that case a list-based reference implementation probably won't help that much.

@digama0 digama0 added the awaiting-review This PR is ready for review; the author thinks it is ready to be merged. label Apr 23, 2024
@leanprover-community-mathlib4-bot leanprover-community-mathlib4-bot added the merge-conflict This PR has merge conflicts with the `main` branch which must be resolved by the author. label May 1, 2024
@somombo
Copy link
Contributor

somombo commented May 13, 2024

I'll leave this here for anyone interested; I have independently completed a specification and verification of Quicksort .. I basically just bruteforced through many of the types of issues highlighted above, so I could get an initial proof. I have been working on refactoring to improve the style and elaboration time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting-review This PR is ready for review; the author thinks it is ready to be merged. merge-conflict This PR has merge conflicts with the `main` branch which must be resolved by the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants