File: Mathlib/FieldTheory/Perfect.lean

full_name: PerfectRing.bijective_frobenius
code: /-- A perfect ring of characteristic `p` (prime) in the sense of Serre.

NB: This is not related to the concept with the same name introduced by Bass (related to projective
covers of modules). -/
class PerfectRing (R : Type*) (p : ℕ) [CommSemiring R] [ExpChar R p] : Prop where
  /-- A ring is perfect if the Frobenius map is bijective. -/
  bijective_frobenius : Bijective <| frobenius R p
goal: Function.Bijective ⇑(frobenius R p)

full_name: PerfectRing
code: /-- A perfect ring of characteristic `p` (prime) in the sense of Serre.

NB: This is not related to the concept with the same name introduced by Bass (related to projective
covers of modules). -/
class PerfectRing (R : Type*) (p : ℕ) [CommSemiring R] [ExpChar R p] : Prop where
  /-- A ring is perfect if the Frobenius map is bijective. -/
  bijective_frobenius : Bijective <| frobenius R p
goal: Prop

full_name: PerfectRing.ofSurjective
code: /-- For a reduced ring, surjectivity of the Frobenius map is a sufficient condition for perfection.
-/
lemma PerfectRing.ofSurjective (R : Type*) (p : ℕ) [CommRing R] [ExpChar R p]
    [IsReduced R] (h : Surjective <| frobenius R p) : PerfectRing R p 
goal: PerfectRing R p

full_name: PerfectRing.ofFiniteOfIsReduced
code: instance PerfectRing.ofFiniteOfIsReduced (R : Type*) [CommRing R] [ExpChar R p]
    [Finite R] [IsReduced R] : PerfectRing R p 
goal: PerfectRing R p

full_name: bijective_frobenius
code: @[simp]
theorem bijective_frobenius : Bijective (frobenius R p) 
goal: Function.Bijective ⇑(frobenius R p)

full_name: bijective_iterateFrobenius
code: theorem bijective_iterateFrobenius : Bijective (iterateFrobenius R p n) 
goal: Function.Bijective ⇑(iterateFrobenius R p n)

full_name: injective_frobenius
code: @[simp]
theorem injective_frobenius : Injective (frobenius R p) 
goal: Function.Injective ⇑(frobenius R p)

full_name: surjective_frobenius
code: @[simp]
theorem surjective_frobenius : Surjective (frobenius R p) 
goal: Function.Surjective ⇑(frobenius R p)

full_name: frobeniusEquiv_apply
code: /-- The Frobenius automorphism for a perfect ring. -/
@[simps! apply]
noncomputable def frobeniusEquiv : R ≃+* R 
goal: (frobeniusEquiv R p) a = (frobenius R p) a

full_name: frobeniusEquiv
code: /-- The Frobenius automorphism for a perfect ring. -/
@[simps! apply]
noncomputable def frobeniusEquiv : R ≃+* R 
goal: R ≃+* R

full_name: coe_frobeniusEquiv
code: @[simp]
theorem coe_frobeniusEquiv : ⇑(frobeniusEquiv R p) = frobenius R p 
goal: ⇑(frobeniusEquiv R p) = ⇑(frobenius R p)

full_name: frobeniusEquiv_def
code: theorem frobeniusEquiv_def (x : R) : frobeniusEquiv R p x = x ^ p 
goal: (frobeniusEquiv R p) x = x ^ p

full_name: iterateFrobeniusEquiv
code: /-- The iterated Frobenius automorphism for a perfect ring. -/
@[simps! apply]
noncomputable def iterateFrobeniusEquiv : R ≃+* R 
goal: R ≃+* R

full_name: iterateFrobeniusEquiv_apply
code: /-- The iterated Frobenius automorphism for a perfect ring. -/
@[simps! apply]
noncomputable def iterateFrobeniusEquiv : R ≃+* R 
goal: (iterateFrobeniusEquiv R p n) a = (iterateFrobenius R p n) a

full_name: coe_iterateFrobeniusEquiv
code: @[simp]
theorem coe_iterateFrobeniusEquiv : ⇑(iterateFrobeniusEquiv R p n) = iterateFrobenius R p n 
goal: ⇑(iterateFrobeniusEquiv R p n) = ⇑(iterateFrobenius R p n)

full_name: iterateFrobeniusEquiv_def
code: theorem iterateFrobeniusEquiv_def (x : R) : iterateFrobeniusEquiv R p n x = x ^ p ^ n 
goal: (iterateFrobeniusEquiv R p n) x = x ^ p ^ n

full_name: iterateFrobeniusEquiv_add_apply
code: theorem iterateFrobeniusEquiv_add_apply (x : R) : iterateFrobeniusEquiv R p (m + n) x =
    iterateFrobeniusEquiv R p m (iterateFrobeniusEquiv R p n x) 
goal: (iterateFrobeniusEquiv R p (m + n)) x = (iterateFrobeniusEquiv R p m) ((iterateFrobeniusEquiv R p n) x)

full_name: iterateFrobeniusEquiv_add
code: theorem iterateFrobeniusEquiv_add : iterateFrobeniusEquiv R p (m + n) =
    (iterateFrobeniusEquiv R p n).trans (iterateFrobeniusEquiv R p m) 
goal: iterateFrobeniusEquiv R p (m + n) = (iterateFrobeniusEquiv R p n).trans (iterateFrobeniusEquiv R p m)

full_name: iterateFrobeniusEquiv_symm_add_apply
code: theorem iterateFrobeniusEquiv_symm_add_apply (x : R) : (iterateFrobeniusEquiv R p (m + n)).symm x =
    (iterateFrobeniusEquiv R p m).symm ((iterateFrobeniusEquiv R p n).symm x) 
goal: (iterateFrobeniusEquiv R p (m + n)).symm x = (iterateFrobeniusEquiv R p m).symm ((iterateFrobeniusEquiv R p n).symm x)

full_name: iterateFrobeniusEquiv_symm_add
code: theorem iterateFrobeniusEquiv_symm_add : (iterateFrobeniusEquiv R p (m + n)).symm =
    (iterateFrobeniusEquiv R p n).symm.trans (iterateFrobeniusEquiv R p m).symm 
goal: (iterateFrobeniusEquiv R p (m + n)).symm = (iterateFrobeniusEquiv R p n).symm.trans (iterateFrobeniusEquiv R p m).symm

full_name: iterateFrobeniusEquiv_zero_apply
code: theorem iterateFrobeniusEquiv_zero_apply (x : R) : iterateFrobeniusEquiv R p 0 x = x 
goal: (iterateFrobeniusEquiv R p 0) x = x

full_name: iterateFrobeniusEquiv_one_apply
code: theorem iterateFrobeniusEquiv_one_apply (x : R) : iterateFrobeniusEquiv R p 1 x = x ^ p 
goal: (iterateFrobeniusEquiv R p 1) x = x ^ p

full_name: iterateFrobeniusEquiv_zero
code: @[simp]
theorem iterateFrobeniusEquiv_zero  : iterateFrobeniusEquiv R p 0 = RingEquiv.refl R 
goal: iterateFrobeniusEquiv R p 0 = RingEquiv.refl R

full_name: iterateFrobeniusEquiv_one
code: @[simp]
theorem iterateFrobeniusEquiv_one : iterateFrobeniusEquiv R p 1 = frobeniusEquiv R p 
goal: iterateFrobeniusEquiv R p 1 = frobeniusEquiv R p

full_name: iterateFrobeniusEquiv_eq_pow
code: theorem iterateFrobeniusEquiv_eq_pow : iterateFrobeniusEquiv R p n = frobeniusEquiv R p ^ n 
goal: iterateFrobeniusEquiv R p n = frobeniusEquiv R p ^ n

full_name: iterateFrobeniusEquiv_symm
code: theorem iterateFrobeniusEquiv_symm :
    (iterateFrobeniusEquiv R p n).symm = (frobeniusEquiv R p).symm ^ n 
goal: (iterateFrobeniusEquiv R p n).symm = (frobeniusEquiv R p).symm ^ n

full_name: frobeniusEquiv_symm_apply_frobenius
code: @[simp]
theorem frobeniusEquiv_symm_apply_frobenius (x : R) :
    (frobeniusEquiv R p).symm (frobenius R p x) = x 
goal: (frobeniusEquiv R p).symm ((frobenius R p) x) = x

full_name: frobenius_apply_frobeniusEquiv_symm
code: @[simp]
theorem frobenius_apply_frobeniusEquiv_symm (x : R) :
    frobenius R p ((frobeniusEquiv R p).symm x) = x 
goal: (frobenius R p) ((frobeniusEquiv R p).symm x) = x

full_name: frobenius_comp_frobeniusEquiv_symm
code: @[simp]
theorem frobenius_comp_frobeniusEquiv_symm :
    (frobenius R p).comp (frobeniusEquiv R p).symm = RingHom.id R 
goal: (frobenius R p).comp ↑(frobeniusEquiv R p).symm = RingHom.id R

full_name: frobeniusEquiv_symm_comp_frobenius
code: @[simp]
theorem frobeniusEquiv_symm_comp_frobenius :
    ((frobeniusEquiv R p).symm : R →+* R).comp (frobenius R p) = RingHom.id R 
goal: (↑(frobeniusEquiv R p).symm).comp (frobenius R p) = RingHom.id R

full_name: frobeniusEquiv_symm_pow_p
code: @[simp]
theorem frobeniusEquiv_symm_pow_p (x : R) : ((frobeniusEquiv R p).symm x) ^ p = x 
goal: (frobeniusEquiv R p).symm x ^ p = x

full_name: injective_pow_p
code: theorem injective_pow_p {x y : R} (h : x ^ p = y ^ p) : x = y 
goal: x = y

full_name: polynomial_expand_eq
code: lemma polynomial_expand_eq (f : R[X]) :
    expand R p f = (f.map (frobeniusEquiv R p).symm) ^ p 
goal: (Polynomial.expand R p) f = Polynomial.map (↑(frobeniusEquiv R p).symm) f ^ p

full_name: not_irreducible_expand
code: @[simp]
theorem not_irreducible_expand (R p) [CommSemiring R] [Fact p.Prime] [CharP R p] [PerfectRing R p]
    (f : R[X]) : ¬ Irreducible (expand R p f) 
goal: ¬Irreducible ((Polynomial.expand R p) f)

full_name: instPerfectRingProd
code: instance instPerfectRingProd (S : Type*) [CommSemiring S] [ExpChar S p] [PerfectRing S p] :
    PerfectRing (R × S) p 
goal: PerfectRing (R × S) p

full_name: PerfectField.separable_of_irreducible
code: /-- A perfect field.

See also `PerfectRing` for a generalisation in positive characteristic. -/
class PerfectField (K : Type*) [Field K] : Prop where
  /-- A field is perfect if every irreducible polynomial is separable. -/
  separable_of_irreducible : ∀ {f : K[X]}, Irreducible f → f.Separable
goal: Irreducible f → f.Separable

full_name: PerfectField
code: /-- A perfect field.

See also `PerfectRing` for a generalisation in positive characteristic. -/
class PerfectField (K : Type*) [Field K] : Prop where
  /-- A field is perfect if every irreducible polynomial is separable. -/
  separable_of_irreducible : ∀ {f : K[X]}, Irreducible f → f.Separable
goal: Prop

full_name: PerfectRing.toPerfectField
code: lemma PerfectRing.toPerfectField (K : Type*) (p : ℕ)
    [Field K] [ExpChar K p] [PerfectRing K p] : PerfectField K 
goal: PerfectField K

full_name: PerfectField.ofCharZero
code: instance ofCharZero [CharZero K] : PerfectField K 
goal: PerfectField K

full_name: PerfectField.ofFinite
code: instance ofFinite [Finite K] : PerfectField K 
goal: PerfectField K

full_name: PerfectField.toPerfectRing
code: /-- A perfect field of characteristic `p` (prime) is a perfect ring. -/
instance toPerfectRing (p : ℕ) [ExpChar K p] : PerfectRing K p 
goal: PerfectRing K p

full_name: PerfectField.separable_iff_squarefree
code: theorem separable_iff_squarefree {g : K[X]} : g.Separable ↔ Squarefree g 
goal: g.Separable ↔ Squarefree g

full_name: Algebra.IsAlgebraic.isSeparable_of_perfectField
code: /-- If `L / K` is an algebraic extension, `K` is a perfect field, then `L / K` is separable. -/
instance Algebra.IsAlgebraic.isSeparable_of_perfectField {K L : Type*} [Field K] [Field L]
    [Algebra K L] [Algebra.IsAlgebraic K L] [PerfectField K] : Algebra.IsSeparable K L 
goal: Algebra.IsSeparable K L

full_name: Algebra.IsAlgebraic.perfectField
code: /-- If `L / K` is an algebraic extension, `K` is a perfect field, then so is `L`. -/
theorem Algebra.IsAlgebraic.perfectField {K L : Type*} [Field K] [Field L] [Algebra K L]
    [Algebra.IsAlgebraic K L] [PerfectField K] : PerfectField L 
goal: PerfectField L

full_name: Polynomial.roots_expand_pow_map_iterateFrobenius_le
code: theorem roots_expand_pow_map_iterateFrobenius_le :
    (expand R (p ^ n) f).roots.map (iterateFrobenius R p n) ≤ p ^ n • f.roots 
goal: Multiset.map (⇑(iterateFrobenius R p n)) ((Polynomial.expand R (p ^ n)) f).roots ≤ p ^ n • f.roots

full_name: Polynomial.roots_expand_map_frobenius_le
code: theorem roots_expand_map_frobenius_le :
    (expand R p f).roots.map (frobenius R p) ≤ p • f.roots 
goal: Multiset.map (⇑(frobenius R p)) ((Polynomial.expand R p) f).roots ≤ p • f.roots

full_name: Polynomial.roots_expand_pow_image_iterateFrobenius_subset
code: theorem roots_expand_pow_image_iterateFrobenius_subset [DecidableEq R] :
    (expand R (p ^ n) f).roots.toFinset.image (iterateFrobenius R p n) ⊆ f.roots.toFinset 
goal: Finset.image (⇑(iterateFrobenius R p n)) ((Polynomial.expand R (p ^ n)) f).roots.toFinset ⊆ f.roots.toFinset

full_name: Polynomial.roots_expand_image_frobenius_subset
code: theorem roots_expand_image_frobenius_subset [DecidableEq R] :
    (expand R p f).roots.toFinset.image (frobenius R p) ⊆ f.roots.toFinset 
goal: Finset.image (⇑(frobenius R p)) ((Polynomial.expand R p) f).roots.toFinset ⊆ f.roots.toFinset

full_name: Polynomial.roots_expand_pow
code: theorem roots_expand_pow :
    (expand R (p ^ n) f).roots = p ^ n • f.roots.map (iterateFrobeniusEquiv R p n).symm 
goal: ((Polynomial.expand R (p ^ n)) f).roots = p ^ n • Multiset.map (⇑(iterateFrobeniusEquiv R p n).symm) f.roots

full_name: Polynomial.roots_expand
code: theorem roots_expand : (expand R p f).roots = p • f.roots.map (frobeniusEquiv R p).symm 
goal: ((Polynomial.expand R p) f).roots = p • Multiset.map (⇑(frobeniusEquiv R p).symm) f.roots

full_name: Polynomial.roots_X_pow_char_pow_sub_C
code: theorem roots_X_pow_char_pow_sub_C {y : R} :
    (X ^ p ^ n - C y).roots = p ^ n • {(iterateFrobeniusEquiv R p n).symm y} 
goal: (Polynomial.X ^ p ^ n - Polynomial.C y).roots = p ^ n • {(iterateFrobeniusEquiv R p n).symm y}

full_name: Polynomial.roots_X_pow_char_pow_sub_C_pow
code: theorem roots_X_pow_char_pow_sub_C_pow {y : R} {m : ℕ} :
    ((X ^ p ^ n - C y) ^ m).roots = (m * p ^ n) • {(iterateFrobeniusEquiv R p n).symm y} 
goal: ((Polynomial.X ^ p ^ n - Polynomial.C y) ^ m).roots = (m * p ^ n) • {(iterateFrobeniusEquiv R p n).symm y}

full_name: Polynomial.roots_X_pow_char_sub_C
code: theorem roots_X_pow_char_sub_C {y : R} :
    (X ^ p - C y).roots = p • {(frobeniusEquiv R p).symm y} 
goal: (Polynomial.X ^ p - Polynomial.C y).roots = p • {(frobeniusEquiv R p).symm y}

full_name: Polynomial.roots_X_pow_char_sub_C_pow
code: theorem roots_X_pow_char_sub_C_pow {y : R} {m : ℕ} :
    ((X ^ p - C y) ^ m).roots = (m * p) • {(frobeniusEquiv R p).symm y} 
goal: ((Polynomial.X ^ p - Polynomial.C y) ^ m).roots = (m * p) • {(frobeniusEquiv R p).symm y}

full_name: Polynomial.roots_expand_pow_map_iterateFrobenius
code: theorem roots_expand_pow_map_iterateFrobenius :
    (expand R (p ^ n) f).roots.map (iterateFrobenius R p n) = p ^ n • f.roots 
goal: Multiset.map (⇑(iterateFrobenius R p n)) ((Polynomial.expand R (p ^ n)) f).roots = p ^ n • f.roots

full_name: Polynomial.roots_expand_map_frobenius
code: theorem roots_expand_map_frobenius : (expand R p f).roots.map (frobenius R p) = p • f.roots 
goal: Multiset.map (⇑(frobenius R p)) ((Polynomial.expand R p) f).roots = p • f.roots

full_name: Polynomial.roots_expand_image_iterateFrobenius
code: theorem roots_expand_image_iterateFrobenius [DecidableEq R] :
    (expand R (p ^ n) f).roots.toFinset.image (iterateFrobenius R p n) = f.roots.toFinset 
goal: Finset.image (⇑(iterateFrobenius R p n)) ((Polynomial.expand R (p ^ n)) f).roots.toFinset = f.roots.toFinset

full_name: Polynomial.roots_expand_image_frobenius
code: theorem roots_expand_image_frobenius [DecidableEq R] :
    (expand R p f).roots.toFinset.image (frobenius R p) = f.roots.toFinset 
goal: Finset.image (⇑(frobenius R p)) ((Polynomial.expand R p) f).roots.toFinset = f.roots.toFinset

full_name: Polynomial.rootsExpandToRoots
code: /-- If `f` is a polynomial over an integral domain `R` of characteristic `p`, then there is
a map from the set of roots of `Polynomial.expand R p f` to the set of roots of `f`.
It's given by `x ↦ x ^ p`, see `rootsExpandToRoots_apply`. -/
noncomputable def rootsExpandToRoots : (expand R p f).roots.toFinset ↪ f.roots.toFinset 
goal: { x // x ∈ ((Polynomial.expand R p) f).roots.toFinset } ↪ { x // x ∈ f.roots.toFinset }

full_name: Polynomial.rootsExpandToRoots_apply
code: @[simp]
theorem rootsExpandToRoots_apply (x) : (rootsExpandToRoots p f x : R) = x ^ p 
goal: ↑((Polynomial.rootsExpandToRoots p f) x) = ↑x ^ p

full_name: Polynomial.rootsExpandPowToRoots
code: /-- If `f` is a polynomial over an integral domain `R` of characteristic `p`, then there is
a map from the set of roots of `Polynomial.expand R (p ^ n) f` to the set of roots of `f`.
It's given by `x ↦ x ^ (p ^ n)`, see `rootsExpandPowToRoots_apply`. -/
noncomputable def rootsExpandPowToRoots :
    (expand R (p ^ n) f).roots.toFinset ↪ f.roots.toFinset 
goal: { x // x ∈ ((Polynomial.expand R (p ^ n)) f).roots.toFinset } ↪ { x // x ∈ f.roots.toFinset }

full_name: Polynomial.rootsExpandPowToRoots_apply
code: @[simp]
theorem rootsExpandPowToRoots_apply (x) : (rootsExpandPowToRoots p n f x : R) = x ^ p ^ n 
goal: ↑((Polynomial.rootsExpandPowToRoots p n f) x) = ↑x ^ p ^ n

full_name: Polynomial.rootsExpandEquivRoots
code: /-- If `f` is a polynomial over a perfect integral domain `R` of characteristic `p`, then there is
a bijection from the set of roots of `Polynomial.expand R p f` to the set of roots of `f`.
It's given by `x ↦ x ^ p`, see `rootsExpandEquivRoots_apply`. -/
noncomputable def rootsExpandEquivRoots : (expand R p f).roots.toFinset ≃ f.roots.toFinset 
goal: { x // x ∈ ((Polynomial.expand R p) f).roots.toFinset } ≃ { x // x ∈ f.roots.toFinset }

full_name: Polynomial.rootsExpandEquivRoots_apply
code: @[simp]
theorem rootsExpandEquivRoots_apply (x) : (rootsExpandEquivRoots p f x : R) = x ^ p 
goal: ↑((Polynomial.rootsExpandEquivRoots p f) x) = ↑x ^ p

full_name: Polynomial.rootsExpandPowEquivRoots
code: /-- If `f` is a polynomial over a perfect integral domain `R` of characteristic `p`, then there is
a bijection from the set of roots of `Polynomial.expand R (p ^ n) f` to the set of roots of `f`.
It's given by `x ↦ x ^ (p ^ n)`, see `rootsExpandPowEquivRoots_apply`. -/
noncomputable def rootsExpandPowEquivRoots (n : ℕ) :
    (expand R (p ^ n) f).roots.toFinset ≃ f.roots.toFinset 
goal: { x // x ∈ ((Polynomial.expand R (p ^ n)) f).roots.toFinset } ≃ { x // x ∈ f.roots.toFinset }

full_name: Polynomial.rootsExpandPowEquivRoots_apply
code: @[simp]
theorem rootsExpandPowEquivRoots_apply (n : ℕ) (x) :
    (rootsExpandPowEquivRoots p f n x : R) = x ^ p ^ n 
goal: ↑((Polynomial.rootsExpandPowEquivRoots p f n) x) = ↑x ^ p ^ n