Zulip Chat Archive

Stream: Is there code for X?

Topic: fail to show termination of mergeSort


Asei Inoue (Aug 23 2025 at 12:17):

variable {α : Type}
variable (le : α  α  Prop) [DecidableRel le]

local infixl:50 " ≼ " => le

def merge (xs ys : Array α) : Array α := Id.run do
  let mut i := 0
  let mut j := 0
  let mut result := Array.empty
  while h : i < xs.size && j < ys.size do
    have : i < xs.size := by grind
    have : j < ys.size := by grind
    if xs[i]  ys[j] then
      result := result.push xs[i]
      i := i + 1
    else
      result := result.push ys[j]
      j := j + 1
  return result ++ xs.extract (start := i) ++ ys.extract (start := j)

#guard merge (fun x y : Nat => x  y) #[] #[] = #[]
#guard merge (fun x y : Nat => x  y) #[1, 2] #[] = #[1, 2]
#guard merge (fun x y : Nat => x  y) #[] #[1, 2] = #[1, 2]
#guard merge (fun x y : Nat => x  y) #[3, 4, 5] #[1, 2] = #[1, 2, 3, 4, 5]

def mergeSort (xs : Array α) : Array α := Id.run do
  if h : xs.size  1 then
    return xs
  else
    let mid := xs.size / 2
    have left_lem : (xs.extract 0 mid).size < xs.size := calc
      _ = mid - 0 := by apply Array.size_extract_of_le (as := xs) (h := by grind)
      _ = xs.size / 2 := by simp [mid]
      _ < xs.size := by grind
    /- 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
      α : Type
      xs : Array α
      h : ¬xs.size ≤ 1
      mid : Nat := xs.size / 2
      left_lem : (xs.extract 0 mid).size < xs.size
      ⊢ sizeOf (xs.extract 0 (xs.size / 2)) < sizeOf xs -/
    let left := mergeSort <| xs.extract (start := 0) (stop := mid)
    let right := mergeSort <| xs.extract (start := mid) (stop := xs.size)

    return merge le left right
termination_by xs

Asei Inoue (Aug 23 2025 at 12:18):

how to show this? I think sizeOf xs = xs.size, but is this wrong?

Weiyi Wang (Aug 23 2025 at 12:22):

Just by specifying termination_by xs.size it passes

Asei Inoue (Aug 23 2025 at 12:24):

@Weiyi Wang Thank you!

Violeta Hernández (Aug 23 2025 at 17:44):

FYI, docs#List.sort is a version of merge-sort for lists.

Robin Arnez (Aug 23 2025 at 18:24):

you probably meant docs#List.mergeSort


Last updated: Dec 20 2025 at 21:32 UTC