l3lab/ntp-mathlib huggingface dataset:
theorem isUnit_norm_of_isGalois [IsGalois K L] {x : 𝓞 L} : IsUnit (norm K x) ↔ IsUnit x := by
  classical
  refine' ⟨fun hx => _, IsUnit.map _⟩
  replace hx : IsUnit (algebraMap (𝓞 K) (𝓞 L) <| norm K x) := hx.map (algebraMap (𝓞 K) <| 𝓞 L)
  refine' @isUnit_of_mul_isUnit_right (𝓞 L) _
    ⟨(univ \ {AlgEquiv.refl}).prod fun σ : L ≃ₐ[K] L => σ x,
      prod_mem fun σ _ => x.2.map (σ : L →+* L).toIntAlgHom⟩ _ _
  convert hx using 1
  ext
  push_cast
  convert_to ((univ \ {AlgEquiv.refl}).prod fun σ : L ≃ₐ[K] L => σ x) *
    ∏ σ : L ≃ₐ[K] L in {AlgEquiv.refl}, σ (x : L) = _
  · 

Proof state:
case h.e'_2
L : Type u_1
K : Type u_2
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Algebra K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsGalois K L
x : ↥(𝓞 L)
hx : IsUnit ((algebraMap ↥(𝓞 K) ↥(𝓞 L)) ((norm K) x))
⊢ (∏ σ in univ \ {AlgEquiv.refl}, σ ↑x) * ↑x = (∏ σ in univ \ {AlgEquiv.refl}, σ ↑x) * ∏ σ in {AlgEquiv.refl}, σ ↑x

Next tactic:
rw [prod_singleton, AlgEquiv.coe_refl, _root_.id]
theorem isUnit_norm_of_isGalois [IsGalois K L] {x : 𝓞 L} : IsUnit (norm K x) ↔ IsUnit x := by
  classical
  refine' ⟨fun hx => _, IsUnit.map _⟩
  replace hx : IsUnit (algebraMap (𝓞 K) (𝓞 L) <| norm K x) := hx.map (algebraMap (𝓞 K) <| 𝓞 L)
  refine' @isUnit_of_mul_isUnit_right (𝓞 L) _
    ⟨(univ \ {AlgEquiv.refl}).prod fun σ : L ≃ₐ[K] L => σ x,
      prod_mem fun σ _ => x.2.map (σ : L →+* L).toIntAlgHom⟩ _ _
  convert hx using 1
  ext
  push_cast
  convert_to ((univ \ {AlgEquiv.refl}).prod fun σ : L ≃ₐ[K] L => σ x) *
    ∏ σ : L ≃ₐ[K] L in {AlgEquiv.refl}, σ (x : L) = _
  · rw [prod_singleton, AlgEquiv.coe_refl, _root_.id]
  · 

Proof state:
case h.e'_3.a.convert_2
L : Type u_1
K : Type u_2
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Algebra K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsGalois K L
x : ↥(𝓞 L)
hx : IsUnit ((algebraMap ↥(𝓞 K) ↥(𝓞 L)) ((norm K) x))
⊢ (∏ σ in univ \ {AlgEquiv.refl}, σ ↑x) * ∏ σ in {AlgEquiv.refl}, σ ↑x = ↑((algebraMap ↥(𝓞 K) ↥(𝓞 L)) ((norm K) x))

Next tactic:
rw [prod_sdiff <| subset_univ _, ← norm_eq_prod_automorphisms, coe_algebraMap_norm]
/-- If `L/K` is a finite Galois extension of fields, then, for all `(x : 𝓞 L)` we have that
`x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x)`. -/
theorem dvd_norm [IsGalois K L] (x : 𝓞 L) : x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x) := by
  

Proof state:
L : Type u_1
K : Type u_2
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Algebra K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsGalois K L
x : ↥(𝓞 L)
⊢ x ∣ (algebraMap ↥(𝓞 K) ↥(𝓞 L)) ((norm K) x)

Next tactic:
classical
  have hint : ∏ σ : L ≃ₐ[K] L in univ.erase AlgEquiv.refl, σ x ∈ 𝓞 L :=
    Subalgebra.prod_mem _ fun σ _ =>
      (mem_ringOfIntegers _ _).2 ((RingOfIntegers.isIntegral_coe x).map σ)
  refine' ⟨⟨_, hint⟩, Subtype.ext _⟩
  rw [coe_algebraMap_norm K x, norm_eq_prod_automorphisms]
  simp [← Finset.mul_prod_erase _ _ (mem_univ AlgEquiv.refl)]
/-- If `L/K` is a finite Galois extension of fields, then, for all `(x : 𝓞 L)` we have that
`x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x)`. -/
theorem dvd_norm [IsGalois K L] (x : 𝓞 L) : x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x) := by
  classical
  

Proof state:
L : Type u_1
K : Type u_2
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Algebra K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsGalois K L
x : ↥(𝓞 L)
⊢ x ∣ (algebraMap ↥(𝓞 K) ↥(𝓞 L)) ((norm K) x)

Next tactic:
have hint : ∏ σ : L ≃ₐ[K] L in univ.erase AlgEquiv.refl, σ x ∈ 𝓞 L :=
    Subalgebra.prod_mem _ fun σ _ =>
      (mem_ringOfIntegers _ _).2 ((RingOfIntegers.isIntegral_coe x).map σ)
/-- If `L/K` is a finite Galois extension of fields, then, for all `(x : 𝓞 L)` we have that
`x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x)`. -/
theorem dvd_norm [IsGalois K L] (x : 𝓞 L) : x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x) := by
  classical
  have hint : ∏ σ : L ≃ₐ[K] L in univ.erase AlgEquiv.refl, σ x ∈ 𝓞 L :=
    Subalgebra.prod_mem _ fun σ _ =>
      (mem_ringOfIntegers _ _).2 ((RingOfIntegers.isIntegral_coe x).map σ)
  

Proof state:
L : Type u_1
K : Type u_2
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Algebra K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsGalois K L
x : ↥(𝓞 L)
hint : ∏ σ in erase univ AlgEquiv.refl, σ ↑x ∈ 𝓞 L
⊢ x ∣ (algebraMap ↥(𝓞 K) ↥(𝓞 L)) ((norm K) x)

Next tactic:
refine' ⟨⟨_, hint⟩, Subtype.ext _⟩
/-- If `L/K` is a finite Galois extension of fields, then, for all `(x : 𝓞 L)` we have that
`x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x)`. -/
theorem dvd_norm [IsGalois K L] (x : 𝓞 L) : x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x) := by
  classical
  have hint : ∏ σ : L ≃ₐ[K] L in univ.erase AlgEquiv.refl, σ x ∈ 𝓞 L :=
    Subalgebra.prod_mem _ fun σ _ =>
      (mem_ringOfIntegers _ _).2 ((RingOfIntegers.isIntegral_coe x).map σ)
  refine' ⟨⟨_, hint⟩, Subtype.ext _⟩
  

Proof state:
L : Type u_1
K : Type u_2
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Algebra K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsGalois K L
x : ↥(𝓞 L)
hint : ∏ σ in erase univ AlgEquiv.refl, σ ↑x ∈ 𝓞 L
⊢ ↑((algebraMap ↥(𝓞 K) ↥(𝓞 L)) ((norm K) x)) = ↑(x * { val := ∏ σ in erase univ AlgEquiv.refl, σ ↑x, property := hint })

Next tactic:
rw [coe_algebraMap_norm K x, norm_eq_prod_automorphisms]
/-- If `L/K` is a finite Galois extension of fields, then, for all `(x : 𝓞 L)` we have that
`x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x)`. -/
theorem dvd_norm [IsGalois K L] (x : 𝓞 L) : x ∣ algebraMap (𝓞 K) (𝓞 L) (norm K x) := by
  classical
  have hint : ∏ σ : L ≃ₐ[K] L in univ.erase AlgEquiv.refl, σ x ∈ 𝓞 L :=
    Subalgebra.prod_mem _ fun σ _ =>
      (mem_ringOfIntegers _ _).2 ((RingOfIntegers.isIntegral_coe x).map σ)
  refine' ⟨⟨_, hint⟩, Subtype.ext _⟩
  rw [coe_algebraMap_norm K x, norm_eq_prod_automorphisms]
  

Proof state:
L : Type u_1
K : Type u_2
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Algebra K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsGalois K L
x : ↥(𝓞 L)
hint : ∏ σ in erase univ AlgEquiv.refl, σ ↑x ∈ 𝓞 L
⊢ ∏ σ : L ≃ₐ[K] L, σ ↑x = ↑(x * { val := ∏ σ in erase univ AlgEquiv.refl, σ ↑x, property := hint })

Next tactic:
simp [← Finset.mul_prod_erase _ _ (mem_univ AlgEquiv.refl)]
theorem norm_norm [IsSeparable K L] [Algebra F L] [IsSeparable F L] [FiniteDimensional F L]
    [IsScalarTower K F L] (x : 𝓞 L) : norm K (norm F x) = norm K x := by
  

Proof state:
L : Type u_1
K : Type u_2
inst✝¹² : Field K
inst✝¹¹ : Field L
inst✝¹⁰ : Algebra K L
inst✝⁹ : FiniteDimensional K L
F : Type u_3
inst✝⁸ : Field F
inst✝⁷ : Algebra K F
inst✝⁶ : IsSeparable K F
inst✝⁵ : FiniteDimensional K F
inst✝⁴ : IsSeparable K L
inst✝³ : Algebra F L
inst✝² : IsSeparable F L
inst✝¹ : FiniteDimensional F L
inst✝ : IsScalarTower K F L
x : ↥(𝓞 L)
⊢ (norm K) ((norm F) x) = (norm K) x

Next tactic:
rw [← Subtype.coe_inj, norm_apply_coe, norm_apply_coe, norm_apply_coe, Algebra.norm_norm]
theorem isUnit_norm [CharZero K] {x : 𝓞 F} : IsUnit (norm K x) ↔ IsUnit x := by
  

Proof state:
L : Type u_1
K : Type u_2
inst✝⁸ : Field K
inst✝⁷ : Field L
inst✝⁶ : Algebra K L
inst✝⁵ : FiniteDimensional K L
F : Type u_3
inst✝⁴ : Field F
inst✝³ : Algebra K F
inst✝² : IsSeparable K F
inst✝¹ : FiniteDimensional K F
inst✝ : CharZero K
x : ↥(𝓞 F)
⊢ IsUnit ((norm K) x) ↔ IsUnit x

Next tactic:
letI : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
theorem isUnit_norm [CharZero K] {x : 𝓞 F} : IsUnit (norm K x) ↔ IsUnit x := by
  letI : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
  

Proof state:
L : Type u_1
K : Type u_2
inst✝⁸ : Field K
inst✝⁷ : Field L
inst✝⁶ : Algebra K L
inst✝⁵ : FiniteDimensional K L
F : Type u_3
inst✝⁴ : Field F
inst✝³ : Algebra K F
inst✝² : IsSeparable K F
inst✝¹ : FiniteDimensional K F
inst✝ : CharZero K
x : ↥(𝓞 F)
this : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
⊢ IsUnit ((norm K) x) ↔ IsUnit x

Next tactic:
let L := normalClosure K F (AlgebraicClosure F)
theorem isUnit_norm [CharZero K] {x : 𝓞 F} : IsUnit (norm K x) ↔ IsUnit x := by
  letI : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
  let L := normalClosure K F (AlgebraicClosure F)
  

Proof state:
L✝ : Type u_1
K : Type u_2
inst✝⁸ : Field K
inst✝⁷ : Field L✝
inst✝⁶ : Algebra K L✝
inst✝⁵ : FiniteDimensional K L✝
F : Type u_3
inst✝⁴ : Field F
inst✝³ : Algebra K F
inst✝² : IsSeparable K F
inst✝¹ : FiniteDimensional K F
inst✝ : CharZero K
x : ↥(𝓞 F)
this : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
L : IntermediateField K (AlgebraicClosure F) := normalClosure K F (AlgebraicClosure F)
⊢ IsUnit ((norm K) x) ↔ IsUnit x

Next tactic:
haveI : FiniteDimensional F L := FiniteDimensional.right K F L
theorem isUnit_norm [CharZero K] {x : 𝓞 F} : IsUnit (norm K x) ↔ IsUnit x := by
  letI : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
  let L := normalClosure K F (AlgebraicClosure F)
  haveI : FiniteDimensional F L := FiniteDimensional.right K F L
  

Proof state:
L✝ : Type u_1
K : Type u_2
inst✝⁸ : Field K
inst✝⁷ : Field L✝
inst✝⁶ : Algebra K L✝
inst✝⁵ : FiniteDimensional K L✝
F : Type u_3
inst✝⁴ : Field F
inst✝³ : Algebra K F
inst✝² : IsSeparable K F
inst✝¹ : FiniteDimensional K F
inst✝ : CharZero K
x : ↥(𝓞 F)
this✝ : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
L : IntermediateField K (AlgebraicClosure F) := normalClosure K F (AlgebraicClosure F)
this : FiniteDimensional F ↥L
⊢ IsUnit ((norm K) x) ↔ IsUnit x

Next tactic:
haveI : IsAlgClosure K (AlgebraicClosure F) :=
    IsAlgClosure.ofAlgebraic K F (AlgebraicClosure F) (Algebra.IsAlgebraic.of_finite K F)
theorem isUnit_norm [CharZero K] {x : 𝓞 F} : IsUnit (norm K x) ↔ IsUnit x := by
  letI : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
  let L := normalClosure K F (AlgebraicClosure F)
  haveI : FiniteDimensional F L := FiniteDimensional.right K F L
  haveI : IsAlgClosure K (AlgebraicClosure F) :=
    IsAlgClosure.ofAlgebraic K F (AlgebraicClosure F) (Algebra.IsAlgebraic.of_finite K F)
  

Proof state:
L✝ : Type u_1
K : Type u_2
inst✝⁸ : Field K
inst✝⁷ : Field L✝
inst✝⁶ : Algebra K L✝
inst✝⁵ : FiniteDimensional K L✝
F : Type u_3
inst✝⁴ : Field F
inst✝³ : Algebra K F
inst✝² : IsSeparable K F
inst✝¹ : FiniteDimensional K F
inst✝ : CharZero K
x : ↥(𝓞 F)
this✝¹ : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
L : IntermediateField K (AlgebraicClosure F) := normalClosure K F (AlgebraicClosure F)
this✝ : FiniteDimensional F ↥L
this : IsAlgClosure K (AlgebraicClosure F)
⊢ IsUnit ((norm K) x) ↔ IsUnit x

Next tactic:
haveI : IsGalois F L := IsGalois.tower_top_of_isGalois K F L
theorem isUnit_norm [CharZero K] {x : 𝓞 F} : IsUnit (norm K x) ↔ IsUnit x := by
  letI : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
  let L := normalClosure K F (AlgebraicClosure F)
  haveI : FiniteDimensional F L := FiniteDimensional.right K F L
  haveI : IsAlgClosure K (AlgebraicClosure F) :=
    IsAlgClosure.ofAlgebraic K F (AlgebraicClosure F) (Algebra.IsAlgebraic.of_finite K F)
  haveI : IsGalois F L := IsGalois.tower_top_of_isGalois K F L
  

Proof state:
L✝ : Type u_1
K : Type u_2
inst✝⁸ : Field K
inst✝⁷ : Field L✝
inst✝⁶ : Algebra K L✝
inst✝⁵ : FiniteDimensional K L✝
F : Type u_3
inst✝⁴ : Field F
inst✝³ : Algebra K F
inst✝² : IsSeparable K F
inst✝¹ : FiniteDimensional K F
inst✝ : CharZero K
x : ↥(𝓞 F)
this✝² : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
L : IntermediateField K (AlgebraicClosure F) := normalClosure K F (AlgebraicClosure F)
this✝¹ : FiniteDimensional F ↥L
this✝ : IsAlgClosure K (AlgebraicClosure F)
this : IsGalois F ↥L
⊢ IsUnit ((norm K) x) ↔ IsUnit x

Next tactic:
calc
    IsUnit (norm K x) ↔ IsUnit ((norm K) x ^ finrank F L) :=
      (isUnit_pow_iff (pos_iff_ne_zero.mp finrank_pos)).symm
    _ ↔ IsUnit (norm K (algebraMap (𝓞 F) (𝓞 L) x)) := by
      rw [← norm_norm K F (algebraMap (𝓞 F) (𝓞 L) x), norm_algebraMap F _, map_pow]
    _ ↔ IsUnit (algebraMap (𝓞 F) (𝓞 L) x) := (isUnit_norm_of_isGalois K)
    _ ↔ IsUnit (norm F (algebraMap (𝓞 F) (𝓞 L) x)) := (isUnit_norm_of_isGalois F).symm
    _ ↔ IsUnit (x ^ finrank F L) := (congr_arg IsUnit (norm_algebraMap F _)).to_iff
    _ ↔ IsUnit x := isUnit_pow_iff (pos_iff_ne_zero.mp finrank_pos)
theorem isUnit_norm [CharZero K] {x : 𝓞 F} : IsUnit (norm K x) ↔ IsUnit x := by
  letI : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
  let L := normalClosure K F (AlgebraicClosure F)
  haveI : FiniteDimensional F L := FiniteDimensional.right K F L
  haveI : IsAlgClosure K (AlgebraicClosure F) :=
    IsAlgClosure.ofAlgebraic K F (AlgebraicClosure F) (Algebra.IsAlgebraic.of_finite K F)
  haveI : IsGalois F L := IsGalois.tower_top_of_isGalois K F L
  calc
    IsUnit (norm K x) ↔ IsUnit ((norm K) x ^ finrank F L) :=
      (isUnit_pow_iff (pos_iff_ne_zero.mp finrank_pos)).symm
    _ ↔ IsUnit (norm K (algebraMap (𝓞 F) (𝓞 L) x)) := by
      

Proof state:
L✝ : Type u_1
K : Type u_2
inst✝⁸ : Field K
inst✝⁷ : Field L✝
inst✝⁶ : Algebra K L✝
inst✝⁵ : FiniteDimensional K L✝
F : Type u_3
inst✝⁴ : Field F
inst✝³ : Algebra K F
inst✝² : IsSeparable K F
inst✝¹ : FiniteDimensional K F
inst✝ : CharZero K
x : ↥(𝓞 F)
this✝² : Algebra K (AlgebraicClosure K) := AlgebraicClosure.instAlgebra K
L : IntermediateField K (AlgebraicClosure F) := normalClosure K F (AlgebraicClosure F)
this✝¹ : FiniteDimensional F ↥L
this✝ : IsAlgClosure K (AlgebraicClosure F)
this : IsGalois F ↥L
⊢ IsUnit ((norm K) x ^ finrank F ↥L) ↔ IsUnit ((norm K) ((algebraMap ↥(𝓞 F) ↥(𝓞 ↥L)) x))

Next tactic:
rw [← norm_norm K F (algebraMap (𝓞 F) (𝓞 L) x), norm_algebraMap F _, map_pow]
theorem frobenius_inj (R : Type*) [CommRing R] [IsReduced R] (p : ℕ) [Fact p.Prime] [CharP R p] :
    Function.Injective (frobenius R p) := fun x h H => by
  

Proof state:
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x h : R
H : (frobenius R p) x = (frobenius R p) h
⊢ x = h

Next tactic:
rw [← sub_eq_zero] at H ⊢
theorem frobenius_inj (R : Type*) [CommRing R] [IsReduced R] (p : ℕ) [Fact p.Prime] [CharP R p] :
    Function.Injective (frobenius R p) := fun x h H => by
  rw [← sub_eq_zero] at H ⊢
  

Proof state:
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x h : R
H : (frobenius R p) x - (frobenius R p) h = 0
⊢ x - h = 0

Next tactic:
rw [← frobenius_sub] at H
theorem frobenius_inj (R : Type*) [CommRing R] [IsReduced R] (p : ℕ) [Fact p.Prime] [CharP R p] :
    Function.Injective (frobenius R p) := fun x h H => by
  rw [← sub_eq_zero] at H ⊢
  rw [← frobenius_sub] at H
  

Proof state:
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x h : R
H : (frobenius R p) (x - h) = 0
⊢ x - h = 0

Next tactic:
exact IsReduced.eq_zero _ ⟨_, H⟩
/-- If `ringChar R = 2`, where `R` is a finite reduced commutative ring,
then every `a : R` is a square. -/
theorem isSquare_of_charTwo' {R : Type*} [Finite R] [CommRing R] [IsReduced R] [CharP R 2]
    (a : R) : IsSquare a := by
  

Proof state:
R : Type u_1
inst✝³ : Finite R
inst✝² : CommRing R
inst✝¹ : IsReduced R
inst✝ : CharP R 2
a : R
⊢ IsSquare a

Next tactic:
cases nonempty_fintype R
/-- If `ringChar R = 2`, where `R` is a finite reduced commutative ring,
then every `a : R` is a square. -/
theorem isSquare_of_charTwo' {R : Type*} [Finite R] [CommRing R] [IsReduced R] [CharP R 2]
    (a : R) : IsSquare a := by
  cases nonempty_fintype R
  

Proof state:
case intro
R : Type u_1
inst✝³ : Finite R
inst✝² : CommRing R
inst✝¹ : IsReduced R
inst✝ : CharP R 2
a : R
val✝ : Fintype R
⊢ IsSquare a

Next tactic:
exact
    Exists.imp (fun b h => pow_two b ▸ Eq.symm h)
      (((Fintype.bijective_iff_injective_and_card _).mpr ⟨frobenius_inj R 2, rfl⟩).surjective a)
@[simp]
theorem pow_prime_pow_mul_eq_one_iff (p k m : ℕ) [Fact p.Prime] [CharP R p] (x : R) :
    x ^ (p ^ k * m) = 1 ↔ x ^ m = 1 := by
  

Proof state:
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p k m : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x : R
⊢ x ^ (p ^ k * m) = 1 ↔ x ^ m = 1

Next tactic:
induction' k with k hk
@[simp]
theorem pow_prime_pow_mul_eq_one_iff (p k m : ℕ) [Fact p.Prime] [CharP R p] (x : R) :
    x ^ (p ^ k * m) = 1 ↔ x ^ m = 1 := by
  induction' k with k hk
  · 

Proof state:
case zero
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p m : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x : R
⊢ x ^ (p ^ Nat.zero * m) = 1 ↔ x ^ m = 1

Next tactic:
rw [pow_zero, one_mul]
@[simp]
theorem pow_prime_pow_mul_eq_one_iff (p k m : ℕ) [Fact p.Prime] [CharP R p] (x : R) :
    x ^ (p ^ k * m) = 1 ↔ x ^ m = 1 := by
  induction' k with k hk
  · rw [pow_zero, one_mul]
  · 

Proof state:
case succ
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p m : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x : R
k : ℕ
hk : x ^ (p ^ k * m) = 1 ↔ x ^ m = 1
⊢ x ^ (p ^ Nat.succ k * m) = 1 ↔ x ^ m = 1

Next tactic:
refine' ⟨fun h => _, fun h => _⟩
@[simp]
theorem pow_prime_pow_mul_eq_one_iff (p k m : ℕ) [Fact p.Prime] [CharP R p] (x : R) :
    x ^ (p ^ k * m) = 1 ↔ x ^ m = 1 := by
  induction' k with k hk
  · rw [pow_zero, one_mul]
  · refine' ⟨fun h => _, fun h => _⟩
    · 

Proof state:
case succ.refine'_1
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p m : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x : R
k : ℕ
hk : x ^ (p ^ k * m) = 1 ↔ x ^ m = 1
h : x ^ (p ^ Nat.succ k * m) = 1
⊢ x ^ m = 1

Next tactic:
rw [pow_succ, mul_assoc, pow_mul', ← frobenius_def, ← frobenius_one p] at h
@[simp]
theorem pow_prime_pow_mul_eq_one_iff (p k m : ℕ) [Fact p.Prime] [CharP R p] (x : R) :
    x ^ (p ^ k * m) = 1 ↔ x ^ m = 1 := by
  induction' k with k hk
  · rw [pow_zero, one_mul]
  · refine' ⟨fun h => _, fun h => _⟩
    · rw [pow_succ, mul_assoc, pow_mul', ← frobenius_def, ← frobenius_one p] at h
      

Proof state:
case succ.refine'_1
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p m : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x : R
k : ℕ
hk : x ^ (p ^ k * m) = 1 ↔ x ^ m = 1
h : (frobenius R p) (x ^ (p ^ k * m)) = (frobenius R p) 1
⊢ x ^ m = 1

Next tactic:
exact hk.1 (frobenius_inj R p h)
@[simp]
theorem pow_prime_pow_mul_eq_one_iff (p k m : ℕ) [Fact p.Prime] [CharP R p] (x : R) :
    x ^ (p ^ k * m) = 1 ↔ x ^ m = 1 := by
  induction' k with k hk
  · rw [pow_zero, one_mul]
  · refine' ⟨fun h => _, fun h => _⟩
    · rw [pow_succ, mul_assoc, pow_mul', ← frobenius_def, ← frobenius_one p] at h
      exact hk.1 (frobenius_inj R p h)
    · 

Proof state:
case succ.refine'_2
R : Type u_1
inst✝³ : CommRing R
inst✝² : IsReduced R
p m : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
x : R
k : ℕ
hk : x ^ (p ^ k * m) = 1 ↔ x ^ m = 1
h : x ^ m = 1
⊢ x ^ (p ^ Nat.succ k * m) = 1

Next tactic:
rw [pow_mul', h, one_pow]
@[simp]
theorem bind₁_X_left : bind₁ (X : σ → MvPolynomial σ R) = AlgHom.id R _ := by
  

Proof state:
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
⊢ bind₁ X = AlgHom.id R (MvPolynomial σ R)

Next tactic:
ext1 i
@[simp]
theorem bind₁_X_left : bind₁ (X : σ → MvPolynomial σ R) = AlgHom.id R _ := by
  ext1 i
  

Proof state:
case hf
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
i : σ
⊢ (bind₁ X) (X i) = (AlgHom.id R (MvPolynomial σ R)) (X i)

Next tactic:
simp
@[simp]
theorem bind₁_C_right (f : σ → MvPolynomial τ R) (x) : bind₁ f (C x) = C x := by
  

Proof state:
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f✝ f : σ → MvPolynomial τ R
x : R
⊢ (bind₁ f) (C x) = C x

Next tactic:
simp [bind₁, algebraMap_eq]
@[simp]
theorem bind₂_C_left : bind₂ (C : R →+* MvPolynomial σ R) = RingHom.id _ := by 

Proof state:
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f : σ → MvPolynomial τ R
⊢ bind₂ C = RingHom.id (MvPolynomial σ R)

Next tactic:
ext : 2
@[simp]
theorem bind₂_C_left : bind₂ (C : R →+* MvPolynomial σ R) = RingHom.id _ := by ext : 2 <;> 

Proof state:
case hC.a
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f : σ → MvPolynomial τ R
x✝ : R
⊢ (RingHom.comp (bind₂ C) C) x✝ = (RingHom.comp (RingHom.id (MvPolynomial σ R)) C) x✝

Next tactic:
simp
@[simp]
theorem bind₂_C_left : bind₂ (C : R →+* MvPolynomial σ R) = RingHom.id _ := by ext : 2 <;> 

Proof state:
case hX.a
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f : σ → MvPolynomial τ R
i✝ : σ
m✝ : σ →₀ ℕ
⊢ coeff m✝ ((bind₂ C) (X i✝)) = coeff m✝ ((RingHom.id (MvPolynomial σ R)) (X i✝))

Next tactic:
simp
@[simp]
theorem join₂_map (f : R →+* MvPolynomial σ S) (φ : MvPolynomial σ R) :
    join₂ (map f φ) = bind₂ f φ := by 

Proof state:
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f✝ : σ → MvPolynomial τ R
f : R →+* MvPolynomial σ S
φ : MvPolynomial σ R
⊢ join₂ ((map f) φ) = (bind₂ f) φ

Next tactic:
simp only [join₂, bind₂, eval₂Hom_map_hom, RingHom.id_comp]
theorem aeval_id_rename (f : σ → MvPolynomial τ R) (p : MvPolynomial σ R) :
    aeval id (rename f p) = aeval f p := by 

Proof state:
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f✝ f : σ → MvPolynomial τ R
p : MvPolynomial σ R
⊢ (aeval id) ((rename f) p) = (aeval f) p

Next tactic:
rw [aeval_rename, Function.comp.left_id]
theorem bind₁_bind₁ {υ : Type*} (f : σ → MvPolynomial τ R) (g : τ → MvPolynomial υ R)
    (φ : MvPolynomial σ R) : (bind₁ g) (bind₁ f φ) = bind₁ (fun i => bind₁ g (f i)) φ := by
  

Proof state:
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f✝ : σ → MvPolynomial τ R
υ : Type u_6
f : σ → MvPolynomial τ R
g : τ → MvPolynomial υ R
φ : MvPolynomial σ R
⊢ (bind₁ g) ((bind₁ f) φ) = (bind₁ fun i => (bind₁ g) (f i)) φ

Next tactic:
simp [bind₁, ← comp_aeval]
theorem bind₁_comp_bind₁ {υ : Type*} (f : σ → MvPolynomial τ R) (g : τ → MvPolynomial υ R) :
    (bind₁ g).comp (bind₁ f) = bind₁ fun i => bind₁ g (f i) := by
  

Proof state:
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f✝ : σ → MvPolynomial τ R
υ : Type u_6
f : σ → MvPolynomial τ R
g : τ → MvPolynomial υ R
⊢ AlgHom.comp (bind₁ g) (bind₁ f) = bind₁ fun i => (bind₁ g) (f i)

Next tactic:
ext1
theorem bind₁_comp_bind₁ {υ : Type*} (f : σ → MvPolynomial τ R) (g : τ → MvPolynomial υ R) :
    (bind₁ g).comp (bind₁ f) = bind₁ fun i => bind₁ g (f i) := by
  ext1
  

Proof state:
case hf
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f✝ : σ → MvPolynomial τ R
υ : Type u_6
f : σ → MvPolynomial τ R
g : τ → MvPolynomial υ R
i✝ : σ
⊢ (AlgHom.comp (bind₁ g) (bind₁ f)) (X i✝) = (bind₁ fun i => (bind₁ g) (f i)) (X i✝)

Next tactic:
apply bind₁_bind₁
theorem bind₂_comp_bind₂ (f : R →+* MvPolynomial σ S) (g : S →+* MvPolynomial σ T) :
    (bind₂ g).comp (bind₂ f) = bind₂ ((bind₂ g).comp f) := by 

Proof state:
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f✝ : σ → MvPolynomial τ R
f : R →+* MvPolynomial σ S
g : S →+* MvPolynomial σ T
⊢ RingHom.comp (bind₂ g) (bind₂ f) = bind₂ (RingHom.comp (bind₂ g) f)

Next tactic:
ext : 2
theorem bind₂_comp_bind₂ (f : R →+* MvPolynomial σ S) (g : S →+* MvPolynomial σ T) :
    (bind₂ g).comp (bind₂ f) = bind₂ ((bind₂ g).comp f) := by ext : 2 <;> 

Proof state:
case hC.a
σ : Type u_1
τ : Type u_2
R : Type u_3
S : Type u_4
T : Type u_5
inst✝² : CommSemiring R
inst✝¹ : CommSemiring S
inst✝ : CommSemiring T
f✝ : σ → MvPolynomial τ R
f : R →+* MvPolynomial σ S
g : S →+* MvPolynomial σ T
x✝ : R
⊢ (RingHom.comp (RingHom.comp (bind₂ g) (bind₂ f)) C) x✝ = (RingHom.comp (bind₂ (RingHom.comp (bind₂ g) f)) C) x✝

Next tactic:
simp