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: Dec 20 2023 at 11:08 UTC