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