Zulip Chat Archive
Stream: lean4
Topic: termination_by and Prod.Lex
Scott Morrison (Oct 04 2023 at 06:04):
I'm failing to work out how to have the correct hypothesis in the following proof so that termination_by works with the lexicographic order.
Can anyone help me with the 2nd call to R r here?
axiom f : Nat → Nat
axiom g : Nat → Nat
axiom s : Nat → Nat
axiom h : (n : Nat) → ¬ (f (s n) < f n) → (f (s n) = f n ∧ g (s n) < g n)
noncomputable def R (n : Nat) : Nat :=
  let r := s n
  if h₀ : f r < f n then
    R r
  else
    have h₁ : f r = f n := (h n h₀).1
    have h₂ : g r < g n := (h n h₀).2
    R r
termination_by R n => (f n, g n)
Scott Morrison (Oct 04 2023 at 06:05):
Note that the error message
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
case h
n: Nat
r: Nat := s n
h₀: ¬f r < f n
h₁: f r = f n
h₂: g r < g n
⊢ f (s n) < f n
incorrectly appears on the 1st call to R r. I'll track down/create the issue for this in a moment.
Scott Morrison (Oct 04 2023 at 10:55):
axiom f : Nat → Nat
axiom g : Nat → Nat
axiom s : Nat → Nat
axiom h : (n : Nat) → ¬ (f (s n) < f n) → (f (s n) = f n ∧ g (s n) < g n)
def Prod.Lex.right'' [LT α] [LT β] {a₁ a₂ : α} {b₁ b₂ : β} (ha : a₁ = a₂) (hb : b₁ < b₂) :
    Prod.Lex (· < ·) (· < · ) (a₁, b₁) (a₂, b₂) :=
  ha ▸ Prod.Lex.right a₁ hb
noncomputable def R (n : Nat) : Nat :=
  let r := s n
  if h₀ : f r < f n then
    R r
  else
    have h₁ : f r = f n := (h n h₀).1
    have h₂ : g r < g n := (h n h₀).2
    have := Prod.Lex.right'' h₁ h₂
    R r
termination_by R n => (f n, g n)
decreasing_by
  first | assumption | (constructor; assumption)
works, but makes me sad.
Scott Morrison (Oct 04 2023 at 10:56):
(both that I needed to define Prod.Lex.right'' and that I needed to write a custom decreasing_by)
Ioannis Konstantoulas (Oct 04 2023 at 11:50):
Never mind, I was being silly.
Ioannis Konstantoulas (Oct 04 2023 at 11:56):
The following manual proof worked for me:
noncomputable def R' (n : Nat) : Nat :=
  let r := s n
  R' r
termination_by R' _ => (f n, g n)
decreasing_by
  simp_wf
  have : (f r < f n) ∨ (f r ≥ f n) :=
    Nat.lt_or_ge (f r) (f n)
  cases this with
  | inl h₉ => apply Prod.Lex.left; exact h₉
  | inr h₈ =>
    have h₅ := Nat.not_lt_of_le h₈
    apply Prod.Lex.right'
    have h₁ : f r = f n := (h n h₅).1
    linarith
    have h₂ : g r < g n := (h n h₅).2
    assumption
Scott Morrison (Oct 04 2023 at 12:13):
It hadn't occurred to me to put all the work in decreasing_by. I think that won't work in my application, but I'll have a think about it, thanks. :-)
Ioannis Konstantoulas (Oct 04 2023 at 12:18):
In any case, the problem seems to be that the type of Prod.Lex.right is
constructor Prod.Lex.right.{u, v} : ∀ {α : Type u} {β : Type v} {ra : α → α → Prop} {rb : β → β → Prop} (a : α)
  {b₁ b₂ : β}, rb b₁ b₂ → Prod.Lex ra rb (a, b₁) (a, b₂)
whereas we intuitively treat it as
constructor Prod.Lex.right1.{u, v} : ∀ {α : Type u} {β : Type v} {ra : α → α → Prop} {rb : β → β → Prop} (a1 a2  : α)
  {h : a1 = a2} {b₁ b₂ : β}, rb b₁ b₂ → Prod.Lex ra rb (a1, b₁) (a2, b₂)
or similar, and Lean cannot reconcile the two.
Ioannis Konstantoulas (Oct 04 2023 at 17:05):
A positional marker in R to distinguish the two calls fixes the error position, but then the required goal is decidedly wrong:
noncomputable def R (n : Nat) (t : Bool) : Nat :=
  let r := s n
  if h₀ : f r < f n then
    R r true
  else
    have h₁ : f r = f n := (h n h₀).1
    have h₂ : g r < g n := (h n h₀).2
    R r false
termination_by R n _ => (f n, g n)
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
case h
n: ℕ
t: Bool
r: ℕ := s n
h₀: ¬f r < f n
h₁: f r = f n
h₂: g r < g n
⊢ f (s n) < f n
So there can be no have that can close the goal in that branch, since the goal is False.
Last updated: May 02 2025 at 03:31 UTC