Zulip Chat Archive

Stream: maths

Topic: Recursive definition


Esteban Martínez Vañó (Dec 19 2024 at 08:30):

Hi everyone.

I want to define a recursive function g from to a nonempty linear order type α in such a way that when given a F: Finset α (nonempty), you get for 0 its minimum and for n + 1 you get the minimum of F \ Finset.image g (Finset.Icc 0 n).

My idea is to do something like:

import Mathlib

variable {α: Type*} [Inhabited α] [LinearOrder α]

def Finset.SMC (F: Finset α) (nemp: F  ) :   α
  | 0 => Finset.min' F (Finset.nonempty_iff_ne_empty.mpr nemp)
  | n + 1 => if h: (F \ Finset.image
    (Finset.SMC F nemp) (Finset.Icc 0 n)).Nonempty then
      Finset.min' (F \ Finset.image (Finset.SMC F nemp) (Finset.Icc 0 n)) h
    else default

But it doesn't work. Any ideas?

Esteban Martínez Vañó (Dec 19 2024 at 08:50):

By making this definition

def Finset.min'' (s: Finset α) := if h: s.Nonempty then Finset.min' s h else default

I can simplify to:

def Finset.SMC (F: Finset α) :   α
  | 0 => Finset.min'' F
  | n + 1 => Finset.min'' (F \ Finset.image (Finset.SMC F) (Finset.Icc 0 n))

But still doesn't work :/

Johannes Tantow (Dec 19 2024 at 08:52):

It is not a #mwe you need to add import Mathlib.
You currently need to compute Finset.SMC F nemp in order to compute Finset.SMC F nemp, which is circular. Why would this work on paper?

Esteban Martínez Vañó (Dec 19 2024 at 08:54):

Of course it works in paper, its simply the recursion theorem. You know the value of the function at 0 and supposing you now the value at all the values less than n you can work the value at n.

Esteban Martínez Vañó (Dec 19 2024 at 08:59):

It seem it works by defining: (THIS IS WRONG)

def Finset.SMC (F: Finset α) :   α
  | 0 => Finset.min'' F
  | n + 1 => Finset.min'' (F \ {Finset.SMC F n})

And at the end it should be the same function, but I still would like if is there a way to make the other definition work.

Johannes Tantow (Dec 19 2024 at 09:20):

In this way Lean definitely sees that n is getting smaller. I guess it needs to know that every argument that is used in in image is smaller than n. It is possible to do it by going a bit more basic:

import Mathlib

variable {α: Type*} [Inhabited α] [LinearOrder α]

def Finset.SMC (F: Finset α) (nemp: F  ) (n: ): α :=
  match n with
  | 0 => Finset.min' F (Finset.nonempty_iff_ne_empty.mpr nemp)
  | m + 1 =>
    let image := (Multiset.map (fun x, _h => Finset.SMC F nemp x) (Finset.Icc 0 m).attach.1).toFinset
    if h: (F \ image).Nonempty then
      Finset.min' (F \ image) h
    else default
termination_by n
decreasing_by
  simp at _h
  exact Nat.lt_add_one_of_le _h

Johannes Tantow (Dec 19 2024 at 09:22):

Now we see exactly that it is only called on smaller elements. For that I had to go to Multisets to use map to see more directly what happens.

Esteban Martínez Vañó (Dec 19 2024 at 09:53):

Okay, I think I get what you have done (although I didn't know that much about Lean) and why the error was ocurring in the first place.
Thank you so much!


Last updated: May 02 2025 at 03:31 UTC