Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
Project: Xena
Views: 18536License: APACHE
/- Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Kenny Lau The perfect closure of a field. -/ import algebra.char_p universes u v /-- A perfect field is a field of characteristic p that has p-th root. -/ class perfect_field (α : Type u) [field α] (p : ℕ) [char_p α p] : Type u := (pth_root : α → α) (frobenius_pth_root : ∀ x, frobenius α p (pth_root x) = x) theorem frobenius_pth_root (α : Type u) [field α] (p : ℕ) [char_p α p] [perfect_field α p] (x : α) : frobenius α p (perfect_field.pth_root p x) = x := perfect_field.frobenius_pth_root p x theorem pth_root_frobenius (α : Type u) [field α] (p : ℕ) [nat.prime p] [char_p α p] [perfect_field α p] (x : α) : perfect_field.pth_root p (frobenius α p x) = x := frobenius_inj α p _ _ (by rw frobenius_pth_root) instance pth_root.is_ring_hom (α : Type u) [field α] (p : ℕ) [nat.prime p] [char_p α p] [perfect_field α p] : is_ring_hom (@perfect_field.pth_root α _ p _ _) := { map_one := frobenius_inj α p _ _ (by rw [frobenius_pth_root, frobenius_one]), map_mul := λ x y, frobenius_inj α p _ _ (by simp only [frobenius_pth_root, frobenius_mul]), map_add := λ x y, frobenius_inj α p _ _ (by simp only [frobenius_pth_root, frobenius_add]) } theorem is_ring_hom.pth_root {α : Type u} [field α] (p : ℕ) [nat.prime p] [char_p α p] [perfect_field α p] {β : Type v} [field β] [char_p β p] [perfect_field β p] (f : α → β) [is_ring_hom f] {x : α} : f (perfect_field.pth_root p x) = perfect_field.pth_root p (f x) := frobenius_inj β p _ _ (by rw [← is_monoid_hom.map_frobenius f, frobenius_pth_root, frobenius_pth_root]) inductive perfect_closure.r (α : Type u) [monoid α] (p : ℕ) : (ℕ × α) → (ℕ × α) → Prop | intro : ∀ n x, perfect_closure.r (n, x) (n+1, frobenius α p x) run_cmd tactic.mk_iff_of_inductive_prop `perfect_closure.r `perfect_closure.r_iff /-- The perfect closure is the smallest extension that makes frobenius surjective. -/ def perfect_closure (α : Type u) [monoid α] (p : ℕ) : Type u := quot (perfect_closure.r α p) namespace perfect_closure variables (α : Type u) private lemma mul_aux_left [comm_monoid α] (p : ℕ) (x1 x2 y : ℕ × α) (H : r α p x1 x2) : quot.mk (r α p) (x1.1 + y.1, ((frobenius α p)^[y.1] x1.2) * ((frobenius α p)^[x1.1] y.2)) = quot.mk (r α p) (x2.1 + y.1, ((frobenius α p)^[y.1] x2.2) * ((frobenius α p)^[x2.1] y.2)) := match x1, x2, H with | _, _, r.intro _ n x := quot.sound $ by rw [← nat.iterate_succ, nat.iterate_succ', nat.iterate_succ', ← frobenius_mul, nat.succ_add]; apply r.intro end private lemma mul_aux_right [comm_monoid α] (p : ℕ) (x y1 y2 : ℕ × α) (H : r α p y1 y2) : quot.mk (r α p) (x.1 + y1.1, ((frobenius α p)^[y1.1] x.2) * ((frobenius α p)^[x.1] y1.2)) = quot.mk (r α p) (x.1 + y2.1, ((frobenius α p)^[y2.1] x.2) * ((frobenius α p)^[x.1] y2.2)) := match y1, y2, H with | _, _, r.intro _ n y := quot.sound $ by rw [← nat.iterate_succ, nat.iterate_succ', nat.iterate_succ', ← frobenius_mul]; apply r.intro end instance [comm_monoid α] (p : ℕ) : has_mul (perfect_closure α p) := ⟨quot.lift (λ x:ℕ×α, quot.lift (λ y:ℕ×α, quot.mk (r α p) (x.1 + y.1, ((frobenius α p)^[y.1] x.2) * ((frobenius α p)^[x.1] y.2))) (mul_aux_right α p x)) (λ x1 x2 (H : r α p x1 x2), funext $ λ e, quot.induction_on e $ λ y, mul_aux_left α p x1 x2 y H)⟩ instance [comm_monoid α] (p : ℕ) : comm_monoid (perfect_closure α p) := { mul_assoc := λ e f g, quot.induction_on e $ λ ⟨m, x⟩, quot.induction_on f $ λ ⟨n, y⟩, quot.induction_on g $ λ ⟨s, z⟩, congr_arg (quot.mk _) $ by simp only [add_assoc, mul_assoc, nat.iterate₂ (frobenius_mul _ _), (nat.iterate_add _ _ _ _).symm, add_comm, add_left_comm], one := quot.mk _ (0, 1), one_mul := λ e, quot.induction_on e (λ ⟨n, x⟩, congr_arg (quot.mk _) $ by simp only [nat.iterate₀ (frobenius_one _ _), nat.iterate_zero, one_mul, zero_add]), mul_one := λ e, quot.induction_on e (λ ⟨n, x⟩, congr_arg (quot.mk _) $ by simp only [nat.iterate₀ (frobenius_one _ _), nat.iterate_zero, mul_one, add_zero]), mul_comm := λ e f, quot.induction_on e (λ ⟨m, x⟩, quot.induction_on f (λ ⟨n, y⟩, congr_arg (quot.mk _) $ by simp only [add_comm, mul_comm])), .. (infer_instance : has_mul (perfect_closure α p)) } instance [comm_monoid α] (p) : inhabited (perfect_closure α p) := ⟨1⟩ private lemma add_aux_left [comm_ring α] (p : ℕ) (hp : nat.prime p) [char_p α p] (x1 x2 y : ℕ × α) (H : r α p x1 x2) : quot.mk (r α p) (x1.1 + y.1, ((frobenius α p)^[y.1] x1.2) + ((frobenius α p)^[x1.1] y.2)) = quot.mk (r α p) (x2.1 + y.1, ((frobenius α p)^[y.1] x2.2) + ((frobenius α p)^[x2.1] y.2)) := match x1, x2, H with | _, _, r.intro _ n x := quot.sound $ by rw [← nat.iterate_succ, nat.iterate_succ', nat.iterate_succ', ← frobenius_add, nat.succ_add]; apply r.intro end private lemma add_aux_right [comm_ring α] (p : ℕ) (hp : nat.prime p) [char_p α p] (x y1 y2 : ℕ × α) (H : r α p y1 y2) : quot.mk (r α p) (x.1 + y1.1, ((frobenius α p)^[y1.1] x.2) + ((frobenius α p)^[x.1] y1.2)) = quot.mk (r α p) (x.1 + y2.1, ((frobenius α p)^[y2.1] x.2) + ((frobenius α p)^[x.1] y2.2)) := match y1, y2, H with | _, _, r.intro _ n y := quot.sound $ by rw [← nat.iterate_succ, nat.iterate_succ', nat.iterate_succ', ← frobenius_add]; apply r.intro end instance [comm_ring α] (p : ℕ) [hp : nat.prime p] [char_p α p] : has_add (perfect_closure α p) := ⟨quot.lift (λ x:ℕ×α, quot.lift (λ y:ℕ×α, quot.mk (r α p) (x.1 + y.1, ((frobenius α p)^[y.1] x.2) + ((frobenius α p)^[x.1] y.2))) (add_aux_right α p hp x)) (λ x1 x2 (H : r α p x1 x2), funext $ λ e, quot.induction_on e $ λ y, add_aux_left α p hp x1 x2 y H)⟩ instance [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] : has_neg (perfect_closure α p) := ⟨quot.lift (λ x:ℕ×α, quot.mk (r α p) (x.1, -x.2)) (λ x y (H : r α p x y), match x, y, H with | _, _, r.intro _ n x := quot.sound $ by rw ← frobenius_neg; apply r.intro end)⟩ theorem mk_zero [comm_ring α] (p : ℕ) [nat.prime p] (n : ℕ) : quot.mk (r α p) (n, 0) = quot.mk (r α p) (0, 0) := by induction n with n ih; [refl, rw ← ih]; symmetry; apply quot.sound; have := r.intro p n (0:α); rwa [frobenius_zero α p] at this theorem r.sound [monoid α] (p m n : ℕ) (x y : α) (H : frobenius α p^[m] x = y) : quot.mk (r α p) (n, x) = quot.mk (r α p) (m + n, y) := by subst H; induction m with m ih; [simp only [zero_add, nat.iterate_zero], rw [ih, nat.succ_add, nat.iterate_succ']]; apply quot.sound; apply r.intro instance [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] : comm_ring (perfect_closure α p) := { add_assoc := λ e f g, quot.induction_on e $ λ ⟨m, x⟩, quot.induction_on f $ λ ⟨n, y⟩, quot.induction_on g $ λ ⟨s, z⟩, congr_arg (quot.mk _) $ by simp only [add_assoc, nat.iterate₂ (frobenius_add α p), (nat.iterate_add _ _ _ _).symm, add_comm, add_left_comm], zero := quot.mk _ (0, 0), zero_add := λ e, quot.induction_on e (λ ⟨n, x⟩, congr_arg (quot.mk _) $ by simp only [nat.iterate₀ (frobenius_zero α p), nat.iterate_zero, zero_add]), add_zero := λ e, quot.induction_on e (λ ⟨n, x⟩, congr_arg (quot.mk _) $ by simp only [nat.iterate₀ (frobenius_zero α p), nat.iterate_zero, add_zero]), add_left_neg := λ e, quot.induction_on e (λ ⟨n, x⟩, show quot.mk _ _ = _, by simp only [nat.iterate₁ (frobenius_neg α p), add_left_neg, mk_zero]; refl), add_comm := λ e f, quot.induction_on e (λ ⟨m, x⟩, quot.induction_on f (λ ⟨n, y⟩, congr_arg (quot.mk _) $ by simp only [add_comm])), left_distrib := λ e f g, quot.induction_on e $ λ ⟨m, x⟩, quot.induction_on f $ λ ⟨n, y⟩, quot.induction_on g $ λ ⟨s, z⟩, show quot.mk _ _ = quot.mk _ _, by simp only [add_assoc, add_comm, add_left_comm]; apply r.sound; simp only [nat.iterate₂ (frobenius_mul α p), nat.iterate₂ (frobenius_add α p), (nat.iterate_add _ _ _ _).symm, mul_add, add_comm, add_left_comm], right_distrib := λ e f g, quot.induction_on e $ λ ⟨m, x⟩, quot.induction_on f $ λ ⟨n, y⟩, quot.induction_on g $ λ ⟨s, z⟩, show quot.mk _ _ = quot.mk _ _, by simp only [add_assoc, add_comm _ s, add_left_comm _ s]; apply r.sound; simp only [nat.iterate₂ (frobenius_mul α p), nat.iterate₂ (frobenius_add α p), (nat.iterate_add _ _ _ _).symm, add_mul, add_comm, add_left_comm], .. (infer_instance : has_add (perfect_closure α p)), .. (infer_instance : has_neg (perfect_closure α p)), .. (infer_instance : comm_monoid (perfect_closure α p)) } instance [discrete_field α] (p : ℕ) [nat.prime p] [char_p α p] : has_inv (perfect_closure α p) := ⟨quot.lift (λ x:ℕ×α, quot.mk (r α p) (x.1, x.2⁻¹)) (λ x y (H : r α p x y), match x, y, H with | _, _, r.intro _ n x := quot.sound $ by simp only [frobenius]; rw ← inv_pow'; apply r.intro end)⟩ theorem eq_iff' [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] (x y : ℕ × α) : quot.mk (r α p) x = quot.mk (r α p) y ↔ ∃ z, (frobenius α p^[y.1 + z] x.2) = (frobenius α p^[x.1 + z] y.2) := begin split, { intro H, replace H := quot.exact _ H, induction H, case eqv_gen.rel : x y H { cases H with n x, exact ⟨0, rfl⟩ }, case eqv_gen.refl : H { exact ⟨0, rfl⟩ }, case eqv_gen.symm : x y H ih { cases ih with w ih, exact ⟨w, ih.symm⟩ }, case eqv_gen.trans : x y z H1 H2 ih1 ih2 { cases ih1 with z1 ih1, cases ih2 with z2 ih2, existsi z2+(y.1+z1), rw [← add_assoc, nat.iterate_add, ih1], rw [← nat.iterate_add, add_comm, nat.iterate_add, ih2], rw [← nat.iterate_add], simp only [add_comm, add_left_comm] } }, intro H, cases x with m x, cases y with n y, cases H with z H, dsimp only at H, rw [r.sound α p (n+z) m x _ rfl, r.sound α p (m+z) n y _ rfl, H], rw [add_assoc, add_comm, add_comm z] end theorem eq_iff [integral_domain α] (p : ℕ) [nat.prime p] [char_p α p] (x y : ℕ × α) : quot.mk (r α p) x = quot.mk (r α p) y ↔ (frobenius α p^[y.1] x.2) = (frobenius α p^[x.1] y.2) := (eq_iff' α p x y).trans ⟨λ ⟨z, H⟩, nat.iterate_inj (frobenius_inj α p) z _ _ $ by simpa only [add_comm, nat.iterate_add] using H, λ H, ⟨0, H⟩⟩ instance [discrete_field α] (p : ℕ) [nat.prime p] [char_p α p] : discrete_field (perfect_closure α p) := { zero_ne_one := λ H, zero_ne_one ((eq_iff _ _ _ _).1 H), mul_inv_cancel := λ e, quot.induction_on e $ λ ⟨m, x⟩ H, have _ := mt (eq_iff _ _ _ _).2 H, (eq_iff _ _ _ _).2 (by simp only [nat.iterate₀ (frobenius_one _ _), nat.iterate₀ (frobenius_zero α p), nat.iterate_zero, (nat.iterate₂ (frobenius_mul α p)).symm] at this ⊢; rw [mul_inv_cancel this, nat.iterate₀ (frobenius_one _ _)]), inv_mul_cancel := λ e, quot.induction_on e $ λ ⟨m, x⟩ H, have _ := mt (eq_iff _ _ _ _).2 H, (eq_iff _ _ _ _).2 (by simp only [nat.iterate₀ (frobenius_one _ _), nat.iterate₀ (frobenius_zero α p), nat.iterate_zero, (nat.iterate₂ (frobenius_mul α p)).symm] at this ⊢; rw [inv_mul_cancel this, nat.iterate₀ (frobenius_one _ _)]), has_decidable_eq := λ e f, quot.rec_on_subsingleton e $ λ ⟨m, x⟩, quot.rec_on_subsingleton f $ λ ⟨n, y⟩, decidable_of_iff' _ (eq_iff α p _ _), inv_zero := congr_arg (quot.mk (r α p)) (by rw [inv_zero]), .. (infer_instance : has_inv (perfect_closure α p)), .. (infer_instance : comm_ring (perfect_closure α p)) } theorem frobenius_mk [comm_monoid α] (p : ℕ) (x : ℕ × α) : frobenius (perfect_closure α p) p (quot.mk (r α p) x) = quot.mk _ (x.1, x.2^p) := begin unfold frobenius, cases x with n x, dsimp only, suffices : ∀ p':ℕ, (quot.mk (r α p) (n, x) ^ p' : perfect_closure α p) = quot.mk (r α p) (n, x ^ p'), { apply this }, intro p, induction p with p ih, case nat.zero { apply r.sound, rw [nat.iterate₀ (frobenius_one _ _), pow_zero] }, case nat.succ { rw [pow_succ, ih], symmetry, apply r.sound, simp only [pow_succ, nat.iterate₂ (frobenius_mul _ _)] } end def frobenius_equiv [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] : perfect_closure α p ≃ perfect_closure α p := { to_fun := frobenius (perfect_closure α p) p, inv_fun := λ e, quot.lift_on e (λ x, quot.mk (r α p) (x.1 + 1, x.2)) (λ x y H, match x, y, H with | _, _, r.intro _ n x := quot.sound (r.intro _ _ _) end), left_inv := λ e, quot.induction_on e (λ ⟨m, x⟩, by rw frobenius_mk; symmetry; apply quot.sound; apply r.intro), right_inv := λ e, quot.induction_on e (λ ⟨m, x⟩, by rw frobenius_mk; symmetry; apply quot.sound; apply r.intro) } theorem frobenius_equiv_apply [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] {x : perfect_closure α p} : frobenius_equiv α p x = frobenius _ p x := rfl theorem nat_cast [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] (n x : ℕ) : (x : perfect_closure α p) = quot.mk (r α p) (n, x) := begin induction n with n ih, { induction x with x ih, {refl}, rw [nat.cast_succ, nat.cast_succ, ih], refl }, rw ih, apply quot.sound, conv {congr, skip, skip, rw ← frobenius_nat_cast α p x}, apply r.intro end theorem int_cast [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] (x : ℤ) : (x : perfect_closure α p) = quot.mk (r α p) (0, x) := by induction x; simp only [int.cast_of_nat, int.cast_neg_succ_of_nat, nat_cast α p 0]; refl theorem nat_cast_eq_iff [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] (x y : ℕ) : (x : perfect_closure α p) = y ↔ (x : α) = y := begin split; intro H, { rw [nat_cast α p 0, nat_cast α p 0, eq_iff'] at H, cases H with z H, simpa only [zero_add, nat.iterate₀ (frobenius_nat_cast α p _)] using H }, rw [nat_cast α p 0, nat_cast α p 0, H] end instance [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] : char_p (perfect_closure α p) p := begin constructor, intro x, rw ← char_p.cast_eq_zero_iff α, rw [← nat.cast_zero, nat_cast_eq_iff, nat.cast_zero] end instance [discrete_field α] (p : ℕ) [nat.prime p] [char_p α p] : perfect_field (perfect_closure α p) p := { pth_root := (frobenius_equiv α p).symm, frobenius_pth_root := (frobenius_equiv α p).apply_symm_apply } def of [monoid α] (p : ℕ) (x : α) : perfect_closure α p := quot.mk _ (0, x) instance [comm_ring α] (p : ℕ) [nat.prime p] [char_p α p] : is_ring_hom (of α p) := { map_one := rfl, map_mul := λ x y, rfl, map_add := λ x y, rfl } theorem eq_pth_root [discrete_field α] (p : ℕ) [nat.prime p] [char_p α p] (m : ℕ) (x : α) : quot.mk (r α p) (m, x) = (perfect_field.pth_root p^[m] (of α p x) : perfect_closure α p) := begin unfold of, induction m with m ih, {refl}, rw [nat.iterate_succ', ← ih]; refl end def UMP [discrete_field α] (p : ℕ) [nat.prime p] [char_p α p] (β : Type v) [discrete_field β] [char_p β p] [perfect_field β p] : { f : α → β // is_ring_hom f } ≃ { f : perfect_closure α p → β // is_ring_hom f } := { to_fun := λ f, ⟨λ e, quot.lift_on e (λ x, perfect_field.pth_root p^[x.1] (f.1 x.2)) (λ x y H, match x, y, H with | _, _, r.intro _ n x := by letI := f.2; simp only [is_monoid_hom.map_frobenius f.1, nat.iterate_succ, pth_root_frobenius] end), show f.1 1 = 1, from f.2.1, λ j k, quot.induction_on j $ λ ⟨m, x⟩, quot.induction_on k $ λ ⟨n, y⟩, show (perfect_field.pth_root p^[_] _) = (perfect_field.pth_root p^[_] _) * (perfect_field.pth_root p^[_] _), by letI := f.2; simp only [is_ring_hom.map_mul f.1, (nat.iterate₁ (λ x, (is_monoid_hom.map_frobenius f.1 p x).symm)).symm, @nat.iterate₂ β _ (*) (λ x y, is_ring_hom.map_mul (perfect_field.pth_root p))]; rw [nat.iterate_add, nat.iterate_cancel (pth_root_frobenius β p), add_comm, nat.iterate_add, nat.iterate_cancel (pth_root_frobenius β p)], λ j k, quot.induction_on j $ λ ⟨m, x⟩, quot.induction_on k $ λ ⟨n, y⟩, show (perfect_field.pth_root p^[_] _) = (perfect_field.pth_root p^[_] _) + (perfect_field.pth_root p^[_] _), by letI := f.2; simp only [is_ring_hom.map_add f.1, (nat.iterate₁ (λ x, (is_monoid_hom.map_frobenius f.1 p x).symm)).symm, @nat.iterate₂ β _ (+) (λ x y, is_ring_hom.map_add (perfect_field.pth_root p))]; rw [nat.iterate_add, nat.iterate_cancel (pth_root_frobenius β p), add_comm m, nat.iterate_add, nat.iterate_cancel (pth_root_frobenius β p)]⟩, inv_fun := λ f, ⟨f.1 ∘ of α p, @@is_ring_hom.comp _ _ _ _ _ _ f.2⟩, left_inv := λ ⟨f, hf⟩, subtype.eq rfl, right_inv := λ ⟨f, hf⟩, subtype.eq $ funext $ λ i, quot.induction_on i $ λ ⟨m, x⟩, show perfect_field.pth_root p^[m] (f _) = f _, by resetI; rw [eq_pth_root, @nat.iterate₁ _ _ _ _ f (λ x:perfect_closure α p, (is_ring_hom.pth_root p f).symm)] } end perfect_closure