-
Notifications
You must be signed in to change notification settings - Fork 273
/
AdmissibleAbsoluteValue.lean
135 lines (116 loc) · 6.4 KB
/
AdmissibleAbsoluteValue.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/-
Copyright (c) 2021 Anne Baanen. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Anne Baanen
-/
import Mathlib.Data.Real.Basic
import Mathlib.Combinatorics.Pigeonhole
import Mathlib.Algebra.Order.EuclideanAbsoluteValue
#align_import number_theory.class_number.admissible_absolute_value from "leanprover-community/mathlib"@"f7fc89d5d5ff1db2d1242c7bb0e9062ce47ef47c"
/-!
# Admissible absolute values
This file defines a structure `AbsoluteValue.IsAdmissible` which we use to show the class number
of the ring of integers of a global field is finite.
## Main definitions
* `AbsoluteValue.IsAdmissible abv` states the absolute value `abv : R → ℤ`
respects the Euclidean domain structure on `R`, and that a large enough set
of elements of `R^n` contains a pair of elements whose remainders are
pointwise close together.
## Main results
* `AbsoluteValue.absIsAdmissible` shows the "standard" absolute value on `ℤ`,
mapping negative `x` to `-x`, is admissible.
* `Polynomial.cardPowDegreeIsAdmissible` shows `cardPowDegree`,
mapping `p : Polynomial 𝔽_q` to `q ^ degree p`, is admissible
-/
local infixl:50 " ≺ " => EuclideanDomain.r
namespace AbsoluteValue
variable {R : Type*} [EuclideanDomain R]
variable (abv : AbsoluteValue R ℤ)
/-- An absolute value `R → ℤ` is admissible if it respects the Euclidean domain
structure and a large enough set of elements in `R^n` will contain a pair of
elements whose remainders are pointwise close together. -/
structure IsAdmissible extends IsEuclidean abv where
protected card : ℝ → ℕ
/-- For all `ε > 0` and finite families `A`, we can partition the remainders of `A` mod `b`
into `abv.card ε` sets, such that all elements in each part of remainders are close together. -/
exists_partition' :
∀ (n : ℕ) {ε : ℝ} (_ : 0 < ε) {b : R} (_ : b ≠ 0) (A : Fin n → R),
∃ t : Fin n → Fin (card ε), ∀ i₀ i₁, t i₀ = t i₁ → (abv (A i₁ % b - A i₀ % b) : ℝ) < abv b • ε
#align absolute_value.is_admissible AbsoluteValue.IsAdmissible
-- Porting note: no docstrings for IsAdmissible
attribute [nolint docBlame] IsAdmissible.card
namespace IsAdmissible
variable {abv}
/-- For all `ε > 0` and finite families `A`, we can partition the remainders of `A` mod `b`
into `abv.card ε` sets, such that all elements in each part of remainders are close together. -/
theorem exists_partition {ι : Type*} [Finite ι] {ε : ℝ} (hε : 0 < ε) {b : R} (hb : b ≠ 0)
(A : ι → R) (h : abv.IsAdmissible) : ∃ t : ι → Fin (h.card ε),
∀ i₀ i₁, t i₀ = t i₁ → (abv (A i₁ % b - A i₀ % b) : ℝ) < abv b • ε := by
rcases Finite.exists_equiv_fin ι with ⟨n, ⟨e⟩⟩
obtain ⟨t, ht⟩ := h.exists_partition' n hε hb (A ∘ e.symm)
refine' ⟨t ∘ e, fun i₀ i₁ h ↦ _⟩
convert (config := {transparency := .default})
ht (e i₀) (e i₁) h <;> simp only [e.symm_apply_apply]
#align absolute_value.is_admissible.exists_partition AbsoluteValue.IsAdmissible.exists_partition
/-- Any large enough family of vectors in `R^n` has a pair of elements
whose remainders are close together, pointwise. -/
theorem exists_approx_aux (n : ℕ) (h : abv.IsAdmissible) :
∀ {ε : ℝ} (_hε : 0 < ε) {b : R} (_hb : b ≠ 0) (A : Fin (h.card ε ^ n).succ → Fin n → R),
∃ i₀ i₁, i₀ ≠ i₁ ∧ ∀ k, (abv (A i₁ k % b - A i₀ k % b) : ℝ) < abv b • ε := by
haveI := Classical.decEq R
induction' n with n ih
· intro ε _hε b _hb A
refine' ⟨0, 1, _, _⟩
· simp
rintro ⟨i, ⟨⟩⟩
intro ε hε b hb A
let M := h.card ε
-- By the "nicer" pigeonhole principle, we can find a collection `s`
-- of more than `M^n` remainders where the first components lie close together:
obtain ⟨s, s_inj, hs⟩ :
∃ s : Fin (M ^ n).succ → Fin (M ^ n.succ).succ,
Function.Injective s ∧ ∀ i₀ i₁, (abv (A (s i₁) 0 % b - A (s i₀) 0 % b) : ℝ) < abv b • ε := by
-- We can partition the `A`s into `M` subsets where
-- the first components lie close together:
obtain ⟨t, ht⟩ :
∃ t : Fin (M ^ n.succ).succ → Fin M,
∀ i₀ i₁, t i₀ = t i₁ → (abv (A i₁ 0 % b - A i₀ 0 % b) : ℝ) < abv b • ε :=
h.exists_partition hε hb fun x ↦ A x 0
-- Since the `M` subsets contain more than `M * M^n` elements total,
-- there must be a subset that contains more than `M^n` elements.
obtain ⟨s, hs⟩ :=
Fintype.exists_lt_card_fiber_of_mul_lt_card (f := t)
(by simpa only [Fintype.card_fin, pow_succ'] using Nat.lt_succ_self (M ^ n.succ))
refine'
⟨fun i ↦ (Finset.univ.filter fun x ↦ t x = s).toList.nthLe i _, _, fun i₀ i₁ ↦ ht _ _ _⟩
· refine' i.2.trans_le _
rwa [Finset.length_toList]
· intro i j h
ext
exact Fin.mk.inj_iff.mp (List.nodup_iff_injective_get.mp (Finset.nodup_toList _) h)
have : ∀ i h, (Finset.univ.filter fun x ↦ t x = s).toList.nthLe i h ∈
Finset.univ.filter fun x ↦ t x = s := by
intro i h
exact Finset.mem_toList.mp (List.get_mem _ i h)
obtain ⟨_, h₀⟩ := Finset.mem_filter.mp (this i₀ _)
obtain ⟨_, h₁⟩ := Finset.mem_filter.mp (this i₁ _)
exact h₀.trans h₁.symm
-- Since `s` is large enough, there are two elements of `A ∘ s`
-- where the second components lie close together.
obtain ⟨k₀, k₁, hk, h⟩ := ih hε hb fun x ↦ Fin.tail (A (s x))
refine' ⟨s k₀, s k₁, fun h ↦ hk (s_inj h), fun i ↦ Fin.cases _ (fun i ↦ _) i⟩
· exact hs k₀ k₁
· exact h i
#align absolute_value.is_admissible.exists_approx_aux AbsoluteValue.IsAdmissible.exists_approx_aux
/-- Any large enough family of vectors in `R^ι` has a pair of elements
whose remainders are close together, pointwise. -/
theorem exists_approx {ι : Type*} [Fintype ι] {ε : ℝ} (hε : 0 < ε) {b : R} (hb : b ≠ 0)
(h : abv.IsAdmissible) (A : Fin (h.card ε ^ Fintype.card ι).succ → ι → R) :
∃ i₀ i₁, i₀ ≠ i₁ ∧ ∀ k, (abv (A i₁ k % b - A i₀ k % b) : ℝ) < abv b • ε := by
let e := Fintype.equivFin ι
obtain ⟨i₀, i₁, ne, h⟩ := h.exists_approx_aux (Fintype.card ι) hε hb fun x y ↦ A x (e.symm y)
refine ⟨i₀, i₁, ne, fun k ↦ ?_⟩
convert h (e k) <;> simp only [e.symm_apply_apply]
#align absolute_value.is_admissible.exists_approx AbsoluteValue.IsAdmissible.exists_approx
end IsAdmissible
end AbsoluteValue