Zulip Chat Archive

Stream: lean4

Topic: Failed to generate equational theorem


Anand Rao (Feb 12 2022 at 12:51):

I am facing an error when trying to simplify function definitions that make use of decreasing_by to show termination. I have created a minimal example of this issue that tries to calculate the length of a list in an extremely contrived way:

inductive ListSplit : List α  Type _
  | split l₁ l₂ : ListSplit (l₁ ++ l₂)

def splitList {α : Type _} : (l : List α)  ListSplit l
  | [] => ListSplit.split [] []
  | h :: t => ListSplit.split [h] t

theorem Nat.lt_add_left {m n : Nat}  : m < n + m := sorry
theorem Nat.lt_add_right {m n : Nat} : m < m + n := sorry

def len : List α  Nat
  | [] => 0
  | a :: [] => 1
  | l =>
    match (splitList l) with
      | ListSplit.split fst snd =>
        len fst + len snd
termination_by _ l => l.length
decreasing_by
  simp [measure, id, invImage, InvImage, Nat.lt_wfRel, WellFoundedRelation.rel, sizeOf] <;>
  first
    | apply Nat.lt_add_right
    | apply Nat.lt_add_left

theorem listlen :  l : List α, l.length = len l := by
  intro l
  induction l with
    | nil => rfl
    | cons h t ih =>
      simp [List.length]
      simp [len] -- Error: failed to generate equational theorem for 'len'

Does anyone know the reason for this issue and how to bypass it? Thank you in advance.

Leonardo de Moura (Feb 12 2022 at 15:58):

This issue has been fixed a few days ago. The Lean 4 master can generate the equational theorems for len.
Here is the full example.

inductive ListSplit : List α  Type _
  | split l₁ l₂ : ListSplit (l₁ ++ l₂)

def splitList {α : Type _} : (l : List α)  ListSplit l
  | [] => ListSplit.split [] []
  | h :: t => ListSplit.split [h] t

theorem Nat.lt_add_left {m n : Nat}  : m < n + m := sorry
theorem Nat.lt_add_right {m n : Nat} : m < m + n := sorry

def len : List α  Nat
  | [] => 0
  | a :: [] => 1
  | l =>
    match splitList l with
    | ListSplit.split fst snd => len fst + len snd
termination_by _ l => l.length
decreasing_by
  simp [measure, id, invImage, InvImage, Nat.lt_wfRel, WellFoundedRelation.rel, sizeOf] <;>
  first
    | apply Nat.lt_add_right
    | apply Nat.lt_add_left

theorem len_nil : len ([] : List α) = 0 := by
  simp [len]

-- The `simp [len]` above generated the following equation theorems for len
#check @len._eq_1
#check @len._eq_2
#check @len._eq_3 -- It is conditional, and may be tricky to use.

theorem len_1 (a : α) : len [a] = 1 := by
  simp [len]

theorem len_2 (a b : α) (bs : List α) : len (a::b::bs) = 1 + len (b::bs) := by
  conv => lhs; unfold len

-- The `unfold` tactic above generated the following theorem
#check @len._unfold

theorem len_cons (a : α) (as : List α) : len (a::as) = 1 + len as := by
  cases as with
  | nil => simp [len_1, len_nil]
  | cons b bs => simp [len_2]

theorem listlen :  l : List α, l.length = len l := by
  intro l
  induction l with
  | nil => rfl
  | cons h t ih =>
    simp [List.length, len_cons, ih]
    rw [Nat.add_comm]

Last updated: Dec 20 2023 at 11:08 UTC