Zulip Chat Archive
Stream: general
Topic: Merge sort termination
Mukesh Tiwari (Dec 19 2022 at 05:13):
Hi everyone,
I am wondering how can I show the termination of mergeList
function. (I understand that I need to turn 1 + sizeOf (xhs ++ yh :: yhs)
into 2 + sizeOf (xhs ++ yhs)
but I am lacking the knowledge of syntax and the required lemmas)
import Init.Data.List
section MergeSort
universe u
variable
{A : Type u}
(f : A -> A -> Bool)
def splitList : Nat -> List A -> List A × List A :=
fun n xs => (List.take n xs, List.drop n xs)
def split : List A -> List A × List A :=
fun xs => splitList (Nat.div (xs.length) 2) xs
def mergeList : List A -> List A -> List A
| [], ys => ys
| xs, [] => xs
| (xh :: xhs), (yh :: yhs) =>
match f xh yh with
| true => xh :: mergeList xhs (yh :: yhs)
| false => yh :: mergeList (xh :: xhs) yhs
termination_by mergeList xs ys => xs ++ ys
have
/-
How to show
A : Type u
xh : A
xhs : List A
yh : A
yhs : List A
⊢ 1 + sizeOf (xhs ++ yhs) < 1 + sizeOf (xhs ++ yh :: yhs)
-/
end MergeSort
Mario Carneiro (Dec 19 2022 at 05:14):
you want to use xs.length + ys.length
as the termination measure, not xs ++ ys
Mukesh Tiwari (Dec 19 2022 at 05:23):
@Mario Carneiro Thanks! Given that the goal is provable, I am still curious about the proof using have
or decreasing_by
syntax.
failed to prove termination, possible solutions:
- Use `have`-expressions to prove the remaining goals
- Use `termination_by` to specify a different well-founded relation
- Use `decreasing_by` to specify your own tactic for discharging this kind of goal
A : Type u
xh : A
xhs : List A
yh : A
yhs : List A
⊢ 1 + sizeOf (xhs ++ yhs) < 1 + sizeOf (xhs ++ yh :: yhs)
Mario Carneiro (Dec 19 2022 at 05:27):
The goal there is more annoying because it relies on the sizeOf
function for lists, which does not have many lemmas about it (because if the automatic proof method doesn't work then you should use something with more sensible proof principles like length
instead)
Mario Carneiro (Dec 19 2022 at 05:31):
theorem foo (xs ys : List A) : sizeOf (xs ++ a :: ys) = 1 + sizeOf a + sizeOf (xs ++ ys) := by
induction xs <;> simp [*]
def mergeList : List A -> List A -> List A
| [], ys => ys
| xs, [] => xs
| (xh :: xhs), (yh :: yhs) =>
match f xh yh with
| true => xh :: mergeList xhs (yh :: yhs)
| false =>
have : 1 + sizeOf (xhs ++ yhs) < 1 + sizeOf (xhs ++ yh :: yhs) := by
simp [foo]; decreasing_trivial
yh :: mergeList (xh :: xhs) yhs
termination_by mergeList xs ys => xs ++ ys
Mario Carneiro (Dec 19 2022 at 05:33):
another termination metric which works here is lexicographic order:
def mergeList : List A -> List A -> List A
| [], ys => ys
| xs, [] => xs
| (xh :: xhs), (yh :: yhs) =>
match f xh yh with
| true => xh :: mergeList xhs (yh :: yhs)
| false => yh :: mergeList (xh :: xhs) yhs
termination_by mergeList xs ys => (xs, ys)
Last updated: Dec 20 2023 at 11:08 UTC