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