Created
March 6, 2024 19:41
-
-
Save britannio/e352a93ee3ee025818629b523f6ab51d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module QuickSortPermutationSimple | |
#push-options "--fuel 1 --ifuel 1" | |
//Some auxiliary definitions to make this a standalone example | |
let rec length #a (l:list a) | |
: nat | |
= match l with | |
| [] -> 0 | |
| _ :: tl -> 1 + length tl | |
let rec append #a (l1 l2:list a) | |
: list a | |
= match l1 with | |
| [] -> l2 | |
| hd :: tl -> hd :: append tl l2 | |
let rec sorted (l:list int) | |
: bool | |
= match l with | |
| [] -> true | |
| [x] -> true | |
| x :: y :: xs -> x <= y && sorted (y :: xs) | |
let rec count (#a:eqtype) (x:a) (l:list a) | |
: nat | |
= match l with | |
| hd::tl -> (if hd = x then 1 else 0) + count x tl | |
| [] -> 0 | |
let mem (#a:eqtype) (i:a) (l:list a) | |
: bool | |
= count i l > 0 | |
let is_permutation (#a:eqtype) (l m:list a) = | |
forall x. count x l = count x m | |
let rec append_count (#t:eqtype) | |
(l1 l2:list t) | |
: Lemma (ensures (forall a. count a (append l1 l2) = (count a l1 + count a l2))) | |
= match l1 with | |
| [] -> () | |
| hd::tl -> append_count tl l2 | |
let rec partition (#a:Type) (f:a -> bool) (l:list a) | |
: x:(list a & list a) { length (fst x) + length (snd x) = length l } | |
= match l with | |
| [] -> [], [] | |
| hd::tl -> | |
let l1, l2 = partition f tl in | |
if f hd | |
then hd::l1, l2 | |
else l1, hd::l2 | |
let rec sort (l:list int) | |
: Tot (list int) (decreases (length l)) | |
= match l with | |
| [] -> [] | |
| pivot :: tl -> | |
let hi, lo = partition ((<=) pivot) tl in | |
append (sort lo) (pivot :: sort hi) | |
let rec partition_mem_permutation (#a:eqtype) | |
(f:(a -> bool)) | |
(l:list a) | |
: Lemma (let l1, l2 = partition f l in | |
(forall x. mem x l1 ==> f x) /\ | |
(forall x. mem x l2 ==> not (f x)) /\ | |
(is_permutation l (append l1 l2))) | |
= match l with | |
| [] -> () | |
| hd :: tl -> | |
partition_mem_permutation f tl; | |
let hi, lo = partition f tl in | |
append_count hi lo; | |
append_count hi (hd::lo); | |
append_count (hd :: hi) lo | |
let rec sorted_concat (l1:list int{sorted l1}) | |
(l2:list int{sorted l2}) | |
(pivot:int) | |
: Lemma (requires (forall y. mem y l1 ==> not (pivot <= y)) /\ | |
(forall y. mem y l2 ==> pivot <= y)) | |
(ensures sorted (append l1 (pivot :: l2))) | |
= match l1 with | |
| [] -> () | |
| hd :: tl -> sorted_concat tl l2 pivot | |
let permutation_app_lemma (#a:eqtype) (hd:a) (tl:list a) | |
(l1:list a) (l2:list a) | |
: Lemma (requires (is_permutation tl (append l1 l2))) | |
(ensures (is_permutation (hd::tl) (append l1 (hd::l2)))) | |
= append_count l1 l2; | |
append_count l1 (hd :: l2) | |
let rec sort_correct (l:list int) | |
: Lemma (ensures ( | |
sorted (sort l) /\ | |
is_permutation l (sort l))) | |
(decreases (length l)) | |
= match l with | |
| [] -> () | |
| pivot :: tl -> | |
let hi, lo = partition ((<=) pivot) tl in | |
partition_mem_permutation ((<=) pivot) tl; | |
append_count lo hi; | |
append_count hi lo; | |
assert (is_permutation tl (append lo hi)); | |
sort_correct hi; | |
sort_correct lo; | |
sorted_concat (sort lo) (sort hi) pivot; | |
append_count (sort lo) (sort hi); | |
assert (is_permutation tl (sort lo `append` sort hi)); | |
permutation_app_lemma pivot tl (sort lo) (sort hi) | |
let rec sort_intrinsic (l:list int) | |
: Tot (m:list int { | |
sorted m /\ | |
is_permutation l m | |
}) | |
(decreases (length l)) | |
= match l with | |
| [] -> [] | |
| pivot :: tl -> | |
let hi, lo = partition ((<=) pivot) tl in | |
partition_mem_permutation ((<=) pivot) tl; | |
append_count lo hi; append_count hi lo; | |
sorted_concat (sort_intrinsic lo) (sort_intrinsic hi) pivot; | |
append_count (sort_intrinsic lo) (sort_intrinsic hi); | |
permutation_app_lemma pivot tl (sort_intrinsic lo) (sort_intrinsic hi); | |
append (sort_intrinsic lo) (pivot :: sort_intrinsic hi) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment