Zulip Chat Archive

Stream: new members

Topic: termination_by from exists lemma


Markus Schmaus (Feb 29 2024 at 07:37):

How can I show termination in this mwe?

import Mathlib

def foo (g : Nat  Nat) (x : Nat) (finite :  (n : Nat), g^[n] x = 0) : Nat :=
  let rec loop (i : Nat) (x : Nat) : Nat :=
    if x = 0 then i
    else loop (i+1) (g x)
  loop 0 x

Joachim Breitner (Feb 29 2024 at 14:47):

Tricky. Note that loop on its own isn’t terminating on all inputs (set g i = i and i > 0). So you at least have to thread through the finiteness assumption through loop.

Then I you’d need a well-founded relation to decrease. If your finiteness predicate was in Type and not Prop (finite : { n : Nat // g^[n] x = 0}), you could extract that n and then use n - i as a decreasing measure. Is that an option for you?

Timo Carlin-Burns (Feb 29 2024 at 15:10):

I think this strategy could work:

import Mathlib

def foo (g : Nat  Nat) (x : Nat) (finite :  (n : Nat), g^[n] x = 0) : Nat :=
  let rec loop (i : Nat) (x : Nat) (finite :  (n : Nat), g^[n] x = 0) : Nat :=
    if hx : x = 0 then i
    else
      have finite' :  (n : Nat), g^[n] (g x) = 0 := sorry
      have :  (m : ), ( n < m, ¬g^[n] (g x) = 0)  ¬g^[m] x = 0 := sorry
      loop (i+1) (g x) finite'
  termination_by Nat.find finite
  loop 0 x finite

Joachim Breitner (Feb 29 2024 at 15:13):

Quite likely, given that foo is essentially Nat.find :) The implementation of Nat.find shows one way of defining this.

Timo Carlin-Burns (Feb 29 2024 at 15:20):

def foo (g : Nat  Nat) (x : Nat) (finite :  (n : Nat), g^[n] x = 0) : Nat :=
  let rec loop (i : Nat) (x : Nat) (finite :  (n : Nat), g^[n] x = 0) : Nat :=
    if hx : x = 0 then i
    else
      have finite' :  (n : Nat), g^[n] (g x) = 0 := by
        rcases finite with n, h
        match n with
        | 0 => contradiction
        | (n + 1) => use n, h
      have :  (m : ), ( n < m, ¬g^[n] (g x) = 0)  ¬g^[m] x = 0
        | 0, _ => hx
        | (m + 1), h => h m (Nat.lt_succ_self m)
      loop (i+1) (g x) finite'
  termination_by Nat.find finite
  loop 0 x finite

Markus Schmaus (Feb 29 2024 at 18:37):

Thank you both for your help. It turns out this question was trickier than I thought it would.

Timo Carlin-Burns (Feb 29 2024 at 19:27):

To be explicit, this minimized example would be better written using Nat.find directly like so:

def foo (g : Nat  Nat) (x : Nat) (finite :  (n : Nat), g^[n] x = 0) : Nat :=
  Nat.find finite

I don't know if that applies to your original problem too.


Last updated: May 02 2025 at 03:31 UTC