Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat(field_theory/finite): Chevalley–Warning #1564

Closed
wants to merge 81 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
792cde8
Start on Chevalley-Warning
jcommelin Oct 16, 2019
74ff642
WIP
jcommelin Oct 16, 2019
804912a
WIP
jcommelin Oct 16, 2019
867eb00
Fix two sorries
jcommelin Oct 17, 2019
68bef93
Annoying stuff is left
jcommelin Oct 17, 2019
3cfe90e
Finish proof of Chevalley-Warning
jcommelin Oct 17, 2019
0f0b1b1
Fix build, and clean up
jcommelin Oct 17, 2019
6603845
Little change
jcommelin Oct 17, 2019
12a306c
Remove commented code
jcommelin Oct 17, 2019
b900b0b
Undo renaming
jcommelin Oct 17, 2019
60da8ea
Oops, forgot one
jcommelin Oct 17, 2019
95b3382
Reorganise files
jcommelin Oct 17, 2019
4f7e38a
Fix build
jcommelin Oct 17, 2019
8d5f72a
Merge branch 'master' into chev-warn
jcommelin Apr 25, 2020
d2944ee
Fix build
jcommelin Apr 25, 2020
ca43045
WIP
jcommelin Apr 25, 2020
7a1afbd
Fix build
jcommelin Apr 26, 2020
a9b7dcf
Implement some suggestions by Reid
jcommelin Apr 26, 2020
1ed8801
Remove field_theory/finite/
jcommelin Apr 26, 2020
be84c3d
Use fact
jcommelin Apr 26, 2020
2450959
Refactoring a bunch of proofs, and linting
jcommelin Apr 27, 2020
00c1756
Minor cleanups
jcommelin Apr 27, 2020
4e1c410
Refactor
jcommelin Apr 27, 2020
49de949
Prove a version of Chev-Warn for 1 polynomial
jcommelin Apr 27, 2020
8e8c871
Linting
jcommelin Apr 27, 2020
57dbc1a
Linting
jcommelin Apr 28, 2020
26c6a07
More refactoring
jcommelin Apr 28, 2020
a242ea1
Move things to proper place
jcommelin Apr 28, 2020
88a5f98
Remove some lemmas that are already there in greater generality
jcommelin Apr 28, 2020
3822558
fix build
jcommelin Apr 28, 2020
fa3dbd6
Minor tweak
jcommelin Apr 29, 2020
9b5d7b2
feat(*): small additions that prepare for Chevalley-Warning
jcommelin Apr 29, 2020
13821c0
Merge branch 'chev-warn-pre1' into chev-warn
jcommelin Apr 29, 2020
8b2cf7d
refactor proof
jcommelin Apr 29, 2020
d40e72f
More refactoring
jcommelin Apr 29, 2020
2fc68f8
Small change
jcommelin Apr 29, 2020
60f0110
More refactoring
jcommelin Apr 30, 2020
57e7847
don't use fintype.prod/sum
jcommelin Apr 30, 2020
f807947
Fix notation
jcommelin May 1, 2020
87c91cd
Merge branch 'master' into chev-warn
jcommelin May 1, 2020
910d679
Merge branch 'master' into chev-warn
jcommelin May 2, 2020
c78d943
refactor(field_theory): merge finite_card into finite
jcommelin May 2, 2020
ee590e2
Update src/field_theory/finite.lean
jcommelin May 2, 2020
5da96f0
Apply suggestions from code review
jcommelin May 3, 2020
b7c3111
Refactor proof
jcommelin May 4, 2020
1d1db80
Add docstring
jcommelin May 4, 2020
b84525f
Merge branch 'master' into finite-fields
jcommelin May 4, 2020
dceef1f
Use the fact that calc now refines
jcommelin May 4, 2020
3797267
Merge branch 'master' into finite-fields
jcommelin May 5, 2020
53c170e
WIP
jcommelin May 5, 2020
8bf853f
chore(field_theory/finite): meaningful variable names
jcommelin May 5, 2020
c81d602
refactor(field_theory): move finite_card.lean into finite.lean
jcommelin May 5, 2020
9734cc2
Ooops, forgot to actually delete the file
jcommelin May 5, 2020
4d24680
Merge branch 'finite-card' into finite-fields
jcommelin May 5, 2020
757475b
Merge branch 'master' into finite-fields
jcommelin May 6, 2020
234d57e
Merge branch 'master' into finite-fields
jcommelin May 13, 2020
e3792ec
Linting
jcommelin May 13, 2020
d34c69f
Slight golfing
jcommelin May 14, 2020
0816f6f
Merge branch 'finite-fields' into chev-warn
jcommelin May 14, 2020
12320ab
Merge branch 'master' into chev-warn
jcommelin May 18, 2020
dbcda17
Fix build
jcommelin May 18, 2020
15261ef
Undo open nat
jcommelin May 18, 2020
e49efc1
Minimise imports
jcommelin May 18, 2020
b46d997
Move code to correct place
jcommelin May 18, 2020
dbd5ce3
Restructure proof
jcommelin May 18, 2020
68e8f6a
Fix implicit/explicit variables and namespaces
jcommelin May 23, 2020
ca76a9b
Apply suggestions from code review
jcommelin May 23, 2020
7399607
Update src/field_theory/chevalley_warning.lean
jcommelin May 25, 2020
b394545
Process the easy comments
jcommelin May 25, 2020
3073980
Little fixes
jcommelin May 25, 2020
312fb08
Linting
jcommelin May 26, 2020
e23560b
Refactor an equiv
jcommelin May 26, 2020
6b47d22
Merge branch 'master' into chev-warn
jcommelin May 26, 2020
7946a32
Linting
jcommelin May 26, 2020
ff4a3fe
Remove deps on awkard instances
jcommelin May 27, 2020
b336013
Move files to correct place in mathlib
jcommelin May 27, 2020
8a79bb2
Merge branch 'community-master' into chev-warn
bryangingechen Jun 6, 2020
a423db5
Merge remote-tracking branch 'community/master' into chev-warn
bryangingechen Jun 6, 2020
02ec503
fix build
bryangingechen Jun 6, 2020
3e0d012
Merge branch 'community-master' into chev-warn
bryangingechen Jun 15, 2020
5fefb9c
fix build
bryangingechen Jun 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
205 changes: 205 additions & 0 deletions src/field_theory/finite/basic.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/-
Copyright (c) 2019 Casper Putz. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes, Joey van Langen, Casper Putz
-/

import data.equiv.algebra
import algebra.char_p
jcommelin marked this conversation as resolved.
Show resolved Hide resolved
import data.zmod.basic
import linear_algebra.basis

/-!
# Finite fields

This file contains basic results about finite fields.
Throughout most of this file, K denotes a finite field with q elements.

## Main results

1. Every finite integral domain is a field (`field_of_integral_domain`).
2. The unit group of a finite field is a cyclic group of order q - 1.
(`finite_field.is_cyclic` and `card_units`)
3. `sum_pow_units`: The sum of x^i, where x ranges over the units of K, is
| q-1 if q-1 ∣ i
| 0 otherwise
4. `finite_field.card`: The cardinality q is a power of the characteristic of K.
See `card'` for a variant.
-/

variables {K : Type*} [discrete_field K] [fintype K]

section

open function finset polynomial nat

variables {R : Type*} [integral_domain R] [decidable_eq R]
variables (S : set (units R)) [is_subgroup S] [fintype S]

lemma card_nth_roots_subgroup_units {n : ℕ} (hn : 0 < n) (a : S) :
(univ.filter (λ b : S, b ^ n = a)).card ≤ (nth_roots n ((a : units R) : R)).card :=
card_le_card_of_inj_on (λ a, ((a : units R) : R))
(by simp [mem_nth_roots hn, (units.coe_pow _ _).symm, -units.coe_pow, units.ext_iff.symm, subtype.coe_ext])
(by simp [units.ext_iff.symm, subtype.coe_ext.symm])

open_locale classical

instance subgroup_units_cyclic : is_cyclic S :=
is_cyclic_of_card_pow_eq_one_le
(λ n hn, le_trans (card_nth_roots_subgroup_units S hn 1) (card_nth_roots _ _))

end

namespace finite_field
variables {K : Type u} [discrete_field K] [fintype K]
local notation `q` := fintype.card K

/-- Every finite integral domain is a field. -/
def field_of_integral_domain [fintype R] [decidable_eq R] [integral_domain R] :
discrete_field R :=
{ has_decidable_eq := by apply_instance,
inv := λ a, if h : a = 0 then 0
else fintype.bij_inv (show function.bijective (* a),
from fintype.injective_iff_bijective.1 $ λ _ _, (domain.mul_right_inj h).1) 1,
inv_mul_cancel := λ a ha, show dite _ _ _ * a = _, by rw dif_neg ha;
exact fintype.right_inverse_bij_inv (show function.bijective (* a), from _) 1,
mul_inv_cancel := λ a ha, show a * dite _ _ _ = _, by rw [dif_neg ha, mul_comm];
exact fintype.right_inverse_bij_inv (show function.bijective (* a), from _) 1,
inv_zero := dif_pos rfl,
..show integral_domain R, by apply_instance }

section
open function finset polynomial

instance : fintype (units K) :=
by haveI := set_fintype {a : K | a ≠ 0}; exact
fintype.of_equiv _ (equiv.units_equiv_ne_zero K).symm

/-- A finite field of cardinality q has a unit group of cardinality q - 1. -/
lemma card_units : fintype.card (units K) = q - 1 :=
begin
rw [eq_comm, nat.sub_eq_iff_eq_add (fintype.card_pos_iff.2 ⟨(0 : K)⟩)],
haveI := set_fintype {a : K | a ≠ 0},
haveI := set_fintype (@set.univ K),
rw [fintype.card_congr (equiv.units_equiv_ne_zero _),
← @set.card_insert _ _ {a : K | a ≠ 0} _ (not_not.2 (eq.refl (0 : K)))
(set.fintype_insert _ _), fintype.card_congr (equiv.set.univ K).symm],
congr, ext, simp [classical.em]
end

instance : is_cyclic (units K) :=
by haveI := set_fintype (@set.univ (units K)); exact
let ⟨g, hg⟩ := is_cyclic.exists_generator (@set.univ (units K)) in
⟨⟨g, λ x, let ⟨n, hn⟩ := hg ⟨x, trivial⟩ in ⟨n, by rw [← is_subgroup.coe_gpow, hn]; refl⟩⟩⟩

lemma prod_univ_units_id_eq_neg_one : univ.prod (λ x, x) = (-1 : units K) :=
have ((@univ (units K) _).erase (-1)).prod (λ x, x) = 1,
from prod_involution (λ x _, x⁻¹) (by simp)
(λ a, by simp [units.inv_eq_self_iff] {contextual := tt})
(λ a, by simp [@inv_eq_iff_inv_eq _ _ a, eq_comm] {contextual := tt})
(by simp),
by rw [← insert_erase (mem_univ (-1 : units K)), prod_insert (not_mem_erase _ _),
this, mul_one]

/-- In a finite field of cardinality q, one has a^(q-1) = 1 for all nonzero a. -/
lemma pow_card_sub_one_eq_one (a : K) (ha : a ≠ 0) : a ^ (q - 1) = 1 :=
calc a ^ (q - 1) = (units.mk0 a ha ^ (q - 1) : units K) : by rw [units.coe_pow, units.mk0_val]
... = 1 : by rw [← card_units, pow_card_eq_one]; refl

variable (K)

/-- The sum of x^i as x ranges over the units of a finite field of cardinality q
is equal to 0 unless (q-1) ∣ i, in which case the sum is q-1. -/
lemma sum_pow_units (i : ℕ) :
univ.sum (λ (x : units K), (x^i : K)) = if (q - 1) ∣ i then q - 1 else 0 :=
begin
have hq : 0 < q - 1,
{ rw [← card_units, fintype.card_pos_iff],
exact ⟨1⟩ },
jcommelin marked this conversation as resolved.
Show resolved Hide resolved
cases is_cyclic.exists_generator (units K) with a ha,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could write

let ⟨a, ha⟩ := is_cyclic.exists_generator (units K) in
calc ...

and avoid "fake tactic mode".

Copy link
Member Author

@jcommelin jcommelin Apr 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mwah... there is so much tactic mode in this proof that I don't care about a little bit of fake tactic mode as well. (I know that calc is a fake tactic. But all the begin ... end blocks aren't)
Anyway, I can fix it if you prefer.

calc univ.sum (λ (x : units K), (x^i : K)) = (range (order_of a)).sum (λ k, ((a^k)^i : K)) :
begin
symmetry,
refine sum_bij (λ i hi, a^i) (λ _ _, mem_univ _) (λ _ _, by rw units.coe_pow) _ _,
{ intros i j hi hj h, rw [mem_range] at hi hj,
exact pow_injective_of_lt_order_of a hi hj h, },
{ intros x hx, specialize ha x,
rwa [mem_gpowers_iff_mem_range_order_of, mem_image] at ha,
rcases ha with ⟨i, hi, rfl⟩, exact ⟨i, hi, rfl⟩ }
end
... = geom_series (a^i : K) (q-1) :
begin
rw [order_of_eq_card_of_forall_mem_gpowers ha, card_units],
apply sum_congr rfl, intros k hk, rw [← pow_mul, mul_comm, pow_mul]
end
... = if (q - 1) ∣ i then q - 1 else 0 :
begin
split_ifs with H H,
{ rcases H with ⟨d, rfl⟩,
have aux : (λ (i:ℕ), ((a : K) ^ ((q - 1) * d)) ^ i) = λ i, 1,
{ funext i, rw [pow_mul, pow_card_sub_one_eq_one _ (units.ne_zero _), one_pow, one_pow], },
rw [geom_series_def, aux, sum_const, card_range, add_monoid.smul_one,
nat.cast_sub, nat.cast_one],
exact le_trans hq (nat.pred_le _), },
{ have key := geom_sum_mul (a^i : K) (q-1),
have hai : (a^i : K) ≠ 0, { rw ← units.coe_pow, apply units.ne_zero },
jcommelin marked this conversation as resolved.
Show resolved Hide resolved
rw [pow_card_sub_one_eq_one _ hai, sub_self] at key,
replace key := eq_zero_or_eq_zero_of_mul_eq_zero key,
rw classical.or_iff_not_imp_right at key, apply key, contrapose! H,
jcommelin marked this conversation as resolved.
Show resolved Hide resolved
rw [← card_units, ← order_of_eq_card_of_forall_mem_gpowers ha],
apply order_of_dvd_of_pow_eq_one,
rwa [units.ext_iff, units.coe_pow, units.coe_one, ← sub_eq_zero], }
end
end

/-- The sum of x^i as x ranges over a finite field of cardinality q is equal to 0 if i < q-1. -/
lemma sum_pow_lt_card_sub_one (i : ℕ) (h : i < q - 1) :
univ.sum (λ x, x^i) = (0:K) :=
begin
have hq : 0 < q - 1,
{ rw [← card_units, fintype.card_pos_iff],
exact ⟨1⟩ },
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't needed after other suggested changes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still a TODO

by_cases hi : i = 0,
{ rcases char_p.exists K with ⟨p, _char_p⟩, resetI,
rcases card K p with ⟨n, hp, hn⟩,
jcommelin marked this conversation as resolved.
Show resolved Hide resolved
simp only [hi, add_monoid.smul_one, sum_const, pow_zero, card_univ, cast_card_eq_zero], },
rw [← sum_sdiff (subset_univ (finset.singleton (0:K))), sum_singleton,
zero_pow (nat.pos_of_ne_zero hi), add_zero],
have := sum_pow_units K i,
have not_dvd_i : ¬q - 1 ∣ i,
jcommelin marked this conversation as resolved.
Show resolved Hide resolved
{ rintro ⟨d, rfl⟩, apply hi, rw nat.mul_eq_zero, right, contrapose! h,
conv { congr, rw ← mul_one (q-1), },
rw mul_le_mul_left hq, exact nat.pos_of_ne_zero h },
rw if_neg not_dvd_i at this,
conv_rhs {rw ← this}, symmetry,
refine sum_bij (λ x _, x) (λ _ _, by simp) (λ _ _, rfl) (λ _ _ _ _, units.ext_iff.mpr) _,
{ intros, refine ⟨units.mk0 b _, mem_univ _, rfl⟩,
simpa only [true_and, mem_sdiff, mem_univ, mem_singleton] using H, },
end

end

theorem card (p : ℕ) [char_p K p] : ∃ (n : ℕ+), nat.prime p ∧ q = p^(n : ℕ) :=
have hp : nat.prime p, from char_p.char_is_prime K p,
have V : vector_space (zmodp p hp) K, from {..zmod.to_module'},
let ⟨n, h⟩ := @vector_space.card_fintype _ _ _ _ V _ _ in
have hn : n > 0, from or.resolve_left (nat.eq_zero_or_pos n)
(assume h0 : n = 0,
have q = 1, by rw[←nat.pow_zero (fintype.card _), ←h0]; exact h,
have (1 : K) = 0, from (fintype.card_le_one_iff.mp (le_of_eq this)) 1 0,
absurd this one_ne_zero),
⟨⟨n, hn⟩, hp, fintype.card_fin p ▸ h⟩

theorem card' : ∃ (p : ℕ) (n : ℕ+), nat.prime p ∧ q = p^(n : ℕ) :=
let ⟨p, hc⟩ := char_p.exists K in ⟨p, @finite_field.card K _ _ p hc⟩

@[simp] lemma cast_card_eq_zero : (q : K) = 0 :=
begin
rcases char_p.exists K with ⟨p, _char_p⟩, resetI,
rcases card K p with ⟨n, hp, hn⟩,
simp only [char_p.cast_eq_zero_iff K p, hn],
conv { congr, rw [← nat.pow_one p] },
exact nat.pow_dvd_pow _ n.2,
end

end finite_field