Created
March 6, 2024 19:21
-
-
Save britannio/89f67a33014db589969c64b16ccd0e8e 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 QuickSortMem | |
//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 total_order (#a:Type) (f: (a -> a -> bool)) = | |
(forall a. f a a) (* reflexivity *) | |
/\ (forall a1 a2. (f a1 a2 /\ a1=!=a2) <==> not (f a2 a1)) (* anti-symmetry *) | |
/\ (forall a1 a2 a3. f a1 a2 /\ f a2 a3 ==> f a1 a3) (* transitivity *) | |
/\ (forall a1 a2. f a1 a2 \/ f a2 a1) (* totality *) | |
let total_order_t (a:Type) = f:(a -> a -> bool) { total_order f } | |
let rec sorted #a (f:total_order_t a) (l:list a) | |
: bool | |
= match l with | |
| [] -> true | |
| [x] -> true | |
| x :: y :: xs -> f x y && sorted f (y :: xs) | |
let rec mem (#a:eqtype) (i:a) (l:list a) | |
: bool | |
= match l with | |
| [] -> false | |
| hd :: tl -> hd = i || mem i tl | |
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 #a (f:total_order_t a) (l:list a) | |
: Tot (list a) (decreases (length l)) | |
= match l with | |
| [] -> [] | |
| pivot :: tl -> | |
let hi, lo = partition (f pivot) tl in | |
append (sort f lo) (pivot :: sort f hi) | |
let rec partition_mem (#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)) /\ | |
(forall x. mem x l = (mem x l1 || mem x l2))) | |
= match l with | |
| [] -> () | |
| hd :: tl -> partition_mem f tl | |
let rec sorted_concat (#a:eqtype) | |
(f:total_order_t a) | |
(l1:list a{sorted f l1}) | |
(l2:list a{sorted f l2}) | |
(pivot:a) | |
: Lemma (requires (forall y. mem y l1 ==> not (f pivot y)) /\ | |
(forall y. mem y l2 ==> f pivot y)) | |
(ensures sorted f (append l1 (pivot :: l2))) | |
= match l1 with | |
| [] -> () | |
| hd :: tl -> sorted_concat f tl l2 pivot | |
let rec append_mem (#t:eqtype) | |
(l1 l2:list t) | |
: Lemma (ensures (forall a. mem a (append l1 l2) = (mem a l1 || mem a l2))) | |
= match l1 with | |
| [] -> () | |
| hd::tl -> append_mem tl l2 | |
let rec sort_correct (#a:eqtype) (f:total_order_t a) (l:list a) | |
: Lemma (ensures ( | |
let m = sort f l in | |
sorted f m /\ | |
(forall i. mem i l = mem i m))) | |
(decreases (length l)) | |
= match l with | |
| [] -> () | |
| pivot :: tl -> | |
let hi, lo = partition (f pivot) tl in | |
sort_correct f hi; | |
sort_correct f lo; | |
partition_mem (f pivot) tl; | |
sorted_concat f (sort f lo) (sort f hi) pivot; | |
append_mem (sort f lo) (pivot :: sort f hi) | |
let rec sort_intrinsic (#a:eqtype) (f:total_order_t a) (l:list a) | |
: Tot (m:list a { | |
sorted f m /\ | |
(forall i. mem i l = mem i m) | |
}) | |
(decreases (length l)) | |
= match l with | |
| [] -> [] | |
| pivot :: tl -> | |
let hi, lo = partition (f pivot) tl in | |
partition_mem (f pivot) tl; | |
sorted_concat f (sort_intrinsic f lo) (sort_intrinsic f hi) pivot; | |
append_mem (sort_intrinsic f lo) (pivot :: sort_intrinsic f hi); | |
append (sort_intrinsic f lo) (pivot :: sort_intrinsic f hi) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment