Module docstring
{"# Definition of merge and mergeSort.
These definitions are intended for verification purposes,
and are replaced at runtime by efficient versions in Init.Data.List.Sort.Impl.
"}
{"# Definition of merge and mergeSort.
These definitions are intended for verification purposes,
and are replaced at runtime by efficient versions in Init.Data.List.Sort.Impl.
"}
List.nil_merge
theorem
(ys : List α) : merge [] ys le = ys
List.merge_right
theorem
(xs : List α) : merge xs [] le = xs
List.MergeSort.Internal.splitInTwo
definition
(l : { l : List α // l.length = n }) : { l : List α // l.length = (n + 1) / 2 } × { l : List α // l.length = n / 2 }
/--
Split a list in two equal parts. If the length is odd, the first part will be one element longer.
This is an implementation detail of `mergeSort`.
-/
def MergeSort.Internal.splitInTwo (l : { l : List α // l.length = n }) :
{ l : List α // l.length = (n+1)/2 }{ l : List α // l.length = (n+1)/2 } × { l : List α // l.length = n/2 } :=
let r := splitAt ((n+1)/2) l.1
(⟨r.1, by simp [r, splitAt_eq, l.2]; omega⟩, ⟨r.2, by simp [r, splitAt_eq, l.2]; omega⟩)
List.mergeSort
definition
: ∀ (xs : List α) (le : α → α → Bool := by exact fun a b => a ≤ b), List α
/--
A stable merge sort.
This function is a simplified implementation that's designed to be easy to reason about, rather than
for efficiency. In particular, it uses the non-tail-recursive `List.merge` function and traverses
lists unnecessarily.
It is replaced at runtime by an efficient implementation that has been proven to be equivalent.
-/
-- Because we want the sort to be stable, it is essential that we split the list in two contiguous
-- sublists.
def mergeSort : ∀ (xs : List α) (le : α → α → Bool := by exact fun a b => a ≤ b), List α
| [], _ => []
| [a], _ => [a]
| a :: b :: xs, le =>
let lr := splitInTwo ⟨a :: b :: xs, rfl⟩
have := by simpa using lr.2.2
have := by simpa using lr.1.2
merge (mergeSort lr.1 le) (mergeSort lr.2 le) le
termination_by xs => xs.length
List.zipIdxLE
definition
(le : α → α → Bool) (a b : α × Nat) : Bool
/--
Given an ordering relation `le : α → α → Bool`,
construct the lexicographic ordering on `α × Nat`.
which first compares the first components using `le`,
but if these are equivalent (in the sense `le a.2 b.2 && le b.2 a.2`)
then compares the second components using `≤`.
This function is only used in stating the stability properties of `mergeSort`.
-/
def zipIdxLE (le : α → α → Bool) (a b : α × Nat) : Bool :=
if le a.1 b.1 then if le b.1 a.1 then a.2 ≤ b.2 else true else false