Zulip Chat Archive

Stream: mathlib4

Topic: Chains to LTSeries


Quinn La Fond (Jul 22 2025 at 16:29):

I am at the tail end of finishing my formalization of the statement: "integral extensions preserve Krull dimension". Unfortunately, , since I was bad at parsing the mathlib4 library when I started this mini project, I formalized all of my "helper" lemmas in terms of finite subsets of PrimeSpectrum A which were totally ordered. In other words, the objects I was dealing with, and inductively applying Going Up to were things like S : Set (PrimeSpectrum A) with attributes S.Finite and IsChain ( . < . ) S.

In hindsight, this was probably not the best way to write everything as Krull DImension is defined using LTSeries which seem to me to be injective functions from Fin(n) to Set(PrimeSpectrum A) preserving the order on Fin(n). Rather than rewrite all of my Lemma's I thought I could prove the following:

lemma krullDim_chain_leq
    {α β : Type*} [PartialOrder α] [PartialOrder β]
    (H :  {S : Set α},
    IsChain (· < ·) S  S.Finite   T : Set β,
    IsChain (· < ·) T  T.Finite  (Nat.card S = Nat.card T)) :
    krullDim α  krullDim β

The strategy of the proof is as follows:
1) Start with an LTSeries in alpha
2) Turn the LTSeries into a set
3) Show this set is finite and is a chain
4) Use the hypothesis H to get a finite chain T of the same cardinality in beta
5) Turn T back into an LTSeries

I am stuck on step 5, i.e. I have a finite chain T of the same cardinality of the set in alpha, but I cannot seem figure out how to get it to be an LTSeries. Does anyone have any advice on how one could approach this?

Aaron Liu (Jul 22 2025 at 19:25):

repeatedly extract the minimum

Quinn La Fond (Jul 22 2025 at 19:35):

@Aaron Liu I agree that that makes sense from a mathematical pov, but I am unsure of how to implement in this procedure in lean.

Aaron Liu (Jul 22 2025 at 19:35):

There should be a theorem that says a finite chain has a minimum element

Aaron Liu (Jul 22 2025 at 19:37):

you can recursively define the nth element from the bottom as the minimum element of the chain minus all the ith elements for which i < n

Quinn La Fond (Jul 23 2025 at 04:15):

Yes I have the minimum element, I meant how do I recursively define an LTSeries? It is a function from Fin(n) for some n to a partially ordered set. I don't know how to actually construct such a function.

Aaron Liu (Jul 23 2025 at 05:18):

Same as you do normally (or have you never done so before?)

Aaron Liu (Jul 23 2025 at 05:19):

Call the function from inside itself

Aaron Liu (Jul 23 2025 at 05:19):

If you can trouble come back with an error message and we can help you fix it

Quinn La Fond (Jul 23 2025 at 05:21):

I have never done so before lol I am very much learning by doing atm

Quinn La Fond (Jul 23 2025 at 05:23):

(I also emberrasingly do not know what it means to call the function from inside itself)

Aaron Liu (Jul 23 2025 at 05:24):

Have you done recursive functions in other programming languages before?

Aaron Liu (Jul 23 2025 at 05:24):

Do you know what it means to call a function?

Quinn La Fond (Jul 23 2025 at 16:24):

I vaguely recall doing this in C like 4 years ago for a computational physics course but that was my only prior exposure to programming languages before this

Quinn La Fond (Jul 23 2025 at 16:25):

Aaron Liu said:

Do you know what it means to call a function?

This is like asking the computer to invoke something you've already defined right?

Kevin Buzzard (Jul 23 2025 at 17:40):

Quinn La Fond said:

I am stuck on step 5, i.e. I have a finite chain T of the same cardinality of the set in alpha, but I cannot seem figure out how to get it to be an LTSeries. Does anyone have any advice on how one could approach this?

My advice is: post a #mwe

Quinn La Fond (Jul 23 2025 at 20:14):

@Kevin Buzzard I read the mean working example page, but I am not totally sure how to provide such an example. I would say that I am essentially trying to prove the following lemma:

import Mathlib
open Order

lemma chain_to_LTseries  {β : Type* } [PartialOrder β]
  (T : Set β)  (T_chain : IsChain (· < · ) T) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
   T_series : LTSeries β , T_series.length  = Nat.card T -1 := by

  sorry

I think my main problem is that I don't really know how to recursively define a function...

Quinn La Fond (Jul 27 2025 at 16:43):

@Aaron Liu Do you have any further insight on this?

Aaron Liu (Jul 27 2025 at 16:44):

Maybe try something simpler first

Quinn La Fond (Jul 27 2025 at 16:44):

Such as?

Aaron Liu (Jul 27 2025 at 16:47):

define a function recursively

Aaron Liu (Jul 27 2025 at 16:48):

try the fibonacci sequence

Quinn La Fond (Jul 27 2025 at 16:49):

I understand conceptually how recursion is supposed to work, I just don't fully understand how it is supposed to work in Lean from a syntax pov.

Kenny Lau (Jul 27 2025 at 16:51):

I think that's why he suggested fibonacci

Kenny Lau (Jul 27 2025 at 16:52):

More specifically, in the NNG you have only been exposed to proving theorems (and in Lean, theorems have no data), so now you're stepping onto a new zone

Kenny Lau (Jul 27 2025 at 16:52):

it's a non-trivial step to go from proving theorems to constructing "data"

Quinn La Fond (Jul 27 2025 at 16:53):

I see, I will search for some way of doing this then.

Quinn La Fond (Jul 27 2025 at 16:53):

thank you

Kenny Lau (Jul 27 2025 at 16:54):

you can look into the library and see how various functions are defined

Kenny Lau (Jul 27 2025 at 16:54):

which would naturally include the Fibonacci

Aaron Liu (Jul 27 2025 at 16:59):

docs#Nat.fib is defined with some stream iterator to make it more efficient

Aaron Liu (Jul 27 2025 at 17:00):

don't know why they couldn't have just used a @[csimp] lemma

Quinn La Fond (Jul 27 2025 at 17:00):

what doe this mean

Aaron Liu (Jul 27 2025 at 17:01):

you'll have to be a bit more specific

Aaron Liu (Jul 27 2025 at 17:02):

wow I checked to source and it's not even a stream iterator

Aaron Liu (Jul 27 2025 at 17:02):

the docstring is outdated

Quinn La Fond (Jul 27 2025 at 17:02):

Kenny stated I should look at how the Fibonacci sequence is defined in library, you then remarked that Nat.fib is defined with some stream iterator; why the remark?

Aaron Liu (Jul 27 2025 at 17:02):

it's not the most obvious choice

Kenny Lau (Jul 27 2025 at 17:04):

@Quinn La Fond look at Nat.add then

Kenny Lau (Jul 27 2025 at 17:04):

(and try to ignore the @&)

Quinn La Fond (Jul 27 2025 at 17:07):

Hmm, so should I be defining my LTSeries as function outside of the lemma I am trying to prove?

Aaron Liu (Jul 27 2025 at 17:07):

yes definitely

Quinn La Fond (Jul 27 2025 at 17:14):

Ok and so the naive idea is something like:

def f : Fin( Nat.card T) \rightarrow \beta
|zero => minimal element of T
|succ b => minimal elment of T\ {f(b),\dots, f(0)}

I need to specify that \beta is partially ordered, and that T is a finite nonempty chain, and it looks like I can declare these things before the colon as I would with a lemma. Am I allowed to prove things inside this def though? I tried using an rcases tactic to get a minimal element of T but lean yelled at me...

Aaron Liu (Jul 27 2025 at 17:15):

you can't use rcases here since you're creating data

Aaron Liu (Jul 27 2025 at 17:15):

try docs#Exists.choose instead

Quinn La Fond (Jul 27 2025 at 17:25):

Should I not be using an := by after the def f : Fin (Nat.card T) \rightarrow \beta?

Kenny Lau (Jul 27 2025 at 17:34):

you generally shouldn't use tactics in defs

Aaron Liu (Jul 27 2025 at 17:35):

the reason is because since you are making data you care about which data you end up making, and when using tactics you don't get to control what they output

Quinn La Fond (Jul 27 2025 at 17:40):

I see. How do I get the minimum the set T inductively then? Do I specify such a hypothesis?

Aaron Liu (Jul 27 2025 at 17:41):

you should prove a theorem saying that there exists a minimum and then choose one out noncomputably

Aaron Liu (Jul 27 2025 at 17:42):

in order to get it computably you will need a few more assumptions

Quinn La Fond (Jul 27 2025 at 17:42):

I mean there is a theorem already written because T is a chain. T_finite.exists_minmal T_Nonempty gives the the hypothesis exists minimal element of T.

Aaron Liu (Jul 27 2025 at 17:43):

great

Aaron Liu (Jul 27 2025 at 17:43):

now use docs#Exists.choose to choose one out

Quinn La Fond (Jul 27 2025 at 17:44):

How does that syntax work without tactics? like naively I want to do H :=T_finite.exists_minmal T_Nonempty and then apply Exists.choose at H.

Aaron Liu (Jul 27 2025 at 17:45):

how about let H := (T_finite.exists_minimal T_Nonempty).choose

Aaron Liu (Jul 27 2025 at 17:45):

does that work for you

Quinn La Fond (Jul 27 2025 at 17:48):

This worked:

def order_chain {β : Type*} [PartialOrder β]
  (T : Set β) (T_chain : IsChain (· < ·) T)
  (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
  Fin (Nat.card T)  β
  | zero =>  (T_finite.exists_minimal T_nonempty).choose

I am not sure if this the best way forward though...

Quinn La Fond (Jul 27 2025 at 17:48):

I have to run, but I will be back in an hour or two. Thank you for all the help.

Quinn La Fond (Jul 27 2025 at 19:23):

What do you think of the zero case?

Aaron Liu (Jul 27 2025 at 19:23):

I would need a #mwe

Quinn La Fond (Jul 27 2025 at 19:24):

Hmm, what would that look like in this case?

Quinn La Fond (Jul 27 2025 at 19:26):

Like in particular, if I do not know how to finish the rest of the construction yet, what is a minimum working example?

Aaron Liu (Jul 27 2025 at 19:27):

just sorry out the rest

Quinn La Fond (Jul 27 2025 at 19:34):

def order_chain {β : Type*} [PartialOrder β]
  (T : Set β) (T_chain : IsChain (· < ·) T)
  (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
  Fin (1)  β
  | 0 =>  (T_finite.exists_minimal T_nonempty).choose

For some reason sorry doesn't help but if I just look at Fin(1) instead this works I think

Aaron Liu (Jul 27 2025 at 19:34):

you're missing imports

Quinn La Fond (Jul 27 2025 at 19:37):

oh right:

import Mathlib

open PrimeSpectrum
open Order
noncomputable
def order_chain {β : Type*} [PartialOrder β]
  (T : Set β) (T_chain : IsChain (· < ·) T)
  (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
  Fin (1)  β
  | 0 =>  (T_finite.exists_minimal T_nonempty).choose

Quinn La Fond (Jul 27 2025 at 19:44):

Oh I think this how I should sorry out the rest:

import Mathlib

open PrimeSpectrum
open Order
noncomputable
def order_chain {β : Type*} [PartialOrder β]
  (T : Set β) (T_chain : IsChain (· < ·) T)
  (T_finite : T.Finite) (card_T : Nat.card T > 0 ) (T_nonempty : T.Nonempty) :
  Fin (Nat.card T)  β
  | 0, _⟩ =>  (T_finite.exists_minimal T_nonempty).choose
  | Nat.succ a, _⟩ => sorry

Aaron Liu (Jul 27 2025 at 19:45):

oh yeah so far it's good

Aaron Liu (Jul 27 2025 at 19:46):

but matching on Fin like that is not something I would recommend if you're going to make it recursive

Quinn La Fond (Jul 27 2025 at 19:46):

Why not/what do you mean

Aaron Liu (Jul 27 2025 at 19:46):

since it will force you to do well-founded recursion

Quinn La Fond (Jul 27 2025 at 19:47):

what does that mean

Quinn La Fond (Jul 27 2025 at 19:47):

I don't really have another option an LTSeries S is a function from Fin(length)\rightarrow to Beta

Aaron Liu (Jul 27 2025 at 19:48):

I would suggest you use docs#Fin.induction instead

Quinn La Fond (Jul 27 2025 at 19:50):

OK, how do I change my zero case to use Fin.induction?

Aaron Liu (Jul 27 2025 at 19:51):

unfortunately I don't think it will work in this case

Aaron Liu (Jul 27 2025 at 19:51):

how about currying it and doing (n : Nat) → n < Nat.card T → β instead?

Quinn La Fond (Jul 27 2025 at 19:52):

I still don't understand what is wrong. If I can prove some generalization of exists_minimal for T\{b_0,\dots, b_i} for all i < n, and any b_i it should be fine right?

Aaron Liu (Jul 27 2025 at 19:52):

the problem is it won't reduce definitionally

Aaron Liu (Jul 27 2025 at 19:52):

this causes trouble sometimes so I try to avoid it if possible

Quinn La Fond (Jul 27 2025 at 19:52):

What do you mean currying it? And what do you mean it won't reduce definitionally?

Quinn La Fond (Jul 28 2025 at 05:37):

import Mathlib

open PrimeSpectrum
open Order

lemma set_diff_finite {β : Type*} [PartialOrder β] (T : Set β) (T_finite : T.Finite)
(S : Set β) :
(T \ S).Finite := by
exact T_finite.subset (by
  intro x hx
  exact hx.1)



lemma strict_set_diff_nonempty {β : Type*} [PartialOrder β] (T : Set β) (T_finite : T.Finite)
(S : Set β) (S_subset_T : S  T)
(S_strict : Nat.card S < Nat.card T) :  (T \ S).Nonempty := by
have h := set_diff_finite T T_finite S
have S_finite := T_finite.subset S_subset_T
have h1 := Set.ncard_diff S_subset_T S_finite
simp at S_strict
have h2 := Nat.sub_pos_of_lt S_strict
rw [ h1] at h2
rw [(T\S).ncard_pos h] at h2

exact h2

noncomputable
def order_set {β : Type*} [PartialOrder β]
  (T : Set β) --(T_chain : IsChain (· < ·) T)
  (T_finite : T.Finite) (card_T : Nat.card T > 0) (T_nonempty : T.Nonempty) :
  Fin (Nat.card T)  T
  | 0, _⟩ => by
    let m := (T_finite.exists_minimal T_nonempty).choose
    have hm : m  T := (T_finite.exists_minimal T_nonempty).choose_spec.1
    exact  m , hm

  | Nat.succ a, ha => by
    let S : Set β := {b |  i : Fin (Nat.succ a ),  (order_set T T_finite card_T T_nonempty
    i ,  lt_trans i.is_lt ha  )=b}
    have S_eq : S= ({b |  i : Fin (Nat.succ a ),  (order_set T T_finite card_T T_nonempty
    i ,  lt_trans i.is_lt ha  )=b} : Set β) := by tauto
    have TS_finite := set_diff_finite T T_finite S
    have S_subset_T : S  T := by
      intro x hx
      rw [S_eq] at hx
      simp at hx
      rcases hx with  i , i_mapto_x 
      rw [ i_mapto_x]
      simp

    have S_strict : Nat.card S < Nat.card T := by
      let g : Fin (a.succ)  β :=
        fun i => (order_set T T_finite card_T T_nonempty
        i, Nat.lt_trans i.is_lt ha).1
      have S_eq' : S = Set.image g Set.univ := by
        simp
        ext c
        constructor
        intro cin
        rw [S_eq] at cin
        tauto
        intro cin
        rw [S_eq]
        tauto
      have S_card_le_a : Nat.card S   Nat.succ a :=by
        simp
        rw [S_eq']
        have h : (Set.univ : Set (Fin (a.succ))).Finite := by
          have a : Finite (Fin (a.succ)) := by infer_instance
          exact Set.finite_univ_iff.2 a
        have H := Nat.card_image_le h (f:=g)
        have h1 :
          Nat.card (Set.univ : Set (Fin (Nat.succ a))) = a+1:= by simp
        rw [h1] at H
        simp at H
        simp
        exact H

      exact LE.le.trans_lt S_card_le_a ha
    have TS_nonempty :=   strict_set_diff_nonempty T T_finite S S_subset_T S_strict
    let m := (TS_finite.exists_minimal TS_nonempty).choose
    have hm : m  T\S := (TS_finite.exists_minimal TS_nonempty).choose_spec.1
    simp at hm
    have hmin : m  T := by
      rcases hm with  alpha , beta
      exact alpha




    exact  m , hmin 

Is it not recommended to use tactics like this ? I tried my best to figure out how to write this but at the end of the day I fell back into what I was more comfortable with. At the moment it seems like it will do what I want it to do, but I guess we will see later when I have try and post compose with inclusion function into beta (is this something I can do?)

Aaron Liu (Jul 28 2025 at 10:03):

If you're just doing let and have then the tactics aren't buying you anything since term mode also have those

Quinn La Fond (Jul 28 2025 at 15:42):

Well I use exact at the end and simp a couple of times

Also if I don't have by then the hypotheses from have don't show up on the right side of the screen

Aaron Liu (Jul 28 2025 at 15:44):

oh don't use simp

Aaron Liu (Jul 28 2025 at 15:44):

that's not good

Aaron Liu (Jul 28 2025 at 15:45):

Quinn La Fond said:

Also if I don't have by then the hypotheses from have don't show up on the right side of the screen

This usually means you cursor is not in the right place

Quinn La Fond (Jul 28 2025 at 15:46):

Why is simp bad?

Aaron Liu (Jul 28 2025 at 15:46):

it gives you casts

Quinn La Fond (Jul 28 2025 at 15:46):

Is it ok to use simp when proving the have statements

Aaron Liu (Jul 28 2025 at 15:47):

only use simp if the type of your goal is Prop

Aaron Liu (Jul 28 2025 at 15:47):

for example if your goal is ⊢ a = b then it's okay to use simp

Quinn La Fond (Jul 28 2025 at 15:48):

ok I actually didnt need the simp at all so I removed it

Aaron Liu (Jul 28 2025 at 15:48):

if your goal is ⊢ Fin (m + n) then don't use simp

Quinn La Fond (Jul 28 2025 at 15:49):

ok that makes sense I think

Quinn La Fond (Jul 31 2025 at 03:39):

So I am now running into the problem that when I call the function I defined, I can't access the hypothesis that that the value of this function is a minimum of some subset of T. is there a way to get this after using .choose?

Yaël Dillies (Jul 31 2025 at 06:28):

Would be easier if you had a #mwe, but from just reading your question the answer should be .choose_spec

Quinn La Fond (Jul 31 2025 at 20:12):

import Mathlib

open PrimeSpectrum
open Order
noncomputable
def order_chain {β : Type*} [PartialOrder β]
  (T : Set β) (T_chain : IsChain (· < ·) T)
  (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
  Fin (1)  β
  | 0 =>  (T_finite.exists_minimal T_nonempty).choose

If I define the above function, then given a finite nonempty chain T, something like

rcases order_chain T T_chain T_finite T_nonempty 0 with \< a, b\>

gives the hypothesis a : Beta, b : a \in T, but I don't get any hypotheses of the form Minimal (fun x ↦ x ∈ T) a

Quinn La Fond (Jul 31 2025 at 23:03):

In particular I cannot change .choose to .choose_spec because then I don't have the element Beta, I have the element in beta+something else.

Yaël Dillies (Aug 01 2025 at 06:34):

The above wasn't quite a MWE :sweat: Is the following one accurate?

import Mathlib

variable {α β : Type*} [PartialOrder α] [PartialOrder β]

noncomputable
def order_chain (T : Set β) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
    Fin 1  β
  | 0 => (T_finite.exists_minimal T_nonempty).choose

example (T : Set (α × β)) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
    True := by
  rcases order_chain T T_finite T_nonempty 0 with a, b
  have : Minimal (·  T) (a, b) := sorry
  trivial

Yaël Dillies (Aug 01 2025 at 06:35):

If so, then indeed you won't be able to fill in that sorry

Quinn La Fond (Aug 01 2025 at 15:56):

Why did you write T : Set (\alpha \times Beta)?

Quinn La Fond (Aug 01 2025 at 16:30):

Oh I see, my \< a , b\> is a : N and b : a <1 which are the necessary hypotheses to feed something to Fin 1.

Aaron Liu (Aug 01 2025 at 17:02):

you can use docs#Finset.orderIsoOfFin on the subtype of your chain which is a linear order

Quinn La Fond (Aug 01 2025 at 17:50):

Is this a different approach than defining my function from Fin (Nat.card T)\rightarrow Beta?

Aaron Liu (Aug 01 2025 at 17:51):

well you get an order isomorphism instead

Quinn La Fond (Aug 01 2025 at 18:22):

My beta is a partial order thought not a linear order.

Aaron Liu (Aug 01 2025 at 18:23):

the subtype of your chain is a linear order

Quinn La Fond (Aug 01 2025 at 18:46):

I see so this would give me a function Fin Nat.card T \rightarrow T?

Quinn La Fond (Aug 01 2025 at 19:46):

Is there not a way to just carry this hypothesis with me though? Like it seems odd to me that wit the expression (something).choose I can't access the propositions of that something.

Aaron Liu (Aug 01 2025 at 19:47):

can you provide a #mwe?

Quinn La Fond (Aug 01 2025 at 19:51):

import Mathlib

variable {α β : Type*} [PartialOrder α] [PartialOrder β]

noncomputable
def order_chain (T : Set β) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
    Fin 1  β
  | 0 => (T_finite.exists_minimal T_nonempty).choose

example (T : Set (β)) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
    True := by
  rcases order_chain T T_finite T_nonempty 0 with a
  have h : Minimal (fun x => x  T) a := sorry
  trivial

I am essentially just trying to fill in that sorry, but the only hypothesis (T_finite.exists_minimal T_nonempty).choose gives me is that a \in beta.

Aaron Liu (Aug 01 2025 at 19:52):

the problem is rcases forgets the value you pass it

Aaron Liu (Aug 01 2025 at 19:52):

you should use let instead

Quinn La Fond (Aug 01 2025 at 19:56):

import Mathlib

variable {α β : Type*} [PartialOrder α] [PartialOrder β]

noncomputable
def order_chain (T : Set β) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
    Fin 1  β
  | 0 => (T_finite.exists_minimal T_nonempty).choose

example (T : Set (β)) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
    True := by
  let a : β := order_chain T T_finite T_nonempty 0
  have a_eq : a = order_chain T T_finite T_nonempty 0 := by tauto
  have h : Minimal (fun x => x  T) a := by
   simp [order_chain] at a_eq
   sorry

  trivial

So this gives me that a= (T_finite.exists_minimal T_nonempty).choose, but how I don't how to access the hypothesis that a is now minimal with respect T.

Aaron Liu (Aug 01 2025 at 19:56):

it's (T_finite.exists_minimal T_nonempty).choose_spec

Quinn La Fond (Aug 01 2025 at 19:58):

import Mathlib

variable {α β : Type*} [PartialOrder α] [PartialOrder β]

noncomputable
def order_chain (T : Set β) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
    Fin 1  β
  | 0 => (T_finite.exists_minimal T_nonempty).choose

example (T : Set (β)) (T_finite : T.Finite) (T_nonempty : T.Nonempty) :
    True := by
  let a : β := order_chain T T_finite T_nonempty 0
  have a_eq : a = order_chain T T_finite T_nonempty 0 := by tauto
  have h : Minimal (fun x => x  T) a := by
   simp [order_chain] at a_eq
   exact  (T_finite.exists_minimal T_nonempty).choose_spec


  trivial

I don't totally understand why this works...like how does lean know that a is the same as this arbitrary (T_finite.exists_minimal T_nonempty).choose_spec?

Aaron Liu (Aug 01 2025 at 19:58):

because a let variable is definitionally equal to its value

Aaron Liu (Aug 01 2025 at 19:59):

You can try #check (T_finite.exists_minimal T_nonempty).choose_spec to see its type

Quinn La Fond (Aug 01 2025 at 19:59):

ok thank you i think that makes sense.


Last updated: Dec 20 2025 at 21:32 UTC