Skip to content

Commit 883250c

Browse files
committed
feat: port RingTheory.WittVector.DiscreteValuationRing (#5557)
1 parent b47e7d2 commit 883250c

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,6 +2755,7 @@ import Mathlib.RingTheory.Valuation.ValuationRing
27552755
import Mathlib.RingTheory.Valuation.ValuationSubring
27562756
import Mathlib.RingTheory.WittVector.Basic
27572757
import Mathlib.RingTheory.WittVector.Defs
2758+
import Mathlib.RingTheory.WittVector.DiscreteValuationRing
27582759
import Mathlib.RingTheory.WittVector.Domain
27592760
import Mathlib.RingTheory.WittVector.Frobenius
27602761
import Mathlib.RingTheory.WittVector.Identities
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/-
2+
Copyright (c) 2022 Robert Y. Lewis. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Robert Y. Lewis, Heather Macbeth, Johan Commelin
5+
6+
! This file was ported from Lean 3 source module ring_theory.witt_vector.discrete_valuation_ring
7+
! leanprover-community/mathlib commit c163ec99dfc664628ca15d215fce0a5b9c265b68
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.RingTheory.WittVector.Domain
12+
import Mathlib.RingTheory.WittVector.MulCoeff
13+
import Mathlib.RingTheory.DiscreteValuationRing.Basic
14+
import Mathlib.Tactic.LinearCombination
15+
16+
/-!
17+
18+
# Witt vectors over a perfect ring
19+
20+
This file establishes that Witt vectors over a perfect field are a discrete valuation ring.
21+
When `k` is a perfect ring, a nonzero `a : 𝕎 k` can be written as `p^m * b` for some `m : ℕ` and
22+
`b : 𝕎 k` with nonzero 0th coefficient.
23+
When `k` is also a field, this `b` can be chosen to be a unit of `𝕎 k`.
24+
25+
## Main declarations
26+
27+
* `WittVector.exists_eq_pow_p_mul`: the existence of this element `b` over a perfect ring
28+
* `WittVector.exists_eq_pow_p_mul'`: the existence of this unit `b` over a perfect field
29+
* `WittVector.discreteValuationRing`: `𝕎 k` is a discrete valuation ring if `k` is a perfect field
30+
31+
-/
32+
33+
34+
noncomputable section
35+
36+
local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue #2220
37+
38+
namespace WittVector
39+
40+
variable {p : ℕ} [hp : Fact p.Prime]
41+
42+
local notation "𝕎" => WittVector p
43+
44+
section CommRing
45+
46+
variable {k : Type _} [CommRing k] [CharP k p]
47+
48+
/-- This is the `n+1`st coefficient of our inverse. -/
49+
def succNthValUnits (n : ℕ) (a : Units k) (A : 𝕎 k) (bs : Fin (n + 1) → k) : k :=
50+
-↑(a⁻¹ ^ p ^ (n + 1)) *
51+
(A.coeff (n + 1) * ↑(a⁻¹ ^ p ^ (n + 1)) + nthRemainder p n (truncateFun (n + 1) A) bs)
52+
#align witt_vector.succ_nth_val_units WittVector.succNthValUnits
53+
54+
/--
55+
Recursively defines the sequence of coefficients for the inverse to a Witt vector whose first entry
56+
is a unit.
57+
-/
58+
noncomputable def inverseCoeff (a : Units k) (A : 𝕎 k) : ℕ → k
59+
| 0 => ↑a⁻¹
60+
| n + 1 => succNthValUnits n a A fun i => inverseCoeff a A i.val
61+
#align witt_vector.inverse_coeff WittVector.inverseCoeff
62+
63+
/--
64+
Upgrade a Witt vector `A` whose first entry `A.coeff 0` is a unit to be, itself, a unit in `𝕎 k`.
65+
-/
66+
def mkUnit {a : Units k} {A : 𝕎 k} (hA : A.coeff 0 = a) : Units (𝕎 k) :=
67+
Units.mkOfMulEqOne A (@WittVector.mk' p _ (inverseCoeff a A)) (by
68+
ext n
69+
induction' n with n _
70+
· simp [WittVector.mul_coeff_zero, inverseCoeff, hA]
71+
let H_coeff := A.coeff (n + 1) * ↑(a⁻¹ ^ p ^ (n + 1)) +
72+
nthRemainder p n (truncateFun (n + 1) A) fun i : Fin (n + 1) => inverseCoeff a A i
73+
have H := Units.mul_inv (a ^ p ^ (n + 1))
74+
linear_combination (norm := skip) -H_coeff * H
75+
have ha : (a : k) ^ p ^ (n + 1) = ↑(a ^ p ^ (n + 1)) := by norm_cast
76+
have ha_inv : (↑a⁻¹ : k) ^ p ^ (n + 1) = ↑(a ^ p ^ (n + 1))⁻¹ := by norm_cast; norm_num
77+
simp only [nthRemainder_spec, inverseCoeff, succNthValUnits, hA,
78+
one_coeff_eq_of_pos, Nat.succ_pos', ha_inv, ha, inv_pow]
79+
ring!)
80+
#align witt_vector.mk_unit WittVector.mkUnit
81+
82+
@[simp]
83+
theorem coe_mkUnit {a : Units k} {A : 𝕎 k} (hA : A.coeff 0 = a) : (mkUnit hA : 𝕎 k) = A :=
84+
rfl
85+
#align witt_vector.coe_mk_unit WittVector.coe_mkUnit
86+
87+
end CommRing
88+
89+
section Field
90+
91+
variable {k : Type _} [Field k] [CharP k p]
92+
93+
theorem isUnit_of_coeff_zero_ne_zero (x : 𝕎 k) (hx : x.coeff 00) : IsUnit x := by
94+
let y : kˣ := Units.mk0 (x.coeff 0) hx
95+
have hy : x.coeff 0 = y := rfl
96+
exact (mkUnit hy).isUnit
97+
#align witt_vector.is_unit_of_coeff_zero_ne_zero WittVector.isUnit_of_coeff_zero_ne_zero
98+
99+
variable (p)
100+
101+
theorem irreducible : Irreducible (p : 𝕎 k) := by
102+
have hp : ¬IsUnit (p : 𝕎 k) := by
103+
intro hp
104+
simpa only [constantCoeff_apply, coeff_p_zero, not_isUnit_zero] using
105+
(constantCoeff : WittVector p k →+* _).isUnit_map hp
106+
refine' ⟨hp, fun a b hab => _⟩
107+
obtain ⟨ha0, hb0⟩ : a ≠ 0 ∧ b ≠ 0 := by
108+
rw [← mul_ne_zero_iff]; intro h; rw [h] at hab; exact p_nonzero p k hab
109+
obtain ⟨m, a, ha, rfl⟩ := verschiebung_nonzero ha0
110+
obtain ⟨n, b, hb, rfl⟩ := verschiebung_nonzero hb0
111+
cases m; · exact Or.inl (isUnit_of_coeff_zero_ne_zero a ha)
112+
cases' n with n; · exact Or.inr (isUnit_of_coeff_zero_ne_zero b hb)
113+
rw [iterate_verschiebung_mul] at hab
114+
apply_fun fun x => coeff x 1 at hab
115+
simp only [coeff_p_one, Nat.add_succ, add_comm _ n, Function.iterate_succ', Function.comp_apply,
116+
verschiebung_coeff_add_one, verschiebung_coeff_zero] at hab
117+
exact (one_ne_zero hab).elim
118+
#align witt_vector.irreducible WittVector.irreducible
119+
120+
end Field
121+
122+
section PerfectRing
123+
124+
variable {k : Type _} [CommRing k] [CharP k p] [PerfectRing k p]
125+
126+
theorem exists_eq_pow_p_mul (a : 𝕎 k) (ha : a ≠ 0) :
127+
∃ (m : ℕ) (b : 𝕎 k), b.coeff 00 ∧ a = (p : 𝕎 k) ^ m * b := by
128+
obtain ⟨m, c, hc, hcm⟩ := WittVector.verschiebung_nonzero ha
129+
obtain ⟨b, rfl⟩ := (frobenius_bijective p k).surjective.iterate m c
130+
rw [WittVector.iterate_frobenius_coeff] at hc
131+
have := congr_fun (WittVector.verschiebung_frobenius_comm.comp_iterate m) b
132+
simp only [Function.comp_apply] at this
133+
rw [← this] at hcm
134+
refine' ⟨m, b, _, _⟩
135+
· contrapose! hc
136+
have : 0 < p ^ m := pow_pos (Nat.Prime.pos Fact.out) _
137+
simp [hc, zero_pow this]
138+
· simp_rw [← mul_left_iterate (p : 𝕎 k) m]
139+
convert hcm using 2
140+
ext1 x
141+
rw [mul_comm, ← WittVector.verschiebung_frobenius x]; rfl
142+
#align witt_vector.exists_eq_pow_p_mul WittVector.exists_eq_pow_p_mul
143+
144+
end PerfectRing
145+
146+
section PerfectField
147+
148+
variable {k : Type _} [Field k] [CharP k p] [PerfectRing k p]
149+
150+
theorem exists_eq_pow_p_mul' (a : 𝕎 k) (ha : a ≠ 0) :
151+
∃ (m : ℕ) (b : Units (𝕎 k)), a = (p : 𝕎 k) ^ m * b := by
152+
obtain ⟨m, b, h₁, h₂⟩ := exists_eq_pow_p_mul a ha
153+
let b₀ := Units.mk0 (b.coeff 0) h₁
154+
have hb₀ : b.coeff 0 = b₀ := rfl
155+
exact ⟨m, mkUnit hb₀, h₂⟩
156+
#align witt_vector.exists_eq_pow_p_mul' WittVector.exists_eq_pow_p_mul'
157+
158+
/-
159+
Note: The following lemma should be an instance, but it seems to cause some
160+
exponential blowups in certain typeclass resolution problems.
161+
See the following Lean4 issue as well as the zulip discussion linked there:
162+
https://github.com/leanprover/lean4/issues/1102
163+
-/
164+
/-- The ring of Witt Vectors of a perfect field of positive characteristic is a DVR.
165+
-/
166+
theorem discreteValuationRing : DiscreteValuationRing (𝕎 k) :=
167+
DiscreteValuationRing.ofHasUnitMulPowIrreducibleFactorization (by
168+
refine' ⟨p, irreducible p, fun {x} hx => _⟩
169+
obtain ⟨n, b, hb⟩ := exists_eq_pow_p_mul' x hx
170+
exact ⟨n, b, hb.symm⟩)
171+
#align witt_vector.discrete_valuation_ring WittVector.discreteValuationRing
172+
173+
end PerfectField
174+
175+
end WittVector

0 commit comments

Comments
 (0)