Zulip Chat Archive

Stream: mathlib4

Topic: Formalization of Nagata's criterion for factoriality


Alexcai (Dec 05 2025 at 22:00):

Hello,
This is Haocheng Cai. I am a math PhD student. For an AI math class project, GitHub copilot and I formalized Nagata's criterion for factoriality. My instructor suggested trying PR this to mathlib. What is my next step?

Kevin Buzzard (Dec 05 2025 at 23:16):

Is your proof really unidiomatic and far too long (as proofs written by AI often are)? If so then your next step is to make it much shorter. Maybe post a #mwe showing the proof so we can judge whether it's a disaster or salvageable? Sad to say, sometimes it's easier just to start again than to rescue an AI proof; mathlib has extremely high code quality standards and most AI tools are very far from meeting them. But of course AI gets better all the time. In short, I think you should show the code before we decide what to do next.

Alexcai (Dec 05 2025 at 23:27):

Thanks for the advice! How exactly should I post a mwe? I have 400 lines of code, and do you want me to copy and paste all of it into a new chat under mathlib4 in Zulip?

Weiyi Wang (Dec 05 2025 at 23:33):

If you have code that you think is complete, why not setting up a proper github repo with CI & doc generated? It is pretty easy with the template generated in vscode

Kevin Buzzard (Dec 05 2025 at 23:33):

Or just post it in this thread using #backticks and with enough imports etc to make it work (in two parts if it's too big for one message)

Weiyi Wang (Dec 05 2025 at 23:34):

(Yeah I don't know 400 would hit certain limit)

Alexcai (Dec 05 2025 at 23:36):

I am a new Github user, so let me first try to post it here as it seems easier for me

Alexcai (Dec 05 2025 at 23:39):

import Mathlib
--In this file we prove Nagata's criterion for UFD: if R is a Noetherian domain
--and T is the localization of R at a prime element f, and T is a UFD,
--then R is also a UFD.
--The main theorem is nagata_theorem at the bottom of the file.
--The proof folllows the outline in https://www.math.wustl.edu/~kumar/courses/Algebra5031fall2015/Nagata.pdf
--show that the algebra map from R to its localization T is injective

theorem nagata_setup {R T : Type*} [CommRing R] [CommRing T] [Algebra R T] [IsDomain R]

[IsDomain T] (f : R) (hf0 : f  0) (hT : IsLocalization.Away (f : R) T) :

Function.Injective (algebraMap R T) :=

IsLocalization.injective T (powers_le_nonZeroDivisors_of_noZeroDivisors hf0)
--factorization in the UFD T

theorem factors_in_T {R T : Type*} [CommRing R] [CommRing T] [Algebra R T] [IsDomain R]

[IsDomain T] (f : R) (hf0 : f  0) (hT : IsLocalization.Away (f : R) T)

[UniqueFactorizationMonoid T] (x : R) (hx : x  0) :

 s : Multiset T, ( p  s, Prime p)  Associated (s.prod : T) (algebraMap R T x) := by

have inj := nagata_setup f hf0 hT

have h_img_ne : algebraMap R T x  0 := by

intro h

have : x = 0 := inj (by simp [h])

contradiction

exact UniqueFactorizationMonoid.exists_prime_factors (algebraMap R T x) h_img_ne
--lemma to lift elements from T to R up to association

theorem clears_denominators {R T : Type*} [CommRing R] [CommRing T] [Algebra R T] [IsDomain R]

[IsDomain T] (f : R) (hT : IsLocalization.Away (f : R) T) (z : T) :

 a : R, Associated z (algebraMap R T a) := by
-- `IsLocalization.Away.sec` chooses `a : R` and `n : ℕ` such that
-- `z * algebraMap R T (f ^ n) = algebraMap R T a`. Mathlib proves the sharper
-- `Associated (algebraMap R T a) z` in `associated_sec_fst`, so we can use that.

let a := (IsLocalization.Away.sec f z).1

exact a, (IsLocalization.Away.associated_sec_fst (x := f) z).symm

/-

If `q : T` is a prime element of the localization `T`, this lemma states that `q` comes from

some prime `p : R` up to a unit in `T` — i.e. `q` is associated to `algebraMap R T p`.
-/

theorem prime_in_T_lifts_to_R {R T : Type*} [CommRing R] [CommRing T] [Algebra R T] [IsDomain R]

[IsDomain T] [IsNoetherianRing R] (f : R) (hf0 : f  0) (hfprime : Prime f)

(hT : IsLocalization.Away (f : R) T) (q : T) (hq : Prime q) :

 p : R, Prime p  Associated q (algebraMap R T p)  ¬ (f  p) := by
-- pick some representative `a0 : R` of `q` from the localization

let a0 := (IsLocalization.Away.sec f q).1

have h_assoc0 : Associated q (algebraMap R T a0) :=

(IsLocalization.Away.associated_sec_fst (x := f) q).symm
-- `a0` is nonzero (its image is associated to the nonzero prime `q`).

have ha0 : a0  0 := by

intro ha0

have : algebraMap R T a0 = 0 := by simp [ha0]

have : q = 0 := by

obtain u, hu := h_assoc0

calc

q = q * (u * u⁻¹) := by simp

_ = (q * u) * u⁻¹ := by ring

_ = algebraMap R T a0 * u⁻¹ := by rw [ hu]

_ = 0 * u⁻¹ := by rw [this]

_ = 0 := by simp

exact hq.ne_zero this
-- from Noetherianity we get the well-founded divisibility property

have wf : WfDvdMonoid R := IsNoetherianRing.wfDvdMonoid
-- remove all factors of `f` from `a0` using the maximal-power lemma

obtain n, a, a_ndvd, ha0_eq := WfDvdMonoid.max_power_factor ha0 hfprime.irreducible
-- now `a0 = f ^ n * a` and `¬ f ∣ a`.
-- the image of `f` is a unit in the localization; make this available

have unit_f_global := hT.algebraMap_isUnit (x := f)
-- algebraMap a0 = (algebraMap f) ^ n * algebraMap a, so algebraMap a is associated to a0

have map_eq : algebraMap R T a0 = (algebraMap R T f) ^ n * algebraMap R T a := by

simp [ha0_eq, map_mul, map_pow]

have unit_pow : IsUnit ((algebraMap R T f) ^ n) := IsUnit.pow n unit_f_global

have assoc_eq : Associated (algebraMap R T a0) ((algebraMap R T f) ^ n * algebraMap R T a) :=

Associated.of_eq map_eq

have assoc_mul := associated_unit_mul_left (algebraMap R T a) ((algebraMap R T f) ^ n) unit_pow

have h_assoc : Associated q (algebraMap R T a) :=

(h_assoc0.trans assoc_eq).trans assoc_mul
-- since `algebraMap R T a` is associated to `q`, it is prime in `T`.

have prime_map_a : Prime (algebraMap R T a) := Associated.prime h_assoc hq
-- now `a` is the reduced representative with `¬ f ∣ a`

have f_ndivide_a : ¬ (f  a) := a_ndvd
-- finally, show that `a` is prime in `R` using the definition of primality

have h_prime_a : Prime a := by

constructor

· -- a ≠ 0: since its image is associated to the nonzero prime q

intro ha_zero

have : algebraMap R T a = 0 := by simp [ha_zero]

have : q = 0 := by

obtain u, hu := h_assoc

calc q = q * (u * u⁻¹) := by simp

_ = (q * u) * u⁻¹ := by ring

_ = algebraMap R T a * u⁻¹ := by rw [ hu]

_ = 0 * u⁻¹ := by rw [this]

_ = 0 := by simp

exact hq.ne_zero this

· constructor

· -- a is not a unit: otherwise algebraMap a would be a unit,
-- so q (associated) would be a unit, contradicting `hq`.

intro ha_unit

have : IsUnit (algebraMap R T a) := IsUnit.map (algebraMap R T) ha_unit
-- associated elements share unit-ness: use `Associated.isUnit` on `h_assoc.symm`

have : IsUnit q := Associated.isUnit h_assoc.symm this

exact hq.not_unit this

· -- primality: if a ∣ b * c in R then a ∣ b or a ∣ c

intros b c hab

obtain d, hd := hab

have : algebraMap R T a  (algebraMap R T b * algebraMap R T c) := by

use algebraMap R T d

calc

algebraMap R T b * algebraMap R T c = algebraMap R T (b * c) := by simp [map_mul]

_ = algebraMap R T (a * d) := by rw [hd]

_ = algebraMap R T a * algebraMap R T d := by simp [map_mul]

let div_case := Prime.dvd_or_dvd prime_map_a this
-- helper: clear denominators and peel off powers of `f` for a single factor `x`.

have inj := nagata_setup f hf0 hT

have case_for :  x : R, (algebraMap R T a  algebraMap R T x)  a  x := by

intro x hx

obtain e, he := hx

obtain n, r, hs' := IsLocalization.Away.surj f e

have eq_xf_ar : algebraMap R T (x * f ^ n) = algebraMap R T (a * r) := by

calc

algebraMap R T (x * f ^ n) = algebraMap R T x * (algebraMap R T f) ^ n := by

simp [map_mul]

_ = (algebraMap R T a * e) * (algebraMap R T f) ^ n := by

rw [he]

_ = algebraMap R T a * (e * (algebraMap R T f) ^ n) := by

ring

_ = algebraMap R T a * algebraMap R T r := by

rw [hs']

_ = algebraMap R T (a * r) := by

simp [map_mul]

have eq_in_R : x * f ^ n = a * r := inj (by simp [eq_xf_ar])

have key :  (n : Nat) (r : R), x * f ^ n = a * r  a  x := by

intro n r h

induction n generalizing r with

| zero => use r; simpa [pow_zero] using h

| succ n ih =>

have f_dvd_ar : f  a * r := by

use x * f ^ n

calc

a * r = x * f ^ (n + 1) := by rw [h]

_ = f * (x * f ^ n) := by ring

have hcases := (hfprime.dvd_mul).1 f_dvd_ar

cases hcases with

| inl hf_a => exact (f_ndivide_a hf_a).elim

| inr hf_r =>

obtain r', hr := hf_r

have h' : x * f ^ (n + 1) = a * (f * r') := by rw [hr] at h; exact h

have mul_expr : ((x * f ^ n) - (a * r')) * f =

x * f ^ (n + 1) - a * (f * r') := by

ring

have : ((x * f ^ n) - (a * r')) * f = 0 := by rw [mul_expr, h']; simp

have left_zero := (mul_eq_zero.mp this).resolve_right hf0

have eq' : x * f ^ n = a * r' := sub_eq_zero.1 left_zero

exact ih r' eq'

exact key n r eq_in_R
-- now finish the two cases: a ∣ b or a ∣ c

cases div_case with

| inl hdiv => exact Or.inl (case_for b hdiv)

| inr hdiv => exact Or.inr (case_for c hdiv)

exact a, h_prime_a, h_assoc, f_ndivide_a
--use above lemma to lift a multiset of primes in T to R

theorem lift_multiset_of_primes {R T : Type*} [CommRing R] [CommRing T] [Algebra R T]

[IsDomain R] [IsDomain T] [IsNoetherianRing R]

(f : R) (hf0 : f  0) (hfprime : Prime f) (hT : IsLocalization.Away (f : R) T)

[UniqueFactorizationMonoid T] :

 s : Multiset T, ( p  s, Prime p)   sR : Multiset R,

( p  sR, Prime p)  ( p  sR, ¬ (f  p)) 

Associated (s.prod : T) (algebraMap R T (sR.prod)) := by

intro s hs_primes

induction s using Multiset.induction with

| empty =>

use (0 : Multiset R)

constructor

· intro p hp; cases hp

constructor

· intro p hp; cases hp

· exact Associated.of_eq (by simp [Multiset.prod_zero])

| cons p s ih =>

have hp : Prime p := hs_primes p (Multiset.mem_cons_self p s)

obtain r, hr_prime, h_assoc_p, hr_ndvd := prime_in_T_lifts_to_R f hf0 hfprime hT p hp

have ih_arg := fun q hq => hs_primes q (Multiset.mem_cons_of_mem hq)

obtain sR', hsR'_primes, hsR'_ndiv, hs_assoc' := ih ih_arg

obtain u1, hu1 := hs_assoc'

obtain u2, hu2 := h_assoc_p

have mul_eq : (p ::ₘ s).prod * (u2 * u1) = algebraMap R T ((sR' + {r}).prod) := by

calc

(p ::ₘ s).prod * (u2 * u1) = p * s.prod * (u2 * u1) := by simp [Multiset.prod_cons]

_ = p * (s.prod * (u2 * u1)) := by ring

_ = p * (s.prod * u1 * u2) := by ring

_ = p * (algebraMap R T (sR'.prod) * u2) := by rw [ hu1]

_ = (p * u2) * algebraMap R T (sR'.prod) := by ring

_ = (algebraMap R T r) * algebraMap R T (sR'.prod) := by rw [hu2]

_ = algebraMap R T (r * sR'.prod) := by simp [map_mul]

_ = algebraMap R T ((sR' + {r}).prod) := by simp [Multiset.prod_add, mul_comm, map_mul]

use sR' + {r}

apply And.intro

· intro q hq; cases Multiset.mem_add.1 hq with

| inl h => exact hsR'_primes q h

| inr h => have : q = r := Multiset.mem_singleton.1 h; subst this; exact hr_prime

apply And.intro

· intro q hq; cases Multiset.mem_add.1 hq with

| inl h => exact hsR'_ndiv q h

| inr h => have : q = r := Multiset.mem_singleton.1 h; subst this; exact hr_ndvd

· use (u2 * u1); exact mul_eq

Alexcai (Dec 05 2025 at 23:40):

--main existence lemma for Nagata's Criterion,
--lifting factorizations from T to R modulo some powers of f, but f is a prime element in R
--So it completes to a full factorization in R by adding some copies of f to the multiset.

theorem existence_step {R T : Type*} [CommRing R] [CommRing T] [Algebra R T] [IsDomain R]

[IsDomain T] [IsNoetherianRing R] (f : R) (hf0 : f  0) (hfprime : Prime f)

(hT : IsLocalization.Away (f : R) T) [UniqueFactorizationMonoid T] :

 x : R, x  0   sR : Multiset R, ( p  sR, Prime p)  Associated (sR.prod : R) x := by
--factor algebraMap x in T, then lift the factors to R up to association by the previous lemmas

intro x hx

obtain s, hs_primes, hs_assoc := factors_in_T f hf0 hT x hx

obtain sR, hsR_primes, hsR_ndiv, hsR_assoc_T :=

lift_multiset_of_primes f hf0 hfprime hT s hs_primes

have final_assoc := (hsR_assoc_T).symm.trans hs_assoc

obtain u, hu := final_assoc

obtain n, a', ha' := IsLocalization.Away.surj f (u : T)

have prod_eq : algebraMap R T (sR.prod * a') = algebraMap R T (x * f ^ n) := by

calc

algebraMap R T (sR.prod * a') =

algebraMap R T (sR.prod) * algebraMap R T a' := by

simp [map_mul]

_ = algebraMap R T (sR.prod) * (u * (algebraMap R T f) ^ n) := by

rw [ ha']

_ = (algebraMap R T (sR.prod) * u) * (algebraMap R T f) ^ n := by ring

_ = algebraMap R T x * (algebraMap R T f) ^ n := by

rw [hu]

_ = algebraMap R T (x * f ^ n) := by simp [map_mul]

have inj := nagata_setup f hf0 hT

have eq_in_R : sR.prod * a' = x * f ^ n := inj (by simp [prod_eq])
-- Since f is prime and does not divide any prime factor of sR, it does not divide sR.prod.

have f_ndvd_prod : ¬ (f  sR.prod) := by

have h_list : ¬ (f  (sR.toList).prod) := by

apply Prime.not_dvd_prod hfprime

intro a ha

have : a  sR := by simpa [Multiset.mem_toList] using ha

exact hsR_ndiv a this

have prod_eq_list := (Multiset.prod_toList sR).symm

intro h

have h' : f  (sR.toList).prod := by rwa [prod_eq_list] at h

exact h_list h'
-- Split on whether the exponent `n` is positive or zero. We handle the `n > 0`
-- Note: we will only prove `f ∣ a'` in the branch where `n > 0`.
-- `n > 0` case first because it will be reduced to the `n = 0` case by dividing `a'` by `f`.

have h_exists :  a'' : R, Associated (sR.prod * a'') x := by
-- define a recursive predicate: for any `m` and `a` with `sR.prod * a = x * f ^ m`
-- produce the required `a''` by cancelling powers of `f` one-by-one.

have rec_aux :  m a, sR.prod * a = x * f ^ m   a'', Associated (sR.prod * a'') x := by

intro m a heq

induction m generalizing a with

| zero =>

use a

simp [pow_zero] at heq

exact Associated.of_eq heq

| succ m' ih =>
-- f divides the right-hand side, so f divides `sR.prod * a` with witness `x * f ^ m'`.

have h_dvd : f  (sR.prod * a) := by

rw [heq]

use x * f ^ m'

ring

cases (hfprime.dvd_mul).1 h_dvd with

| inl hf_sR => exact (f_ndvd_prod hf_sR).elim

| inr hf_a =>

obtain a1, ha1 := hf_a
-- substitute `a = f * a1` and cancel one `f` from both sides

have heq1 : sR.prod * (f * a1) = x * f ^ (m' + 1) := by

rw [ha1] at heq

exact heq

have eq_mul : (sR.prod * a1) * f = (x * f ^ m') * f := by

calc

(sR.prod * a1) * f = sR.prod * (a1 * f) := by ring

_ = sR.prod * (f * a1) := by ring

_ = x * f ^ (m' + 1) := by exact heq1

_ = (x * f ^ m') * f := by simp [pow_succ, mul_assoc]

have eq_reduced : sR.prod * a1 = x * f ^ m' := mul_right_cancel₀ hf0 eq_mul

exact ih a1 eq_reduced

exact rec_aux n a' eq_in_R
-- now we have some `a''` with `sR.prod * a''` associated to `x`

obtain a'', h_assoc := h_exists

have h_map_unit : IsUnit (algebraMap R T a'') := by
-- h_assoc : (sR.prod * a'') * v = x for some unit v in R

obtain v, hv := h_assoc
-- map that equality to T and massage into a convenient shape

have map_hv_raw := congrArg (algebraMap R T) hv

have map_hv : (algebraMap R T (sR.prod * a'')) * (algebraMap R T (v)) = algebraMap R T x := by

simpa [map_mul] using map_hv_raw

have map_eq_raw :

(algebraMap R T (sR.prod) * (algebraMap R T a'') * (algebraMap R T (v)))

= algebraMap R T (sR.prod) * (u : T) := by

calc

(algebraMap R T (sR.prod) * (algebraMap R T a'') * (algebraMap R T (v)))

= (algebraMap R T (sR.prod * a'')) * (algebraMap R T (v)) := by simp [map_mul]

_ = algebraMap R T x := by exact map_hv

_ = algebraMap R T (sR.prod) * (u : T) := by rw [hu]

have map_eq := by simpa using map_eq_raw
-- `algebraMap R T (sR.prod)` is nonzero.
-- Its product with the unit `u` equals `algebraMap R T x`, so `x` would be 0 otherwise.

have map_sR_ne : algebraMap R T (sR.prod)  0 := by

intro H

have map_x_zero : algebraMap R T x = 0 := by rw [ hu]; simp [H]

have inj := nagata_setup f hf0 hT

have : x = 0 := inj (by simp [map_x_zero])

contradiction
-- cancel the common left factor `algebraMap R T (sR.prod)` in the domain `T`

have map_eq2 :

(algebraMap R T sR.prod) * ((algebraMap R T a'') * (algebraMap R T (v)))

= (algebraMap R T sR.prod) * (u : T) := by

simpa [mul_assoc] using map_eq

have mul_cancel := mul_left_cancel₀ map_sR_ne map_eq2
-- now (algebraMap a'') * (algebraMap v) = ↑u, so algebraMap a'' is a unit

let unit_v := Units.map (algebraMap R T : R →* T) v
-- we have (algebraMap a'') * ↑unit_v = ↑u by `mul_cancel`

have hprod_unit : (algebraMap R T a'') * (unit_v * (u⁻¹)) = 1 := by

have h1 : (algebraMap R T a'') * unit_v = (u : T) := mul_cancel

calc

(algebraMap R T a'') * (unit_v * (u⁻¹)) =

((algebraMap R T a'') * unit_v) * (u⁻¹) := by ring

_ = u * (u⁻¹) := by rw [h1]

_ = 1 := by simp

let unit_w := Units.mkOfMulEqOne (algebraMap R T a'') (unit_v * (u⁻¹)) hprod_unit

have : (unit_w : T) = algebraMap R T a'' := Units.val_mkOfMulEqOne hprod_unit

use unit_w
-- we have shown the image of `a''` in `T` is a unit

have h_a_map_unit := h_map_unit
-- since `algebraMap R T a''` is a unit in `T`, obtain an inverse `e : T`.

obtain e, he_right := IsUnit.exists_right_inv h_a_map_unit
-- because `T` is commutative, the right-inverse is also a left-inverse.

have he_left : e * algebraMap R T a'' = 1 := by

rw [mul_comm]

exact he_right
-- now we can lift e, find e' in R such that e' = e * f^m for some m

obtain m, e', he' := IsLocalization.Away.surj f e
-- calculate the product a'' * e' in R

have prod_eq_in_R : a'' * e' = f ^ m := by

have map_eq : algebraMap R T (a'' * e') = algebraMap R T (f ^ m) := by

calc

algebraMap R T (a'' * e') = (algebraMap R T a'') * (algebraMap R T e') := by simp [map_mul]

_ = (algebraMap R T a'') * (e * (algebraMap R T f) ^ m) := by rw [he']

_ = (algebraMap R T a'' * e) * (algebraMap R T f) ^ m := by ring

_ = 1 * (algebraMap R T f) ^ m := by rw [he_right]

_ = algebraMap R T (f ^ m) := by simp [map_pow]

have inj := nagata_setup f hf0 hT

exact inj map_eq
-- use the prime-power splitting lemma to conclude `a''` is a power of `f` times a unit

have hx : a'' * e' = (1 : R) * f ^ m := by

calc

a'' * e' = f ^ m := prod_eq_in_R

_ = (1 : R) * f ^ m := by simp

rcases mul_eq_mul_prime_pow hfprime hx with i, j, b, c, hij, hb_mul_c, ha''_eq, he'_eq
-- here `1 = b * c`, `a'' = b * f ^ i`, `e' = c * f ^ j` and `i + j = m`.

have hb_unit : IsUnit b := isUnit_of_mul_eq_one b c (Eq.symm hb_mul_c)
-- form the final multiset by adding `i` copies of `f` to `sR`.

let sR_fin := sR + Multiset.replicate i f

have prod_rep : sR_fin.prod = sR.prod * (f ^ i) := by simp [sR_fin]

have eq_prod_b : sR_fin.prod * b = sR.prod * a'' := by

calc

sR_fin.prod * b = (sR.prod * f ^ i) * b := by simp [prod_rep]

_ = sR.prod * (f ^ i * b) := by ring

_ = sR.prod * a'' := by rw [mul_comm (f ^ i) b, ha''_eq.symm]

have assoc_step1 : Associated sR_fin.prod (sR_fin.prod * b) := by

have one_assoc_rev : Associated b (1 : R) := associated_one_iff_isUnit.mpr hb_unit

let one_assoc := one_assoc_rev.symm

have h := Associated.mul_left sR_fin.prod one_assoc

simpa [mul_one] using h

have assoc_step2 : Associated (sR_fin.prod * b) (sR.prod * a'') := Associated.of_eq eq_prod_b

have final_associated : Associated sR_fin.prod x :=

assoc_step1.trans (assoc_step2.trans h_assoc)

use sR_fin

constructor

· intro p hp; cases Multiset.mem_add.1 hp with

| inl h => exact hsR_primes p h

| inr h => have : p = f := Multiset.eq_of_mem_replicate h; subst this; exact hfprime

· exact final_associated
--main theorem: Nagata's criterion for UFDs
--Notice that the existence_step is the only nontrivial part of the proof,
--the uniqueness of factorization in R follows directly from the existence of factorizations

theorem nagata_theorem {R T : Type*}

[CommRing R] [CommRing T] [Algebra R T] [IsDomain R] [IsDomain T]

[IsNoetherianRing R] (f : R) (hf0 : f  0) (hfprime : Prime f)

(hT : IsLocalization.Away (f : R) T) [UniqueFactorizationMonoid T] :

UniqueFactorizationMonoid R := by
-- For any nonzero `x : R` factor `algebraMap R T x` in `T` and lift the factors to `R`.

have existence_step_inst := existence_step (R := R) (T := T) f hf0 hfprime hT

exact UniqueFactorizationMonoid.of_exists_prime_factors existence_step_inst

Kevin Buzzard (Dec 05 2025 at 23:52):

Your code as posted is garbled, you have too many newlines and no indentation; you can see it doesn't work becasue if you click on "View in Lean 4 playground" at the top right of your first post, it doesn't work. It would be good if you could fix this; hopefully it's not too much trouble.

However your theorem names are unidiomatic and your proofs are way too long. It is going to be difficult (not impossible, but a lot of work) to make this mathlib-worthy. Unfortunately, "the code compiles" is not a sufficient condition for merging into mathlib; it has an extremely high bar for code quality and AI is just nowhere near this bar right now.

Alexcai (Dec 05 2025 at 23:55):

I think the indentation problem was due to the copy and paste issue

Alexcai (Dec 05 2025 at 23:57):

I see. Anyway, thanks for reviewing! I guess I just have to learn a lot more lean to improve the code.

Kevin Buzzard (Dec 05 2025 at 23:59):

If you can get it so that it's a working #mwe then it will be much easier for other people to have a look and make suggestions as to what is needed. See if you can edit your post to remove all the spurious newlines.

Alexcai (Dec 06 2025 at 00:00):

The link to my github file here:
https://github.com/AlexCai007/Nagata-Theorem/blob/main/Nagata%20theorem.lean

Alexcai (Dec 06 2025 at 00:01):

The indentation is quite a messy task. I give up on editing the posts.

Alexcai (Dec 06 2025 at 00:11):

I guess it works the best by copying the code from the link about to the online lean playground.

Edison Xie (Dec 13 2025 at 08:00):


Junyan Xu (Dec 13 2025 at 15:45):

Alexcai said:

The indentation is quite a messy task. I give up on editing the posts.

Usually when copying any rich text (e.g. from VSCode) I need to first paste it in some pure text editor (e.g. Notepad(++)) and then copying from there before pasting on Zulip (or Obsidian). When copying a single line from a browser I sometimes paste it in the address bar and copy from there.


Last updated: Dec 20 2025 at 21:32 UTC